From 2e0513bb502d3e8452e5e1544745a3351dfd2e9a Mon Sep 17 00:00:00 2001 From: oranges Date: Sun, 1 Oct 2017 18:51:53 +1300 Subject: [PATCH 01/82] Fixes master --- code/game/gamemodes/cult/cult_structures.dm | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index c1ccf9a368..ef51a2e01a 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -107,8 +107,19 @@ pickedtype = /obj/item/clothing/suit/hooded/cultrobes/cult_shield if("Flagellant's Robe") pickedtype = /obj/item/clothing/suit/hooded/cultrobes/berserker +<<<<<<< HEAD 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)].") + cooldowntime = 0 + return +>>>>>>> e997bc4... Merge pull request #31198 from Jordie0608/apparentlythisbuildcompletedthefirsttimeidkhow 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)) From 4e648765db9f674127f1546037f14d71df28ed41 Mon Sep 17 00:00:00 2001 From: KorPhaeron Date: Tue, 3 Oct 2017 18:10:39 -0500 Subject: [PATCH 02/82] Ports dash weapons to the dash datum --- code/datums/action.dm | 4 + code/datums/dash_weapon.dm | 50 ++++++ code/game/gamemodes/cult/cult_items.dm | 167 ++++++++++++++++++ code/modules/mining/equipment/survival_pod.dm | 2 +- code/modules/ninja/energy_katana.dm | 100 ++++------- code/modules/ninja/outfit.dm | 2 +- code/modules/ninja/suit/suit.dm | 2 +- tgstation.dme | 1 + 8 files changed, 257 insertions(+), 71 deletions(-) create mode 100644 code/datums/dash_weapon.dm diff --git a/code/datums/action.dm b/code/datums/action.dm index a65294fa40..b0ee243978 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -591,3 +591,7 @@ var/mob/M = owner var/datum/language_holder/H = M.get_language_holder() H.open_language_menu(usr) +<<<<<<< HEAD +======= + +>>>>>>> 380413f... Ports dash weapons to the dash datum (#31222) diff --git a/code/datums/dash_weapon.dm b/code/datums/dash_weapon.dm new file mode 100644 index 0000000000..1637655d18 --- /dev/null +++ b/code/datums/dash_weapon.dm @@ -0,0 +1,50 @@ +/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/current_charges = 1 + var/max_charges = 1 + 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(current_charges > 0) + 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) + if(!IsAvailable()) + return + 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) + current_charges-- + holder.update_action_buttons_icon() + addtimer(CALLBACK(src, .proc/charge), charge_rate) + +/datum/action/innate/dash/proc/charge() + current_charges = Clamp(current_charges + 1, 0, max_charges) + holder.update_action_buttons_icon() + if(recharge_sound) + playsound(dashing_item, recharge_sound, 50, 1) + to_chat(holder, "[src] now has [current_charges]/[max_charges] charges.") \ No newline at end of file diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index 55f8ece5e6..b6f25fc746 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -72,6 +72,173 @@ if(is_servant_of_ratvar(C) && C.reagents) C.reagents.add_reagent("heparin", 1) +<<<<<<< HEAD +======= +/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.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) && current_charges) + 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() +>>>>>>> 380413f... Ports dash weapons to the dash datum (#31222) /obj/item/restraints/legcuffs/bola/cult name = "nar'sien bola" diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm index 5b8c40a976..bb44f22752 100644 --- a/code/modules/mining/equipment/survival_pod.dm +++ b/code/modules/mining/equipment/survival_pod.dm @@ -307,7 +307,7 @@ /obj/item/melee/supermatter_sword, /obj/item/shield/changeling, /obj/item/lava_staff, - /obj/item/dash/energy_katana, + /obj/item/energy_katana, /obj/item/hierophant_club, /obj/item/his_grace, /obj/item/gun/ballistic/minigun, diff --git a/code/modules/ninja/energy_katana.dm b/code/modules/ninja/energy_katana.dm index 8901c1b9fa..33283db352 100644 --- a/code/modules/ninja/energy_katana.dm +++ b/code/modules/ninja/energy_katana.dm @@ -1,60 +1,4 @@ -/obj/item/dash - name = "abstract dash weapon" - var/max_charges = 3 - var/current_charges = 3 - var/charge_rate = 30 //In deciseconds - var/dash_toggled = TRUE - - var/bypass_density = FALSE //Can we beam past windows/airlocks/etc - - var/start_effect_type = /obj/effect/temp_visual/dir_setting/ninja/phase/out - var/end_effect_type = /obj/effect/temp_visual/dir_setting/ninja/phase - var/beam_icon_state = "blur" - var/dash_beam_type = /obj/effect/ebeam - -/obj/item/dash/proc/charge() - current_charges = Clamp(current_charges + 1, 0, max_charges) - if(istype(loc, /mob/living)) - to_chat(loc, "[src] now has [current_charges]/[max_charges] charges.") - -/obj/item/dash/attack_self(mob/user) - dash_toggled = !dash_toggled - to_chat(user, "You [dash_toggled ? "enable" : "disable"] the dash function on [src].") - -/obj/item/dash/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - if(dash_toggled) - dash(user, target) - return - -/obj/item/dash/proc/dash(mob/user, atom/target) - if(!current_charges) - return - - if(Adjacent(target)) - return - - if(target.density) - return - - var/turf/T = get_turf(target) - - if(!bypass_density) - for(var/turf/turf in getline(get_turf(user),T)) - for(var/atom/A in turf) - if(A.density) - return - - if(target in view(user.client.view, get_turf(user))) - var/obj/spot1 = new start_effect_type(T, user.dir) - user.forceMove(T) - playsound(T, 'sound/magic/blink.ogg', 25, 1) - playsound(T, "sparks", 50, 1) - var/obj/spot2 = new end_effect_type(get_turf(user), user.dir) - spot1.Beam(spot2, beam_icon_state,time = 2, maxdistance = 20, beam_type = dash_beam_type) - current_charges-- - addtimer(CALLBACK(src, .proc/charge), charge_rate) - -/obj/item/dash/energy_katana +/obj/item/energy_katana name = "energy katana" desc = "A katana infused with strong energy." icon_state = "energy_katana" @@ -73,23 +17,40 @@ sharpness = IS_SHARP max_integrity = 200 resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF - bypass_density = TRUE var/datum/effect_system/spark_spread/spark_system + var/datum/action/innate/dash/ninja/jaunt + var/dash_toggled = TRUE -/obj/item/dash/energy_katana/afterattack(atom/target, mob/user, proximity_flag, click_parameters) +/obj/item/energy_katana/Initialize() + . = ..() + jaunt = new(src) + spark_system = new /datum/effect_system/spark_spread() + spark_system.set_up(5, 0, src) + spark_system.attach(src) + +/obj/item/energy_katana/afterattack(atom/target, mob/user, proximity_flag, click_parameters) if(dash_toggled) - return ..() + jaunt.Teleport(user, target) if(proximity_flag && (isobj(target) || issilicon(target))) spark_system.start() playsound(user, "sparks", 50, 1) playsound(user, 'sound/weapons/blade1.ogg', 50, 1) target.emag_act(user) +/obj/item/energy_katana/pickup(mob/living/user) + . = ..() + jaunt.Grant(user, src) + user.update_icons() + +/obj/item/energy_katana/dropped(mob/user) + . = ..() + jaunt.Remove(user) + user.update_icons() //If we hit the Ninja who owns this Katana, they catch it. //Works for if the Ninja throws it or it throws itself or someone tries //To throw it at the ninja -/obj/item/dash/energy_katana/throw_impact(atom/hit_atom) +/obj/item/energy_katana/throw_impact(atom/hit_atom) if(ishuman(hit_atom)) var/mob/living/carbon/human/H = hit_atom if(istype(H.wear_suit, /obj/item/clothing/suit/space/space_ninja)) @@ -100,7 +61,7 @@ ..() -/obj/item/dash/energy_katana/proc/returnToOwner(mob/living/carbon/human/user, doSpark = 1, caught = 0) +/obj/item/energy_katana/proc/returnToOwner(mob/living/carbon/human/user, doSpark = 1, caught = 0) if(!istype(user)) return forceMove(get_turf(user)) @@ -127,12 +88,15 @@ if(msg) to_chat(user, "[msg]") -/obj/item/dash/energy_katana/Initialize() - . = ..() - spark_system = new /datum/effect_system/spark_spread() - spark_system.set_up(5, 0, src) - spark_system.attach(src) -/obj/item/dash/energy_katana/Destroy() +/obj/item/energy_katana/Destroy() QDEL_NULL(spark_system) return ..() + +/datum/action/innate/dash/ninja + current_charges = 3 + max_charges = 3 + charge_rate = 30 + recharge_sound = null + + diff --git a/code/modules/ninja/outfit.dm b/code/modules/ninja/outfit.dm index 4ec9cde23c..2fd732f0ce 100644 --- a/code/modules/ninja/outfit.dm +++ b/code/modules/ninja/outfit.dm @@ -12,7 +12,7 @@ l_pocket = /obj/item/grenade/plastic/x4 r_pocket = /obj/item/tank/internals/emergency_oxygen internals_slot = slot_r_store - belt = /obj/item/dash/energy_katana + belt = /obj/item/energy_katana implants = list(/obj/item/implant/explosive) diff --git a/code/modules/ninja/suit/suit.dm b/code/modules/ninja/suit/suit.dm index 40d18951e6..1dcfed99c0 100644 --- a/code/modules/ninja/suit/suit.dm +++ b/code/modules/ninja/suit/suit.dm @@ -30,7 +30,7 @@ Contents: var/datum/effect_system/spark_spread/spark_system var/list/stored_research = list()//For stealing station research. var/obj/item/disk/tech_disk/t_disk//To copy design onto disk. - var/obj/item/dash/energy_katana/energyKatana //For teleporting the katana back to the ninja (It's an ability) + var/obj/item/energy_katana/energyKatana //For teleporting the katana back to the ninja (It's an ability) //Other articles of ninja gear worn together, used to easily reference them after initializing. var/obj/item/clothing/head/helmet/space/space_ninja/n_hood diff --git a/tgstation.dme b/tgstation.dme index 1d878fc78b..2dba779e78 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -257,6 +257,7 @@ #include "code\datums\browser.dm" #include "code\datums\callback.dm" #include "code\datums\cinematic.dm" +#include "code\datums\dash_weapon.dm" #include "code\datums\datacore.dm" #include "code\datums\datum.dm" #include "code\datums\datumvars.dm" From 460fea66c86b0277bf2e5f3e805fcbd987cbad7f Mon Sep 17 00:00:00 2001 From: bawhoppen Date: Wed, 4 Oct 2017 11:59:27 -0500 Subject: [PATCH 03/82] Moves all stack object sprites from items_and_weapons.dmi to their own file --- code/game/objects/items/stacks/medical.dm | 2 +- .../game/objects/items/stacks/sheets/mineral.dm | 2 +- code/game/objects/items/stacks/stack.dm | 1 + icons/obj/stack_objects.dmi | Bin 0 -> 27430 bytes 4 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 icons/obj/stack_objects.dmi diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 02d835da16..6c073f4b69 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -1,7 +1,7 @@ /obj/item/stack/medical name = "medical pack" singular_name = "medical pack" - icon = 'icons/obj/items_and_weapons.dmi' + icon = 'icons/obj/stack_objects.dmi' amount = 6 max_amount = 6 w_class = WEIGHT_CLASS_TINY diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 8056674074..2bb5d110fc 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -63,7 +63,7 @@ GLOBAL_LIST_INIT(sandstone_recipes, list ( \ /obj/item/stack/sheet/mineral/sandbags name = "sandbags" - icon = 'icons/obj/items_and_weapons.dmi' + icon = 'icons/obj/stack_objects.dmi' icon_state = "sandbags" singular_name = "sandbag" layer = LOW_ITEM_LAYER diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 3a79ce23db..6e7ffddeb3 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -8,6 +8,7 @@ * Stacks */ /obj/item/stack + icon = 'icons/obj/stack_objects.dmi' origin_tech = "materials=1" gender = PLURAL var/list/datum/stack_recipe/recipes diff --git a/icons/obj/stack_objects.dmi b/icons/obj/stack_objects.dmi new file mode 100644 index 0000000000000000000000000000000000000000..f21c6c75797bf7f4c9307f0715e384c1fb8c849a GIT binary patch literal 27430 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�(YybZ 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 literal 0 HcmV?d00001 From 441514937e15c78bc7cc204663af25eecb67b459 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Wed, 4 Oct 2017 13:19:18 -0400 Subject: [PATCH 04/82] Moves laughter to the emote --- code/modules/mob/living/emote.dm | 347 ++++++++++++++++++ .../chemistry/reagents/drink_reagents.dm | 13 +- 2 files changed, 348 insertions(+), 12 deletions(-) diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index db47d43bd5..3912f68955 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -1,3 +1,4 @@ +<<<<<<< HEAD //The code execution of the emote datum is located at code/datums/emotes.dm /mob/living/emote(act, m_type = null, message = null) act = lowertext(act) @@ -326,6 +327,352 @@ /datum/emote/living/surrender key = "surrender" key_third_person = "surrenders" +======= +//The code execution of the emote datum is located at code/datums/emotes.dm +/mob/living/emote(act, m_type = null, message = null) + act = lowertext(act) + var/param = message + var/custom_param = findchar(act, " ") + if(custom_param) + param = copytext(act, custom_param + 1, length(act) + 1) + act = copytext(act, 1, custom_param) + + var/datum/emote/E + E = E.emote_list[act] + if(!E) + to_chat(src, "Unusable emote '[act]'. Say *help for a list.") + return + E.run_emote(src, param, m_type) + +/* EMOTE DATUMS */ +/datum/emote/living + mob_type_allowed_typecache = list(/mob/living) + mob_type_blacklist_typecache = list(/mob/living/simple_animal/slime, /mob/living/brain) + +/datum/emote/living/blush + key = "blush" + key_third_person = "blushes" + message = "blushes." + +/datum/emote/living/bow + key = "bow" + key_third_person = "bows" + message = "bows." + message_param = "bows to %t." + +/datum/emote/living/burp + key = "burp" + key_third_person = "burps" + message = "burps." + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/choke + key = "choke" + key_third_person = "chokes" + message = "chokes!" + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/cross + key = "cross" + key_third_person = "crosses" + message = "crosses their arms." + restraint_check = TRUE + +/datum/emote/living/chuckle + key = "chuckle" + key_third_person = "chuckles" + message = "chuckles." + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/collapse + key = "collapse" + key_third_person = "collapses" + message = "collapses!" + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/collapse/run_emote(mob/user, params) + . = ..() + if(. && isliving(user)) + var/mob/living/L = user + L.Unconscious(40) + +/datum/emote/living/cough + key = "cough" + key_third_person = "coughs" + message = "coughs!" + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/dance + key = "dance" + key_third_person = "dances" + message = "dances around happily." + restraint_check = TRUE + +/datum/emote/living/deathgasp + key = "deathgasp" + key_third_person = "deathgasps" + message = "seizes up and falls limp, their eyes dead and lifeless..." + message_robot = "shudders violently for a moment before falling still, its eyes slowly darkening." + message_AI = "lets out a flurry of sparks, its screen flickering as its systems slowly halt." + message_alien = "lets out a waning guttural screech, green blood bubbling from its maw..." + message_larva = "lets out a sickly hiss of air and falls limply to the floor..." + message_monkey = "lets out a faint chimper as it collapses and stops moving..." + message_simple = "stops moving..." + stat_allowed = UNCONSCIOUS + +/datum/emote/living/deathgasp/run_emote(mob/user, params) + var/mob/living/simple_animal/S = user + if(istype(S) && S.deathmessage) + message_simple = S.deathmessage + . = ..() + message_simple = initial(message_simple) + if(. && isalienadult(user)) + playsound(user.loc, 'sound/voice/hiss6.ogg', 80, 1, 1) + +/datum/emote/living/drool + key = "drool" + key_third_person = "drools" + message = "drools." + +/datum/emote/living/faint + key = "faint" + key_third_person = "faints" + message = "faints." + +/datum/emote/living/faint/run_emote(mob/user, params) + . = ..() + if(. && isliving(user)) + var/mob/living/L = user + L.SetSleeping(200) + +/datum/emote/living/flap + key = "flap" + key_third_person = "flaps" + message = "flaps their wings." + var/wing_time = 20 + +/datum/emote/living/flap/run_emote(mob/user, params) + . = ..() + if(. && ishuman(user)) + var/mob/living/carbon/human/H = user + var/open = FALSE + if(H.dna.features["wings"] != "None") + if("wingsopen" in H.dna.species.mutant_bodyparts) + open = TRUE + H.CloseWings() + else + H.OpenWings() + addtimer(CALLBACK(H, open ? /mob/living/carbon/human.proc/OpenWings : /mob/living/carbon/human.proc/CloseWings), wing_time) + +/datum/emote/living/flap/aflap + key = "aflap" + key_third_person = "aflaps" + message = "flaps their wings ANGRILY!" + wing_time = 10 + +/datum/emote/living/flip + key = "flip" + key_third_person = "flips" + restraint_check = TRUE + +/datum/emote/living/flip/run_emote(mob/user, params) + . = ..() + if(!.) + user.SpinAnimation(7,1) + +/datum/emote/living/frown + key = "frown" + key_third_person = "frowns" + message = "frowns." + +/datum/emote/living/gag + key = "gag" + key_third_person = "gags" + message = "gags." + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/gasp + key = "gasp" + key_third_person = "gasps" + message = "gasps!" + emote_type = EMOTE_AUDIBLE + stat_allowed = UNCONSCIOUS + +/datum/emote/living/giggle + key = "giggle" + key_third_person = "giggles" + message = "giggles." + message_mime = "giggles silently!" + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/glare + key = "glare" + key_third_person = "glares" + message = "glares." + message_param = "glares at %t." + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/grin + key = "grin" + key_third_person = "grins" + message = "grins." + +/datum/emote/living/groan + key = "groan" + key_third_person = "groans" + message = "groans!" + message_mime = "appears to groan!" + +/datum/emote/living/grimace + key = "grimace" + key_third_person = "grimaces" + message = "grimaces." + +/datum/emote/living/jump + key = "jump" + key_third_person = "jumps" + message = "jumps!" + restraint_check = TRUE + +/datum/emote/living/kiss + key = "kiss" + key_third_person = "kisses" + message = "blows a kiss." + message_param = "blows a kiss to %t." + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/laugh + key = "laugh" + key_third_person = "laughs" + message = "laughs." + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/laugh/can_run_emote(mob/living/user) + . = ..() + if(. && iscarbon(user)) + var/mob/living/carbon/C = user + return !C.silent + +/datum/emote/living/laugh/run_emote(mob/user, params) + . = ..() + if(. && ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.dna.species.id == "human") + if(user.gender == FEMALE) + playsound(H, 'sound/voice/human/womanlaugh.ogg', 50, 1) + else + playsound(H, pick('sound/voice/human/manlaugh1.ogg', 'sound/voice/human/manlaugh2.ogg'), 50, 1) + +/datum/emote/living/look + key = "look" + key_third_person = "looks" + message = "looks." + message_param = "looks at %t." + +/datum/emote/living/nod + key = "nod" + key_third_person = "nods" + message = "nods." + message_param = "nods at %t." + +/datum/emote/living/point + key = "point" + key_third_person = "points" + message = "points." + message_param = "points at %t." + restraint_check = TRUE + +/datum/emote/living/pout + key = "pout" + key_third_person = "pouts" + message = "pouts." + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/scream + key = "scream" + key_third_person = "screams" + message = "screams." + message_mime = "acts out a scream!" + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/scowl + key = "scowl" + key_third_person = "scowls" + message = "scowls." + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/shake + key = "shake" + key_third_person = "shakes" + message = "shakes their head." + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/shiver + key = "shiver" + key_third_person = "shiver" + message = "shivers." + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/sigh + key = "sigh" + key_third_person = "sighs" + message = "sighs." + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/sit + key = "sit" + key_third_person = "sits" + message = "sits down." + +/datum/emote/living/smile + key = "smile" + key_third_person = "smiles" + message = "smiles." + +/datum/emote/living/sneeze + key = "sneeze" + key_third_person = "sneezes" + message = "sneezes." + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/smug + key = "smug" + key_third_person = "smugs" + message = "grins smugly." + +/datum/emote/living/sniff + key = "sniff" + key_third_person = "sniffs" + message = "sniffs." + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/snore + key = "snore" + key_third_person = "snores" + message = "snores." + message_mime = "sleeps soundly." + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/stare + key = "stare" + key_third_person = "stares" + message = "stares." + message_param = "stares at %t." + +/datum/emote/living/strech + key = "stretch" + key_third_person = "stretches" + message = "stretches their arms." + +/datum/emote/living/sulk + key = "sulk" + key_third_person = "sulks" + message = "sulks down sadly." + +/datum/emote/living/surrender + key = "surrender" + key_third_person = "surrenders" +>>>>>>> 32050be... Moves laughter to the emote (#31276) message = "puts their hands on their head and falls to the ground, they surrender!" emote_type = EMOTE_AUDIBLE diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index a3db8f7bc2..308fd47a16 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -169,18 +169,7 @@ /datum/reagent/consumable/laughter/on_mob_life(mob/living/carbon/M) if(!iscarbon(M)) return - if(!M.silent)//cant laugh if you're mute - M.emote("laugh") - var/laughnum = rand(1,2) - if(M.gender == MALE) - if(laughnum == 1) - playsound(get_turf(M), 'sound/voice/human/manlaugh1.ogg', 50, 1) - if(laughnum == 2) - playsound(get_turf(M), 'sound/voice/human/manlaugh2.ogg', 50, 1) - else if(M.gender == FEMALE) - playsound(get_turf(M), 'sound/voice/human/womanlaugh.ogg', 65, 1) - else//non-binary gender just sounds like a man - playsound(get_turf(M), 'sound/voice/human/manlaugh1.ogg', 50, 1) + M.emote("laugh") ..() /datum/reagent/consumable/potato_juice From 77c422d01148a31f8951a901525a79c73bcc3cdf Mon Sep 17 00:00:00 2001 From: LetterJay Date: Wed, 4 Oct 2017 16:11:24 -0500 Subject: [PATCH 05/82] Update emote.dm --- code/modules/mob/living/emote.dm | 660 ++++++++----------------------- 1 file changed, 165 insertions(+), 495 deletions(-) diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index 3912f68955..3e1724150a 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -1,333 +1,4 @@ -<<<<<<< HEAD -//The code execution of the emote datum is located at code/datums/emotes.dm -/mob/living/emote(act, m_type = null, message = null) - act = lowertext(act) - var/param = message - var/custom_param = findchar(act, " ") - if(custom_param) - param = copytext(act, custom_param + 1, length(act) + 1) - act = copytext(act, 1, custom_param) - - var/datum/emote/E - E = E.emote_list[act] - if(!E) - to_chat(src, "Unusable emote '[act]'. Say *help for a list.") - return - E.run_emote(src, param, m_type) - -/* EMOTE DATUMS */ -/datum/emote/living - mob_type_allowed_typecache = list(/mob/living) - mob_type_blacklist_typecache = list(/mob/living/simple_animal/slime, /mob/living/brain) - -/datum/emote/living/blush - key = "blush" - key_third_person = "blushes" - message = "blushes." - -/datum/emote/living/bow - key = "bow" - key_third_person = "bows" - message = "bows." - message_param = "bows to %t." - -/datum/emote/living/burp - key = "burp" - key_third_person = "burps" - message = "burps." - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/choke - key = "choke" - key_third_person = "chokes" - message = "chokes!" - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/cross - key = "cross" - key_third_person = "crosses" - message = "crosses their arms." - restraint_check = TRUE - -/datum/emote/living/chuckle - key = "chuckle" - key_third_person = "chuckles" - message = "chuckles." - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/collapse - key = "collapse" - key_third_person = "collapses" - message = "collapses!" - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/collapse/run_emote(mob/user, params) - . = ..() - if(. && isliving(user)) - var/mob/living/L = user - L.Unconscious(40) - -/datum/emote/living/cough - key = "cough" - key_third_person = "coughs" - message = "coughs!" - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/dance - key = "dance" - key_third_person = "dances" - message = "dances around happily." - restraint_check = TRUE - -/datum/emote/living/deathgasp - key = "deathgasp" - key_third_person = "deathgasps" - message = "seizes up and falls limp, their eyes dead and lifeless..." - message_robot = "shudders violently for a moment before falling still, its eyes slowly darkening." - message_AI = "lets out a flurry of sparks, its screen flickering as its systems slowly halt." - message_alien = "lets out a waning guttural screech, green blood bubbling from its maw..." - message_larva = "lets out a sickly hiss of air and falls limply to the floor..." - message_monkey = "lets out a faint chimper as it collapses and stops moving..." - message_simple = "stops moving..." - stat_allowed = UNCONSCIOUS - -/datum/emote/living/deathgasp/run_emote(mob/user, params) - var/mob/living/simple_animal/S = user - if(istype(S) && S.deathmessage) - message_simple = S.deathmessage - . = ..() - message_simple = initial(message_simple) - if(. && isalienadult(user)) - playsound(user.loc, 'sound/voice/hiss6.ogg', 80, 1, 1) - -/datum/emote/living/drool - key = "drool" - key_third_person = "drools" - message = "drools." - -/datum/emote/living/faint - key = "faint" - key_third_person = "faints" - message = "faints." - -/datum/emote/living/faint/run_emote(mob/user, params) - . = ..() - if(. && isliving(user)) - var/mob/living/L = user - L.SetSleeping(200) - -/datum/emote/living/flap - key = "flap" - key_third_person = "flaps" - message = "flaps their wings." - var/wing_time = 20 - -/datum/emote/living/flap/run_emote(mob/user, params) - . = ..() - if(. && ishuman(user)) - var/mob/living/carbon/human/H = user - var/open = FALSE - if(H.dna.features["wings"] != "None") - if("wingsopen" in H.dna.species.mutant_bodyparts) - open = TRUE - H.CloseWings() - else - H.OpenWings() - addtimer(CALLBACK(H, open ? /mob/living/carbon/human.proc/OpenWings : /mob/living/carbon/human.proc/CloseWings), wing_time) - -/datum/emote/living/flap/aflap - key = "aflap" - key_third_person = "aflaps" - message = "flaps their wings ANGRILY!" - wing_time = 10 - -/datum/emote/living/flip - key = "flip" - key_third_person = "flips" - restraint_check = TRUE - -/datum/emote/living/flip/run_emote(mob/user, params) - . = ..() - if(!.) - user.SpinAnimation(7,1) - -/datum/emote/living/frown - key = "frown" - key_third_person = "frowns" - message = "frowns." - -/datum/emote/living/gag - key = "gag" - key_third_person = "gags" - message = "gags." - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/gasp - key = "gasp" - key_third_person = "gasps" - message = "gasps!" - emote_type = EMOTE_AUDIBLE - stat_allowed = UNCONSCIOUS - -/datum/emote/living/giggle - key = "giggle" - key_third_person = "giggles" - message = "giggles." - message_mime = "giggles silently!" - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/glare - key = "glare" - key_third_person = "glares" - message = "glares." - message_param = "glares at %t." - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/grin - key = "grin" - key_third_person = "grins" - message = "grins." - -/datum/emote/living/groan - key = "groan" - key_third_person = "groans" - message = "groans!" - message_mime = "appears to groan!" - -/datum/emote/living/grimace - key = "grimace" - key_third_person = "grimaces" - message = "grimaces." - -/datum/emote/living/jump - key = "jump" - key_third_person = "jumps" - message = "jumps!" - restraint_check = TRUE - -/datum/emote/living/kiss - key = "kiss" - key_third_person = "kisses" - message = "blows a kiss." - message_param = "blows a kiss to %t." - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/laugh - key = "laugh" - key_third_person = "laughs" - message = "laughs." - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/look - key = "look" - key_third_person = "looks" - message = "looks." - message_param = "looks at %t." - -/datum/emote/living/nod - key = "nod" - key_third_person = "nods" - message = "nods." - message_param = "nods at %t." - -/datum/emote/living/point - key = "point" - key_third_person = "points" - message = "points." - message_param = "points at %t." - restraint_check = TRUE - -/datum/emote/living/pout - key = "pout" - key_third_person = "pouts" - message = "pouts." - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/scream - key = "scream" - key_third_person = "screams" - message = "screams." - message_mime = "acts out a scream!" - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/scowl - key = "scowl" - key_third_person = "scowls" - message = "scowls." - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/shake - key = "shake" - key_third_person = "shakes" - message = "shakes their head." - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/shiver - key = "shiver" - key_third_person = "shiver" - message = "shivers." - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/sigh - key = "sigh" - key_third_person = "sighs" - message = "sighs." - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/sit - key = "sit" - key_third_person = "sits" - message = "sits down." - -/datum/emote/living/smile - key = "smile" - key_third_person = "smiles" - message = "smiles." - -/datum/emote/living/sneeze - key = "sneeze" - key_third_person = "sneezes" - message = "sneezes." - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/smug - key = "smug" - key_third_person = "smugs" - message = "grins smugly." - -/datum/emote/living/sniff - key = "sniff" - key_third_person = "sniffs" - message = "sniffs." - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/snore - key = "snore" - key_third_person = "snores" - message = "snores." - message_mime = "sleeps soundly." - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/stare - key = "stare" - key_third_person = "stares" - message = "stares." - message_param = "stares at %t." - -/datum/emote/living/strech - key = "stretch" - key_third_person = "stretches" - message = "stretches their arms." - -/datum/emote/living/sulk - key = "sulk" - key_third_person = "sulks" - message = "sulks down sadly." - -/datum/emote/living/surrender - key = "surrender" - key_third_person = "surrenders" -======= +<<<<<<< HEAD //The code execution of the emote datum is located at code/datums/emotes.dm /mob/living/emote(act, m_type = null, message = null) act = lowertext(act) @@ -672,169 +343,168 @@ /datum/emote/living/surrender key = "surrender" key_third_person = "surrenders" ->>>>>>> 32050be... Moves laughter to the emote (#31276) message = "puts their hands on their head and falls to the ground, they surrender!" - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/surrender/run_emote(mob/user, params) - . = ..() - if(. && isliving(user)) - var/mob/living/L = user - L.Knockdown(200) - -/datum/emote/living/sway - key = "sway" - key_third_person = "sways" - message = "sways around dizzily." - -/datum/emote/living/tremble - key = "tremble" - key_third_person = "trembles" - message = "trembles in fear!" - -/datum/emote/living/twitch - key = "twitch" - key_third_person = "twitches" - message = "twitches violently." - -/datum/emote/living/twitch_s - key = "twitch_s" - message = "twitches." - -/datum/emote/living/wave - key = "wave" - key_third_person = "waves" - message = "waves." - -/datum/emote/living/whimper - key = "whimper" - key_third_person = "whimpers" - message = "whimpers." - message_mime = "appears hurt." - -/datum/emote/living/wsmile - key = "wsmile" - key_third_person = "wsmiles" - message = "smiles weakly." - -/datum/emote/living/yawn - key = "yawn" - key_third_person = "yawns" - message = "yawns." - emote_type = EMOTE_AUDIBLE - -/datum/emote/living/custom - key = "me" - key_third_person = "custom" - message = null - -/datum/emote/living/custom/proc/check_invalid(mob/user, input) - . = TRUE - if(copytext(input,1,5) == "says") - to_chat(user, "Invalid emote.") - else if(copytext(input,1,9) == "exclaims") - to_chat(user, "Invalid emote.") - else if(copytext(input,1,6) == "yells") - to_chat(user, "Invalid emote.") - else if(copytext(input,1,5) == "asks") - to_chat(user, "Invalid emote.") - else - . = FALSE - -/datum/emote/living/custom/run_emote(mob/user, params, type_override = null) - if(jobban_isbanned(user, "emote")) - to_chat(user, "You cannot send custom emotes (banned).") - return FALSE - else if(user.client && user.client.prefs.muted & MUTE_IC) - to_chat(user, "You cannot send IC messages (muted).") - return FALSE - else if(!params) - var/custom_emote = copytext(sanitize(input("Choose an emote to display.") as text|null), 1, MAX_MESSAGE_LEN) - if(custom_emote && !check_invalid(user, custom_emote)) - var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable") - switch(type) - if("Visible") - emote_type = EMOTE_VISIBLE - if("Hearable") - emote_type = EMOTE_AUDIBLE - else - alert("Unable to use this emote, must be either hearable or visible.") - return - message = custom_emote - else - message = params - if(type_override) - emote_type = type_override - . = ..() - message = null - emote_type = EMOTE_VISIBLE - -/datum/emote/living/custom/replace_pronoun(mob/user, message) - return message - -/datum/emote/living/help - key = "help" - -/datum/emote/living/help/run_emote(mob/user, params) - var/list/keys = list() - var/list/message = list("Available emotes, you can use them with say \"*emote\": ") - - var/datum/emote/E - var/list/emote_list = E.emote_list - for(var/e in emote_list) - if(e in keys) - continue - E = emote_list[e] - if(E.can_run_emote(user, TRUE)) - keys += E.key - - keys = sortList(keys) - - for(var/emote in keys) - if(LAZYLEN(message) > 1) - message += ", [emote]" - else - message += "[emote]" - - message += "." - - message = jointext(message, "") - - to_chat(user, message) - -/datum/emote/sound/beep - key = "beep" - key_third_person = "beeps" - message = "beeps." - message_param = "beeps at %t." - sound = 'sound/machines/twobeep.ogg' - -/datum/emote/living/spin - key = "spin" - key_third_person = "spins" - -/datum/emote/living/spin/run_emote(mob/user) - user.spin(20, 1) - if(iscyborg(user)) - var/mob/living/silicon/robot/R = user - if(R.buckled_mobs) - for(var/mob/M in R.buckled_mobs) - if(R.riding_datum) - R.riding_datum.force_dismount(M) - else - R.unbuckle_all_mobs() - ..() - -/datum/emote/living/circle - key = "circle" - key_third_person = "circles" - restraint_check = TRUE - -/datum/emote/living/circle/run_emote(mob/user, params) - . = ..() - var/obj/item/circlegame/N = new(user) - if(user.put_in_hands(N)) - to_chat(user, "You make a circle with your hand.") - else - qdel(N) - to_chat(user, "You don't have any free hands to make a circle with.") + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/surrender/run_emote(mob/user, params) + . = ..() + if(. && isliving(user)) + var/mob/living/L = user + L.Knockdown(200) + +/datum/emote/living/sway + key = "sway" + key_third_person = "sways" + message = "sways around dizzily." + +/datum/emote/living/tremble + key = "tremble" + key_third_person = "trembles" + message = "trembles in fear!" + +/datum/emote/living/twitch + key = "twitch" + key_third_person = "twitches" + message = "twitches violently." + +/datum/emote/living/twitch_s + key = "twitch_s" + message = "twitches." + +/datum/emote/living/wave + key = "wave" + key_third_person = "waves" + message = "waves." + +/datum/emote/living/whimper + key = "whimper" + key_third_person = "whimpers" + message = "whimpers." + message_mime = "appears hurt." + +/datum/emote/living/wsmile + key = "wsmile" + key_third_person = "wsmiles" + message = "smiles weakly." + +/datum/emote/living/yawn + key = "yawn" + key_third_person = "yawns" + message = "yawns." + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/custom + key = "me" + key_third_person = "custom" + message = null + +/datum/emote/living/custom/proc/check_invalid(mob/user, input) + . = TRUE + if(copytext(input,1,5) == "says") + to_chat(user, "Invalid emote.") + else if(copytext(input,1,9) == "exclaims") + to_chat(user, "Invalid emote.") + else if(copytext(input,1,6) == "yells") + to_chat(user, "Invalid emote.") + else if(copytext(input,1,5) == "asks") + to_chat(user, "Invalid emote.") + else + . = FALSE + +/datum/emote/living/custom/run_emote(mob/user, params, type_override = null) + if(jobban_isbanned(user, "emote")) + to_chat(user, "You cannot send custom emotes (banned).") + return FALSE + else if(user.client && user.client.prefs.muted & MUTE_IC) + to_chat(user, "You cannot send IC messages (muted).") + return FALSE + else if(!params) + var/custom_emote = copytext(sanitize(input("Choose an emote to display.") as text|null), 1, MAX_MESSAGE_LEN) + if(custom_emote && !check_invalid(user, custom_emote)) + var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable") + switch(type) + if("Visible") + emote_type = EMOTE_VISIBLE + if("Hearable") + emote_type = EMOTE_AUDIBLE + else + alert("Unable to use this emote, must be either hearable or visible.") + return + message = custom_emote + else + message = params + if(type_override) + emote_type = type_override + . = ..() + message = null + emote_type = EMOTE_VISIBLE + +/datum/emote/living/custom/replace_pronoun(mob/user, message) + return message + +/datum/emote/living/help + key = "help" + +/datum/emote/living/help/run_emote(mob/user, params) + var/list/keys = list() + var/list/message = list("Available emotes, you can use them with say \"*emote\": ") + + var/datum/emote/E + var/list/emote_list = E.emote_list + for(var/e in emote_list) + if(e in keys) + continue + E = emote_list[e] + if(E.can_run_emote(user, TRUE)) + keys += E.key + + keys = sortList(keys) + + for(var/emote in keys) + if(LAZYLEN(message) > 1) + message += ", [emote]" + else + message += "[emote]" + + message += "." + + message = jointext(message, "") + + to_chat(user, message) + +/datum/emote/sound/beep + key = "beep" + key_third_person = "beeps" + message = "beeps." + message_param = "beeps at %t." + sound = 'sound/machines/twobeep.ogg' + +/datum/emote/living/spin + key = "spin" + key_third_person = "spins" + +/datum/emote/living/spin/run_emote(mob/user) + user.spin(20, 1) + if(iscyborg(user)) + var/mob/living/silicon/robot/R = user + if(R.buckled_mobs) + for(var/mob/M in R.buckled_mobs) + if(R.riding_datum) + R.riding_datum.force_dismount(M) + else + R.unbuckle_all_mobs() + ..() + +/datum/emote/living/circle + key = "circle" + key_third_person = "circles" + restraint_check = TRUE + +/datum/emote/living/circle/run_emote(mob/user, params) + . = ..() + var/obj/item/circlegame/N = new(user) + if(user.put_in_hands(N)) + to_chat(user, "You make a circle with your hand.") + else + qdel(N) + to_chat(user, "You don't have any free hands to make a circle with.") From cfd98caf9801a875004443dd13933e7d7523034b Mon Sep 17 00:00:00 2001 From: LetterJay Date: Wed, 4 Oct 2017 17:42:38 -0500 Subject: [PATCH 06/82] Update emote.dm --- code/modules/mob/living/emote.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index 3e1724150a..9f31c5b055 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -1,4 +1,3 @@ -<<<<<<< HEAD //The code execution of the emote datum is located at code/datums/emotes.dm /mob/living/emote(act, m_type = null, message = null) act = lowertext(act) From 42c59b67b5cf203d85ffd8f5d2d9d4cc800b3182 Mon Sep 17 00:00:00 2001 From: oranges Date: Thu, 5 Oct 2017 11:54:45 +1300 Subject: [PATCH 07/82] Removes /datum/reagents/process(), changes cryostylane & pyrosium reaction speed --- code/modules/reagents/chemistry/holder.dm | 13 ++++++++++++- code/modules/reagents/chemistry/reagents.dm | 4 ---- .../chemistry/reagents/pyrotechnic_reagents.dm | 14 -------------- .../reagents/chemistry/recipes/pyrotechnics.dm | 17 +++++++++++++++++ 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 9bcd909faf..c383dd5a7d 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -16,8 +16,11 @@ /datum/reagents/New(maximum=100) maximum_volume = maximum +<<<<<<< HEAD if(!(flags_1 & REAGENT_NOREACT)) START_PROCESSING(SSobj, src) +======= +>>>>>>> b8ea267... Merge pull request #31281 from vuonojenmustaturska/clowncult //I dislike having these here but map-objects are initialised before world/New() is called. >_> if(!GLOB.chemical_reagents_list) @@ -54,7 +57,6 @@ /datum/reagents/Destroy() . = ..() - STOP_PROCESSING(SSobj, src) var/list/cached_reagents = reagent_list for(var/reagent in cached_reagents) var/datum/reagent/R = reagent @@ -288,6 +290,7 @@ C.update_stamina() update_total() +<<<<<<< HEAD /datum/reagents/process() var/list/cached_reagents = reagent_list if(flags_1 & REAGENT_NOREACT) @@ -307,6 +310,14 @@ else STOP_PROCESSING(SSobj, src) flags_1 |= REAGENT_NOREACT +======= + +/datum/reagents/proc/set_reacting(react = TRUE) + if(react) + flags &= ~(REAGENT_NOREACT) + else + flags |= REAGENT_NOREACT +>>>>>>> b8ea267... Merge pull request #31281 from vuonojenmustaturska/clowncult /datum/reagents/proc/conditional_update_move(atom/A, Running = 0) var/list/cached_reagents = reagent_list diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index 342e2154f8..5f76a87654 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -80,10 +80,6 @@ /datum/reagent/proc/on_update(atom/A) return -// Called every time reagent containers process. -/datum/reagent/proc/on_tick(data) - return - // Called when the reagent container is hit by an explosion /datum/reagent/proc/on_ex_act(severity) return diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm index 36320459e8..4c1965058c 100644 --- a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm @@ -196,13 +196,6 @@ M.bodytemperature -= 15 ..() -/datum/reagent/cryostylane/on_tick() - if(holder.has_reagent("oxygen")) - holder.remove_reagent("oxygen", 1) - holder.chem_temp -= 10 - holder.handle_reactions() - ..() - /datum/reagent/cryostylane/reaction_turf(turf/T, reac_volume) if(reac_volume >= 5) for(var/mob/living/simple_animal/slime/M in T) @@ -222,13 +215,6 @@ M.bodytemperature += 15 ..() -/datum/reagent/pyrosium/on_tick() - if(holder.has_reagent("oxygen")) - holder.remove_reagent("oxygen", 1) - holder.chem_temp += 10 - holder.handle_reactions() - ..() - /datum/reagent/teslium //Teslium. Causes periodic shocks, and makes shocks against the target much more effective. name = "Teslium" id = "teslium" diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm index 8ca65a6588..aa97dd3180 100644 --- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm +++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm @@ -342,6 +342,23 @@ holder.chem_temp = 20 // cools the fuck down return +/datum/chemical_reaction/cryostylane_oxygen + name = "ephemeral cryostylane reaction" + id = "cryostylane_oxygen" + results = list("cryostylane" = 1) + required_reagents = list("cryostylane" = 1, "oxygen" = 1) + +/datum/chemical_reaction/cryostylane_oxygen/on_reaction(datum/reagents/holder, created_volume) + holder.chem_temp -= 10*created_volume + +/datum/chemical_reaction/pyrosium_oxygen + name = "ephemeral pyrosium reaction" + id = "pyrosium_oxygen" + results = list("pyrosium" = 1) + required_reagents = list("pyrosium" = 1, "oxygen" = 1) + +/datum/chemical_reaction/pyrosium_oxygen/on_reaction(datum/reagents/holder, created_volume) + holder.chem_temp += 10*created_volume /datum/chemical_reaction/pyrosium name = "pyrosium" From e5f5b427bad1792bfa3cad12eea91d0b7c98829f Mon Sep 17 00:00:00 2001 From: Leo Date: Wed, 4 Oct 2017 21:24:44 -0300 Subject: [PATCH 08/82] Makes the energy katana swwwwwwish when drawn --- code/modules/ninja/energy_katana.dm | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/code/modules/ninja/energy_katana.dm b/code/modules/ninja/energy_katana.dm index 8901c1b9fa..b2f01212f5 100644 --- a/code/modules/ninja/energy_katana.dm +++ b/code/modules/ninja/energy_katana.dm @@ -85,6 +85,19 @@ playsound(user, 'sound/weapons/blade1.ogg', 50, 1) target.emag_act(user) +<<<<<<< HEAD +======= +/obj/item/energy_katana/pickup(mob/living/user) + . = ..() + jaunt.Grant(user, src) + user.update_icons() + playsound(src, 'sound/items/unsheath.ogg', 25, 1) + +/obj/item/energy_katana/dropped(mob/user) + . = ..() + jaunt.Remove(user) + user.update_icons() +>>>>>>> 4ffb1cd... Merge pull request #31289 from ShizCalev/hacknslash //If we hit the Ninja who owns this Katana, they catch it. //Works for if the Ninja throws it or it throws itself or someone tries From dec28eabfc0710a4434d0d046885a0fa21e559ec Mon Sep 17 00:00:00 2001 From: Leo Date: Wed, 4 Oct 2017 21:26:19 -0300 Subject: [PATCH 09/82] Merge pull request #31287 from ShizCalev/wizard-name Correctly applies wizard names --- code/game/gamemodes/wizard/wizard.dm | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index 8256d0aaf0..d25c7613bc 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -111,10 +111,7 @@ if (!newname) newname = randomname - wizard_mob.real_name = newname - wizard_mob.name = newname - if(wizard_mob.mind) - wizard_mob.mind.name = newname + wizard_mob.fully_replace_character_name(wizard_mob.real_name, newname) /* Wizards by nature cannot be too young. */ if(wizard_mob.age < WIZARD_AGE_MIN) From 39cf9bb7a0564ece5e43e34de33c655c880166da Mon Sep 17 00:00:00 2001 From: Leo Date: Wed, 4 Oct 2017 21:25:31 -0300 Subject: [PATCH 11/82] Merge pull request #31286 from KorPhaeron/ismachinery ismachinery define --- code/__DEFINES/is_helpers.dm | 2 ++ code/game/gamemodes/blob/blob_report.dm | 2 +- code/game/objects/objs.dm | 2 +- code/modules/holodeck/area_copy.dm | 2 +- .../mob/living/simple_animal/hostile/giant_spider.dm | 2 +- code/modules/mob/living/simple_animal/hostile/mimic.dm | 2 +- code/modules/modular_computers/hardware/recharger.dm | 6 +++--- code/modules/power/singularity/containment_field.dm | 6 +++--- code/modules/power/tesla/energy_ball.dm | 2 +- 9 files changed, 14 insertions(+), 12 deletions(-) diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 4376ba9c03..1de917d5e1 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -140,6 +140,8 @@ #define isstructure(A) (istype(A, /obj/structure)) +#define ismachinery(A) (istype(A, /obj/machinery)) + #define ismecha(A) (istype(A, /obj/mecha)) #define is_cleanable(A) (istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/rune)) //if something is cleanable diff --git a/code/game/gamemodes/blob/blob_report.dm b/code/game/gamemodes/blob/blob_report.dm index e90626485a..519fc2e296 100644 --- a/code/game/gamemodes/blob/blob_report.dm +++ b/code/game/gamemodes/blob/blob_report.dm @@ -85,7 +85,7 @@ src.grille += 1 else if(istype(O, /obj/machinery/door)) src.door += 1 - else if(istype(O, /obj/machinery)) + else if(ismachinery(O)) src.mach += 1 if(count_territories) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index dffa22670c..f2537945db 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -51,7 +51,7 @@ T.add_blueprints_preround(src) /obj/Destroy(force=FALSE) - if(!istype(src, /obj/machinery)) + if(!ismachinery(src)) STOP_PROCESSING(SSobj, src) // TODO: Have a processing bitflag to reduce on unnecessary loops through the processing lists SStgui.close_uis(src) . = ..() diff --git a/code/modules/holodeck/area_copy.dm b/code/modules/holodeck/area_copy.dm index 272fb1c536..9da772eaee 100644 --- a/code/modules/holodeck/area_copy.dm +++ b/code/modules/holodeck/area_copy.dm @@ -31,7 +31,7 @@ GLOBAL_LIST_INIT(duplicate_forbidden_vars,list("tag","area","type","loc","locs", I.damtype = STAMINA // thou shalt not N.update_icon() - if(istype(O, /obj/machinery)) + if(ismachinery(O)) var/obj/machinery/M = O M.power_change() diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index e5ee4f671c..aa288e52d7 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -275,7 +275,7 @@ if(O.anchored) continue - if(isitem(O) || isstructure(O) || istype(O, /obj/machinery)) + if(isitem(O) || isstructure(O) || ismachinery(O)) cocoon_target = O busy = MOVING_TO_TARGET stop_automated_movement = 1 diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm index b46000c339..edcf1a0f73 100644 --- a/code/modules/mob/living/simple_animal/hostile/mimic.dm +++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm @@ -144,7 +144,7 @@ GLOBAL_LIST_INIT(protected_objects, list(/obj/structure/table, /obj/structure/ca icon_living = icon_state copy_overlays(O) add_overlay(googly_eyes) - if(isstructure(O) || istype(O, /obj/machinery)) + if(isstructure(O) || ismachinery(O)) health = (anchored * 50) + 50 destroy_objects = 1 if(O.density && O.anchored) diff --git a/code/modules/modular_computers/hardware/recharger.dm b/code/modules/modular_computers/hardware/recharger.dm index 08ecc6e8c8..7096233d3a 100644 --- a/code/modules/modular_computers/hardware/recharger.dm +++ b/code/modules/modular_computers/hardware/recharger.dm @@ -31,7 +31,7 @@ origin_tech = "programming=2;engineering=2;powerstorage=3" /obj/item/computer_hardware/recharger/APC/use_power(amount, charging=0) - if(istype(holder.physical, /obj/machinery)) + if(ismachinery(holder.physical)) var/obj/machinery/M = holder.physical if(M.powered()) M.use_power(amount) @@ -55,13 +55,13 @@ origin_tech = "engineering=2;powerstorage=1" /obj/item/computer_hardware/recharger/wired/can_install(obj/item/device/modular_computer/M, mob/living/user = null) - if(istype(M.physical, /obj/machinery) && M.physical.anchored) + if(ismachinery(M.physical) && M.physical.anchored) return ..() to_chat(user, "\The [src] is incompatible with portable computers!") return 0 /obj/item/computer_hardware/recharger/wired/use_power(amount, charging=0) - if(istype(holder.physical, /obj/machinery) && holder.physical.anchored) + if(ismachinery(holder.physical) && holder.physical.anchored) var/obj/machinery/M = holder.physical var/turf/T = M.loc if(!T || !istype(T)) diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm index f2610f97b0..f4d09167c8 100644 --- a/code/modules/power/singularity/containment_field.dm +++ b/code/modules/power/singularity/containment_field.dm @@ -58,7 +58,7 @@ if(isliving(mover)) shock(mover) - if(istype(mover, /obj/machinery) || isstructure(mover) || ismecha(mover)) + if(ismachinery(mover) || isstructure(mover) || ismecha(mover)) bump_field(mover) /obj/machinery/field/containment/proc/set_master(master1,master2) @@ -90,13 +90,13 @@ if(isliving(mover)) shock(mover) return - if(istype(mover, /obj/machinery) || isstructure(mover) || ismecha(mover)) + if(ismachinery(mover) || isstructure(mover) || ismecha(mover)) bump_field(mover) return /obj/machinery/field/CanPass(atom/movable/mover, turf/target) - if(hasShocked || isliving(mover) || istype(mover, /obj/machinery) || isstructure(mover) || ismecha(mover)) + if(hasShocked || isliving(mover) || ismachinery(mover) || isstructure(mover) || ismecha(mover)) return FALSE return ..() diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index d8d396d311..503196aa4e 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -222,7 +222,7 @@ else if(closest_mob) continue - else if(istype(A, /obj/machinery)) + else if(ismachinery(A)) var/obj/machinery/M = A var/dist = get_dist(source, A) if(dist <= zap_range && (dist < closest_dist || !closest_machine) && !M.being_shocked) From c873c1747815e5a89044bf959d3a2bc675ddf1f9 Mon Sep 17 00:00:00 2001 From: Leo Date: Wed, 4 Oct 2017 21:26:38 -0300 Subject: [PATCH 13/82] Merge pull request #31284 from tgstation/Cyberboss-patch-1 Code cleanup in snack_meats.dm --- .../food_and_drinks/food/snacks_meat.dm | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/code/modules/food_and_drinks/food/snacks_meat.dm b/code/modules/food_and_drinks/food/snacks_meat.dm index 11426a4e04..f5a5857fea 100644 --- a/code/modules/food_and_drinks/food/snacks_meat.dm +++ b/code/modules/food_and_drinks/food/snacks_meat.dm @@ -25,8 +25,8 @@ tastes = list("fish" = 1) foodtype = MEAT -/obj/item/reagent_containers/food/snacks/carpmeat/New() - ..() +/obj/item/reagent_containers/food/snacks/carpmeat/Initialize() + . = ..() eatverb = pick("bite","chew","choke down","gnaw","swallow","chomp") /obj/item/reagent_containers/food/snacks/carpmeat/imitation @@ -114,8 +114,8 @@ tastes = list("meat" = 1) foodtype = MEAT -/obj/item/reagent_containers/food/snacks/sausage/New() - ..() +/obj/item/reagent_containers/food/snacks/sausage/Initialize() + . = ..() eatverb = pick("bite","chew","nibble","deep throat","gobble","chomp") /obj/item/reagent_containers/food/snacks/kebab @@ -185,8 +185,8 @@ /obj/item/reagent_containers/food/snacks/monkeycube/proc/Expand() visible_message("[src] expands!") - var/mob/spammer = get_mob_by_key(src.fingerprintslast) - var/mob/living/carbon/monkey/bananas = new(get_turf(src)) + var/mob/spammer = get_mob_by_key(fingerprintslast) + var/mob/living/carbon/monkey/bananas = new(drop_location()) bananas.log_message("Spawned via [src] at [COORD(src)], Last attached mob: [key_name(spammer)].", INDIVIDUAL_ATTACK_LOG) qdel(src) @@ -212,8 +212,8 @@ tastes = list("soy" = 1, "vegetables" = 1) foodtype = VEGETABLES -/obj/item/reagent_containers/food/snacks/stewedsoymeat/New() - ..() +/obj/item/reagent_containers/food/snacks/stewedsoymeat/Initialize() + . = ..() eatverb = pick("slurp","sip","suck","inhale","drink") /obj/item/reagent_containers/food/snacks/boiledspiderleg @@ -257,8 +257,8 @@ tastes = list("\"chicken\"" = 1) foodtype = MEAT -/obj/item/reagent_containers/food/snacks/nugget/New() - ..() +/obj/item/reagent_containers/food/snacks/nugget/Initialize() + . = ..() var/shape = pick("lump", "star", "lizard", "corgi") desc = "A 'chicken' nugget vaguely shaped like a [shape]." icon_state = "nugget_[shape]" From 63aa1c715387112b282c5eff230bf1ed1b8e1bc6 Mon Sep 17 00:00:00 2001 From: Supermichael777 Date: Wed, 4 Oct 2017 20:28:44 -0400 Subject: [PATCH 15/82] Makes the pda font a prefernce --- code/__DEFINES/misc.dm | 6 +++ code/game/objects/items/devices/PDA/PDA.dm | 52 +++++++++++++++------ code/modules/client/preferences.dm | 8 +++- code/modules/client/preferences_savefile.dm | 22 +++++++++ 4 files changed, 74 insertions(+), 14 deletions(-) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index c5d917ece4..bdb9ad35a9 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -288,6 +288,12 @@ GLOBAL_LIST_INIT(ghost_accs_options, list(GHOST_ACCS_NONE, GHOST_ACCS_DIR, GHOST GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DEFAULT_SPRITE, GHOST_OTHERS_THEIR_SETTING)) //Same as ghost_accs_options. +//pda fonts +#define MONO "Monospaced" +#define VT "VT323" +#define ORBITRON "Orbitron" +#define SHARE "Share Tech Mono" + //Color Defines #define OOC_COLOR "#002eb8" diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index ccfe70e662..a5ed03919a 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -27,13 +27,17 @@ GLOBAL_LIST_EMPTY(PDAs) var/mode = 0 //Controls what menu the PDA will display. 0 is hub; the rest are either built in or based on cartridge. var/icon_alert = "pda-r" //Icon to be overlayed for message alerts. Taken from the pda icon file. var/font_index = 0 //This int tells DM which font is currently selected and lets DM know when the last font has been selected so that it can cycle back to the first font when "toggle font" is pressed again. - var/font_mode = "font-family:\"VT323\", monospace;letter-spacing:1px;" //The currently selected font. + var/font_mode = "font-family:monospace;" //The currently selected font. var/background_color = "#808000" //The currently selected background color. - #define FONT_VT 0 - #define FONT_SHARE 1 - #define FONT_ORBITRON 2 - #define FONT_MONO 3 + #define FONT_MONO "font-family:monospace;" + #define FONT_SHARE "font-family:\"Share Tech Mono\", monospace;letter-spacing:0px;" + #define FONT_ORBITRON "font-family:\"Orbitron\", monospace;letter-spacing:0px; font-size:15px" + #define FONT_VT "font-family:\"VT323\", monospace;letter-spacing:1px;" + #define MODE_MONO 0 + #define MODE_SHARE 1 + #define MODE_ORBITRON 2 + #define MODE_VT 3 //Secondary variables var/scanmode = 0 //1 is medical scanner, 2 is forensics, 3 is reagent scanner. @@ -54,6 +58,7 @@ GLOBAL_LIST_EMPTY(PDAs) var/detonatable = TRUE // Can the PDA be blown up? var/hidden = 0 // Is the PDA hidden from the PDA list? var/emped = 0 + var/equipped = FALSE //used here to determine if this is the first time its been picked up var/obj/item/card/id/id = null //Making it possible to slot an ID card into the PDA so it can function as both. var/ownjob = null //related to above @@ -87,6 +92,27 @@ GLOBAL_LIST_EMPTY(PDAs) inserted_item = new /obj/item/pen(src) update_icon() +/obj/item/device/pda/equipped(mob/user, slot) + if(!equipped) + if(user.client) + switch(user.client.prefs.pda_style) + if(MONO) + font_index = MODE_MONO + font_mode = FONT_MONO + if(SHARE) + font_index = MODE_SHARE + font_mode = FONT_SHARE + if(ORBITRON) + font_index = MODE_ORBITRON + font_mode = FONT_ORBITRON + if(VT) + font_index = MODE_VT + font_mode = FONT_VT + else + font_index = MODE_MONO + font_mode = FONT_MONO + equipped = TRUE + /obj/item/device/pda/proc/update_label() name = "PDA-[owner] ([ownjob])" //Name generalisation @@ -335,14 +361,14 @@ GLOBAL_LIST_EMPTY(PDAs) font_index = (font_index + 1) % 4 switch(font_index) - if (FONT_VT) - font_mode = "font-family:\"VT323\", monospace;letter-spacing:1px;" - if (FONT_SHARE) - font_mode = "font-family:\"Share Tech Mono\", monospace;letter-spacing:0px;" - if (FONT_ORBITRON) - font_mode = "font-family:\"Orbitron\", monospace;letter-spacing:0px; font-size:15px" - if (FONT_MONO) - font_mode = "font-family:monospace;" + if (MODE_MONO) + font_mode = FONT_MONO + if (MODE_SHARE) + font_mode = FONT_SHARE + if (MODE_ORBITRON) + font_mode = FONT_ORBITRON + if (MODE_VT) + font_mode = FONT_VT if ("Change_Color") var/new_color = input("Please enter a color name or hex value (Default is \'#808000\').")as color background_color = new_color diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 38e0b0bd90..bcbeb55dd2 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -44,7 +44,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/inquisitive_ghost = 1 var/allow_midround_antag = 1 var/preferred_map = null - + var/pda_style = MONO + var/uses_glasses_colour = 0 var/screenshake = 100 @@ -446,6 +447,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Keybindings: [(hotkeys) ? "Hotkeys" : "Default"]
" dat += "Action Buttons: [(buttons_locked) ? "Locked In Place" : "Unlocked"]
" dat += "tgui Style: [(tgui_fancy) ? "Fancy" : "No Frills"]
" + dat += "PDA Style: [pda_style]
" dat += "tgui Monitors: [(tgui_lock) ? "Primary" : "All"]
" dat += "Window Flashing: [(windowflashing) ? "Yes" : "No"]
" dat += "Play admin midis: [(toggles & SOUND_MIDI) ? "Yes" : "No"]
" @@ -1449,6 +1451,10 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/pickedui = input(user, "Choose your UI style.", "Character Preference") as null|anything in list("Midnight", "Plasmafire", "Retro", "Slimecore", "Operative", "Clockwork") if(pickedui) UI_style = pickedui + if("PDA") + var/pickedPDA = input(user, "Choose your PDA style.", "Character Preference") as null|anything in list(MONO, SHARE, ORBITRON, VT) + if(pickedPDA) + pda_style = pickedPDA //citadel code if("cock_color") diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index d58d1cec77..e14b484bc3 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -2,7 +2,11 @@ #define SAVEFILE_VERSION_MIN 15 //This is the current version, anything below this will attempt to update (if it's not obsolete) +<<<<<<< HEAD #define SAVEFILE_VERSION_MAX 20 +======= +#define SAVEFILE_VERSION_MAX 19 +>>>>>>> f770b69... Makes the pda font a prefernce (#31193) /* SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn This proc checks if the current directory of the savefile S needs updating @@ -107,6 +111,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car joblessrole = BEASSISTANT if(current_version < 17) features["legs"] = "Normal Legs" +<<<<<<< HEAD if(current_version < 20)//Raise this to the max savefile version every time we change something so we don't sanitize this whole list every time you save. features["mam_body_markings"] = sanitize_inlist(features["mam_body_markings"], GLOB.mam_body_markings_list) features["mam_ears"] = sanitize_inlist(features["mam_ears"], GLOB.mam_ears_list) @@ -139,6 +144,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car features["vag_color"] = sanitize_hexcolor(features["vag_color"], 3, 0) //womb features features["has_womb"] = sanitize_integer(features["has_womb"], 0, 1, 0) +======= + if(current_version < 19) + pda_style = "mono" + +>>>>>>> f770b69... Makes the pda font a prefernce (#31193) /datum/preferences/proc/load_path(ckey,filename="preferences.sav") if(!ckey) @@ -187,12 +197,16 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["menuoptions"] >> menuoptions S["enable_tips"] >> enable_tips S["tip_delay"] >> tip_delay +<<<<<<< HEAD S["parallax"] >> parallax S["menuoptions"] >> menuoptions //citadel code S["arousable"] >> arousable S["screenshake"] >> screenshake S["damagescreenshake"] >> damagescreenshake +======= + S["pda_style"] >> pda_style +>>>>>>> f770b69... Makes the pda font a prefernce (#31193) //try to fix any outdated data if necessary if(needs_update >= 0) @@ -217,9 +231,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car ghost_others = sanitize_inlist(ghost_others, GLOB.ghost_others_options, GHOST_OTHERS_DEFAULT_OPTION) menuoptions = SANITIZE_LIST(menuoptions) be_special = SANITIZE_LIST(be_special) +<<<<<<< HEAD screenshake = sanitize_integer(screenshake, 0, 200, initial(screenshake)) damagescreenshake = sanitize_integer(damagescreenshake, 0, 2, initial(damagescreenshake)) +======= + pda_style = sanitize_inlist(MONO, VT, SHARE, ORBITRON) +>>>>>>> f770b69... Makes the pda font a prefernce (#31193) return 1 @@ -259,10 +277,14 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["menuoptions"], menuoptions) WRITE_FILE(S["enable_tips"], enable_tips) WRITE_FILE(S["tip_delay"], tip_delay) +<<<<<<< HEAD //citadel code WRITE_FILE(S["screenshake"], screenshake) WRITE_FILE(S["damagescreenshake"], damagescreenshake) WRITE_FILE(S["arousable"], arousable) +======= + WRITE_FILE(S["pda_style"], pda_style) +>>>>>>> f770b69... Makes the pda font a prefernce (#31193) return 1 From 4c38a8b1e2c655450fa96cb41a8008395497d818 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Wed, 4 Oct 2017 20:51:37 -0500 Subject: [PATCH 16/82] Update energy_katana.dm --- code/modules/ninja/energy_katana.dm | 3 --- 1 file changed, 3 deletions(-) diff --git a/code/modules/ninja/energy_katana.dm b/code/modules/ninja/energy_katana.dm index b2f01212f5..853cca2057 100644 --- a/code/modules/ninja/energy_katana.dm +++ b/code/modules/ninja/energy_katana.dm @@ -85,8 +85,6 @@ playsound(user, 'sound/weapons/blade1.ogg', 50, 1) target.emag_act(user) -<<<<<<< HEAD -======= /obj/item/energy_katana/pickup(mob/living/user) . = ..() jaunt.Grant(user, src) @@ -97,7 +95,6 @@ . = ..() jaunt.Remove(user) user.update_icons() ->>>>>>> 4ffb1cd... Merge pull request #31289 from ShizCalev/hacknslash //If we hit the Ninja who owns this Katana, they catch it. //Works for if the Ninja throws it or it throws itself or someone tries From 09f6eb615640f6066eef24a9a3d5bd840502c371 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Wed, 4 Oct 2017 20:53:42 -0500 Subject: [PATCH 17/82] Update preferences_savefile.dm --- code/modules/client/preferences_savefile.dm | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index e14b484bc3..999d2255ac 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -2,12 +2,8 @@ #define SAVEFILE_VERSION_MIN 15 //This is the current version, anything below this will attempt to update (if it's not obsolete) -<<<<<<< HEAD #define SAVEFILE_VERSION_MAX 20 -======= -#define SAVEFILE_VERSION_MAX 19 ->>>>>>> f770b69... Makes the pda font a prefernce (#31193) -/* + SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn This proc checks if the current directory of the savefile S needs updating It is to be used by the load_character and load_preferences procs. @@ -111,7 +107,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car joblessrole = BEASSISTANT if(current_version < 17) features["legs"] = "Normal Legs" -<<<<<<< HEAD if(current_version < 20)//Raise this to the max savefile version every time we change something so we don't sanitize this whole list every time you save. features["mam_body_markings"] = sanitize_inlist(features["mam_body_markings"], GLOB.mam_body_markings_list) features["mam_ears"] = sanitize_inlist(features["mam_ears"], GLOB.mam_ears_list) @@ -144,12 +139,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car features["vag_color"] = sanitize_hexcolor(features["vag_color"], 3, 0) //womb features features["has_womb"] = sanitize_integer(features["has_womb"], 0, 1, 0) -======= if(current_version < 19) pda_style = "mono" ->>>>>>> f770b69... Makes the pda font a prefernce (#31193) - /datum/preferences/proc/load_path(ckey,filename="preferences.sav") if(!ckey) return @@ -197,16 +189,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["menuoptions"] >> menuoptions S["enable_tips"] >> enable_tips S["tip_delay"] >> tip_delay -<<<<<<< HEAD S["parallax"] >> parallax S["menuoptions"] >> menuoptions //citadel code S["arousable"] >> arousable S["screenshake"] >> screenshake S["damagescreenshake"] >> damagescreenshake -======= S["pda_style"] >> pda_style ->>>>>>> f770b69... Makes the pda font a prefernce (#31193) //try to fix any outdated data if necessary if(needs_update >= 0) @@ -231,13 +220,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car ghost_others = sanitize_inlist(ghost_others, GLOB.ghost_others_options, GHOST_OTHERS_DEFAULT_OPTION) menuoptions = SANITIZE_LIST(menuoptions) be_special = SANITIZE_LIST(be_special) -<<<<<<< HEAD screenshake = sanitize_integer(screenshake, 0, 200, initial(screenshake)) damagescreenshake = sanitize_integer(damagescreenshake, 0, 2, initial(damagescreenshake)) - -======= pda_style = sanitize_inlist(MONO, VT, SHARE, ORBITRON) ->>>>>>> f770b69... Makes the pda font a prefernce (#31193) return 1 @@ -277,14 +262,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["menuoptions"], menuoptions) WRITE_FILE(S["enable_tips"], enable_tips) WRITE_FILE(S["tip_delay"], tip_delay) -<<<<<<< HEAD //citadel code WRITE_FILE(S["screenshake"], screenshake) WRITE_FILE(S["damagescreenshake"], damagescreenshake) WRITE_FILE(S["arousable"], arousable) -======= WRITE_FILE(S["pda_style"], pda_style) ->>>>>>> f770b69... Makes the pda font a prefernce (#31193) return 1 From f57929b26c008f478a28dd9606f8c178fef3fd21 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Wed, 4 Oct 2017 21:14:25 -0500 Subject: [PATCH 18/82] Update book.dm --- code/game/objects/items/storage/book.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm index 28856e17d8..c0c861f4c4 100644 --- a/code/game/objects/items/storage/book.dm +++ b/code/game/objects/items/storage/book.dm @@ -162,7 +162,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible", 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) + for(var/obj/item/device/soulstone/SS in sword.contents) SS.usability = TRUE for(var/mob/living/simple_animal/shade/EX in SS) SSticker.mode.remove_cultist(EX.mind, 1, 0) From 7c4373c1fe257c32237ecda756bc7a6241ef23f4 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Wed, 4 Oct 2017 21:15:11 -0500 Subject: [PATCH 19/82] Update cult_items.dm --- code/game/gamemodes/cult/cult_items.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index 62fe64ecee..2780598d06 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -163,7 +163,7 @@ /obj/item/twohanded/required/cult_bastard/afterattack(atom/target, mob/user, proximity, click_parameters) . = ..() - if(dash_toggled) + if(dash_toggled && jaunt.IsAvailable()) jaunt.Teleport(user, target) return if(!proximity) @@ -193,7 +193,7 @@ phaseout = /obj/effect/temp_visual/dir_setting/cult/phase/out /datum/action/innate/dash/cult/IsAvailable() - if(iscultist(holder) && current_charges) + if(iscultist(holder) && charged) return TRUE else return FALSE From c2d8f048f864a2bf1e0246f9f453bef8814f6481 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Wed, 4 Oct 2017 21:49:46 -0500 Subject: [PATCH 20/82] Update cult_items.dm --- code/game/gamemodes/cult/cult_items.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index 2780598d06..a3da1c6cbe 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -193,7 +193,7 @@ phaseout = /obj/effect/temp_visual/dir_setting/cult/phase/out /datum/action/innate/dash/cult/IsAvailable() - if(iscultist(holder) && charged) + if(iscultist(holder) && current_charges) return TRUE else return FALSE From fb7a0d7606baf3de9f8b5d6764042313ee7dc087 Mon Sep 17 00:00:00 2001 From: RandomMarine Date: Wed, 4 Oct 2017 21:24:02 -0700 Subject: [PATCH 21/82] Experimental fix for bloom issue (#31299) --- code/modules/mob/living/simple_animal/simple_animal.dm | 7 ------- 1 file changed, 7 deletions(-) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 4edf7a6dcb..d4b2c8f7c6 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -101,13 +101,6 @@ init_belly() verbs |= /mob/living/proc/animal_nom - -/mob/living/simple_animal/Login() - if(src && src.client) - src.client.screen = list() - client.screen += client.void - ..() - /mob/living/simple_animal/updatehealth() ..() health = Clamp(health, 0, maxHealth) From d50c0e10f6be578d98c8e4892612af560a228bfd Mon Sep 17 00:00:00 2001 From: Emmett Gaines Date: Thu, 5 Oct 2017 03:30:32 -0400 Subject: [PATCH 23/82] Makes shuttle movement a bit smoother and faster --- code/modules/shuttle/on_move.dm | 22 +++++++++++----------- code/modules/shuttle/shuttle.dm | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index b527894d0a..2359a130cb 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -203,7 +203,7 @@ All ShuttleMove procs go here if(pipe_vision_img) pipe_vision_img.loc = loc -/obj/machinery/computer/auxillary_base/onShuttleMove(turf/newT, turf/oldT, rotation, list/movement_force, move_dir, old_dock) +/obj/machinery/computer/auxillary_base/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir) . = ..() if(z == ZLEVEL_MINING) //Avoids double logging and landing on other Z-levels due to badminnery SSblackbox.add_details("colonies_dropped", "[x]|[y]|[z]") //Number of times a base has been dropped! @@ -297,24 +297,25 @@ All ShuttleMove procs go here /************************************Item move procs************************************/ -/obj/item/storage/pod/onShuttleMove(turf/newT, turf/oldT, rotation, list/movement_force, move_dir, old_dock) +/obj/item/storage/pod/afterShuttleMove(turf/newT, turf/oldT, rotation, list/movement_force, move_dir, old_dock) + . = ..() unlocked = TRUE // If the pod was launched, the storage will always open. - return ..() /************************************Mob move procs************************************/ /mob/onShuttleMove(turf/newT, turf/oldT, rotation, list/movement_force, move_dir, old_dock) if(!move_on_shuttle) - return 0 - . = ..() - if(!.) return - if(client) + . = ..() + +/mob/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir) + . = ..() + if(client && movement_force) + var/shake_force = max(movement_force["THROW"], movement_force["KNOCKDOWN"]) if(buckled) - shake_camera(src, 2, 1) // turn it down a bit come on - else - shake_camera(src, 7, 1) + shake_force *= 0.25 + shake_camera(src, shake_force, 1) /mob/living/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir) . = ..() @@ -373,7 +374,6 @@ All ShuttleMove procs go here /obj/docking_port/stationary/public_mining_dock/onShuttleMove(turf/newT, turf/oldT, rotation, list/movement_force, move_dir, old_dock) id = "mining_public" //It will not move with the base, but will become enabled as a docking point. - return 0 /obj/effect/abstract/proximity_checker/onShuttleMove(turf/newT, turf/oldT, rotation, list/movement_force, move_dir, old_dock) //timer so it only happens once diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 99d707d289..88daa3a016 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -553,6 +553,8 @@ var/list/moved_atoms = list() //Everything not a turf that gets moved in the shuttle var/list/areas_to_move = list() //unique assoc list of areas on turfs being moved + CHECK_TICK + /****************************************All beforeShuttleMove procs*****************************************/ var/index = 0 for(var/place in old_turfs) @@ -578,6 +580,7 @@ areas_to_move[old_area] = TRUE old_turfs[place] = move_mode + CHECK_TICK /*******************************************All onShuttleMove procs******************************************/ @@ -608,17 +611,32 @@ var/turf/oldT = thing var/turf/newT = new_turfs[index] newT.afterShuttleMove(oldT) //turfs + CHECK_TICK for(var/i in 1 to moved_atoms.len) var/atom/movable/moved_object = moved_atoms[i] moved_object.afterShuttleMove(movement_force, dir, preferred_direction, movement_direction) //atoms + CHECK_TICK underlying_old_area.afterShuttleMove() for(var/thing in areas_to_move) var/area/internal_area = thing internal_area.afterShuttleMove() //areas + CHECK_TICK +<<<<<<< HEAD +======= + // Parallax handling + var/new_parallax_dir = FALSE + if(istype(new_dock, /obj/docking_port/stationary/transit)) + new_parallax_dir = preferred_direction + for(var/i in shuttle_areas) + var/area/place = i + place.parallax_movedir = new_parallax_dir + CHECK_TICK + +>>>>>>> e16fd1b... Makes shuttle movement a bit smoother and faster (#31255) check_poddoors() new_dock.last_dock_time = world.time setDir(new_dock.dir) From 0cdda0ea7c853223c9caf5c27c4715edefc67635 Mon Sep 17 00:00:00 2001 From: oranges Date: Thu, 5 Oct 2017 20:59:08 +1300 Subject: [PATCH 24/82] Merge pull request #31297 from ShizCalev/ninja-sword-sprite-fix Corrects ninja sword mob sprite --- icons/mob/belt.dmi | Bin 16620 -> 16627 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/mob/belt.dmi b/icons/mob/belt.dmi index f73a54ab1d17ba5acaebfc127305798897d9f613..1ae0b0a2b59233ef6f333e6c093bc4894b3e15f1 100644 GIT binary patch delta 5327 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 delta 5357 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 IeDmS|05ZG@6aWAK From 4ecc019353f408d8cfe7fb8e53aec10f761d6b36 Mon Sep 17 00:00:00 2001 From: JJRcop Date: Thu, 5 Oct 2017 03:58:49 -0400 Subject: [PATCH 26/82] Moved admin music volume slider to its own menu (#31277) * Moved admin music volume slider to its own menu * Minor fixes to goonchat --- .../browserassets/css/browserOutput.css | 24 ++--- .../browserassets/html/browserOutput.html | 25 +++-- .../browserassets/js/browserOutput.js | 97 +++++++++++-------- 3 files changed, 84 insertions(+), 62 deletions(-) diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css index f6810d0b05..153444c0ed 100644 --- a/code/modules/goonchat/browserassets/css/browserOutput.css +++ b/code/modules/goonchat/browserassets/css/browserOutput.css @@ -83,7 +83,7 @@ a.popt {text-decoration: none;} #ping { position: fixed; top: 0; - right: 40px; + right: 80px; width: 45px; background: #ddd; height: 30px; @@ -96,12 +96,12 @@ a.popt {text-decoration: none;} font-size: 8pt; padding-top: 2px; } -#options { +#userBar { position: fixed; top: 0; right: 0; } -#options .optionsCell { +#userBar .subCell { background: #ddd; height: 30px; padding: 5px 0; @@ -111,23 +111,23 @@ a.popt {text-decoration: none;} line-height: 28px; border-top: 1px solid #b4b4b4; } -#options .optionsCell:hover {background: #ccc;} -#options .toggle { +#userBar .subCell:hover {background: #ccc;} +#userBar .toggle { width: 40px; background: #ccc; border-top: 0; float: right; text-align: center; } -#options .sub {clear: both; display: none; width: 160px;} -#options .sub.scroll {overflow-y: scroll;} -#options .sub.optionsCell {padding: 3px 0 3px 8px; line-height: 30px; font-size: 0.9em; clear: both;} -#options .sub span { +#userBar .sub {clear: both; display: none; width: 160px;} +#userBar .sub.scroll {overflow-y: scroll;} +#userBar .sub.subCell {padding: 3px 0 3px 8px; line-height: 30px; font-size: 0.9em; clear: both;} +#userBar .sub span { display: block; line-height: 30px; float: left; } -#options .sub i { +#userBar .sub i { display: block; padding: 0 5px; font-size: 1.1em; @@ -136,14 +136,14 @@ a.popt {text-decoration: none;} line-height: 30px; float: right; } -#options .sub input { +#userBar .sub input { position: absolute; padding: 7px 5px; width: 121px; line-height: 30px; float: left; } -#options .decreaseFont {border-top: 0;} +#userBar .topCell {border-top: 0;} /* POPUPS */ .popup { diff --git a/code/modules/goonchat/browserassets/html/browserOutput.html b/code/modules/goonchat/browserassets/html/browserOutput.html index a9e30b6b51..7b2d3ecfe0 100644 --- a/code/modules/goonchat/browserassets/html/browserOutput.html +++ b/code/modules/goonchat/browserassets/html/browserOutput.html @@ -27,17 +27,22 @@ --ms +
+ +
+ +
+ Admin music volume
diff --git a/code/modules/goonchat/browserassets/js/browserOutput.js b/code/modules/goonchat/browserassets/js/browserOutput.js index bb555982cc..f027b523aa 100644 --- a/code/modules/goonchat/browserassets/js/browserOutput.js +++ b/code/modules/goonchat/browserassets/js/browserOutput.js @@ -22,7 +22,7 @@ window.onerror = function(msg, url, line, col, error) { //Globals window.status = 'Output'; -var $messages, $subOptions, $contextMenu, $filterMessages; +var $messages, $subOptions, $subAudio, $selectedSub, $contextMenu, $filterMessages; var opts = { //General 'messageCount': 0, //A count...of messages... @@ -37,8 +37,8 @@ var opts = { 'restarting': false, //Is the round restarting? //Options menu - 'subOptionsLoop': null, //Contains the interval loop for closing the options menu - 'suppressOptionsClose': false, //Whether or not we should be hiding the suboptions menu + 'selectedSubLoop': null, //Contains the interval loop for closing the selected sub menu + 'suppressSubClose': false, //Whether or not we should be hiding the selected sub menu 'highlightTerms': [], 'highlightLimit': 5, 'highlightColor': '#FFFF00', //The color of the highlighted message @@ -483,6 +483,46 @@ function sendVolumeUpdate() { } } +function subSlideUp() { + $(this).removeClass('scroll'); + $(this).css('height', ''); +} + +function startSubLoop() { + if (opts.selectedSubLoop) { + clearInterval(opts.selectedSubLoop); + } + return setInterval(function() { + if (!opts.suppressSubClose && $selectedSub.is(':visible')) { + $selectedSub.slideUp('fast', subSlideUp); + clearInterval(opts.selectedSubLoop); + } + }, 5000); //every 5 seconds +} + +function handleToggleClick($sub, $toggle) { + if ($selectedSub !== $sub && $selectedSub.is(':visible')) { + $selectedSub.slideUp('fast', subSlideUp); + } + $selectedSub = $sub + if ($selectedSub.is(':visible')) { + $selectedSub.slideUp('fast', subSlideUp); + clearInterval(opts.selectedSubLoop); + } else { + $selectedSub.slideDown('fast', function() { + var windowHeight = $(window).height(); + var toggleHeight = $toggle.outerHeight(); + var priorSubHeight = $selectedSub.outerHeight(); + var newSubHeight = windowHeight - toggleHeight; + $(this).height(newSubHeight); + if (priorSubHeight > (windowHeight - toggleHeight)) { + $(this).addClass('scroll'); + } + }); + opts.selectedSubLoop = startSubLoop(); + } +} + /***************************************** * * DOM READY @@ -497,6 +537,8 @@ if (typeof $ === 'undefined') { $(function() { $messages = $('#messages'); $subOptions = $('#subOptions'); + $subAudio = $('#subAudio'); + $selectedSub = $subOptions; //Hey look it's a controller loop! setInterval(function() { @@ -607,12 +649,9 @@ $(function() { }); $messages.on('mousedown', function(e) { - if ($subOptions && $subOptions.is(':visible')) { - $subOptions.slideUp('fast', function() { - $(this).removeClass('scroll'); - $(this).css('height', ''); - }); - clearInterval(opts.subOptionsLoop); + if ($selectedSub && $selectedSub.is(':visible')) { + $selectedSub.slideUp('fast', subSlideUp); + clearInterval(opts.selectedSubLoop); } }); @@ -731,41 +770,19 @@ $(function() { }); $('#toggleOptions').click(function(e) { - if ($subOptions.is(':visible')) { - $subOptions.slideUp('fast', function() { - $(this).removeClass('scroll'); - $(this).css('height', ''); - }); - clearInterval(opts.subOptionsLoop); - } else { - $subOptions.slideDown('fast', function() { - var windowHeight = $(window).height(); - var toggleHeight = $('#toggleOptions').outerHeight(); - var priorSubHeight = $subOptions.outerHeight(); - var newSubHeight = windowHeight - toggleHeight; - $(this).height(newSubHeight); - if (priorSubHeight > (windowHeight - toggleHeight)) { - $(this).addClass('scroll'); - } - }); - opts.subOptionsLoop = setInterval(function() { - if (!opts.suppressOptionsClose && $('#subOptions').is(':visible')) { - $subOptions.slideUp('fast', function() { - $(this).removeClass('scroll'); - $(this).css('height', ''); - }); - clearInterval(opts.subOptionsLoop); - } - }, 5000); //Every 5 seconds - } + handleToggleClick($subOptions, $(this)); }); - $('#subOptions, #toggleOptions').mouseenter(function() { - opts.suppressOptionsClose = true; + $('#toggleAudio').click(function(e) { + handleToggleClick($subAudio, $(this)); }); - $('#subOptions, #toggleOptions').mouseleave(function() { - opts.suppressOptionsClose = false; + $('.sub, .toggle').mouseenter(function() { + opts.suppressSubClose = true; + }); + + $('.sub, .toggle').mouseleave(function() { + opts.suppressSubClose = false; }); $('#decreaseFont').click(function(e) { From 682269ab63fd800717079ddd05ed7e282cbcd40c Mon Sep 17 00:00:00 2001 From: Ashe Higgs Date: Thu, 5 Oct 2017 04:00:06 -0400 Subject: [PATCH 28/82] Lizzers and plasmamen can now be servants of Ratvar (#31244) * Removes racial discrimination from Ratvar's servants * Activates plasma internals; thank you Y0SH1M4S73R! * Update clock_cult.dm --- code/game/gamemodes/clock_cult/clock_cult.dm | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm index 7d6f9bcdd1..261a258101 100644 --- a/code/game/gamemodes/clock_cult/clock_cult.dm +++ b/code/game/gamemodes/clock_cult/clock_cult.dm @@ -163,7 +163,6 @@ Credit where due: if(!M || !ishuman(M)) return FALSE var/mob/living/carbon/human/L = M - L.set_species(/datum/species/human) L.equipOutfit(/datum/outfit/servant_of_ratvar) var/obj/item/clockwork/slab/S = new var/slot = "At your feet" @@ -239,6 +238,7 @@ Credit where due: //Servant of Ratvar outfit /datum/outfit/servant_of_ratvar + name = "Servant of Ratvar" uniform = /obj/item/clothing/under/chameleon/ratvar shoes = /obj/item/clothing/shoes/workboots back = /obj/item/storage/backpack @@ -248,6 +248,15 @@ Credit where due: backpack_contents = list(/obj/item/storage/box/engineer = 1, \ /obj/item/clockwork/replica_fabricator = 1, /obj/item/stack/tile/brass/fifty = 1, /obj/item/paper/servant_primer = 1) id = /obj/item/card/id + var/plasmaman //We use this to determine if we should activate internals in post_equip() + +/datum/outfit/servant_of_ratvar/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(H.dna.species.id == "plasmaman") //Plasmamen get additional equipment because of how they work + head = /obj/item/clothing/head/helmet/space/plasmaman + uniform = /obj/item/clothing/under/plasmaman //Plasmamen generally shouldn't need chameleon suits anyways, since everyone expects them to wear their fire suit + r_hand = /obj/item/tank/internals/plasmaman/belt/full + mask = /obj/item/clothing/mask/breath + plasmaman = TRUE /datum/outfit/servant_of_ratvar/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) var/obj/item/card/id/W = H.wear_id @@ -255,6 +264,9 @@ Credit where due: W.access += ACCESS_MAINT_TUNNELS W.registered_name = H.real_name W.update_label() + if(plasmaman && !visualsOnly) //If we need to breathe from the plasma tank, we should probably start doing that + H.internal = H.get_item_for_held_index(2) + H.update_internals_hud_icon(1) /obj/item/paper/servant_primer name = "The Ark And You: A Primer On Servitude" From 574e1669517a19f858e6c8182192549f92350063 Mon Sep 17 00:00:00 2001 From: oranges Date: Thu, 5 Oct 2017 21:01:19 +1300 Subject: [PATCH 30/82] Merge pull request #31269 from Firecage/doublehardsuitrebalance Makes the ERT and Chronosuit hardsuits and helmets have the same armor stats. --- code/modules/clothing/spacesuits/chronosuit.dm | 2 +- code/modules/clothing/spacesuits/miscellaneous.dm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/clothing/spacesuits/chronosuit.dm b/code/modules/clothing/spacesuits/chronosuit.dm index dfc2421add..e15f54a500 100644 --- a/code/modules/clothing/spacesuits/chronosuit.dm +++ b/code/modules/clothing/spacesuits/chronosuit.dm @@ -4,7 +4,7 @@ icon_state = "chronohelmet" item_state = "chronohelmet" slowdown = 1 - armor = list(melee = 60, bullet = 30/*bullet through the visor*/, laser = 60, energy = 60, bomb = 30, bio = 90, rad = 90, fire = 100, acid = 100) + armor = list(melee = 60, bullet = 60, laser = 60, energy = 60, bomb = 30, bio = 90, rad = 90, fire = 100, acid = 100) resistance_flags = FIRE_PROOF | ACID_PROOF var/obj/item/clothing/suit/space/chronos/suit = null diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index c5af37506c..1136be711f 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -173,7 +173,7 @@ Contains: item_state = "ert_command" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals) - armor = list(melee = 30, bullet = 50, laser = 30, energy = 50, bomb = 50, bio = 100, rad = 100, fire = 0, acid = 95) + armor = list(melee = 65, bullet = 50, laser = 50, energy = 50, bomb = 50, bio = 100, rad = 100, fire = 80, acid = 80) slowdown = 0 strip_delay = 130 From ad08855056f538e7ffb70a079d65c1293633b4fc Mon Sep 17 00:00:00 2001 From: oranges Date: Thu, 5 Oct 2017 21:03:34 +1300 Subject: [PATCH 32/82] Merge pull request #31291 from ShizCalev/shuttle-templates Cleans up non-timid shuttle templates & some dirty vars --- _maps/map_files/BoxStation/BoxStation.dmm | 1 - _maps/map_files/OmegaStation/OmegaStation.dmm | 1 - _maps/shuttles/emergency_box.dmm | 2 +- _maps/shuttles/whiteship_box.dmm | 2 +- 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index 1ef76788eb..0562f3c77f 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -2282,7 +2282,6 @@ }, /obj/docking_port/mobile/emergency{ name = "Box emergency shuttle"; - timid = 0 }, /obj/docking_port/stationary{ dir = 4; diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm index 14282b7ebf..2badff3bb5 100644 --- a/_maps/map_files/OmegaStation/OmegaStation.dmm +++ b/_maps/map_files/OmegaStation/OmegaStation.dmm @@ -16885,7 +16885,6 @@ dwidth = 5; height = 11; name = "Omega emergency shuttle"; - timid = 0; width = 19 }, /obj/docking_port/stationary{ diff --git a/_maps/shuttles/emergency_box.dmm b/_maps/shuttles/emergency_box.dmm index 1645d971c2..5d09eb9614 100644 --- a/_maps/shuttles/emergency_box.dmm +++ b/_maps/shuttles/emergency_box.dmm @@ -224,7 +224,7 @@ }, /obj/docking_port/mobile/emergency{ name = "Box emergency shuttle"; - timid = 0 + timid = 1 }, /turf/open/floor/plating, /area/shuttle/escape) diff --git a/_maps/shuttles/whiteship_box.dmm b/_maps/shuttles/whiteship_box.dmm index 338212e727..49d9d76a77 100644 --- a/_maps/shuttles/whiteship_box.dmm +++ b/_maps/shuttles/whiteship_box.dmm @@ -21,7 +21,7 @@ port_direction = 8; preferred_direction = 4; roundstart_move = "whiteship_away"; - timid = null; + timid = 1; width = 35 }, /turf/open/floor/mineral/titanium, From cedb56af1ba7856c7719f9e3a0cf4be90c10e41c Mon Sep 17 00:00:00 2001 From: oranges Date: Thu, 5 Oct 2017 21:05:16 +1300 Subject: [PATCH 34/82] Merge pull request #31302 from ninjanomnom/shuttle-rotation Move shuttleRotate into the shuttle module --- code/game/turfs/simulated/minerals.dm | 4 - code/modules/awaymissions/gateway.dm | 4 - code/modules/mining/equipment/survival_pod.dm | 8 -- code/modules/mob/mob.dm | 4 - code/modules/power/cable.dm | 15 --- code/modules/power/gravitygenerator.dm | 4 - code/modules/recycling/disposal-structures.dm | 10 -- code/modules/shuttle/on_move.dm | 37 +------ code/modules/shuttle/shuttle_rotate.dm | 100 ++++++++++++++++++ code/modules/shuttle/special.dm | 4 - tgstation.dme | 1 + 11 files changed, 102 insertions(+), 89 deletions(-) create mode 100644 code/modules/shuttle/shuttle_rotate.dm diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm index a597022448..1a5d0b78ec 100644 --- a/code/game/turfs/simulated/minerals.dm +++ b/code/game/turfs/simulated/minerals.dm @@ -38,10 +38,6 @@ if(istype(T, /turf/closed/mineral/random)) Spread(T) -/turf/closed/mineral/shuttleRotate(rotation) - setDir(angle2dir(rotation+dir2angle(dir))) - queue_smooth(src) - /turf/closed/mineral/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir) if(turf_type) underlay_appearance.icon = initial(turf_type.icon) diff --git a/code/modules/awaymissions/gateway.dm b/code/modules/awaymissions/gateway.dm index 12f99f3c50..a46b32f853 100644 --- a/code/modules/awaymissions/gateway.dm +++ b/code/modules/awaymissions/gateway.dm @@ -60,10 +60,6 @@ GLOBAL_DATUM(the_gateway, /obj/machinery/gateway/centerstation) return icon_state = "off" -//prevents shuttles attempting to rotate this since it messes up sprites -/obj/machinery/gateway/shuttleRotate() - return - /obj/machinery/gateway/attack_hand(mob/user) if(!detect()) return diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm index bb44f22752..5fe25b1d1f 100644 --- a/code/modules/mining/equipment/survival_pod.dm +++ b/code/modules/mining/equipment/survival_pod.dm @@ -104,10 +104,6 @@ direction = expected_dir ..() -/obj/machinery/door/airlock/survival_pod/shuttleRotate(rotation) - expected_dir = angle2dir(rotation+dir2angle(dir)) - ..() - /obj/machinery/door/airlock/survival_pod/vertical dir = EAST expected_dir = EAST @@ -127,10 +123,6 @@ direction = expected_dir ..() -/obj/structure/door_assembly/door_assembly_pod/shuttleRotate(rotation) - expected_dir = angle2dir(rotation+dir2angle(dir)) - ..() - /obj/structure/door_assembly/door_assembly_pod/vertical dir = EAST expected_dir = EAST diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index c75e0a27fb..4165651dbd 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -743,10 +743,6 @@ mob_spell_list -= S qdel(S) -//override to avoid rotating pixel_xy on mobs -/mob/shuttleRotate(rotation) - setDir(angle2dir(rotation+dir2angle(dir))) - //You can buckle on mobs if you're next to them since most are dense /mob/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE) if(M.buckled) diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 37ec831462..503eb88cd2 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -437,21 +437,6 @@ By design, d1 is the smallest direction and d2 is the highest if(!P.connect_to_network()) //can't find a node cable on a the turf to connect to P.disconnect_from_network() //remove from current network -/obj/structure/cable/shuttleRotate(rotation) - //..() is not called because wires are not supposed to have a non-default direction - //Rotate connections - if(d1) - d1 = angle2dir(rotation+dir2angle(d1)) - if(d2) - d2 = angle2dir(rotation+dir2angle(d2)) - - //d1 should be less than d2 for cable icons to work - if(d1 > d2) - var/temp = d1 - d1 = d2 - d2 = temp - update_icon() - /////////////////////////////////////////////// // The cable coil object, used for laying cable diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm index 346ede4eb8..3ad3f6bc13 100644 --- a/code/modules/power/gravitygenerator.dm +++ b/code/modules/power/gravitygenerator.dm @@ -48,10 +48,6 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne ..() icon_state = "[get_status()]_[sprite_number]" -//prevents shuttles attempting to rotate this since it messes up sprites -/obj/machinery/gravity_generator/shuttleRotate() - return - /obj/machinery/gravity_generator/proc/get_status() return "off" diff --git a/code/modules/recycling/disposal-structures.dm b/code/modules/recycling/disposal-structures.dm index acb89f4bee..2fe36972e0 100644 --- a/code/modules/recycling/disposal-structures.dm +++ b/code/modules/recycling/disposal-structures.dm @@ -339,16 +339,6 @@ if(current_size >= STAGE_FIVE) deconstruct() -//Fixes dpdir on shuttle rotation -/obj/structure/disposalpipe/shuttleRotate(rotation) - ..() - var/new_dpdir = 0 - for(var/D in GLOB.cardinals) - if(dpdir & D) - new_dpdir = new_dpdir | angle2dir(rotation+dir2angle(D)) - dpdir = new_dpdir - - // *** TEST verb //client/verb/dispstop() // for(var/obj/structure/disposalholder/H in world) diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index b527894d0a..5ded58450a 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -83,7 +83,7 @@ All ShuttleMove procs go here return if(rotation) - shuttleRotate(rotation) + shuttleRotate(rotation) //see shuttle_rotate.dm loc = newT if(length(client_mobs_in_contents)) update_parallax_contents() @@ -126,26 +126,6 @@ All ShuttleMove procs go here /area/proc/afterShuttleMove() return TRUE -/************************************Shuttle Rotation************************************/ - -/atom/proc/shuttleRotate(rotation) - //rotate our direction - setDir(angle2dir(rotation+dir2angle(dir))) - - //resmooth if need be. - if(smooth) - queue_smooth(src) - - //rotate the pixel offsets too. - if (pixel_x || pixel_y) - if (rotation < 0) - rotation += 360 - for (var/turntimes=rotation/90;turntimes>0;turntimes--) - var/oldPX = pixel_x - var/oldPY = pixel_y - pixel_x = oldPY - pixel_y = (oldPX*(-1)) - /************************************Turf move procs************************************/ /turf/open/afterShuttleMove(turf/oldT) //Recalculates SSair stuff for turfs on both sides @@ -223,21 +203,6 @@ All ShuttleMove procs go here . = ..() . |= MOVE_CONTENTS -//Properly updates pipes on shuttle movement -/obj/machinery/atmospherics/shuttleRotate(rotation) - var/list/real_node_connect = getNodeConnects() - for(DEVICE_TYPE_LOOP) - real_node_connect[I] = angle2dir(rotation+dir2angle(real_node_connect[I])) - - . = ..() - SetInitDirections() - var/list/supposed_node_connect = getNodeConnects() - var/list/nodes_copy = nodes.Copy() - - for(DEVICE_TYPE_LOOP) - var/new_pos = supposed_node_connect.Find(real_node_connect[I]) - nodes[new_pos] = nodes_copy[I] - /obj/machinery/atmospherics/afterShuttleMove(list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir) . = ..() var/missing_nodes = FALSE diff --git a/code/modules/shuttle/shuttle_rotate.dm b/code/modules/shuttle/shuttle_rotate.dm new file mode 100644 index 0000000000..389a2406ed --- /dev/null +++ b/code/modules/shuttle/shuttle_rotate.dm @@ -0,0 +1,100 @@ +/* +All shuttleRotate procs go here +*/ + +/************************************Base proc************************************/ + +/atom/proc/shuttleRotate(rotation) + //rotate our direction + setDir(angle2dir(rotation+dir2angle(dir))) + + //resmooth if need be. + if(smooth) + queue_smooth(src) + + //rotate the pixel offsets too. + if (pixel_x || pixel_y) + if (rotation < 0) + rotation += 360 + for (var/turntimes=rotation/90;turntimes>0;turntimes--) + var/oldPX = pixel_x + var/oldPY = pixel_y + pixel_x = oldPY + pixel_y = (oldPX*(-1)) + +/************************************Turf rotate procs************************************/ + +/turf/closed/mineral/shuttleRotate(rotation) + setDir(angle2dir(rotation+dir2angle(dir))) + queue_smooth(src) + +/************************************Mob rotate procs************************************/ + +//override to avoid rotating pixel_xy on mobs +/mob/shuttleRotate(rotation) + setDir(angle2dir(rotation+dir2angle(dir))) + +/************************************Structure rotate procs************************************/ + +/obj/structure/door_assembly/door_assembly_pod/shuttleRotate(rotation) + . = ..() + expected_dir = angle2dir(rotation+dir2angle(dir)) + +/obj/structure/cable/shuttleRotate(rotation) + //..() is not called because wires are not supposed to have a non-default direction + //Rotate connections + if(d1) + d1 = angle2dir(rotation+dir2angle(d1)) + if(d2) + d2 = angle2dir(rotation+dir2angle(d2)) + + //d1 should be less than d2 for cable icons to work + if(d1 > d2) + var/temp = d1 + d1 = d2 + d2 = temp + update_icon() + +//Fixes dpdir on shuttle rotation +/obj/structure/disposalpipe/shuttleRotate(rotation) + . = ..() + var/new_dpdir = 0 + for(var/D in GLOB.cardinals) + if(dpdir & D) + new_dpdir = new_dpdir | angle2dir(rotation+dir2angle(D)) + dpdir = new_dpdir + +/obj/structure/table/wood/bar/shuttleRotate(rotation) + . = ..() + boot_dir = angle2dir(rotation + dir2angle(boot_dir)) + +/obj/structure/alien/weeds/shuttleRotate(rotation) + return + +/************************************Machine rotate procs************************************/ + +/obj/machinery/atmospherics/shuttleRotate(rotation) + var/list/real_node_connect = getNodeConnects() + for(DEVICE_TYPE_LOOP) + real_node_connect[I] = angle2dir(rotation+dir2angle(real_node_connect[I])) + + . = ..() + SetInitDirections() + var/list/supposed_node_connect = getNodeConnects() + var/list/nodes_copy = nodes.Copy() + + for(DEVICE_TYPE_LOOP) + var/new_pos = supposed_node_connect.Find(real_node_connect[I]) + nodes[new_pos] = nodes_copy[I] + +//prevents shuttles attempting to rotate this since it messes up sprites +/obj/machinery/gateway/shuttleRotate() + return + +/obj/machinery/door/airlock/survival_pod/shuttleRotate(rotation) + expected_dir = angle2dir(rotation+dir2angle(dir)) + return ..() + +//prevents shuttles attempting to rotate this since it messes up sprites +/obj/machinery/gravity_generator/shuttleRotate() + return \ No newline at end of file diff --git a/code/modules/shuttle/special.dm b/code/modules/shuttle/special.dm index 0373ea5b53..f2d451f6e2 100644 --- a/code/modules/shuttle/special.dm +++ b/code/modules/shuttle/special.dm @@ -195,10 +195,6 @@ else . = ..() -/obj/structure/table/wood/bar/shuttleRotate(rotation) - . = ..() - boot_dir = angle2dir(rotation + dir2angle(boot_dir)) - /obj/structure/table/wood/bar/proc/is_barstaff(mob/living/user) . = FALSE if(ishuman(user)) diff --git a/tgstation.dme b/tgstation.dme index 2dba779e78..8b927cf2bb 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -2154,6 +2154,7 @@ #include "code\modules\shuttle\on_move.dm" #include "code\modules\shuttle\ripple.dm" #include "code\modules\shuttle\shuttle.dm" +#include "code\modules\shuttle\shuttle_rotate.dm" #include "code\modules\shuttle\special.dm" #include "code\modules\shuttle\supply.dm" #include "code\modules\shuttle\syndicate.dm" From bb9982e772a7254a6d70ffb585c8a5e19f62cd7d Mon Sep 17 00:00:00 2001 From: oranges Date: Thu, 5 Oct 2017 21:04:20 +1300 Subject: [PATCH 36/82] Merge pull request #31296 from ShizCalev/landmark-cleanup Cleans up and fixes old landmarks --- code/datums/mind.dm | 2 +- code/modules/admin/verbs/randomverbs.dm | 10 +++------- code/modules/mob/dead/new_player/new_player.dm | 2 +- code/modules/shuttle/manipulator.dm | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 093e828452..0e1b754fc9 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -1119,7 +1119,7 @@ message_admins("[key_name_admin(usr)] has nuke op'ed [current].") log_admin("[key_name(usr)] has nuke op'ed [current].") if("lair") - current.forceMove(get_turf(locate("landmark*Syndicate-Spawn"))) + current.forceMove(pick(GLOB.nukeop_start)) if("dressup") var/mob/living/carbon/human/H = current qdel(H.belt) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index e354d26ab0..e81ab011e4 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -381,13 +381,10 @@ Traitors and the like can also be revived with the previous role mostly intact. switch(new_character.mind.special_role) if("Wizard") - new_character.loc = pick(GLOB.wizardstart) - //SSticker.mode.learn_basic_spells(new_character) + new_character.forceMove(pick(GLOB.wizardstart)) SSticker.mode.equip_wizard(new_character) if("Syndicate") - var/obj/effect/landmark/synd_spawn = locate("landmark*Syndicate-Spawn") - if(synd_spawn) - new_character.loc = get_turf(synd_spawn) + new_character.forceMove(pick(GLOB.nukeop_start)) call(/datum/game_mode/proc/equip_syndicate)(new_character) if("Space Ninja") var/list/ninja_spawn = list() @@ -396,8 +393,7 @@ Traitors and the like can also be revived with the previous role mostly intact. var/datum/antagonist/ninja/ninjadatum = new_character.mind.has_antag_datum(ANTAG_DATUM_NINJA) ninjadatum.equip_space_ninja() if(ninja_spawn.len) - var/obj/effect/landmark/ninja_spawn_here = pick(ninja_spawn) - new_character.loc = ninja_spawn_here.loc + new_character.forceMove(pick(ninja_spawn)) else//They may also be a cyborg or AI. switch(new_character.mind.assigned_role) diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index aca1d9b63f..666fd767ba 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -273,7 +273,7 @@ observer.started_as_observer = TRUE close_spawn_windows() - var/obj/O = locate("landmark*Observer-Start") + var/obj/effect/landmark/observer_start/O = locate(/obj/effect/landmark/observer_start) in GLOB.landmarks_list to_chat(src, "Now teleporting.") if (O) observer.loc = O.loc diff --git a/code/modules/shuttle/manipulator.dm b/code/modules/shuttle/manipulator.dm index 6e2741a6d7..3da4bcc03e 100644 --- a/code/modules/shuttle/manipulator.dm +++ b/code/modules/shuttle/manipulator.dm @@ -242,7 +242,7 @@ /obj/machinery/shuttle_manipulator/proc/load_template( datum/map_template/shuttle/S) // load shuttle template, centred at shuttle import landmark, - var/turf/landmark_turf = get_turf(locate("landmark*Shuttle Import")) + var/turf/landmark_turf = get_turf(locate(/obj/effect/landmark/shuttle_import) in GLOB.landmarks_list) S.load(landmark_turf, centered = TRUE) var/affected = S.get_affected_turfs(landmark_turf, centered=TRUE) From 08f3503a810d27e5ff23ddc929b355fc6661a7c4 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Thu, 5 Oct 2017 05:14:27 -0500 Subject: [PATCH 38/82] Update holder.dm --- code/modules/reagents/chemistry/holder.dm | 29 ----------------------- 1 file changed, 29 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index c383dd5a7d..927ccb9994 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -16,12 +16,6 @@ /datum/reagents/New(maximum=100) maximum_volume = maximum -<<<<<<< HEAD - if(!(flags_1 & REAGENT_NOREACT)) - START_PROCESSING(SSobj, src) -======= ->>>>>>> b8ea267... Merge pull request #31281 from vuonojenmustaturska/clowncult - //I dislike having these here but map-objects are initialised before world/New() is called. >_> if(!GLOB.chemical_reagents_list) //Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id @@ -290,34 +284,11 @@ C.update_stamina() update_total() -<<<<<<< HEAD -/datum/reagents/process() - var/list/cached_reagents = reagent_list - if(flags_1 & REAGENT_NOREACT) - STOP_PROCESSING(SSobj, src) - return - - for(var/reagent in cached_reagents) - var/datum/reagent/R = reagent - R.on_tick() - -/datum/reagents/proc/set_reacting(react = TRUE) - if(react) - // Order is important, process() can remove from processing if - // the flag is present - flags_1 &= ~(REAGENT_NOREACT) - START_PROCESSING(SSobj, src) - else - STOP_PROCESSING(SSobj, src) - flags_1 |= REAGENT_NOREACT -======= - /datum/reagents/proc/set_reacting(react = TRUE) if(react) flags &= ~(REAGENT_NOREACT) else flags |= REAGENT_NOREACT ->>>>>>> b8ea267... Merge pull request #31281 from vuonojenmustaturska/clowncult /datum/reagents/proc/conditional_update_move(atom/A, Running = 0) var/list/cached_reagents = reagent_list From abeb003465cc9bbb15d7a32d9b66a3fc90684358 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Thu, 5 Oct 2017 05:18:04 -0500 Subject: [PATCH 39/82] Update preferences_savefile.dm --- code/modules/client/preferences_savefile.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 999d2255ac..dddac1e506 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -3,7 +3,7 @@ //This is the current version, anything below this will attempt to update (if it's not obsolete) #define SAVEFILE_VERSION_MAX 20 - +/* SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn This proc checks if the current directory of the savefile S needs updating It is to be used by the load_character and load_preferences procs. From 47b72055cde3a7213e2b2b0bf0a8695783da539c Mon Sep 17 00:00:00 2001 From: LetterJay Date: Thu, 5 Oct 2017 05:19:49 -0500 Subject: [PATCH 40/82] Update shuttle.dm --- code/modules/shuttle/shuttle.dm | 4 ---- 1 file changed, 4 deletions(-) diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 88daa3a016..22368c92fb 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -625,8 +625,6 @@ internal_area.afterShuttleMove() //areas CHECK_TICK -<<<<<<< HEAD -======= // Parallax handling var/new_parallax_dir = FALSE if(istype(new_dock, /obj/docking_port/stationary/transit)) @@ -635,8 +633,6 @@ var/area/place = i place.parallax_movedir = new_parallax_dir CHECK_TICK - ->>>>>>> e16fd1b... Makes shuttle movement a bit smoother and faster (#31255) check_poddoors() new_dock.last_dock_time = world.time setDir(new_dock.dir) From ced865f76dbca281bbeb7b1df9dff9aef59aa4a7 Mon Sep 17 00:00:00 2001 From: Leo Date: Thu, 5 Oct 2017 08:47:31 -0300 Subject: [PATCH 41/82] Merge pull request #31290 from YPOQ/jaunterfix Fixes jaunters chasm-saving feature --- code/modules/mining/equipment/wormhole_jaunter.dm | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/code/modules/mining/equipment/wormhole_jaunter.dm b/code/modules/mining/equipment/wormhole_jaunter.dm index d72d0e5f73..28a946a56b 100644 --- a/code/modules/mining/equipment/wormhole_jaunter.dm +++ b/code/modules/mining/equipment/wormhole_jaunter.dm @@ -17,7 +17,7 @@ /obj/item/device/wormhole_jaunter/attack_self(mob/user) user.visible_message("[user.name] activates the [src.name]!") SSblackbox.add_details("jaunter", "User") // user activated - activate(user) + activate(user, TRUE) /obj/item/device/wormhole_jaunter/proc/turf_check(mob/user) var/turf/device_turf = get_turf(user) @@ -46,7 +46,7 @@ return destinations -/obj/item/device/wormhole_jaunter/proc/activate(mob/user) +/obj/item/device/wormhole_jaunter/proc/activate(mob/user, adjacent) if(!turf_check(user)) return @@ -56,7 +56,8 @@ return var/chosen_beacon = pick(L) var/obj/effect/portal/wormhole/jaunt_tunnel/J = new (get_turf(src), src, 100, null, FALSE, get_turf(chosen_beacon)) - try_move_adjacent(J) + if(adjacent) + try_move_adjacent(J) playsound(src,'sound/effects/sparks4.ogg',50,1) qdel(src) @@ -78,7 +79,7 @@ if(user.get_item_by_slot(slot_belt) == src) to_chat(user, "Your [src] activates, saving you from the chasm!") SSblackbox.add_details("jaunter","Chasm") // chasm automatic activation - activate(user) + activate(user, FALSE) else to_chat(user, "The [src] is not attached to your belt, preventing it from saving you from the chasm. RIP.") From 5a0d1e5aebec607b51c619d01430103bdcfc630a Mon Sep 17 00:00:00 2001 From: Leo Date: Thu, 5 Oct 2017 08:49:00 -0300 Subject: [PATCH 43/82] Merge pull request #31294 from YPOQ/sciencetoolfix Fix abductor scientist being unable to use science tool --- code/datums/antagonists/datum_abductor.dm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/datums/antagonists/datum_abductor.dm b/code/datums/antagonists/datum_abductor.dm index 6d08d61b8a..81329928b3 100644 --- a/code/datums/antagonists/datum_abductor.dm +++ b/code/datums/antagonists/datum_abductor.dm @@ -58,3 +58,9 @@ break SSticker.mode.update_abductor_icons_added(owner) + +/datum/antagonist/abductor/scientist/finalize_abductor() + ..() + var/mob/living/carbon/human/H = owner.current + var/datum/species/abductor/A = H.dna.species + A.scientist = TRUE From 8e1a31c8af16a6ab92450f907e629733566ed736 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Thu, 5 Oct 2017 06:51:59 -0500 Subject: [PATCH 45/82] Update holder.dm --- code/modules/reagents/chemistry/holder.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 927ccb9994..42980f4f4d 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -11,7 +11,7 @@ var/last_tick = 1 var/addiction_tick = 1 var/list/datum/reagent/addiction_list = new/list() - var/flags_1 + var/flags /datum/reagents/New(maximum=100) maximum_volume = maximum From 3d364f08f22274c79bb12bf8e4f5a4abdaba6dd2 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Thu, 5 Oct 2017 07:11:14 -0500 Subject: [PATCH 46/82] Update holder.dm --- code/modules/reagents/chemistry/holder.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 42980f4f4d..eeb5016445 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -308,7 +308,7 @@ var/list/cached_reagents = reagent_list var/list/cached_reactions = GLOB.chemical_reactions_list var/datum/cached_my_atom = my_atom - if(flags_1 & REAGENT_NOREACT) + if(flags & REAGENT_NOREACT) return //Yup, no reactions here. No siree. var/reaction_occurred = 0 From ab44b9fb625b2893da9a890b60b595a5abf9b51b Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 5 Oct 2017 07:31:24 -0500 Subject: [PATCH 47/82] Automatic changelog generation for PR #3135 [ci skip] --- html/changelogs/AutoChangeLog-pr-3135.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3135.yml diff --git a/html/changelogs/AutoChangeLog-pr-3135.yml b/html/changelogs/AutoChangeLog-pr-3135.yml new file mode 100644 index 0000000000..faef26ffd8 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3135.yml @@ -0,0 +1,4 @@ +author: "Naksu" +delete-after: True +changes: + - balance: "Pyrosium and cryostylane now react at ludicrous speeds." From fcad8c077a1a1185caf2709fa9e5081b32be8416 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 5 Oct 2017 07:31:43 -0500 Subject: [PATCH 48/82] Automatic changelog generation for PR #3138 [ci skip] --- html/changelogs/AutoChangeLog-pr-3138.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3138.yml diff --git a/html/changelogs/AutoChangeLog-pr-3138.yml b/html/changelogs/AutoChangeLog-pr-3138.yml new file mode 100644 index 0000000000..3fdfa942c2 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3138.yml @@ -0,0 +1,4 @@ +author: "ShizCalev" +delete-after: True +changes: + - soundadd: "Space ninja energy katanas now make a swish when drawn!" From 20f88b815a54e2f9e9ed0492c57a42a4e11ad48d Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 5 Oct 2017 07:31:58 -0500 Subject: [PATCH 49/82] Automatic changelog generation for PR #3139 [ci skip] --- html/changelogs/AutoChangeLog-pr-3139.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3139.yml diff --git a/html/changelogs/AutoChangeLog-pr-3139.yml b/html/changelogs/AutoChangeLog-pr-3139.yml new file mode 100644 index 0000000000..88cb158819 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3139.yml @@ -0,0 +1,4 @@ +author: "ShizCalev" +delete-after: True +changes: + - bugfix: "Wizards will now have the correct name when attacked with Envy's knife!" From 28f5c31a72fc97c49529521f41007971ecd70de7 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 5 Oct 2017 07:38:21 -0500 Subject: [PATCH 50/82] Automatic changelog generation for PR #3142 [ci skip] --- html/changelogs/AutoChangeLog-pr-3142.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3142.yml diff --git a/html/changelogs/AutoChangeLog-pr-3142.yml b/html/changelogs/AutoChangeLog-pr-3142.yml new file mode 100644 index 0000000000..e502707a59 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3142.yml @@ -0,0 +1,4 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - tweak: "The PDA default font has been switched from \"eye bleed\" to old-style monospace. Check your preference." From 986e06d721a07c63241b3a356de7ff83ed97cbe7 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 5 Oct 2017 07:45:57 -0500 Subject: [PATCH 51/82] Automatic changelog generation for PR #3144 [ci skip] --- html/changelogs/AutoChangeLog-pr-3144.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3144.yml diff --git a/html/changelogs/AutoChangeLog-pr-3144.yml b/html/changelogs/AutoChangeLog-pr-3144.yml new file mode 100644 index 0000000000..bf65dca23d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3144.yml @@ -0,0 +1,4 @@ +author: "RandomMarine" +delete-after: True +changes: + - bugfix: "Simple mobs should no longer experience severe hud/lighting glitches when reconnecting." From 905e1806a1f8b18049249c6f0fbf7a406ad74d2b Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 5 Oct 2017 08:10:49 -0500 Subject: [PATCH 52/82] Automatic changelog generation for PR #3147 [ci skip] --- html/changelogs/AutoChangeLog-pr-3147.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3147.yml diff --git a/html/changelogs/AutoChangeLog-pr-3147.yml b/html/changelogs/AutoChangeLog-pr-3147.yml new file mode 100644 index 0000000000..556149df01 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3147.yml @@ -0,0 +1,4 @@ +author: "JJRcop" +delete-after: True +changes: + - tweak: "Admin volume slider moved to its own menu for better visibility." From e84b7a7af6e5354ad90014c52d56ef5188b8803a Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 5 Oct 2017 08:11:39 -0500 Subject: [PATCH 53/82] Automatic changelog generation for PR #3148 [ci skip] --- html/changelogs/AutoChangeLog-pr-3148.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3148.yml diff --git a/html/changelogs/AutoChangeLog-pr-3148.yml b/html/changelogs/AutoChangeLog-pr-3148.yml new file mode 100644 index 0000000000..c9662ac387 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3148.yml @@ -0,0 +1,4 @@ +author: "Xhuis and Y0SH1_M4S73R" +delete-after: True +changes: + - bugfix: "Servants of Ratvar now spawn in as the actual race set on their preferences, with plasmamen getting the gear they need to not immediately die." From 18465adc90788b82e829a447dc935652bc00f44a Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 5 Oct 2017 08:12:46 -0500 Subject: [PATCH 54/82] Automatic changelog generation for PR #3153 [ci skip] --- html/changelogs/AutoChangeLog-pr-3153.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3153.yml diff --git a/html/changelogs/AutoChangeLog-pr-3153.yml b/html/changelogs/AutoChangeLog-pr-3153.yml new file mode 100644 index 0000000000..a79a3982ca --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3153.yml @@ -0,0 +1,4 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - bugfix: "Jaunters equipped on the belt slot will save you from chasms again." From f91dc76e1a8eb4698f75cf2086454c2a78e59d17 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Thu, 5 Oct 2017 10:21:14 -0400 Subject: [PATCH 55/82] Merge pull request #31310 from ShizCalev/lobby-timer-fix Fixes lobby timer showing as delayed when it's just waiting for more players --- code/modules/mob/dead/new_player/new_player.dm | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 666fd767ba..8a978bc44b 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -79,9 +79,12 @@ if(SSticker.current_state == GAME_STATE_PREGAME) var/time_remaining = SSticker.GetTimeLeft() - if(time_remaining >= 0) - time_remaining /= 10 - stat("Time To Start:", (time_remaining >= 0) ? "[round(time_remaining)]s" : "DELAYED") + if(time_remaining > 0) + stat("Time To Start:", "[round(time_remaining/10)]s") + else if(time_remaining == -10) + stat("Time To Start:", "DELAYED") + else + stat("Time To Start:", "SOON") stat("Players:", "[SSticker.totalPlayers]") if(client.holder) From f45344ed8c7b1d8a4ff0d58362576521ee9d75ef Mon Sep 17 00:00:00 2001 From: AnturK Date: Thu, 5 Oct 2017 16:23:06 +0200 Subject: [PATCH 57/82] Adds wigs --- code/game/machinery/vending.dm | 5 +- code/modules/clothing/head/misc_special.dm | 224 +++++++++++++++++++++ 2 files changed, 227 insertions(+), 2 deletions(-) diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index b3a7f99758..d4a06d0580 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -1009,8 +1009,9 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C /obj/item/clothing/mask/joy = 1, /obj/item/clothing/head/cueball = 1, /obj/item/clothing/under/scratch = 1, - /obj/item/clothing/under/sailor = 1, - /obj/item/clothing/ears/headphones = 2) + /obj/item/clothing/under/sailor = 1, + /obj/item/clothing/ears/headphones = 2, + /obj/item/clothing/head/wig/random = 3) contraband = list(/obj/item/clothing/suit/judgerobe = 1, /obj/item/clothing/head/powdered_wig = 1, /obj/item/gun/magic/wand = 2, /obj/item/clothing/glasses/sunglasses/garb = 2, /obj/item/clothing/glasses/sunglasses/blindfold = 1, /obj/item/clothing/mask/muzzle = 2) premium = list(/obj/item/clothing/suit/pirate/captain = 2, /obj/item/clothing/head/pirate/captain = 2, /obj/item/clothing/head/helmet/roman = 1, /obj/item/clothing/head/helmet/roman/legionaire = 1, /obj/item/clothing/under/roman = 1, /obj/item/clothing/shoes/roman = 1, /obj/item/shield/riot/roman = 1, /obj/item/skub = 1) refill_canister = /obj/item/vending_refill/autodrobe diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 314f39f48b..d14ef81806 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -1,3 +1,4 @@ +<<<<<<< HEAD /* * Contents: * Welding mask @@ -177,3 +178,226 @@ /obj/item/clothing/head/cardborg/dropped(mob/living/user) ..() user.remove_alt_appearance("standard_borg_disguise") +======= +/* + * Contents: + * Welding mask + * Cakehat + * Ushanka + * Pumpkin head + * Kitty ears + * Cardborg disguise + */ + +/* + * Welding mask + */ +/obj/item/clothing/head/welding + name = "welding helmet" + desc = "A head-mounted face cover designed to protect the wearer completely from space-arc eye." + icon_state = "welding" + flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH + item_state = "welding" + materials = list(MAT_METAL=1750, MAT_GLASS=400) +// var/up = 0 + flash_protect = 2 + tint = 2 + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 60) + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE + actions_types = list(/datum/action/item_action/toggle) + visor_flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE + visor_flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH + resistance_flags = FIRE_PROOF + +/obj/item/clothing/head/welding/attack_self(mob/user) + weldingvisortoggle(user) + + +/* + * Cakehat + */ +/obj/item/clothing/head/hardhat/cakehat + name = "cakehat" + desc = "You put the cake on your head. Brilliant." + icon_state = "hardhat0_cakehat" + item_state = "hardhat0_cakehat" + item_color = "cakehat" + hitsound = 'sound/weapons/tap.ogg' + flags_inv = HIDEEARS|HIDEHAIR + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0) + brightness_on = 2 //luminosity when on + flags_cover = HEADCOVERSEYES + heat = 1000 + +/obj/item/clothing/head/hardhat/cakehat/process() + var/turf/location = src.loc + if(ishuman(location)) + var/mob/living/carbon/human/M = location + if(M.is_holding(src) || M.head == src) + location = M.loc + + if(isturf(location)) + location.hotspot_expose(700, 1) + +/obj/item/clothing/head/hardhat/cakehat/turn_on() + ..() + force = 15 + throwforce = 15 + damtype = BURN + hitsound = 'sound/items/welder.ogg' + START_PROCESSING(SSobj, src) + +/obj/item/clothing/head/hardhat/cakehat/turn_off() + ..() + force = 0 + throwforce = 0 + damtype = BRUTE + hitsound = 'sound/weapons/tap.ogg' + STOP_PROCESSING(SSobj, src) + +/obj/item/clothing/head/hardhat/cakehat/is_hot() + return on * heat +/* + * Ushanka + */ +/obj/item/clothing/head/ushanka + name = "ushanka" + desc = "Perfect for winter in Siberia, da?" + icon_state = "ushankadown" + item_state = "ushankadown" + flags_inv = HIDEEARS|HIDEHAIR + var/earflaps = 1 + cold_protection = HEAD + min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT + + dog_fashion = /datum/dog_fashion/head/ushanka + +/obj/item/clothing/head/ushanka/attack_self(mob/user) + if(earflaps) + src.icon_state = "ushankaup" + src.item_state = "ushankaup" + earflaps = 0 + to_chat(user, "You raise the ear flaps on the ushanka.") + else + src.icon_state = "ushankadown" + src.item_state = "ushankadown" + earflaps = 1 + to_chat(user, "You lower the ear flaps on the ushanka.") + +/* + * Pumpkin head + */ +/obj/item/clothing/head/hardhat/pumpkinhead + name = "carved pumpkin" + desc = "A jack o' lantern! Believed to ward off evil spirits." + icon_state = "hardhat0_pumpkin" + item_state = "hardhat0_pumpkin" + item_color = "pumpkin" + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0) + brightness_on = 2 //luminosity when on + flags_cover = HEADCOVERSEYES + +/* + * Kitty ears + */ +/obj/item/clothing/head/kitty + name = "kitty ears" + desc = "A pair of kitty ears. Meow!" + icon_state = "kitty" + color = "#999999" + dynamic_hair_suffix = "" + + dog_fashion = /datum/dog_fashion/head/kitty + +/obj/item/clothing/head/kitty/equipped(mob/living/carbon/human/user, slot) + if(ishuman(user) && slot == slot_head) + update_icon(user) + user.update_inv_head() //Color might have been changed by update_icon. + ..() + +/obj/item/clothing/head/kitty/update_icon(mob/living/carbon/human/user) + if(ishuman(user)) + add_atom_colour("#[user.hair_color]", FIXED_COLOUR_PRIORITY) + +/obj/item/clothing/head/kitty/genuine + desc = "A pair of kitty ears. A tag on the inside says \"Hand made from real cats.\"" + + +/obj/item/clothing/head/hardhat/reindeer + name = "novelty reindeer hat" + desc = "Some fake antlers and a very fake red nose." + icon_state = "hardhat0_reindeer" + item_state = "hardhat0_reindeer" + item_color = "reindeer" + flags_inv = 0 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0) + brightness_on = 1 //luminosity when on + dynamic_hair_suffix = "" + + dog_fashion = /datum/dog_fashion/head/reindeer + +/obj/item/clothing/head/cardborg + name = "cardborg helmet" + desc = "A helmet made out of a box." + icon_state = "cardborg_h" + item_state = "cardborg_h" + flags_cover = HEADCOVERSEYES + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR + + dog_fashion = /datum/dog_fashion/head/cardborg + +/obj/item/clothing/head/cardborg/equipped(mob/living/user, slot) + ..() + if(ishuman(user) && slot == slot_head) + var/mob/living/carbon/human/H = user + if(istype(H.wear_suit, /obj/item/clothing/suit/cardborg)) + var/obj/item/clothing/suit/cardborg/CB = H.wear_suit + CB.disguise(user, src) + +/obj/item/clothing/head/cardborg/dropped(mob/living/user) + ..() + user.remove_alt_appearance("standard_borg_disguise") + + + +/obj/item/clothing/head/wig + name = "wig" + desc = "A bunch of hair without a head attached." + icon_state = "" + item_state = "pwig" + flags_inv = HIDEHAIR + var/hair_style = "Very Long Hair" + var/hair_color = "#000" + +/obj/item/clothing/head/wig/Initialize(mapload) + . = ..() + update_icon() + +/obj/item/clothing/head/wig/update_icon() + cut_overlays() + var/datum/sprite_accessory/S = GLOB.hair_styles_list[hair_style] + if(!S) + icon_state = "pwig" + else + var/mutable_appearance/M = mutable_appearance(S.icon,S.icon_state) + M.appearance_flags |= RESET_COLOR + M.color = hair_color + add_overlay(M) + +/obj/item/clothing/head/wig/worn_overlays(isinhands = FALSE, file2use) + . = list() + if(!isinhands) + var/datum/sprite_accessory/S = GLOB.hair_styles_list[hair_style] + if(!S) + return + var/mutable_appearance/M = mutable_appearance(S.icon, S.icon_state,layer = -HAIR_LAYER) + M.appearance_flags |= RESET_COLOR + M.color = hair_color + . += M + +/obj/item/clothing/head/wig/random/Initialize(mapload) + hair_style = pick(GLOB.hair_styles_list - "Bald") //Don't want invisible wig + hair_color = "#[random_short_color()]" + . = ..() +>>>>>>> d17d66f... Adds wigs (#31304) From 33364920b33d1d0da51926ff0e6b5ef132b5944b Mon Sep 17 00:00:00 2001 From: YPOQ <30683121+YPOQ@users.noreply.github.com> Date: Thu, 5 Oct 2017 08:24:34 -0600 Subject: [PATCH 58/82] Fixes crafting stacks without breaking crafted machinery (#31298) * Revert "Fixes stacking when crafting items" * Fixes crafted stacked items properly * Update stack.dm --- code/game/objects/items/stacks/stack.dm | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 6e7ffddeb3..7cef6094ea 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -151,7 +151,11 @@ if(!building_checks(R, multiplier)) return - var/obj/O = new R.result_type() + var/obj/O + if(R.max_res_amount > 1) //Is it a stack? + O = new R.result_type(usr.drop_location(), R.res_amount * multiplier) + else + O = new R.result_type(usr.drop_location()) O.setDir(usr.dir) use(R.req_amount * multiplier) @@ -164,16 +168,11 @@ W.ini_dir = W.dir //END: oh fuck i'm so sorry - //is it a stack ? - if (R.max_res_amount > 1) - var/obj/item/stack/new_item = O - new_item.amount = R.res_amount*multiplier - new_item.update_icon() + if (QDELETED(O)) + return //It's a stack and has already been merged if (isitem(O)) usr.put_in_hands(O) - else - O.forceMove(usr.drop_location()) O.add_fingerprint(usr) //BubbleWrap - so newly formed boxes are empty From 5b0b2fd5bb8f021c61296a76ec9bb254461f6d1e Mon Sep 17 00:00:00 2001 From: XDTM Date: Thu, 5 Oct 2017 17:52:47 +0200 Subject: [PATCH 60/82] Adds H.E.C.K. suits, spraycan_paintable component, and reworks item's attackby() --- code/_onclick/item_attack.dm | 2 +- code/datums/components/paintable.dm | 29 +++++++++ code/game/objects/effects/effects.dm | 6 +- code/game/objects/items.dm | 6 ++ code/game/objects/items/crayons.dm | 32 +++++----- code/game/objects/objs.dm | 1 + code/modules/clothing/head/helmet.dm | 22 +++++-- .../modules/mining/equipment/explorer_gear.dm | 61 +++++++++++++++++++ .../mining/lavaland/necropolis_chests.dm | 2 + .../living/simple_animal/bot/construction.dm | 22 ------- tgstation.dme | 1 + 11 files changed, 137 insertions(+), 47 deletions(-) create mode 100644 code/datums/components/paintable.dm diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 987818924f..4c0eeccf1d 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -20,7 +20,7 @@ return SendSignal(COMSIG_PARENT_ATTACKBY, W, user, params) /obj/attackby(obj/item/I, mob/living/user, params) - return ..() || I.attack_obj(src, user) + return ..() || (can_be_hit && I.attack_obj(src, user)) /mob/living/attackby(obj/item/I, mob/living/user, params) user.changeNext_move(CLICK_CD_MELEE) diff --git a/code/datums/components/paintable.dm b/code/datums/components/paintable.dm new file mode 100644 index 0000000000..2ea94334d0 --- /dev/null +++ b/code/datums/components/paintable.dm @@ -0,0 +1,29 @@ +/datum/component/spraycan_paintable + var/current_paint + +/datum/component/spraycan_paintable/Initialize() + RegisterSignal(COMSIG_PARENT_ATTACKBY, .proc/Repaint) + +/datum/component/spraycan_paintable/Destroy() + RemoveCurrentCoat() + return ..() + +/datum/component/spraycan_paintable/proc/RemoveCurrentCoat() + var/atom/A = parent + A.remove_atom_colour(FIXED_COLOUR_PRIORITY, current_paint) + +/datum/component/spraycan_paintable/proc/Repaint(obj/item/toy/crayon/spraycan/spraycan, mob/living/user) + if(!istype(spraycan) || user.a_intent == INTENT_HARM) + return FALSE + . = TRUE + if(spraycan.is_capped) + to_chat(user, "Take the cap off first!") + return + RemoveCurrentCoat() + if(spraycan.use_charges(user, 2)) + var/colour = spraycan.paint_color + current_paint = colour + var/atom/A = parent + A.add_atom_colour(colour, FIXED_COLOUR_PRIORITY) + playsound(spraycan, 'sound/effects/spray.ogg', 5, 1, 5) + to_chat(user, "You spray [spraycan] on [A], painting it.") diff --git a/code/game/objects/effects/effects.dm b/code/game/objects/effects/effects.dm index 4406c32fbd..d5f8e28d2a 100644 --- a/code/game/objects/effects/effects.dm +++ b/code/game/objects/effects/effects.dm @@ -4,9 +4,7 @@ /obj/effect icon = 'icons/effects/effects.dmi' resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF - -/obj/effect/attackby(obj/item/I, mob/living/user, params) - return + can_be_hit = FALSE /obj/effect/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) return @@ -57,4 +55,4 @@ return /obj/effect/abstract/singularity_act() - return \ No newline at end of file + return diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 072896ac01..362148c801 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -26,6 +26,8 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) max_integrity = 200 + can_be_hit = FALSE + var/hitsound = null var/usesound = null var/throwhitsound = null @@ -322,6 +324,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) // Due to storage type consolidation this should get used more now. // I have cleaned it up a little, but it could probably use more. -Sayu // The lack of ..() is intentional, do not add one +// added one, fuck the police /obj/item/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/storage)) var/obj/item/storage/S = W @@ -346,9 +349,12 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) qdel(progress) to_chat(user, "You put everything you could [S.preposition] [S].") + return else if(S.can_be_inserted(src)) S.handle_item_insertion(src) + return + return ..() /obj/item/proc/handle_mass_pickup(obj/item/storage/S, list/things, atom/thing_loc, list/rejections, datum/progressbar/progress) for(var/obj/item/I in things) diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 23905200e9..882335d5e7 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -107,20 +107,19 @@ var/amount = weight * units_per_weight reagents.add_reagent(reagent, amount) -/obj/item/toy/crayon/proc/use_charges(amount) +/obj/item/toy/crayon/proc/use_charges(mob/user, amount = 1, requires_full = TRUE) // Returns number of charges actually used - switch(paint_mode) - if(PAINT_LARGE_HORIZONTAL) - amount *= 3 - if(charges == -1) . = amount refill() else - . = min(charges_left, amount) - charges_left -= . + if(check_empty(user, amount, requires_full)) + return 0 + else + . = min(charges_left, amount) + charges_left -= . -/obj/item/toy/crayon/proc/check_empty(mob/user) +/obj/item/toy/crayon/proc/check_empty(mob/user, amount = 1, requires_full = TRUE) // When eating a crayon, check_empty() can be called twice producing // two messages unless we check for being deleted first if(QDELETED(src)) @@ -131,10 +130,13 @@ if(charges == -1) . = FALSE else if(!charges_left) - to_chat(user, "There is no more of \the [src.name] left!") + to_chat(user, "There is no more of [src] left!") if(self_contained) qdel(src) . = TRUE + else if(charges_left < amount && requires_full) + to_chat(user, "There is not enough of [src] left!") + . = TRUE /obj/item/toy/crayon/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state) // tgui is a plague upon this codebase @@ -298,7 +300,7 @@ var/takes_time = !instant var/wait_time = 50 - if(PAINT_LARGE_HORIZONTAL) + if(paint_mode == PAINT_LARGE_HORIZONTAL) wait_time *= 3 if(takes_time) @@ -343,7 +345,7 @@ var/cost = 1 if(paint_mode == PAINT_LARGE_HORIZONTAL) cost = 5 - . = use_charges(cost) + . = use_charges(user, cost) var/fraction = min(1, . / reagents.maximum_volume) if(affected_turfs.len) fraction /= affected_turfs.len @@ -355,7 +357,7 @@ /obj/item/toy/crayon/attack(mob/M, mob/user) if(edible && (M == user)) to_chat(user, "You take a bite of the [src.name]. Delicious!") - var/eaten = use_charges(5) + var/eaten = use_charges(user, 5, FALSE) if(check_empty(user)) //Prevents divsion by zero return var/fraction = min(eaten / reagents.total_volume, 1) @@ -527,7 +529,7 @@ H.lip_style = "spray_face" H.lip_color = paint_color H.update_body() - var/used = use_charges(10) + var/used = use_charges(user, 10, FALSE) var/fraction = min(1, used / reagents.maximum_volume) reagents.reaction(user, VAPOR, fraction * volume_multiplier) reagents.trans_to(user, used, volume_multiplier) @@ -583,7 +585,7 @@ H.update_body() // Caution, spray cans contain inflammable substances - . = use_charges(10) + . = use_charges(user, 10, FALSE) var/fraction = min(1, . / reagents.maximum_volume) reagents.reaction(C, VAPOR, fraction * volume_multiplier) @@ -596,7 +598,7 @@ target.set_opacity(255) else target.set_opacity(initial(target.opacity)) - . = use_charges(2) + . = use_charges(user, 2) var/fraction = min(1, . / reagents.maximum_volume) reagents.reaction(target, TOUCH, fraction * volume_multiplier) reagents.trans_to(target, ., volume_multiplier) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index f2537945db..fb5a4344f0 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -13,6 +13,7 @@ var/integrity_failure = 0 //0 if we have no special broken behavior var/resistance_flags = 0 // INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ON_FIRE | UNACIDABLE | ACID_PROOF + var/can_be_hit = TRUE //can this be bludgeoned by items? var/acid_level = 0 //how much acid is on that obj diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index d89671d06d..da4fe1cf5c 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -17,13 +17,25 @@ dog_fashion = /datum/dog_fashion/head/helmet - -/obj/item/clothing/head/helmet/Initialize() - . = ..() - /obj/item/clothing/head/helmet/sec can_flashlight = 1 +/obj/item/clothing/head/helmet/sec/attackby(obj/item/I, mob/user, params) + if(issignaler(I)) + var/obj/item/device/assembly/signaler/S = I + if(F) //Has a flashlight. Player must remove it, else it will be lost forever. + to_chat(user, "The mounted flashlight is in the way, remove it first!") + return + + if(S.secured) + qdel(S) + var/obj/item/secbot_assembly/A = new /obj/item/secbot_assembly + user.put_in_hands(A) + to_chat(user, "You add the signaler to the helmet.") + qdel(src) + return + return ..() + /obj/item/clothing/head/helmet/alt name = "bulletproof helmet" desc = "A bulletproof combat helmet that excels in protecting the wearer against traditional projectile weaponry and explosives to a minor extent." @@ -281,7 +293,7 @@ qdel(THL) return - ..() + return ..() /obj/item/clothing/head/helmet/proc/toggle_helmlight() set name = "Toggle Helmetlight" diff --git a/code/modules/mining/equipment/explorer_gear.dm b/code/modules/mining/equipment/explorer_gear.dm index 1b21b88447..f2cdefa9a4 100644 --- a/code/modules/mining/equipment/explorer_gear.dm +++ b/code/modules/mining/equipment/explorer_gear.dm @@ -46,3 +46,64 @@ /obj/item/clothing/mask/gas/explorer/folded/New() ..() adjustmask() + +/obj/item/clothing/suit/space/hostile_environment + name = "H.E.C.K. suit" + desc = "Hostile Environiment Cross-Kinetic Suit: A suit designed to withstand the wide variety of hazards from Lavaland. It wasn't enough for its last owner." + icon_state = "hostile_env" + item_state = "hostile_env" + flags_1 = THICKMATERIAL_1 //not spaceproof + max_heat_protection_temperature = FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT + resistance_flags = FIRE_PROOF | LAVA_PROOF + slowdown = 0 + armor = list("melee" = 70, "bullet" = 40, "laser" = 10, "energy" = 10, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/device/mining_scanner, /obj/item/device/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe) + +/obj/item/clothing/suit/space/hostile_environment/Initialize() + . = ..() + AddComponent(/datum/component/spraycan_paintable) + START_PROCESSING(SSobj, src) + +/obj/item/clothing/suit/space/hostile_environment/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/clothing/suit/space/hostile_environment/process() + var/mob/living/carbon/C = loc + if(istype(C) && prob(2)) //cursed by bubblegum + if(prob(15)) + new /datum/hallucination/oh_yeah(C) + to_chat(C, "[pick("I AM IMMORTAL.","I SHALL TAKE BACK WHAT'S MINE.","I SEE YOU.","YOU CANNOT ESCAPE ME FOREVER.","DEATH CANNOT HOLD ME.")]") + else + to_chat(C, "[pick("You hear faint whispers.","You smell ash.","You feel hot.","You hear a roar in the distance.")]") + +/obj/item/clothing/head/helmet/space/hostile_environment + name = "H.E.C.K. helmet" + desc = "Hostile Environiment Cross-Kinetic Helmet: A helmet designed to withstand the wide variety of hazards from Lavaland. It wasn't enough for its last owner." + icon_state = "hostile_env" + item_state = "hostile_env" + w_class = WEIGHT_CLASS_NORMAL + max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT + flags_1 = THICKMATERIAL_1 // no space protection + armor = list("melee" = 70, "bullet" = 40, "laser" = 10, "energy" = 10, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + resistance_flags = FIRE_PROOF | LAVA_PROOF + +/obj/item/clothing/head/helmet/space/hostile_environment/Initialize() + . = ..() + AddComponent(/datum/component/spraycan_paintable) + update_icon() + +/obj/item/clothing/head/helmet/space/hostile_environment/update_icon() + ..() + cut_overlays() + var/mutable_appearance/glass_overlay = mutable_appearance(icon, "hostile_env_glass") + glass_overlay.appearance_flags = RESET_COLOR + add_overlay(glass_overlay) + +/obj/item/clothing/head/helmet/space/hostile_environment/worn_overlays(isinhands) + . = ..() + if(!isinhands) + var/mutable_appearance/M = mutable_appearance('icons/mob/head.dmi', "hostile_env_glass") + M.appearance_flags = RESET_COLOR + . += M + diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index e16077fec1..95c4898605 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -932,6 +932,8 @@ name = "bubblegum chest" /obj/structure/closet/crate/necropolis/bubblegum/PopulateContents() + new /obj/item/clothing/suit/space/hostile_environment(src) + new /obj/item/clothing/head/helmet/space/hostile_environment(src) var/loot = rand(1,3) switch(loot) if(1) diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm index 0d1f346dcf..c53925e076 100644 --- a/code/modules/mob/living/simple_animal/bot/construction.dm +++ b/code/modules/mob/living/simple_animal/bot/construction.dm @@ -357,28 +357,6 @@ var/build_step = 0 var/created_name = "Securitron" //To preserve the name if it's a unique securitron I guess -/obj/item/clothing/head/helmet/attackby(obj/item/device/assembly/signaler/S, mob/user, params) - ..() - if(!issignaler(S)) - ..() - return - - if(type != /obj/item/clothing/head/helmet/sec) //Eh, but we don't want people making secbots out of space helmets. - return - - if(F) //Has a flashlight. Player must remove it, else it will be lost forever. - to_chat(user, "The mounted flashlight is in the way, remove it first!") - return - - if(S.secured) - qdel(S) - var/obj/item/secbot_assembly/A = new /obj/item/secbot_assembly - user.put_in_hands(A) - to_chat(user, "You add the signaler to the helmet.") - qdel(src) - else - return - /obj/item/secbot_assembly/attackby(obj/item/I, mob/user, params) ..() if(istype(I, /obj/item/weldingtool)) diff --git a/tgstation.dme b/tgstation.dme index 8b927cf2bb..b996531842 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -294,6 +294,7 @@ #include "code\datums\components\_component.dm" #include "code\datums\components\archaeology.dm" #include "code\datums\components\material_container.dm" +#include "code\datums\components\paintable.dm" #include "code\datums\components\slippery.dm" #include "code\datums\components\squeek.dm" #include "code\datums\diseases\_disease.dm" From a5f86b1e67e0ba1eeae99e35b41cba9a4ef41a1b Mon Sep 17 00:00:00 2001 From: Kevak Date: Thu, 5 Oct 2017 09:59:13 -0700 Subject: [PATCH 61/82] Fixes plasmaman sprites --- icons/obj/surgery.dmi | Bin 31018 -> 32112 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index d18a1bf262fadc379d7528c6dd0e3d5613e322fa..18bbcb36105d581053c2e6a2730777263c50eb08 100755 GIT binary patch delta 12695 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 HF#P^MijN%w delta 11593 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 From 2a75083f80237f85fa2b57115c2e152cc021472f Mon Sep 17 00:00:00 2001 From: Joan Lung <3886584+ChangelingRain@users.noreply.github.com> Date: Thu, 5 Oct 2017 16:04:29 -0400 Subject: [PATCH 62/82] Makes angle2dir() much more accurate --- code/__HELPERS/type2type.dm | 470 ++++++++++++++++++++++++++++++++++++ 1 file changed, 470 insertions(+) diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 46d6c2ce5c..ab06de1b8b 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -75,6 +75,7 @@ /world/proc/file2list(filename, seperator="\n", trim = TRUE) if (trim) return splittext(trim(file2text(filename)),seperator) +<<<<<<< HEAD return splittext(file2text(filename),seperator) //Turns a direction into text @@ -539,6 +540,475 @@ if(!istype(the_matrix) || the_matrix.len != 20) return "#ffffffff" return rgb(the_matrix[1]*255, the_matrix[6]*255, the_matrix[11]*255, the_matrix[16]*255) +======= + return splittext(file2text(filename),seperator) + +//Turns a direction into text +/proc/dir2text(direction) + switch(direction) + if(1) + return "north" + if(2) + return "south" + if(4) + return "east" + if(8) + return "west" + if(5) + return "northeast" + if(6) + return "southeast" + if(9) + return "northwest" + if(10) + return "southwest" + else + return + +//Turns text into proper directions +/proc/text2dir(direction) + switch(uppertext(direction)) + if("NORTH") + return 1 + if("SOUTH") + return 2 + if("EAST") + return 4 + if("WEST") + return 8 + if("NORTHEAST") + return 5 + if("NORTHWEST") + return 9 + if("SOUTHEAST") + return 6 + if("SOUTHWEST") + return 10 + else + return + +//Converts an angle (degrees) into an ss13 direction +/proc/angle2dir(degree) + + degree = SimplifyDegrees(degree) + switch(degree) + if(0 to 22.5) //north requires two angle ranges + return NORTH + if(22.5 to 67.5) //each range covers 45 degrees + return NORTHEAST + if(67.5 to 112.5) + return EAST + if(112.5 to 157.5) + return SOUTHEAST + if(157.5 to 202.5) + return SOUTH + if(202.5 to 247.5) + return SOUTHWEST + if(247.5 to 292.5) + return WEST + if(292.5 to 337.5) + return NORTHWEST + if(337.5 to 360) + return NORTH + +//returns the north-zero clockwise angle in degrees, given a direction + +/proc/dir2angle(D) + switch(D) + if(NORTH) + return 0 + if(SOUTH) + return 180 + if(EAST) + return 90 + if(WEST) + return 270 + if(NORTHEAST) + return 45 + if(SOUTHEAST) + return 135 + if(NORTHWEST) + return 315 + if(SOUTHWEST) + return 225 + else + return null + +//Returns the angle in english +/proc/angle2text(degree) + return dir2text(angle2dir(degree)) + +//Converts a blend_mode constant to one acceptable to icon.Blend() +/proc/blendMode2iconMode(blend_mode) + switch(blend_mode) + if(BLEND_MULTIPLY) + return ICON_MULTIPLY + if(BLEND_ADD) + return ICON_ADD + if(BLEND_SUBTRACT) + return ICON_SUBTRACT + else + return ICON_OVERLAY + +//Converts a rights bitfield into a string +/proc/rights2text(rights, seperator="", list/adds, list/subs) + if(rights & R_BUILDMODE) + . += "[seperator]+BUILDMODE" + if(rights & R_ADMIN) + . += "[seperator]+ADMIN" + if(rights & R_BAN) + . += "[seperator]+BAN" + if(rights & R_FUN) + . += "[seperator]+FUN" + if(rights & R_SERVER) + . += "[seperator]+SERVER" + if(rights & R_DEBUG) + . += "[seperator]+DEBUG" + if(rights & R_POSSESS) + . += "[seperator]+POSSESS" + if(rights & R_PERMISSIONS) + . += "[seperator]+PERMISSIONS" + if(rights & R_STEALTH) + . += "[seperator]+STEALTH" + if(rights & R_POLL) + . += "[seperator]+POLL" + if(rights & R_VAREDIT) + . += "[seperator]+VAREDIT" + if(rights & R_SOUNDS) + . += "[seperator]+SOUND" + if(rights & R_SPAWN) + . += "[seperator]+SPAWN" + + for(var/verbpath in adds) + . += "[seperator]+[verbpath]" + for(var/verbpath in subs) + . += "[seperator]-[verbpath]" + return . + +/proc/ui_style2icon(ui_style) + switch(ui_style) + if("Retro") + return 'icons/mob/screen_retro.dmi' + if("Plasmafire") + return 'icons/mob/screen_plasmafire.dmi' + if("Slimecore") + return 'icons/mob/screen_slimecore.dmi' + if("Operative") + return 'icons/mob/screen_operative.dmi' + if("Clockwork") + return 'icons/mob/screen_clockwork.dmi' + else + return 'icons/mob/screen_midnight.dmi' + +//colour formats +/proc/rgb2hsl(red, green, blue) + red /= 255;green /= 255;blue /= 255; + var/max = max(red,green,blue) + var/min = min(red,green,blue) + var/range = max-min + + var/hue=0;var/saturation=0;var/lightness=0; + lightness = (max + min)/2 + if(range != 0) + if(lightness < 0.5) + saturation = range/(max+min) + else + saturation = range/(2-max-min) + + var/dred = ((max-red)/(6*max)) + 0.5 + var/dgreen = ((max-green)/(6*max)) + 0.5 + var/dblue = ((max-blue)/(6*max)) + 0.5 + + if(max==red) + hue = dblue - dgreen + else if(max==green) + hue = dred - dblue + (1/3) + else + hue = dgreen - dred + (2/3) + if(hue < 0) + hue++ + else if(hue > 1) + hue-- + + return list(hue, saturation, lightness) + +/proc/hsl2rgb(hue, saturation, lightness) + var/red;var/green;var/blue; + if(saturation == 0) + red = lightness * 255 + green = red + blue = red + else + var/a;var/b; + if(lightness < 0.5) + b = lightness*(1+saturation) + else + b = (lightness+saturation) - (saturation*lightness) + a = 2*lightness - b + + red = round(255 * hue2rgb(a, b, hue+(1/3))) + green = round(255 * hue2rgb(a, b, hue)) + blue = round(255 * hue2rgb(a, b, hue-(1/3))) + + return list(red, green, blue) + +/proc/hue2rgb(a, b, hue) + if(hue < 0) + hue++ + else if(hue > 1) + hue-- + if(6*hue < 1) + return (a+(b-a)*6*hue) + if(2*hue < 1) + return b + if(3*hue < 2) + return (a+(b-a)*((2/3)-hue)*6) + return a + +// Very ugly, BYOND doesn't support unix time and rounding errors make it really hard to convert it to BYOND time. +// returns "YYYY-MM-DD" by default +/proc/unix2date(timestamp, seperator = "-") + + if(timestamp < 0) + return 0 //Do not accept negative values + + var/year = 1970 //Unix Epoc begins 1970-01-01 + var/dayInSeconds = 86400 //60secs*60mins*24hours + var/daysInYear = 365 //Non Leap Year + var/daysInLYear = daysInYear + 1//Leap year + var/days = round(timestamp / dayInSeconds) //Days passed since UNIX Epoc + var/tmpDays = days + 1 //If passed (timestamp < dayInSeconds), it will return 0, so add 1 + var/monthsInDays = list() //Months will be in here ***Taken from the PHP source code*** + var/month = 1 //This will be the returned MONTH NUMBER. + var/day //This will be the returned day number. + + while(tmpDays > daysInYear) //Start adding years to 1970 + year++ + if(isLeap(year)) + tmpDays -= daysInLYear + else + tmpDays -= daysInYear + + if(isLeap(year)) //The year is a leap year + monthsInDays = list(-1,30,59,90,120,151,181,212,243,273,304,334) + else + monthsInDays = list(0,31,59,90,120,151,181,212,243,273,304,334) + + var/mDays = 0; + var/monthIndex = 0; + + for(var/m in monthsInDays) + monthIndex++ + if(tmpDays > m) + mDays = m + month = monthIndex + + day = tmpDays - mDays //Setup the date + + return "[year][seperator][((month < 10) ? "0[month]" : month)][seperator][((day < 10) ? "0[day]" : day)]" + +/proc/isLeap(y) + return ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0)) + + + +//Turns a Body_parts_covered bitfield into a list of organ/limb names. +//(I challenge you to find a use for this) +/proc/body_parts_covered2organ_names(bpc) + var/list/covered_parts = list() + + if(!bpc) + return 0 + + if(bpc & FULL_BODY) + covered_parts |= list("l_arm","r_arm","head","chest","l_leg","r_leg") + + else + if(bpc & HEAD) + covered_parts |= list("head") + if(bpc & CHEST) + covered_parts |= list("chest") + if(bpc & GROIN) + covered_parts |= list("chest") + + if(bpc & ARMS) + covered_parts |= list("l_arm","r_arm") + else + if(bpc & ARM_LEFT) + covered_parts |= list("l_arm") + if(bpc & ARM_RIGHT) + covered_parts |= list("r_arm") + + if(bpc & HANDS) + covered_parts |= list("l_arm","r_arm") + else + if(bpc & HAND_LEFT) + covered_parts |= list("l_arm") + if(bpc & HAND_RIGHT) + covered_parts |= list("r_arm") + + if(bpc & LEGS) + covered_parts |= list("l_leg","r_leg") + else + if(bpc & LEG_LEFT) + covered_parts |= list("l_leg") + if(bpc & LEG_RIGHT) + covered_parts |= list("r_leg") + + if(bpc & FEET) + covered_parts |= list("l_leg","r_leg") + else + if(bpc & FOOT_LEFT) + covered_parts |= list("l_leg") + if(bpc & FOOT_RIGHT) + covered_parts |= list("r_leg") + + return covered_parts + + + +//adapted from http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/ +/proc/heat2colour(temp) + return rgb(heat2colour_r(temp), heat2colour_g(temp), heat2colour_b(temp)) + + +/proc/heat2colour_r(temp) + temp /= 100 + if(temp <= 66) + . = 255 + else + . = max(0, min(255, 329.698727446 * (temp - 60) ** -0.1332047592)) + + +/proc/heat2colour_g(temp) + temp /= 100 + if(temp <= 66) + . = max(0, min(255, 99.4708025861 * log(temp) - 161.1195681661)) + else + . = max(0, min(255, 288.1221685293 * ((temp - 60) ** -0.075148492))) + + +/proc/heat2colour_b(temp) + temp /= 100 + if(temp >= 66) + . = 255 + else + if(temp <= 16) + . = 0 + else + . = max(0, min(255, 138.5177312231 * log(temp - 10) - 305.0447927307)) + +/proc/color2hex(color) //web colors + if(!color) + return "#000000" + + switch(color) + if("white") + return "#FFFFFF" + if("black") + return "#000000" + if("gray") + return "#808080" + if("brown") + return "#A52A2A" + if("red") + return "#FF0000" + if("darkred") + return "#8B0000" + if("crimson") + return "#DC143C" + if("orange") + return "#FFA500" + if("yellow") + return "#FFFF00" + if("green") + return "#008000" + if("lime") + return "#00FF00" + if("darkgreen") + return "#006400" + if("cyan") + return "#00FFFF" + if("blue") + return "#0000FF" + if("navy") + return "#000080" + if("teal") + return "#008080" + if("purple") + return "#800080" + if("indigo") + return "#4B0082" + else + return "#FFFFFF" + + +//This is a weird one: +//It returns a list of all var names found in the string +//These vars must be in the [var_name] format +//It's only a proc because it's used in more than one place + +//Takes a string and a datum +//The string is well, obviously the string being checked +//The datum is used as a source for var names, to check validity +//Otherwise every single word could technically be a variable! +/proc/string2listofvars(var/t_string, var/datum/var_source) + if(!t_string || !var_source) + return list() + + . = list() + + var/var_found = findtext(t_string,"\[") //Not the actual variables, just a generic "should we even bother" check + if(var_found) + //Find var names + + // "A dog said hi [name]!" + // splittext() --> list("A dog said hi ","name]!" + // jointext() --> "A dog said hi name]!" + // splittext() --> list("A","dog","said","hi","name]!") + + t_string = replacetext(t_string,"\[","\[ ")//Necessary to resolve "word[var_name]" scenarios + var/list/list_value = splittext(t_string,"\[") + var/intermediate_stage = jointext(list_value, null) + + list_value = splittext(intermediate_stage," ") + for(var/value in list_value) + if(findtext(value,"]")) + value = splittext(value,"]") //"name]!" --> list("name","!") + for(var/A in value) + if(var_source.vars.Find(A)) + . += A + +//assumes format #RRGGBB #rrggbb +/proc/color_hex2num(A) + if(!A) + return 0 + var/R = hex2num(copytext(A,2,4)) + var/G = hex2num(copytext(A,4,6)) + var/B = hex2num(copytext(A,6,0)) + return R+G+B + +//word of warning: using a matrix like this as a color value will simplify it back to a string after being set +/proc/color_hex2color_matrix(string) + var/length = length(string) + if(length != 7 && length != 9) + return color_matrix_identity() + var/r = hex2num(copytext(string, 2, 4))/255 + var/g = hex2num(copytext(string, 4, 6))/255 + var/b = hex2num(copytext(string, 6, 8))/255 + var/a = 1 + if(length == 9) + a = hex2num(copytext(string, 8, 10))/255 + if(!isnum(r) || !isnum(g) || !isnum(b) || !isnum(a)) + return color_matrix_identity() + return list(r,0,0,0, 0,g,0,0, 0,0,b,0, 0,0,0,a, 0,0,0,0) + +//will drop all values not on the diagonal +/proc/color_matrix2color_hex(list/the_matrix) + if(!istype(the_matrix) || the_matrix.len != 20) + return "#ffffffff" + return rgb(the_matrix[1]*255, the_matrix[6]*255, the_matrix[11]*255, the_matrix[16]*255) +>>>>>>> 6b8775f... Makes angle2dir() much more accurate (#30989) /proc/type2parent(child) var/string_type = "[child]" From c8e5928517e6d6e67b90ebe4bf138d94230d1aa3 Mon Sep 17 00:00:00 2001 From: Robustin Date: Thu, 5 Oct 2017 16:10:47 -0400 Subject: [PATCH 63/82] Emotes now shatter 80% less immersions (#31240) * Emote Checks by Default * Removes emote argument * More emote fixes * Overhauled emote check * Closed Spans --- code/datums/emotes.dm | 11 ++++++----- code/modules/mob/living/emote.dm | 30 ++++++++++++++++++------------ 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm index 455ec0f62a..88e6148c5f 100644 --- a/code/datums/emotes.dm +++ b/code/datums/emotes.dm @@ -42,7 +42,7 @@ I.trigger(key, L) if(!msg) - return FALSE + return user.log_message(msg, INDIVIDUAL_EMOTE_LOG) msg = "[user] " + msg @@ -91,21 +91,22 @@ /datum/emote/proc/select_param(mob/user, params) return replacetext(message_param, "%t", params) -/datum/emote/proc/can_run_emote(mob/user, help_check) +/datum/emote/proc/can_run_emote(mob/user, status_check = TRUE) . = TRUE if(!is_type_in_typecache(user, mob_type_allowed_typecache)) return FALSE if(is_type_in_typecache(user, mob_type_blacklist_typecache)) return FALSE - if(!help_check) + if(status_check) if(user.stat > stat_allowed || (user.status_flags & FAKEDEATH)) + to_chat(user, "You cannot [key] while unconscious.") return FALSE - if(restraint_check && user.restrained()) + if(restraint_check && (user.restrained() || user.buckled)) + to_chat(user, "You cannot [key] while restrained.") return FALSE if(user.reagents && user.reagents.has_reagent("mimesbane")) return FALSE - /datum/emote/sound var/sound //Sound to play when emote is called var/vary = FALSE //used for the honk borg emote diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index 9f31c5b055..bbe02a3f8e 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -29,6 +29,7 @@ key_third_person = "bows" message = "bows." message_param = "bows to %t." + restraint_check = TRUE /datum/emote/living/burp key = "burp" @@ -119,6 +120,7 @@ key = "flap" key_third_person = "flaps" message = "flaps their wings." + restraint_check = TRUE var/wing_time = 20 /datum/emote/living/flap/run_emote(mob/user, params) @@ -138,6 +140,7 @@ key = "aflap" key_third_person = "aflaps" message = "flaps their wings ANGRILY!" + restraint_check = TRUE wing_time = 10 /datum/emote/living/flip @@ -147,7 +150,7 @@ /datum/emote/living/flip/run_emote(mob/user, params) . = ..() - if(!.) + if(.) user.SpinAnimation(7,1) /datum/emote/living/frown @@ -454,7 +457,7 @@ if(e in keys) continue E = emote_list[e] - if(E.can_run_emote(user, TRUE)) + if(E.can_run_emote(user, status_check = FALSE)) keys += E.key keys = sortList(keys) @@ -481,18 +484,21 @@ /datum/emote/living/spin key = "spin" key_third_person = "spins" + restraint_check = TRUE /datum/emote/living/spin/run_emote(mob/user) - user.spin(20, 1) - if(iscyborg(user)) - var/mob/living/silicon/robot/R = user - if(R.buckled_mobs) - for(var/mob/M in R.buckled_mobs) - if(R.riding_datum) - R.riding_datum.force_dismount(M) - else - R.unbuckle_all_mobs() - ..() + . = ..() + if(.) + user.spin(20, 1) + if(iscyborg(user)) + var/mob/living/silicon/robot/R = user + if(R.buckled_mobs) + for(var/mob/M in R.buckled_mobs) + if(R.riding_datum) + R.riding_datum.force_dismount(M) + else + R.unbuckle_all_mobs() + /datum/emote/living/circle key = "circle" From b3243d59004945760137471caba66b4711a24a00 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Thu, 5 Oct 2017 16:31:34 -0400 Subject: [PATCH 65/82] Removes old ass belt.dm (#31317) --- .../objects/items/weapons/storage/belt.dm | 531 ------------------ 1 file changed, 531 deletions(-) delete mode 100644 code/game/objects/items/weapons/storage/belt.dm diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm deleted file mode 100644 index f8a020b677..0000000000 --- a/code/game/objects/items/weapons/storage/belt.dm +++ /dev/null @@ -1,531 +0,0 @@ -/obj/item/weapon/storage/belt - name = "belt" - desc = "Can hold various things." - icon = 'icons/obj/clothing/belts.dmi' - icon_state = "utilitybelt" - item_state = "utility" - slot_flags = SLOT_BELT - attack_verb = list("whipped", "lashed", "disciplined") - max_integrity = 300 - var/content_overlays = FALSE //If this is true, the belt will gain overlays based on what it's holding - -/obj/item/weapon/storage/belt/update_icon() - cut_overlays() - if(content_overlays) - for(var/obj/item/I in contents) - var/mutable_appearance/M = I.get_belt_overlay() - add_overlay(M) - ..() - -/obj/item/weapon/storage/belt/Initialize() - . = ..() - update_icon() - -/obj/item/weapon/storage/belt/utility - name = "toolbelt" //Carn: utility belt is nicer, but it bamboozles the text parsing. - desc = "Holds tools." - icon_state = "utilitybelt" - item_state = "utility" - can_hold = list( - /obj/item/weapon/crowbar, - /obj/item/weapon/screwdriver, - /obj/item/weapon/weldingtool, - /obj/item/weapon/wirecutters, - /obj/item/weapon/wrench, - /obj/item/device/multitool, - /obj/item/device/flashlight, - /obj/item/stack/cable_coil, - /obj/item/device/t_scanner, - /obj/item/device/analyzer, - /obj/item/weapon/extinguisher/mini, - /obj/item/device/radio, - /obj/item/clothing/gloves - ) - content_overlays = TRUE - -/obj/item/weapon/storage/belt/utility/chief - name = "\improper Chief Engineer's toolbelt" //"the Chief Engineer's toolbelt", because "Chief Engineer's toolbelt" is not a proper noun - desc = "Holds tools, looks snazzy." - icon_state = "utilitybelt_ce" - item_state = "utility_ce" - -/obj/item/weapon/storage/belt/utility/chief/full/PopulateContents() - new /obj/item/weapon/screwdriver/power(src) - new /obj/item/weapon/crowbar/power(src) - new /obj/item/weapon/weldingtool/experimental(src)//This can be changed if this is too much - new /obj/item/device/multitool(src) - new /obj/item/stack/cable_coil(src,30,pick("red","yellow","orange")) - new /obj/item/weapon/extinguisher/mini(src) - new /obj/item/device/analyzer(src) - //much roomier now that we've managed to remove two tools - - -/obj/item/weapon/storage/belt/utility/full/PopulateContents() - new /obj/item/weapon/screwdriver(src) - new /obj/item/weapon/wrench(src) - new /obj/item/weapon/weldingtool(src) - new /obj/item/weapon/crowbar(src) - new /obj/item/weapon/wirecutters(src) - new /obj/item/device/multitool(src) - new /obj/item/stack/cable_coil(src,30,pick("red","yellow","orange")) - -/obj/item/weapon/storage/belt/utility/full/engi/PopulateContents() - new /obj/item/weapon/screwdriver(src) - new /obj/item/weapon/wrench(src) - new /obj/item/weapon/weldingtool/largetank(src) - new /obj/item/weapon/crowbar(src) - new /obj/item/weapon/wirecutters(src) - new /obj/item/device/multitool(src) - new /obj/item/stack/cable_coil(src,30,pick("red","yellow","orange")) - - -/obj/item/weapon/storage/belt/utility/atmostech/PopulateContents() - new /obj/item/weapon/screwdriver(src) - new /obj/item/weapon/wrench(src) - new /obj/item/weapon/weldingtool(src) - new /obj/item/weapon/crowbar(src) - new /obj/item/weapon/wirecutters(src) - new /obj/item/device/t_scanner(src) - new /obj/item/weapon/extinguisher/mini(src) - - -/obj/item/weapon/storage/belt/utility/servant/PopulateContents() - new /obj/item/weapon/screwdriver/brass(src) - new /obj/item/weapon/wirecutters/brass(src) - new /obj/item/weapon/wrench/brass(src) - new /obj/item/weapon/crowbar/brass(src) - new /obj/item/weapon/weldingtool/experimental/brass(src) - new /obj/item/device/multitool(src) - new /obj/item/stack/cable_coil(src, 30, "yellow") - - -/obj/item/weapon/storage/belt/medical - name = "medical belt" - desc = "Can hold various medical equipment." - icon_state = "medicalbelt" - item_state = "medical" - max_w_class = WEIGHT_CLASS_BULKY - can_hold = list( - /obj/item/device/healthanalyzer, - /obj/item/weapon/dnainjector, - /obj/item/weapon/reagent_containers/dropper, - /obj/item/weapon/reagent_containers/glass/beaker, - /obj/item/weapon/reagent_containers/glass/bottle, - /obj/item/weapon/reagent_containers/pill, - /obj/item/weapon/reagent_containers/syringe, - /obj/item/weapon/lighter, - /obj/item/weapon/storage/fancy/cigarettes, - /obj/item/weapon/storage/pill_bottle, - /obj/item/stack/medical, - /obj/item/device/flashlight/pen, - /obj/item/weapon/extinguisher/mini, - /obj/item/weapon/reagent_containers/hypospray, - /obj/item/device/sensor_device, - /obj/item/device/radio, - /obj/item/clothing/gloves/, - /obj/item/weapon/lazarus_injector, - /obj/item/weapon/bikehorn/rubberducky, - /obj/item/clothing/mask/surgical, - /obj/item/clothing/mask/breath, - /obj/item/clothing/mask/breath/medical, - /obj/item/weapon/surgical_drapes, //for true paramedics - /obj/item/weapon/scalpel, - /obj/item/weapon/circular_saw, - /obj/item/weapon/surgicaldrill, - /obj/item/weapon/retractor, - /obj/item/weapon/cautery, - /obj/item/weapon/hemostat, - /obj/item/device/geiger_counter, - /obj/item/clothing/neck/stethoscope, - /obj/item/weapon/stamp, - /obj/item/clothing/glasses, - /obj/item/weapon/wrench/medical, - /obj/item/clothing/mask/muzzle, - /obj/item/weapon/storage/bag/chemistry, - /obj/item/weapon/storage/bag/bio, - /obj/item/weapon/reagent_containers/blood, - /obj/item/weapon/tank/internals/emergency_oxygen - ) - - -/obj/item/weapon/storage/belt/security - name = "security belt" - desc = "Can hold security gear like handcuffs and flashes." - icon_state = "securitybelt" - item_state = "security"//Could likely use a better one. - storage_slots = 5 - max_w_class = WEIGHT_CLASS_NORMAL //Because the baton wouldn't fit otherwise. - Neerti - can_hold = list( - /obj/item/weapon/melee/baton, - /obj/item/weapon/melee/classic_baton, - /obj/item/weapon/grenade, - /obj/item/weapon/reagent_containers/spray/pepper, - /obj/item/weapon/restraints/handcuffs, - /obj/item/device/assembly/flash/handheld, - /obj/item/clothing/glasses, - /obj/item/ammo_casing/shotgun, - /obj/item/ammo_box, - /obj/item/weapon/reagent_containers/food/snacks/donut, - /obj/item/weapon/reagent_containers/food/snacks/donut/jelly, - /obj/item/weapon/kitchen/knife/combat, - /obj/item/device/flashlight/seclite, - /obj/item/weapon/melee/classic_baton/telescopic, - /obj/item/device/radio, - /obj/item/clothing/gloves/, - /obj/item/weapon/restraints/legcuffs/bola - ) - content_overlays = TRUE - -/obj/item/weapon/storage/belt/security/full/PopulateContents() - new /obj/item/weapon/reagent_containers/spray/pepper(src) - new /obj/item/weapon/restraints/handcuffs(src) - new /obj/item/weapon/grenade/flashbang(src) - new /obj/item/device/assembly/flash/handheld(src) - new /obj/item/weapon/melee/baton/loaded(src) - update_icon() - - -/obj/item/weapon/storage/belt/mining - name = "explorer's webbing" - desc = "A versatile chest rig, cherished by miners and hunters alike." - icon_state = "explorer1" - item_state = "explorer1" - storage_slots = 6 - w_class = WEIGHT_CLASS_BULKY - max_w_class = WEIGHT_CLASS_BULKY //Pickaxes are big. - max_combined_w_class = 20 //Not an issue with this whitelist, probably. - can_hold = list( - /obj/item/weapon/crowbar, - /obj/item/weapon/screwdriver, - /obj/item/weapon/weldingtool, - /obj/item/weapon/wirecutters, - /obj/item/weapon/wrench, - /obj/item/device/flashlight, - /obj/item/stack/cable_coil, - /obj/item/device/analyzer, - /obj/item/weapon/extinguisher/mini, - /obj/item/device/radio, - /obj/item/clothing/gloves, - /obj/item/weapon/resonator, - /obj/item/device/mining_scanner, - /obj/item/weapon/pickaxe, - /obj/item/stack/sheet/animalhide, - /obj/item/stack/sheet/sinew, - /obj/item/stack/sheet/bone, - /obj/item/weapon/lighter, - /obj/item/weapon/storage/fancy/cigarettes, - /obj/item/weapon/reagent_containers/food/drinks/bottle, - /obj/item/stack/medical, - /obj/item/weapon/kitchen/knife, - /obj/item/weapon/reagent_containers/hypospray, - /obj/item/device/gps, - /obj/item/weapon/storage/bag/ore, - /obj/item/weapon/survivalcapsule, - /obj/item/device/t_scanner/adv_mining_scanner, - /obj/item/weapon/reagent_containers/pill, - /obj/item/weapon/storage/pill_bottle, - /obj/item/weapon/ore, - /obj/item/weapon/reagent_containers/food/drinks, - /obj/item/organ/regenerative_core, - /obj/item/device/wormhole_jaunter, - /obj/item/weapon/storage/bag/plants, - /obj/item/stack/marker_beacon - ) - - -/obj/item/weapon/storage/belt/mining/vendor - contents = newlist(/obj/item/weapon/survivalcapsule) - -/obj/item/weapon/storage/belt/mining/alt - icon_state = "explorer2" - item_state = "explorer2" - -/obj/item/weapon/storage/belt/mining/primitive - name = "hunter's belt" - desc = "A versatile belt, woven from sinew." - storage_slots = 5 - icon_state = "ebelt" - item_state = "ebelt" - -/obj/item/weapon/storage/belt/soulstone - name = "soul stone belt" - desc = "Designed for ease of access to the shards during a fight, as to not let a single enemy spirit slip away" - icon_state = "soulstonebelt" - item_state = "soulstonebelt" - storage_slots = 6 - can_hold = list( - /obj/item/device/soulstone - ) - -/obj/item/weapon/storage/belt/soulstone/full/PopulateContents() - for(var/i in 1 to 6) - new /obj/item/device/soulstone(src) - -/obj/item/weapon/storage/belt/champion - name = "championship belt" - desc = "Proves to the world that you are the strongest!" - icon_state = "championbelt" - item_state = "champion" - materials = list(MAT_GOLD=400) - storage_slots = 1 - can_hold = list( - /obj/item/clothing/mask/luchador - ) - -/obj/item/weapon/storage/belt/military - name = "chest rig" - desc = "A set of tactical webbing worn by Syndicate boarding parties." - icon_state = "militarywebbing" - item_state = "militarywebbing" - max_w_class = WEIGHT_CLASS_SMALL - -/obj/item/weapon/storage/belt/military/abductor - name = "agent belt" - desc = "A belt used by abductor agents." - icon = 'icons/obj/abductor.dmi' - icon_state = "belt" - item_state = "security" - -/obj/item/weapon/storage/belt/military/abductor/full/PopulateContents() - new /obj/item/weapon/screwdriver/abductor(src) - new /obj/item/weapon/wrench/abductor(src) - new /obj/item/weapon/weldingtool/abductor(src) - new /obj/item/weapon/crowbar/abductor(src) - new /obj/item/weapon/wirecutters/abductor(src) - new /obj/item/device/multitool/abductor(src) - new /obj/item/stack/cable_coil(src,30,"white") - - -/obj/item/weapon/storage/belt/military/army - name = "army belt" - desc = "A belt used by military forces." - icon_state = "grenadebeltold" - item_state = "security" - -/obj/item/weapon/storage/belt/military/assault - name = "assault belt" - desc = "A tactical assault belt." - icon_state = "assaultbelt" - item_state = "security" - storage_slots = 6 - -/obj/item/weapon/storage/belt/grenade - name = "grenadier belt" - desc = "A belt for holding grenades." - icon_state = "grenadebeltnew" - item_state = "security" - max_w_class = WEIGHT_CLASS_BULKY - display_contents_with_number = TRUE - storage_slots = 30 - max_combined_w_class = 60 //needs to be this high - can_hold = list( - /obj/item/weapon/grenade, - /obj/item/weapon/screwdriver, - /obj/item/weapon/lighter, - /obj/item/device/multitool, - /obj/item/weapon/reagent_containers/food/drinks/bottle/molotov, - /obj/item/weapon/grenade/plastic/c4, - ) -/obj/item/weapon/storage/belt/grenade/full/PopulateContents() - new /obj/item/weapon/grenade/flashbang(src) - new /obj/item/weapon/grenade/smokebomb(src) - new /obj/item/weapon/grenade/smokebomb(src) - new /obj/item/weapon/grenade/smokebomb(src) - new /obj/item/weapon/grenade/smokebomb(src) - new /obj/item/weapon/grenade/empgrenade(src) - new /obj/item/weapon/grenade/empgrenade(src) - new /obj/item/weapon/grenade/syndieminibomb/concussion/frag(src) - new /obj/item/weapon/grenade/syndieminibomb/concussion/frag(src) - new /obj/item/weapon/grenade/syndieminibomb/concussion/frag(src) - new /obj/item/weapon/grenade/syndieminibomb/concussion/frag(src) - new /obj/item/weapon/grenade/syndieminibomb/concussion/frag(src) - new /obj/item/weapon/grenade/syndieminibomb/concussion/frag(src) - new /obj/item/weapon/grenade/syndieminibomb/concussion/frag(src) - new /obj/item/weapon/grenade/syndieminibomb/concussion/frag(src) - new /obj/item/weapon/grenade/syndieminibomb/concussion/frag(src) - new /obj/item/weapon/grenade/syndieminibomb/concussion/frag(src) - new /obj/item/weapon/grenade/gluon(src) - new /obj/item/weapon/grenade/gluon(src) - new /obj/item/weapon/grenade/gluon(src) - new /obj/item/weapon/grenade/gluon(src) - new /obj/item/weapon/grenade/chem_grenade/incendiary(src) - new /obj/item/weapon/grenade/chem_grenade/incendiary(src) - new /obj/item/weapon/grenade/chem_grenade/facid(src) - new /obj/item/weapon/grenade/syndieminibomb(src) - new /obj/item/weapon/grenade/syndieminibomb(src) - new /obj/item/weapon/screwdriver(src) - new /obj/item/device/multitool(src) - -/obj/item/weapon/storage/belt/wands - name = "wand belt" - desc = "A belt designed to hold various rods of power. A veritable fanny pack of exotic magic." - icon_state = "soulstonebelt" - item_state = "soulstonebelt" - storage_slots = 6 - can_hold = list( - /obj/item/weapon/gun/magic/wand - ) - -/obj/item/weapon/storage/belt/wands/full/PopulateContents() - new /obj/item/weapon/gun/magic/wand/death(src) - new /obj/item/weapon/gun/magic/wand/resurrection(src) - new /obj/item/weapon/gun/magic/wand/polymorph(src) - new /obj/item/weapon/gun/magic/wand/teleport(src) - new /obj/item/weapon/gun/magic/wand/door(src) - new /obj/item/weapon/gun/magic/wand/fireball(src) - - for(var/obj/item/weapon/gun/magic/wand/W in contents) //All wands in this pack come in the best possible condition - W.max_charges = initial(W.max_charges) - W.charges = W.max_charges - -/obj/item/weapon/storage/belt/janitor - name = "janibelt" - desc = "A belt used to hold most janitorial supplies." - icon_state = "janibelt" - item_state = "janibelt" - storage_slots = 6 - max_w_class = WEIGHT_CLASS_BULKY // Set to this so the light replacer can fit. - can_hold = list( - /obj/item/weapon/grenade/chem_grenade, - /obj/item/device/lightreplacer, - /obj/item/device/flashlight, - /obj/item/weapon/reagent_containers/spray, - /obj/item/weapon/soap, - /obj/item/weapon/holosign_creator, - /obj/item/key/janitor, - /obj/item/clothing/gloves - ) - -/obj/item/weapon/storage/belt/bandolier - name = "bandolier" - desc = "A bandolier for holding shotgun ammunition." - icon_state = "bandolier" - item_state = "bandolier" - storage_slots = 18 - display_contents_with_number = TRUE - can_hold = list( - /obj/item/ammo_casing/shotgun - ) - -/obj/item/weapon/storage/belt/holster - name = "shoulder holster" - desc = "A holster to carry a handgun and ammo. WARNING: Badasses only." - icon_state = "holster" - item_state = "holster" - storage_slots = 3 - max_w_class = WEIGHT_CLASS_NORMAL - can_hold = list( - /obj/item/weapon/gun/ballistic/automatic/pistol, - /obj/item/weapon/gun/ballistic/revolver, - /obj/item/ammo_box, - ) - alternate_worn_layer = UNDER_SUIT_LAYER - -/obj/item/weapon/storage/belt/holster/full/PopulateContents() - new /obj/item/weapon/gun/ballistic/revolver/detective(src) - new /obj/item/ammo_box/c38(src) - new /obj/item/ammo_box/c38(src) - -/obj/item/weapon/storage/belt/fannypack - name = "fannypack" - desc = "A dorky fannypack for keeping small items in." - icon_state = "fannypack_leather" - item_state = "fannypack_leather" - storage_slots = 3 - max_w_class = WEIGHT_CLASS_SMALL - -/obj/item/weapon/storage/belt/fannypack/black - name = "black fannypack" - icon_state = "fannypack_black" - item_state = "fannypack_black" - -/obj/item/weapon/storage/belt/fannypack/red - name = "red fannypack" - icon_state = "fannypack_red" - item_state = "fannypack_red" - -/obj/item/weapon/storage/belt/fannypack/purple - name = "purple fannypack" - icon_state = "fannypack_purple" - item_state = "fannypack_purple" - -/obj/item/weapon/storage/belt/fannypack/blue - name = "blue fannypack" - icon_state = "fannypack_blue" - item_state = "fannypack_blue" - -/obj/item/weapon/storage/belt/fannypack/orange - name = "orange fannypack" - icon_state = "fannypack_orange" - item_state = "fannypack_orange" - -/obj/item/weapon/storage/belt/fannypack/white - name = "white fannypack" - icon_state = "fannypack_white" - item_state = "fannypack_white" - -/obj/item/weapon/storage/belt/fannypack/green - name = "green fannypack" - icon_state = "fannypack_green" - item_state = "fannypack_green" - -/obj/item/weapon/storage/belt/fannypack/pink - name = "pink fannypack" - icon_state = "fannypack_pink" - item_state = "fannypack_pink" - -/obj/item/weapon/storage/belt/fannypack/cyan - name = "cyan fannypack" - icon_state = "fannypack_cyan" - item_state = "fannypack_cyan" - -/obj/item/weapon/storage/belt/fannypack/yellow - name = "yellow fannypack" - icon_state = "fannypack_yellow" - item_state = "fannypack_yellow" - -/obj/item/weapon/storage/belt/sabre - name = "sabre sheath" - desc = "An ornate sheath designed to hold an officer's blade." - icon_state = "sheath" - item_state = "sheath" - storage_slots = 1 - rustle_jimmies = FALSE - w_class = WEIGHT_CLASS_BULKY - max_w_class = WEIGHT_CLASS_BULKY - can_hold = list( - /obj/item/weapon/melee/sabre - ) - -/obj/item/weapon/storage/belt/sabre/examine(mob/user) - ..() - if(contents.len) - to_chat(user, "Alt-click it to quickly draw the blade.") - -/obj/item/weapon/storage/belt/sabre/AltClick(mob/user) - if(!ishuman(user) || !user.canUseTopic(src, be_close=TRUE)) - return - if(contents.len) - var/obj/item/I = contents[1] - user.visible_message("[user] takes [I] out of [src].", "You take [I] out of [src].",\ - ) - user.put_in_hands(I) - update_icon() - else - to_chat(user, "[src] is empty.") - -/obj/item/weapon/storage/belt/sabre/update_icon() - icon_state = "sheath" - item_state = "sheath" - if(contents.len) - icon_state += "-sabre" - item_state += "-sabre" - if(loc && isliving(loc)) - var/mob/living/L = loc - L.regenerate_icons() - ..() - - -/obj/item/weapon/storage/belt/sabre/PopulateContents() - new /obj/item/weapon/melee/sabre(src) - update_icon() From 645d8fdc7cf1d691addd8c67ede26c8923430a45 Mon Sep 17 00:00:00 2001 From: oranges Date: Fri, 6 Oct 2017 11:42:44 +1300 Subject: [PATCH 67/82] Merge pull request #31315 from tgstation/Cyberboss-patch-3 Removes shitty sleep from area/Entered --- code/game/area/areas.dm | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index b062b8f054..222ce73f92 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -449,10 +449,11 @@ GLOBAL_LIST_EMPTY(teleportlocs) if(!L.client.played) SEND_SOUND(L, sound(sound, repeat = 0, wait = 0, volume = 25, channel = CHANNEL_AMBIENCE)) - L.client.played = 1 - sleep(600) //ewww - this is very very bad - if(L.&& L.client) - L.client.played = 0 + L.client.played = TRUE + addtimer(CALLBACK(L.client, /client/proc/ResetAmbiencePlayed), 600) + +/client/proc/ResetAmbiencePlayed() + played = FALSE /atom/proc/has_gravity(turf/T) if(!T || !isturf(T)) From 13eedff76702d3729517eca6a23132c4ad9fd1b6 Mon Sep 17 00:00:00 2001 From: The-clown-known-as-Pepe Date: Fri, 6 Oct 2017 00:47:49 +0200 Subject: [PATCH 69/82] Fixes rubber shot after unintended nerf. (#31316) * Update bullets.dm * fix * refactor * Update ammo_casings.dm --- code/modules/projectiles/projectile/bullets.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 8395ef4d83..cf38d5bfff 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -8,7 +8,7 @@ hitsound_wall = "ricochet" impact_effect_type = /obj/effect/temp_visual/impact_effect -/obj/item/projectile/bullet/pellet/Range() +/obj/item/projectile/bullet/pellet/shotgun_buckshot/Range() ..() damage -= 0.75 if(damage < 0) From 648040de9c1866f582847569c9f92d27c067da05 Mon Sep 17 00:00:00 2001 From: vuonojenmustaturska Date: Fri, 6 Oct 2017 01:58:25 +0300 Subject: [PATCH 71/82] Makes a couple of atmos procs a tiny bit faster, removes /datum/gas_mixture/thermal_energy() (#31321) * Atmos stuff * moved the define --- code/__DEFINES/atmospherics.dm | 2 ++ code/modules/atmospherics/gasmixtures/gas_mixture.dm | 5 +---- code/modules/atmospherics/gasmixtures/reactions.dm | 4 ++-- code/modules/atmospherics/machinery/datum_pipeline.dm | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm index a79850b04f..c6ca2cf0ec 100644 --- a/code/__DEFINES/atmospherics.dm +++ b/code/__DEFINES/atmospherics.dm @@ -174,3 +174,5 @@ #define LAVALAND_EQUIPMENT_EFFECT_PRESSURE 50 //what pressure you have to be under to increase the effect of equipment meant for lavaland #define LAVALAND_DEFAULT_ATMOS "o2=14;n2=23;TEMP=300" + +#define THERMAL_ENERGY(gas) (gas.temperature * gas.heat_capacity()) \ No newline at end of file diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index ad1ba46d86..ac8349f5f7 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -119,9 +119,6 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) /datum/gas_mixture/proc/return_volume() //liters return max(0, volume) -/datum/gas_mixture/proc/thermal_energy() //joules - return temperature * heat_capacity() - /datum/gas_mixture/proc/archive() //Update archived versions of variables //Returns: 1 in all cases @@ -424,7 +421,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) var/list/cached_gases = gases var/temp = temperature - var/ener = thermal_energy() + var/ener = THERMAL_ENERGY(src) reaction_loop: for(var/r in SSair.gas_reactions) diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm index a37e4d61c4..abbfcf8924 100644 --- a/code/modules/atmospherics/gasmixtures/reactions.dm +++ b/code/modules/atmospherics/gasmixtures/reactions.dm @@ -199,13 +199,13 @@ var/old_heat_capacity = air.heat_capacity() var/carbon_efficency = min(cached_gases["plasma"][MOLES]/cached_gases["co2"][MOLES],MAX_CARBON_EFFICENCY) - var/reaction_energy = air.thermal_energy() + var/reaction_energy = THERMAL_ENERGY(air) var/moles_impurities = air.total_moles()-(cached_gases["plasma"][MOLES]+cached_gases["co2"][MOLES]) var/plasma_fused = (PLASMA_FUSED_COEFFICENT*carbon_efficency)*(temperature/PLASMA_BINDING_ENERGY) var/carbon_catalyzed = (CARBON_CATALYST_COEFFICENT*carbon_efficency)*(temperature/PLASMA_BINDING_ENERGY) var/oxygen_added = carbon_catalyzed - var/nitrogen_added = (plasma_fused-oxygen_added)-(air.thermal_energy()/PLASMA_BINDING_ENERGY) + var/nitrogen_added = (plasma_fused-oxygen_added)-(THERMAL_ENERGY(air)/PLASMA_BINDING_ENERGY) reaction_energy = max(reaction_energy+((carbon_efficency*cached_gases["plasma"][MOLES])/((moles_impurities/carbon_efficency)+2)*10)+((plasma_fused/(moles_impurities/carbon_efficency))*PLASMA_BINDING_ENERGY),0) diff --git a/code/modules/atmospherics/machinery/datum_pipeline.dm b/code/modules/atmospherics/machinery/datum_pipeline.dm index 11a7881a98..ad7fdb921a 100644 --- a/code/modules/atmospherics/machinery/datum_pipeline.dm +++ b/code/modules/atmospherics/machinery/datum_pipeline.dm @@ -232,7 +232,7 @@ total_gas_mixture.merge(G) - total_thermal_energy += G.thermal_energy() + total_thermal_energy += THERMAL_ENERGY(G) total_heat_capacity += G.heat_capacity() total_gas_mixture.temperature = total_heat_capacity ? total_thermal_energy/total_heat_capacity : 0 From 4d06415a4bef979ff3fa462a64df5b84556220ba Mon Sep 17 00:00:00 2001 From: Joan Lung <3886584+ChangelingRain@users.noreply.github.com> Date: Thu, 5 Oct 2017 20:21:33 -0400 Subject: [PATCH 73/82] Makes Ocular Wardens effective again (#31325) * Makes Ocular Wardens effective again * get that, too --- .../clock_cult/clock_structures/ocular_warden.dm | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/code/game/gamemodes/clock_cult/clock_structures/ocular_warden.dm b/code/game/gamemodes/clock_cult/clock_structures/ocular_warden.dm index cdff486eea..364c967ae9 100644 --- a/code/game/gamemodes/clock_cult/clock_structures/ocular_warden.dm +++ b/code/game/gamemodes/clock_cult/clock_structures/ocular_warden.dm @@ -11,7 +11,7 @@ break_message = "The warden's eye gives a glare of utter hate before falling dark!" debris = list(/obj/item/clockwork/component/belligerent_eye/blind_eye = 1) resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF - var/damage_per_tick = 2.5 + var/damage_per_tick = 3 var/sight_range = 3 var/atom/movable/target var/list/idle_messages = list(" sulkily glares around.", " lazily drifts from side to side.", " looks around for something to burn.", " slowly turns in circles.") @@ -141,8 +141,12 @@ . = 1 if(target) for(var/turf/T in getline(src, target)) + if(T.density) + . -= 0.1 + continue for(var/obj/structure/O in T) - if(O.density) - . -= 0.15 + if(O != src && O.density) + . -= 0.1 + break . -= (get_dist(src, target) * 0.05) . = max(., 0.1) //The lowest damage a warden can do is 10% of its normal amount (0.25 by default) From 52c57543cba0b903184ebee03c267b279ed5bb7a Mon Sep 17 00:00:00 2001 From: LetterJay Date: Thu, 5 Oct 2017 22:43:08 -0500 Subject: [PATCH 75/82] Update misc_special.dm --- code/modules/clothing/head/misc_special.dm | 182 --------------------- 1 file changed, 182 deletions(-) diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index d14ef81806..4a86008ad2 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -1,184 +1,3 @@ -<<<<<<< HEAD -/* - * Contents: - * Welding mask - * Cakehat - * Ushanka - * Pumpkin head - * Kitty ears - * Cardborg disguise - */ - -/* - * Welding mask - */ -/obj/item/clothing/head/welding - name = "welding helmet" - desc = "A head-mounted face cover designed to protect the wearer completely from space-arc eye." - icon_state = "welding" - flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH - item_state = "welding" - materials = list(MAT_METAL=1750, MAT_GLASS=400) -// var/up = 0 - flash_protect = 2 - tint = 2 - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 60) - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE - actions_types = list(/datum/action/item_action/toggle) - visor_flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE - visor_flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH - resistance_flags = FIRE_PROOF - -/obj/item/clothing/head/welding/attack_self(mob/user) - weldingvisortoggle(user) - - -/* - * Cakehat - */ -/obj/item/clothing/head/hardhat/cakehat - name = "cakehat" - desc = "You put the cake on your head. Brilliant." - icon_state = "hardhat0_cakehat" - item_state = "hardhat0_cakehat" - item_color = "cakehat" - hitsound = 'sound/weapons/tap.ogg' - flags_inv = HIDEEARS|HIDEHAIR - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0) - brightness_on = 2 //luminosity when on - flags_cover = HEADCOVERSEYES - heat = 100 - -/obj/item/clothing/head/hardhat/cakehat/process() - var/turf/location = src.loc - if(ishuman(location)) - var/mob/living/carbon/human/M = location - if(M.is_holding(src) || M.head == src) - location = M.loc - - if(isturf(location)) - location.hotspot_expose(700, 1) - -/obj/item/clothing/head/hardhat/cakehat/turn_on() - ..() - force = 2 - throwforce = 2 - damtype = BURN - hitsound = 'sound/items/welder.ogg' - START_PROCESSING(SSobj, src) - -/obj/item/clothing/head/hardhat/cakehat/turn_off() - ..() - force = 0 - throwforce = 0 - damtype = BRUTE - hitsound = 'sound/weapons/tap.ogg' - STOP_PROCESSING(SSobj, src) - -/obj/item/clothing/head/hardhat/cakehat/is_hot() - return on * heat -/* - * Ushanka - */ -/obj/item/clothing/head/ushanka - name = "ushanka" - desc = "Perfect for winter in Siberia, da?" - icon_state = "ushankadown" - item_state = "ushankadown" - flags_inv = HIDEEARS|HIDEHAIR - var/earflaps = 1 - cold_protection = HEAD - min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT - - dog_fashion = /datum/dog_fashion/head/ushanka - -/obj/item/clothing/head/ushanka/attack_self(mob/user) - if(earflaps) - src.icon_state = "ushankaup" - src.item_state = "ushankaup" - earflaps = 0 - to_chat(user, "You raise the ear flaps on the ushanka.") - else - src.icon_state = "ushankadown" - src.item_state = "ushankadown" - earflaps = 1 - to_chat(user, "You lower the ear flaps on the ushanka.") - -/* - * Pumpkin head - */ -/obj/item/clothing/head/hardhat/pumpkinhead - name = "carved pumpkin" - desc = "A jack o' lantern! Believed to ward off evil spirits." - icon_state = "hardhat0_pumpkin" - item_state = "hardhat0_pumpkin" - item_color = "pumpkin" - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0) - brightness_on = 2 //luminosity when on - flags_cover = HEADCOVERSEYES - -/* - * Kitty ears - */ -/obj/item/clothing/head/kitty - name = "kitty ears" - desc = "A pair of kitty ears. Meow!" - icon_state = "kitty" - color = "#999999" - dynamic_hair_suffix = "" - - dog_fashion = /datum/dog_fashion/head/kitty - -/obj/item/clothing/head/kitty/equipped(mob/living/carbon/human/user, slot) - if(ishuman(user) && slot == slot_head) - update_icon(user) - user.update_inv_head() //Color might have been changed by update_icon. - ..() - -/obj/item/clothing/head/kitty/update_icon(mob/living/carbon/human/user) - if(ishuman(user)) - add_atom_colour("#[user.hair_color]", FIXED_COLOUR_PRIORITY) - -/obj/item/clothing/head/kitty/genuine - desc = "A pair of kitty ears. A tag on the inside says \"Hand made from real cats.\"" - - -/obj/item/clothing/head/hardhat/reindeer - name = "novelty reindeer hat" - desc = "Some fake antlers and a very fake red nose." - icon_state = "hardhat0_reindeer" - item_state = "hardhat0_reindeer" - item_color = "reindeer" - flags_inv = 0 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0) - brightness_on = 1 //luminosity when on - dynamic_hair_suffix = "" - - dog_fashion = /datum/dog_fashion/head/reindeer - -/obj/item/clothing/head/cardborg - name = "cardborg helmet" - desc = "A helmet made out of a box." - icon_state = "cardborg_h" - item_state = "cardborg_h" - flags_cover = HEADCOVERSEYES - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR - - dog_fashion = /datum/dog_fashion/head/cardborg - -/obj/item/clothing/head/cardborg/equipped(mob/living/user, slot) - ..() - if(ishuman(user) && slot == slot_head) - var/mob/living/carbon/human/H = user - if(istype(H.wear_suit, /obj/item/clothing/suit/cardborg)) - var/obj/item/clothing/suit/cardborg/CB = H.wear_suit - CB.disguise(user, src) - -/obj/item/clothing/head/cardborg/dropped(mob/living/user) - ..() - user.remove_alt_appearance("standard_borg_disguise") -======= /* * Contents: * Welding mask @@ -400,4 +219,3 @@ hair_style = pick(GLOB.hair_styles_list - "Bald") //Don't want invisible wig hair_color = "#[random_short_color()]" . = ..() ->>>>>>> d17d66f... Adds wigs (#31304) From d50c1034b92bc1525694c7be178b93b1b6b763ae Mon Sep 17 00:00:00 2001 From: LetterJay Date: Thu, 5 Oct 2017 22:44:50 -0500 Subject: [PATCH 76/82] Update type2type.dm --- code/__HELPERS/type2type.dm | 615 +++++------------------------------- 1 file changed, 74 insertions(+), 541 deletions(-) diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index ab06de1b8b..75985f9c2e 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -1,546 +1,80 @@ -/* - * Holds procs designed to change one type of value, into another. - * Contains: - * hex2num & num2hex - * file2list - * angle2dir - * angle2text - * worldtime2text - * text2dir_extended & dir2text_short - */ - -//Returns an integer given a hex input, supports negative values "-ff" -//skips preceding invalid characters -//breaks when hittin invalid characters thereafter -/proc/hex2num(hex) - . = 0 - if(istext(hex)) - var/negative = 0 - var/len = length(hex) - for(var/i=1, i<=len, i++) - var/num = text2ascii(hex,i) - switch(num) - if(48 to 57) - num -= 48 //0-9 - if(97 to 102) - num -= 87 //a-f - if(65 to 70) - num -= 55 //A-F - if(45) - negative = 1//- - else - if(num) - break - else - continue - . *= 16 - . += num - if(negative) - . *= -1 - return . - -//Returns the hex value of a decimal number -//len == length of returned string -//if len < 0 then the returned string will be as long as it needs to be to contain the data -//Only supports positive numbers -//if an invalid number is provided, it assumes num==0 -//Note, unlike previous versions, this one works from low to high <-- that way -/proc/num2hex(num, len=2) - if(!isnum(num)) - num = 0 - num = round(abs(num)) - . = "" - var/i=0 - while(1) - if(len<=0) - if(!num) - break - else - if(i>=len) - break - var/remainder = num/16 - num = round(remainder) - remainder = (remainder - num) * 16 - switch(remainder) - if(9,8,7,6,5,4,3,2,1) - . = "[remainder]" + . - if(10,11,12,13,14,15) - . = ascii2text(remainder+87) + . - else - . = "0" + . - i++ - return . - -//Splits the text of a file at seperator and returns them in a list. +/* + * Holds procs designed to change one type of value, into another. + * Contains: + * hex2num & num2hex + * file2list + * angle2dir + * angle2text + * worldtime2text + * text2dir_extended & dir2text_short + */ + +//Returns an integer given a hex input, supports negative values "-ff" +//skips preceding invalid characters +//breaks when hittin invalid characters thereafter +/proc/hex2num(hex) + . = 0 + if(istext(hex)) + var/negative = 0 + var/len = length(hex) + for(var/i=1, i<=len, i++) + var/num = text2ascii(hex,i) + switch(num) + if(48 to 57) + num -= 48 //0-9 + if(97 to 102) + num -= 87 //a-f + if(65 to 70) + num -= 55 //A-F + if(45) + negative = 1//- + else + if(num) + break + else + continue + . *= 16 + . += num + if(negative) + . *= -1 + return . + +//Returns the hex value of a decimal number +//len == length of returned string +//if len < 0 then the returned string will be as long as it needs to be to contain the data +//Only supports positive numbers +//if an invalid number is provided, it assumes num==0 +//Note, unlike previous versions, this one works from low to high <-- that way +/proc/num2hex(num, len=2) + if(!isnum(num)) + num = 0 + num = round(abs(num)) + . = "" + var/i=0 + while(1) + if(len<=0) + if(!num) + break + else + if(i>=len) + break + var/remainder = num/16 + num = round(remainder) + remainder = (remainder - num) * 16 + switch(remainder) + if(9,8,7,6,5,4,3,2,1) + . = "[remainder]" + . + if(10,11,12,13,14,15) + . = ascii2text(remainder+87) + . + else + . = "0" + . + i++ + return . + +//Splits the text of a file at seperator and returns them in a list. /world/proc/file2list(filename, seperator="\n", trim = TRUE) if (trim) return splittext(trim(file2text(filename)),seperator) -<<<<<<< HEAD - return splittext(file2text(filename),seperator) - -//Turns a direction into text -/proc/dir2text(direction) - switch(direction) - if(1) - return "north" - if(2) - return "south" - if(4) - return "east" - if(8) - return "west" - if(5) - return "northeast" - if(6) - return "southeast" - if(9) - return "northwest" - if(10) - return "southwest" - else - return - -//Turns text into proper directions -/proc/text2dir(direction) - switch(uppertext(direction)) - if("NORTH") - return 1 - if("SOUTH") - return 2 - if("EAST") - return 4 - if("WEST") - return 8 - if("NORTHEAST") - return 5 - if("NORTHWEST") - return 9 - if("SOUTHEAST") - return 6 - if("SOUTHWEST") - return 10 - else - return - -//Converts an angle (degrees) into an ss13 direction -/proc/angle2dir(degree) - - degree = SimplifyDegrees(degree) - - if(degree < 45) - return NORTH - if(degree < 90) - return NORTHEAST - if(degree < 135) - return EAST - if(degree < 180) - return SOUTHEAST - if(degree < 225) - return SOUTH - if(degree < 270) - return SOUTHWEST - if(degree < 315) - return WEST - return NORTH|WEST - -//returns the north-zero clockwise angle in degrees, given a direction - -/proc/dir2angle(D) - switch(D) - if(NORTH) - return 0 - if(SOUTH) - return 180 - if(EAST) - return 90 - if(WEST) - return 270 - if(NORTHEAST) - return 45 - if(SOUTHEAST) - return 135 - if(NORTHWEST) - return 315 - if(SOUTHWEST) - return 225 - else - return null - -//Returns the angle in english -/proc/angle2text(degree) - return dir2text(angle2dir(degree)) - -//Converts a blend_mode constant to one acceptable to icon.Blend() -/proc/blendMode2iconMode(blend_mode) - switch(blend_mode) - if(BLEND_MULTIPLY) - return ICON_MULTIPLY - if(BLEND_ADD) - return ICON_ADD - if(BLEND_SUBTRACT) - return ICON_SUBTRACT - else - return ICON_OVERLAY - -//Converts a rights bitfield into a string -/proc/rights2text(rights, seperator="", list/adds, list/subs) - if(rights & R_BUILDMODE) - . += "[seperator]+BUILDMODE" - if(rights & R_ADMIN) - . += "[seperator]+ADMIN" - if(rights & R_BAN) - . += "[seperator]+BAN" - if(rights & R_FUN) - . += "[seperator]+FUN" - if(rights & R_SERVER) - . += "[seperator]+SERVER" - if(rights & R_DEBUG) - . += "[seperator]+DEBUG" - if(rights & R_POSSESS) - . += "[seperator]+POSSESS" - if(rights & R_PERMISSIONS) - . += "[seperator]+PERMISSIONS" - if(rights & R_STEALTH) - . += "[seperator]+STEALTH" - if(rights & R_POLL) - . += "[seperator]+POLL" - if(rights & R_VAREDIT) - . += "[seperator]+VAREDIT" - if(rights & R_SOUNDS) - . += "[seperator]+SOUND" - if(rights & R_SPAWN) - . += "[seperator]+SPAWN" - - for(var/verbpath in adds) - . += "[seperator]+[verbpath]" - for(var/verbpath in subs) - . += "[seperator]-[verbpath]" - return . - -/proc/ui_style2icon(ui_style) - switch(ui_style) - if("Retro") - return 'icons/mob/screen_retro.dmi' - if("Plasmafire") - return 'icons/mob/screen_plasmafire.dmi' - if("Slimecore") - return 'icons/mob/screen_slimecore.dmi' - if("Operative") - return 'icons/mob/screen_operative.dmi' - if("Clockwork") - return 'icons/mob/screen_clockwork.dmi' - else - return 'icons/mob/screen_midnight.dmi' - -//colour formats -/proc/rgb2hsl(red, green, blue) - red /= 255;green /= 255;blue /= 255; - var/max = max(red,green,blue) - var/min = min(red,green,blue) - var/range = max-min - - var/hue=0;var/saturation=0;var/lightness=0; - lightness = (max + min)/2 - if(range != 0) - if(lightness < 0.5) - saturation = range/(max+min) - else - saturation = range/(2-max-min) - - var/dred = ((max-red)/(6*max)) + 0.5 - var/dgreen = ((max-green)/(6*max)) + 0.5 - var/dblue = ((max-blue)/(6*max)) + 0.5 - - if(max==red) - hue = dblue - dgreen - else if(max==green) - hue = dred - dblue + (1/3) - else - hue = dgreen - dred + (2/3) - if(hue < 0) - hue++ - else if(hue > 1) - hue-- - - return list(hue, saturation, lightness) - -/proc/hsl2rgb(hue, saturation, lightness) - var/red;var/green;var/blue; - if(saturation == 0) - red = lightness * 255 - green = red - blue = red - else - var/a;var/b; - if(lightness < 0.5) - b = lightness*(1+saturation) - else - b = (lightness+saturation) - (saturation*lightness) - a = 2*lightness - b - - red = round(255 * hue2rgb(a, b, hue+(1/3))) - green = round(255 * hue2rgb(a, b, hue)) - blue = round(255 * hue2rgb(a, b, hue-(1/3))) - - return list(red, green, blue) - -/proc/hue2rgb(a, b, hue) - if(hue < 0) - hue++ - else if(hue > 1) - hue-- - if(6*hue < 1) - return (a+(b-a)*6*hue) - if(2*hue < 1) - return b - if(3*hue < 2) - return (a+(b-a)*((2/3)-hue)*6) - return a - -// Very ugly, BYOND doesn't support unix time and rounding errors make it really hard to convert it to BYOND time. -// returns "YYYY-MM-DD" by default -/proc/unix2date(timestamp, seperator = "-") - - if(timestamp < 0) - return 0 //Do not accept negative values - - var/year = 1970 //Unix Epoc begins 1970-01-01 - var/dayInSeconds = 86400 //60secs*60mins*24hours - var/daysInYear = 365 //Non Leap Year - var/daysInLYear = daysInYear + 1//Leap year - var/days = round(timestamp / dayInSeconds) //Days passed since UNIX Epoc - var/tmpDays = days + 1 //If passed (timestamp < dayInSeconds), it will return 0, so add 1 - var/monthsInDays = list() //Months will be in here ***Taken from the PHP source code*** - var/month = 1 //This will be the returned MONTH NUMBER. - var/day //This will be the returned day number. - - while(tmpDays > daysInYear) //Start adding years to 1970 - year++ - if(isLeap(year)) - tmpDays -= daysInLYear - else - tmpDays -= daysInYear - - if(isLeap(year)) //The year is a leap year - monthsInDays = list(-1,30,59,90,120,151,181,212,243,273,304,334) - else - monthsInDays = list(0,31,59,90,120,151,181,212,243,273,304,334) - - var/mDays = 0; - var/monthIndex = 0; - - for(var/m in monthsInDays) - monthIndex++ - if(tmpDays > m) - mDays = m - month = monthIndex - - day = tmpDays - mDays //Setup the date - - return "[year][seperator][((month < 10) ? "0[month]" : month)][seperator][((day < 10) ? "0[day]" : day)]" - -/proc/isLeap(y) - return ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0)) - - - -//Turns a Body_parts_covered bitfield into a list of organ/limb names. -//(I challenge you to find a use for this) -/proc/body_parts_covered2organ_names(bpc) - var/list/covered_parts = list() - - if(!bpc) - return 0 - - if(bpc & FULL_BODY) - covered_parts |= list("l_arm","r_arm","head","chest","l_leg","r_leg") - - else - if(bpc & HEAD) - covered_parts |= list("head") - if(bpc & CHEST) - covered_parts |= list("chest") - if(bpc & GROIN) - covered_parts |= list("chest") - - if(bpc & ARMS) - covered_parts |= list("l_arm","r_arm") - else - if(bpc & ARM_LEFT) - covered_parts |= list("l_arm") - if(bpc & ARM_RIGHT) - covered_parts |= list("r_arm") - - if(bpc & HANDS) - covered_parts |= list("l_arm","r_arm") - else - if(bpc & HAND_LEFT) - covered_parts |= list("l_arm") - if(bpc & HAND_RIGHT) - covered_parts |= list("r_arm") - - if(bpc & LEGS) - covered_parts |= list("l_leg","r_leg") - else - if(bpc & LEG_LEFT) - covered_parts |= list("l_leg") - if(bpc & LEG_RIGHT) - covered_parts |= list("r_leg") - - if(bpc & FEET) - covered_parts |= list("l_leg","r_leg") - else - if(bpc & FOOT_LEFT) - covered_parts |= list("l_leg") - if(bpc & FOOT_RIGHT) - covered_parts |= list("r_leg") - - return covered_parts - - - -//adapted from http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/ -/proc/heat2colour(temp) - return rgb(heat2colour_r(temp), heat2colour_g(temp), heat2colour_b(temp)) - - -/proc/heat2colour_r(temp) - temp /= 100 - if(temp <= 66) - . = 255 - else - . = max(0, min(255, 329.698727446 * (temp - 60) ** -0.1332047592)) - - -/proc/heat2colour_g(temp) - temp /= 100 - if(temp <= 66) - . = max(0, min(255, 99.4708025861 * log(temp) - 161.1195681661)) - else - . = max(0, min(255, 288.1221685293 * ((temp - 60) ** -0.075148492))) - - -/proc/heat2colour_b(temp) - temp /= 100 - if(temp >= 66) - . = 255 - else - if(temp <= 16) - . = 0 - else - . = max(0, min(255, 138.5177312231 * log(temp - 10) - 305.0447927307)) - -/proc/color2hex(color) //web colors - if(!color) - return "#000000" - - switch(color) - if("white") - return "#FFFFFF" - if("black") - return "#000000" - if("gray") - return "#808080" - if("brown") - return "#A52A2A" - if("red") - return "#FF0000" - if("darkred") - return "#8B0000" - if("crimson") - return "#DC143C" - if("orange") - return "#FFA500" - if("yellow") - return "#FFFF00" - if("green") - return "#008000" - if("lime") - return "#00FF00" - if("darkgreen") - return "#006400" - if("cyan") - return "#00FFFF" - if("blue") - return "#0000FF" - if("navy") - return "#000080" - if("teal") - return "#008080" - if("purple") - return "#800080" - if("indigo") - return "#4B0082" - else - return "#FFFFFF" - - -//This is a weird one: -//It returns a list of all var names found in the string -//These vars must be in the [var_name] format -//It's only a proc because it's used in more than one place - -//Takes a string and a datum -//The string is well, obviously the string being checked -//The datum is used as a source for var names, to check validity -//Otherwise every single word could technically be a variable! -/proc/string2listofvars(var/t_string, var/datum/var_source) - if(!t_string || !var_source) - return list() - - . = list() - - var/var_found = findtext(t_string,"\[") //Not the actual variables, just a generic "should we even bother" check - if(var_found) - //Find var names - - // "A dog said hi [name]!" - // splittext() --> list("A dog said hi ","name]!" - // jointext() --> "A dog said hi name]!" - // splittext() --> list("A","dog","said","hi","name]!") - - t_string = replacetext(t_string,"\[","\[ ")//Necessary to resolve "word[var_name]" scenarios - var/list/list_value = splittext(t_string,"\[") - var/intermediate_stage = jointext(list_value, null) - - list_value = splittext(intermediate_stage," ") - for(var/value in list_value) - if(findtext(value,"]")) - value = splittext(value,"]") //"name]!" --> list("name","!") - for(var/A in value) - if(var_source.vars.Find(A)) - . += A - -//assumes format #RRGGBB #rrggbb -/proc/color_hex2num(A) - if(!A) - return 0 - var/R = hex2num(copytext(A,2,4)) - var/G = hex2num(copytext(A,4,6)) - var/B = hex2num(copytext(A,6,0)) - return R+G+B - -//word of warning: using a matrix like this as a color value will simplify it back to a string after being set -/proc/color_hex2color_matrix(string) - var/length = length(string) - if(length != 7 && length != 9) - return color_matrix_identity() - var/r = hex2num(copytext(string, 2, 4))/255 - var/g = hex2num(copytext(string, 4, 6))/255 - var/b = hex2num(copytext(string, 6, 8))/255 - var/a = 1 - if(length == 9) - a = hex2num(copytext(string, 8, 10))/255 - if(!isnum(r) || !isnum(g) || !isnum(b) || !isnum(a)) - return color_matrix_identity() - return list(r,0,0,0, 0,g,0,0, 0,0,b,0, 0,0,0,a, 0,0,0,0) - -//will drop all values not on the diagonal -/proc/color_matrix2color_hex(list/the_matrix) - if(!istype(the_matrix) || the_matrix.len != 20) - return "#ffffffff" - return rgb(the_matrix[1]*255, the_matrix[6]*255, the_matrix[11]*255, the_matrix[16]*255) -======= return splittext(file2text(filename),seperator) //Turns a direction into text @@ -1008,7 +542,6 @@ if(!istype(the_matrix) || the_matrix.len != 20) return "#ffffffff" return rgb(the_matrix[1]*255, the_matrix[6]*255, the_matrix[11]*255, the_matrix[16]*255) ->>>>>>> 6b8775f... Makes angle2dir() much more accurate (#30989) /proc/type2parent(child) var/string_type = "[child]" From 4fc286289e2deb870c729aa2ede06fdc216e3ff3 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Fri, 6 Oct 2017 01:11:34 -0500 Subject: [PATCH 77/82] Automatic changelog generation for PR #3157 [ci skip] --- html/changelogs/AutoChangeLog-pr-3157.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3157.yml diff --git a/html/changelogs/AutoChangeLog-pr-3157.yml b/html/changelogs/AutoChangeLog-pr-3157.yml new file mode 100644 index 0000000000..69e7b10920 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3157.yml @@ -0,0 +1,4 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - rscadd: "Wigs are now available in AutoDrobe" From e1a72d16abfe9dedf1441896006f43a4c98ea846 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Fri, 6 Oct 2017 01:12:08 -0500 Subject: [PATCH 78/82] Automatic changelog generation for PR #3159 [ci skip] --- html/changelogs/AutoChangeLog-pr-3159.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3159.yml diff --git a/html/changelogs/AutoChangeLog-pr-3159.yml b/html/changelogs/AutoChangeLog-pr-3159.yml new file mode 100644 index 0000000000..d835ae4122 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3159.yml @@ -0,0 +1,7 @@ +author: "XDTM" +delete-after: True +changes: + - rscadd: "Added the H.E.C.K. suit, a guaranteed loot frop from Bubblegum." + - rscadd: "The H.E.C.K. suit is fully fire (and ash) proof, and has very good melee armor." + - rscadd: "H.E.C.K. suits can also be painted with spraycans, to fully customize your experience." + - rscadd: "Despite spending centuries inside a demon king, H.E.C.K. suits are most definitely safe." From 6c77fa5cb684430af31faac81eea799ec26f0067 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Fri, 6 Oct 2017 01:12:23 -0500 Subject: [PATCH 79/82] Automatic changelog generation for PR #3160 [ci skip] --- html/changelogs/AutoChangeLog-pr-3160.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3160.yml diff --git a/html/changelogs/AutoChangeLog-pr-3160.yml b/html/changelogs/AutoChangeLog-pr-3160.yml new file mode 100644 index 0000000000..c9d48dc583 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3160.yml @@ -0,0 +1,5 @@ +author: "Kevak/Neri" +delete-after: True +changes: + - bugfix: "Fixed plasmaman organsprites being missing" + - imageadd: "Plasmaman organ sprites added. Credit to Toriate for the sprites" From 31febed84950555aed0e57f20d81bb4b3e59e0eb Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Fri, 6 Oct 2017 01:12:44 -0500 Subject: [PATCH 80/82] Automatic changelog generation for PR #3163 [ci skip] --- html/changelogs/AutoChangeLog-pr-3163.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3163.yml diff --git a/html/changelogs/AutoChangeLog-pr-3163.yml b/html/changelogs/AutoChangeLog-pr-3163.yml new file mode 100644 index 0000000000..3c82b42146 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3163.yml @@ -0,0 +1,4 @@ +author: "Robustin" +delete-after: True +changes: + - bugfix: "Emotes (e.g. spinning and flipping) will now properly check for consciousness, restraints, etc. when appropriate." From 3f761e3403014b77d066827bb5e87a107e08dc65 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Fri, 6 Oct 2017 01:14:04 -0500 Subject: [PATCH 81/82] Automatic changelog generation for PR #3168 [ci skip] --- html/changelogs/AutoChangeLog-pr-3168.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3168.yml diff --git a/html/changelogs/AutoChangeLog-pr-3168.yml b/html/changelogs/AutoChangeLog-pr-3168.yml new file mode 100644 index 0000000000..ee61a58860 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3168.yml @@ -0,0 +1,4 @@ +author: "Naksu" +delete-after: True +changes: + - tweak: "Made atmos tiny bit faster" From 446c075fa18630b87b57d1c6722d562732c52d51 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Fri, 6 Oct 2017 01:14:17 -0500 Subject: [PATCH 82/82] Automatic changelog generation for PR #3170 [ci skip] --- html/changelogs/AutoChangeLog-pr-3170.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3170.yml diff --git a/html/changelogs/AutoChangeLog-pr-3170.yml b/html/changelogs/AutoChangeLog-pr-3170.yml new file mode 100644 index 0000000000..eeb9a06f55 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3170.yml @@ -0,0 +1,6 @@ +author: "Joan" +delete-after: True +changes: + - balance: "Ocular Warden base damage per second changed from 12.5 to 15." + - bugfix: "Ocular Wardens no longer count themselves when checking for dense objects, which decreased their overall damage by 15%." + - balance: "Ocular Wardens now only reduce their damage by 10% per dense object, and only do so once per turf. However, dense turfs now reduce their damage with the same 10% penalty."