Merge remote-tracking branch 'citadel/master' into combat_rework

This commit is contained in:
kevinz000
2020-05-27 18:11:15 -07:00
149 changed files with 3488 additions and 1036 deletions
-8
View File
@@ -731,14 +731,6 @@
if(next_use_time > world.time)
START_PROCESSING(SSfastprocess, src)
//Stickmemes
/datum/action/item_action/stickmen
name = "Summon Stick Minions"
desc = "Allows you to summon faithful stickmen allies to aide you in battle."
icon_icon = 'icons/mob/actions/actions_minor_antag.dmi'
button_icon_state = "art_summon"
//surf_ss13
/datum/action/item_action/bhop
name = "Activate Jump Boots"
+60
View File
@@ -0,0 +1,60 @@
//Magical traumas, caused by spells and curses.
//Blurs the line between the victim's imagination and reality
//Unlike regular traumas this can affect the victim's body and surroundings
/datum/brain_trauma/magic
resilience = TRAUMA_RESILIENCE_LOBOTOMY
/datum/brain_trauma/magic/stalker
name = "Stalking Phantom"
desc = "Patient is stalked by a phantom only they can see."
scan_desc = "extra-sensory paranoia"
gain_text = "<span class='warning'>You feel like something wants to kill you...</span>"
lose_text = "<span class='notice'>You no longer feel eyes on your back.</span>"
var/obj/effect/hallucination/simple/stalker_phantom/stalker
var/close_stalker = FALSE //For heartbeat
/datum/brain_trauma/magic/stalker/on_gain()
create_stalker()
..()
/datum/brain_trauma/magic/stalker/proc/create_stalker()
var/turf/stalker_source = locate(owner.x + pick(-12, 12), owner.y + pick(-12, 12), owner.z) //random corner
stalker = new(stalker_source, owner)
/datum/brain_trauma/magic/stalker/on_lose()
QDEL_NULL(stalker)
..()
/datum/brain_trauma/magic/stalker/on_life()
// Dead and unconscious people are not interesting to the psychic stalker.
if(owner.stat != CONSCIOUS)
return
// Not even nullspace will keep it at bay.
if(!stalker || !stalker.loc || stalker.z != owner.z)
qdel(stalker)
create_stalker()
if(get_dist(owner, stalker) <= 1)
playsound(owner, 'sound/magic/demon_attack1.ogg', 50)
owner.visible_message("<span class='warning'>[owner] is torn apart by invisible claws!</span>", "<span class='userdanger'>Ghostly claws tear your body apart!</span>")
owner.take_bodypart_damage(rand(20, 45))
else if(prob(50))
stalker.forceMove(get_step_towards(stalker, owner))
if(get_dist(owner, stalker) <= 8)
if(!close_stalker)
var/sound/slowbeat = sound('sound/health/slowbeat.ogg', repeat = TRUE)
owner.playsound_local(owner, slowbeat, 40, 0, channel = CHANNEL_HEARTBEAT)
close_stalker = TRUE
else
if(close_stalker)
owner.stop_sound_channel(CHANNEL_HEARTBEAT)
close_stalker = FALSE
..()
/obj/effect/hallucination/simple/stalker_phantom
name = "???"
desc = "It's coming closer..."
image_icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
image_state = "curseblob"
-56
View File
@@ -1,56 +0,0 @@
#define BAD_ART 12.5
#define GOOD_ART 25
#define GREAT_ART 50
/datum/component/art
var/impressiveness = 0
/datum/component/art/Initialize(impress)
impressiveness = impress
if(isobj(parent))
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_obj_examine)
else
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_other_examine)
if(isstructure(parent))
RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, .proc/on_attack_hand)
if(isitem(parent))
RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/apply_moodlet)
/datum/component/art/proc/apply_moodlet(mob/M, impress)
M.visible_message("<span class='notice'>[M] stops and looks intently at [parent].</span>", \
"<span class='notice'>You stop to take in [parent].</span>")
switch(impress)
if (0 to BAD_ART)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad)
if (BAD_ART to GOOD_ART)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artok", /datum/mood_event/artok)
if (GOOD_ART to GREAT_ART)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgood", /datum/mood_event/artgood)
if(GREAT_ART to INFINITY)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat)
/datum/component/art/proc/on_other_examine(datum/source, mob/M)
apply_moodlet(M, impressiveness)
/datum/component/art/proc/on_obj_examine(datum/source, mob/M)
var/obj/O = parent
apply_moodlet(M, impressiveness *(O.obj_integrity/O.max_integrity))
/datum/component/art/proc/on_attack_hand(datum/source, mob/M)
to_chat(M, "<span class='notice'>You start examining [parent]...</span>")
if(!do_after(M, 20, target = parent))
return
on_obj_examine(source, M)
/datum/component/art/rev
/datum/component/art/rev/apply_moodlet(mob/M, impress)
M.visible_message("<span class='notice'>[M] stops to inspect [parent].</span>", \
"<span class='notice'>You take in [parent], inspecting the fine craftsmanship of the proletariat.</span>")
if(M.mind && M.mind.has_antag_datum(/datum/antagonist/rev))
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat)
else
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad)
+217
View File
@@ -0,0 +1,217 @@
/**
* Combat mode component. It makes the user face whichever atom the mouse pointer is hovering,
* amongst other things designed outside of this file, namely PvP and PvE stuff, hence the name.
* Can be toggled on and off by clicking the screen hud object or by pressing the assigned hotkey (default 'C')
*/
/datum/component/combat_mode
var/mode_flags = COMBAT_MODE_INACTIVE
var/combatmessagecooldown
var/lastmousedir
var/obj/screen/combattoggle/hud_icon
var/hud_loc
/datum/component/combat_mode/Initialize(hud_loc = ui_combat_toggle)
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
var/mob/living/L = parent
src.hud_loc = hud_loc
RegisterSignal(L, SIGNAL_TRAIT(TRAIT_COMBAT_MODE_LOCKED), .proc/update_combat_lock)
RegisterSignal(L, COMSIG_TOGGLE_COMBAT_MODE, .proc/user_toggle_intentional_combat_mode)
RegisterSignal(L, COMSIG_DISABLE_COMBAT_MODE, .proc/safe_disable_combat_mode)
RegisterSignal(L, COMSIG_ENABLE_COMBAT_MODE, .proc/safe_enable_combat_mode)
RegisterSignal(L, COMSIG_MOB_DEATH, .proc/on_death)
RegisterSignal(L, COMSIG_MOB_CLIENT_LOGOUT, .proc/on_logout)
RegisterSignal(L, COMSIG_MOB_HUD_CREATED, .proc/on_mob_hud_created)
RegisterSignal(L, COMSIG_COMBAT_MODE_CHECK, .proc/check_flags)
update_combat_lock()
if(L.client)
on_mob_hud_created(L)
/datum/component/combat_mode/Destroy()
if(parent)
safe_disable_combat_mode(parent)
if(hud_icon)
QDEL_NULL(hud_icon)
return ..()
/// Creates the hud screen object.
/datum/component/combat_mode/proc/on_mob_hud_created(mob/source)
hud_icon = new
hud_icon.hud = source.hud_used
hud_icon.icon = tg_ui_icon_to_cit_ui(source.hud_used.ui_style)
hud_icon.screen_loc = hud_loc
source.hud_used.static_inventory += hud_icon
hud_icon.update_icon()
/// Combat mode can be locked out, forcibly disabled by a status trait.
/datum/component/combat_mode/proc/update_combat_lock()
var/locked = HAS_TRAIT(parent, TRAIT_COMBAT_MODE_LOCKED)
var/desired = (mode_flags & COMBAT_MODE_TOGGLED)
var/actual = (mode_flags & COMBAT_MODE_ACTIVE)
if(actual)
if(locked)
disable_combat_mode(parent, FALSE, TRUE)
else if(!desired)
disable_combat_mode(parent, TRUE, TRUE)
else
if(desired && !locked)
enable_combat_mode(parent, FALSE, TRUE)
/// Enables combat mode. Please use 'safe_enable_combat_mode' instead, if you wish to also enable the toggle flag.
/datum/component/combat_mode/proc/enable_combat_mode(mob/living/source, silent = TRUE, forced = TRUE, visible = FALSE, locked = FALSE, playsound = FALSE)
if(locked)
if(hud_icon)
hud_icon.combat_on = TRUE
hud_icon.update_icon()
return
if(mode_flags & COMBAT_MODE_ACTIVE)
return
mode_flags |= COMBAT_MODE_ACTIVE
mode_flags &= ~COMBAT_MODE_INACTIVE
SEND_SIGNAL(source, COMSIG_LIVING_COMBAT_ENABLED, forced)
if(!silent)
var/self_message = forced? "<span class='warning'>Your muscles reflexively tighten!</span>" : "<span class='warning'>You drop into a combative stance!</span>"
if(visible && (forced || world.time >= combatmessagecooldown))
combatmessagecooldown = world.time + 10 SECONDS
if(!forced)
if(source.a_intent != INTENT_HELP)
source.visible_message("<span class='warning'>[source] [source.resting ? "tenses up" : "drops into a combative stance"].</span>", self_message)
else
source.visible_message("<span class='notice'>[source] [pick("looks","seems","goes")] [pick("alert","attentive","vigilant")].</span>")
else
source.visible_message("<span class='warning'>[source] drops into a combative stance!</span>", self_message)
else
to_chat(source, self_message)
if(playsound)
source.playsound_local(source, 'sound/misc/ui_toggle.ogg', 50, FALSE, pressure_affected = FALSE) //Sound from interbay!
RegisterSignal(source, COMSIG_MOB_CLIENT_MOUSEMOVE, .proc/onMouseMove)
RegisterSignal(source, COMSIG_MOVABLE_MOVED, .proc/on_move)
RegisterSignal(source, COMSIG_MOB_CLIENT_MOVE, .proc/on_client_move)
if(hud_icon)
hud_icon.combat_on = TRUE
hud_icon.update_icon()
/// Disables combat mode. Please use 'safe_disable_combat_mode' instead, if you wish to also disable the toggle flag.
/datum/component/combat_mode/proc/disable_combat_mode(mob/living/source, silent = TRUE, forced = TRUE, visible = FALSE, locked = FALSE, playsound = FALSE)
if(locked)
if(hud_icon)
hud_icon.combat_on = FALSE
hud_icon.update_icon()
return
if(!(mode_flags & COMBAT_MODE_ACTIVE))
return
mode_flags &= ~COMBAT_MODE_ACTIVE
mode_flags |= COMBAT_MODE_INACTIVE
SEND_SIGNAL(source, COMSIG_LIVING_COMBAT_DISABLED, forced)
if(!silent)
var/self_message = forced? "<span class='warning'>Your muscles are forcibly relaxed!</span>" : "<span class='warning'>You relax your stance.</span>"
if(visible)
source.visible_message("<span class='warning'>[source] relaxes [source.p_their()] stance.</span>", self_message)
else
to_chat(source, self_message)
if(playsound)
source.playsound_local(source, 'sound/misc/ui_toggleoff.ogg', 50, FALSE, pressure_affected = FALSE) //Slightly modified version of the toggleon sound!
UnregisterSignal(source, list(COMSIG_MOB_CLIENT_MOUSEMOVE, COMSIG_MOVABLE_MOVED, COMSIG_MOB_CLIENT_MOVE))
if(hud_icon)
hud_icon.combat_on = FALSE
hud_icon.update_icon()
///Changes the user direction to (try) keep match the pointer.
/datum/component/combat_mode/proc/on_move(atom/movable/source, dir, atom/oldloc, forced)
var/mob/living/L = source
if(mode_flags & COMBAT_MODE_ACTIVE && L.client && lastmousedir && lastmousedir != dir)
L.setDir(lastmousedir, ismousemovement = TRUE)
/// Added movement delay if moving backward.
/datum/component/combat_mode/proc/on_client_move(mob/source, client/client, direction, n, oldloc, added_delay)
if(oldloc != n && direction == REVERSE_DIR(source.dir))
client.move_delay += added_delay*0.5
///Changes the user direction to (try) match the pointer.
/datum/component/combat_mode/proc/onMouseMove(mob/source, object, location, control, params)
if(source.client.show_popup_menus)
return
source.face_atom(object, TRUE)
lastmousedir = source.dir
/// Toggles whether the user is intentionally in combat mode. THIS should be the proc you generally use! Has built in visual/to other player feedback, as well as an audible cue to ourselves.
/datum/component/combat_mode/proc/user_toggle_intentional_combat_mode(mob/living/source)
if(mode_flags & COMBAT_MODE_TOGGLED)
safe_disable_combat_mode(source)
else if(source.stat == CONSCIOUS && !(source.combat_flags & COMBAT_FLAG_HARD_STAMCRIT))
safe_enable_combat_mode(source)
/// Enables intentionally being in combat mode. Please try to use the COMSIG_COMBAT_MODE_CHECK signal for feedback when possible.
/datum/component/combat_mode/proc/safe_enable_combat_mode(mob/living/source, silent = FALSE, visible = TRUE)
if((mode_flags & COMBAT_MODE_TOGGLED) && (mode_flags & COMBAT_MODE_ACTIVE))
return TRUE
mode_flags |= COMBAT_MODE_TOGGLED
enable_combat_mode(source, silent, FALSE, visible, HAS_TRAIT(source, TRAIT_COMBAT_MODE_LOCKED), TRUE)
if(source.client)
source.client.show_popup_menus = FALSE
if(iscarbon(source)) //I dislike this typecheck. It probably should be removed once that spoiled apple is componentized too.
var/mob/living/carbon/C = source
if(C.voremode)
C.disable_vore_mode()
return TRUE
/// Disables intentionally being in combat mode. Please try to use the COMSIG_COMBAT_MODE_CHECK signal for feedback when possible.
/datum/component/combat_mode/proc/safe_disable_combat_mode(mob/living/source, silent = FALSE, visible = FALSE)
if(!(mode_flags & COMBAT_MODE_TOGGLED) && !(mode_flags & COMBAT_MODE_ACTIVE))
return TRUE
mode_flags &= ~COMBAT_MODE_TOGGLED
disable_combat_mode(source, silent, FALSE, visible, !(mode_flags & COMBAT_MODE_ACTIVE), TRUE)
if(source.client)
source.client.show_popup_menus = TRUE
return TRUE
/// Returns a field of flags that are contained in both the second arg and our bitfield variable.
/datum/component/combat_mode/proc/check_flags(mob/living/source, flags)
return mode_flags & (flags)
/// Disables combat mode upon death.
/datum/component/combat_mode/proc/on_death(mob/living/source)
safe_disable_combat_mode(source)
/// Disables combat mode upon logout
/datum/component/combat_mode/proc/on_logout(mob/living/source)
safe_disable_combat_mode(source)
/// The screen button.
/obj/screen/combattoggle
name = "toggle combat mode"
icon = 'modular_citadel/icons/ui/screen_midnight.dmi'
icon_state = "combat_off"
var/mutable_appearance/flashy
var/combat_on = FALSE ///Wheter combat mode is enabled or not, so we don't have to store a reference.
/obj/screen/combattoggle/Click()
if(hud && usr == hud.mymob)
SEND_SIGNAL(hud.mymob, COMSIG_TOGGLE_COMBAT_MODE)
/obj/screen/combattoggle/update_icon_state()
var/mob/living/user = hud?.mymob
if(!user)
return
if(combat_on)
icon_state = "combat"
else if(HAS_TRAIT(user, TRAIT_COMBAT_MODE_LOCKED))
icon_state = "combat_locked"
else
icon_state = "combat_off"
/obj/screen/combattoggle/update_overlays()
. = ..()
var/mob/living/carbon/user = hud?.mymob
if(!(user?.client))
return
if(combat_on)
if(!flashy)
flashy = mutable_appearance('icons/mob/screen_gen.dmi', "togglefull_flash")
flashy.color = user.client.prefs.hud_toggle_color
. += flashy //TODO - beg lummox jr for the ability to force mutable appearances or images to be created rendering from their first frame of animation rather than being based entirely around the client's frame count
@@ -12,6 +12,7 @@
/obj/item/weaponcrafting/stock
name = "rifle stock"
desc = "A classic rifle stock that doubles as a grip, roughly carved out of wood."
custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 6)
icon_state = "riflestock"
/obj/item/weaponcrafting/durathread_string
@@ -116,4 +116,41 @@
always_availible = FALSE
reqs = list(/obj/item/stack/rods = 1,
/obj/item/stack/sheet/mineral/sandstone = 4)
category = CAT_PRIMAL
category = CAT_PRIMAL
/datum/crafting_recipe/rib
name = "Collosal Rib"
always_availible = FALSE
reqs = list(
/obj/item/stack/sheet/bone = 10,
/datum/reagent/oil = 5)
result = /obj/structure/statue/bone/rib
subcategory = CAT_PRIMAL
/datum/crafting_recipe/skull
name = "Skull Carving"
always_availible = FALSE
reqs = list(
/obj/item/stack/sheet/bone = 6,
/datum/reagent/oil = 5)
result = /obj/structure/statue/bone/skull
category = CAT_PRIMAL
/datum/crafting_recipe/halfskull
name = "Cracked Skull Carving"
always_availible = FALSE
reqs = list(
/obj/item/stack/sheet/bone = 3,
/datum/reagent/oil = 5)
result = /obj/structure/statue/bone/skull/half
category = CAT_PRIMAL
/datum/crafting_recipe/boneshovel
name = "Serrated Bone Shovel"
always_availible = FALSE
reqs = list(
/obj/item/stack/sheet/bone = 4,
/datum/reagent/oil = 5,
/obj/item/shovel/spade = 1)
result = /obj/item/shovel/serrated
category = CAT_PRIMAL
+2 -5
View File
@@ -47,14 +47,11 @@
if(icon_state)
lock_icon_state = icon_state
generate_lock_visuals()
var/mob/M = parent
LAZYOR(M.mousemove_intercept_objects, src)
RegisterSignal(parent, COMSIG_MOB_CLIENT_MOUSEMOVE, .proc/onMouseMove)
START_PROCESSING(SSfastprocess, src)
/datum/component/lockon_aiming/Destroy()
var/mob/M = parent
clear_visuals()
LAZYREMOVE(M.mousemove_intercept_objects, src)
STOP_PROCESSING(SSfastprocess, src)
return ..()
@@ -120,7 +117,7 @@
return
LAZYREMOVE(immune_weakrefs, A.weak_reference)
/datum/component/lockon_aiming/onMouseMove(object,location,control,params)
/datum/component/lockon_aiming/proc/onMouseMove(object,location,control,params)
var/mob/M = parent
if(!istype(M) || !M.client)
return
+22
View File
@@ -321,6 +321,28 @@
if(0 to NUTRITION_LEVEL_STARVING)
add_event(null, "nutrition", /datum/mood_event/starving)
/datum/component/mood/proc/update_beauty(area/A)
if(A.outdoors) //if we're outside, we don't care.
clear_event(null, "area_beauty")
return FALSE
if(HAS_TRAIT(parent, TRAIT_SNOB))
switch(A.beauty)
if(-INFINITY to BEAUTY_LEVEL_HORRID)
add_event(null, "area_beauty", /datum/mood_event/horridroom)
return
if(BEAUTY_LEVEL_HORRID to BEAUTY_LEVEL_BAD)
add_event(null, "area_beauty", /datum/mood_event/badroom)
return
switch(A.beauty)
if(-INFINITY to BEAUTY_LEVEL_DECENT)
clear_event(null, "area_beauty")
if(BEAUTY_LEVEL_DECENT to BEAUTY_LEVEL_GOOD)
add_event(null, "area_beauty", /datum/mood_event/decentroom)
if(BEAUTY_LEVEL_GOOD to BEAUTY_LEVEL_GREAT)
add_event(null, "area_beauty", /datum/mood_event/goodroom)
if(BEAUTY_LEVEL_GREAT to INFINITY)
add_event(null, "area_beauty", /datum/mood_event/greatroom)
///Called when parent is revived.
/datum/component/mood/proc/on_revive(datum/source, full_heal)
START_PROCESSING(SSdcs, src)
+1 -1
View File
@@ -20,7 +20,7 @@
valid_slots = _valid_slots
/datum/component/wearertargeting/phantomthief/proc/handlefilterstuff(mob/living/user, was_forced = FALSE)
if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
if(!SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE))
user.remove_filter("phantomthief")
else
user.add_filter("phantomthief", 4, list(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, color = filter_color))
+1 -1
View File
@@ -59,7 +59,7 @@
var/mob/living/simple_animal/L = new chosen_mob_type(spawn_location)
if(ishostile(L))
var/mob/living/simple_animal/hostile/H = L
H.friends += summoner // do not attack our summon boy
H.friends[summoner]++ // do not attack our summon boy
spawned_mobs += L
if(faction != null)
L.faction = faction
+64
View File
@@ -0,0 +1,64 @@
#define BAD_ART 12.5
#define GOOD_ART 25
#define GREAT_ART 50
/datum/element/art
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
id_arg_index = 2
var/impressiveness = 0
/datum/element/art/Attach(datum/target, impress)
. = ..()
if(. == ELEMENT_INCOMPATIBLE || !isatom(target) || isarea(target))
return ELEMENT_INCOMPATIBLE
impressiveness = impress
if(isobj(target))
RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/on_obj_examine)
if(isstructure(target))
RegisterSignal(target, COMSIG_ATOM_ATTACK_HAND, .proc/on_attack_hand)
if(isitem(target))
RegisterSignal(target, COMSIG_ITEM_ATTACK_SELF, .proc/apply_moodlet)
else
RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/on_other_examine)
/datum/element/art/Detach(datum/target)
UnregisterSignal(target, list(COMSIG_PARENT_EXAMINE, COMSIG_ATOM_ATTACK_HAND, COMSIG_ITEM_ATTACK_SELF))
return ..()
/datum/element/art/proc/apply_moodlet(atom/source, mob/M, impress)
M.visible_message("<span class='notice'>[M] stops and looks intently at [source].</span>", \
"<span class='notice'>You stop to take in [source].</span>")
switch(impress)
if (0 to BAD_ART)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad)
if (BAD_ART to GOOD_ART)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artok", /datum/mood_event/artok)
if (GOOD_ART to GREAT_ART)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgood", /datum/mood_event/artgood)
if(GREAT_ART to INFINITY)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat)
/datum/element/art/proc/on_other_examine(atom/source, mob/M)
apply_moodlet(source, M, impressiveness)
/datum/element/art/proc/on_obj_examine(atom/source, mob/M)
var/obj/O = source
apply_moodlet(source, M, impressiveness *(O.obj_integrity/O.max_integrity))
/datum/element/art/proc/on_attack_hand(atom/source, mob/M)
to_chat(M, "<span class='notice'>You start examining [source]...</span>")
if(!do_after(M, 20, target = source))
return
on_obj_examine(source, M)
/datum/element/art/rev
/datum/element/art/rev/apply_moodlet(atom/source, mob/M, impress)
M.visible_message("<span class='notice'>[M] stops to inspect [source].</span>", \
"<span class='notice'>You take in [source], inspecting the fine craftsmanship of the proletariat.</span>")
if(M.mind && M.mind.has_antag_datum(/datum/antagonist/rev))
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat)
else
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad)
+34
View File
@@ -0,0 +1,34 @@
/datum/element/beauty
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
id_arg_index = 2
var/beauty = 0
/datum/element/beauty/Attach(datum/target, beautyamount)
. = ..()
if(. == ELEMENT_INCOMPATIBLE || !isatom(target) || isarea(target))
return ELEMENT_INCOMPATIBLE
beauty = beautyamount
RegisterSignal(target, COMSIG_ENTER_AREA, .proc/enter_area)
RegisterSignal(target, COMSIG_EXIT_AREA, .proc/exit_area)
var/area/A = get_area(target)
if(A)
enter_area(null, A)
/datum/element/beauty/Detach(datum/target)
UnregisterSignal(target, list(COMSIG_ENTER_AREA, COMSIG_EXIT_AREA))
var/area/A = get_area(target)
if(A)
exit_area(null, A)
return ..()
/datum/element/beauty/proc/enter_area(datum/source, area/A)
if(A.outdoors)
return
A.totalbeauty += beauty
A.update_beauty()
/datum/element/beauty/proc/exit_area(datum/source, area/A)
if(A.outdoors)
return
A.totalbeauty -= beauty
A.update_beauty()
+2 -2
View File
@@ -14,12 +14,12 @@
/datum/element/tactical/Detach(datum/target)
UnregisterSignal(target, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED))
unmodify()
unmodify(target)
return ..()
/datum/element/tactical/proc/modify(obj/item/source, mob/user, slot)
if(allowed_slot && slot != allowed_slot)
unmodify()
unmodify(source, user)
return
var/image/I = image(icon = source.icon, icon_state = source.icon_state, loc = user)
+2 -2
View File
@@ -43,11 +43,11 @@
/datum/martial_art/proc/damage_roll(mob/living/carbon/human/A, mob/living/carbon/human/D)
//Here we roll for our damage to be added into the damage var in the various attack procs. This is changed depending on whether we are in combat mode, lying down, or if our target is in combat mode.
var/damage = rand(A.dna.species.punchdamagelow, A.dna.species.punchdamagehigh)
if(!(D.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
if(SEND_SIGNAL(D, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
damage *= 1.5
if(!CHECK_MOBILITY(A, MOBILITY_STAND))
damage *= 0.5
if(!(A.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
if(SEND_SIGNAL(A, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
damage *= 0.25
return damage
+5
View File
@@ -24,6 +24,8 @@ Simple datum which is instanced once per type and is used for every object of sa
var/value_per_unit = 0
///Armor modifiers, multiplies an items normal armor vars by these amounts.
var/armor_modifiers = list("melee" = 1, "bullet" = 1, "laser" = 1, "energy" = 1, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 1, "acid" = 1)
///How beautiful is this material per unit?
var/beauty_modifier = 0
///This proc is called when the material is added to an object.
/datum/material/proc/on_applied(atom/source, amount, material_flags)
@@ -39,6 +41,9 @@ Simple datum which is instanced once per type and is used for every object of sa
if(istype(source, /obj)) //objs
on_applied_obj(source, amount, material_flags)
if(beauty_modifier)
addtimer(CALLBACK(source, /datum.proc/_AddElement, list(/datum/element/beauty, beauty_modifier * amount)), 0)
///This proc is called when the material is added to an object specifically.
/datum/material/proc/on_applied_obj(var/obj/o, amount, material_flags)
if(material_flags & MATERIAL_AFFECT_STATISTICS)
+38
View File
@@ -19,6 +19,7 @@
integrity_modifier = 0.1
sheet_type = /obj/item/stack/sheet/glass
value_per_unit = 0.0025
beauty_modifier = 0.05
armor_modifiers = list("melee" = 0.2, "bullet" = 0.2, "laser" = 0, "energy" = 1, "bomb" = 0, "bio" = 0.2, "rad" = 0.2, "fire" = 1, "acid" = 0.2) // yeah ok
/*
@@ -35,6 +36,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
sheet_type = /obj/item/stack/sheet/mineral/silver
value_per_unit = 0.025
beauty_modifier = 0.075
///Slight force increase
/datum/material/gold
@@ -46,6 +48,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
sheet_type = /obj/item/stack/sheet/mineral/gold
value_per_unit = 0.0625
beauty_modifier = 0.15
armor_modifiers = list("melee" = 1.1, "bullet" = 1.1, "laser" = 1.15, "energy" = 1.15, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 0.7, "acid" = 1.1)
///Has no special properties
@@ -58,6 +61,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
sheet_type = /obj/item/stack/sheet/mineral/diamond
value_per_unit = 0.25
beauty_modifier = 0.3
armor_modifiers = list("melee" = 1.3, "bullet" = 1.3, "laser" = 0.6, "energy" = 1, "bomb" = 1.2, "bio" = 1, "rad" = 1, "fire" = 1, "acid" = 1)
///Is slightly radioactive
/datum/material/uranium
@@ -68,6 +73,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
sheet_type = /obj/item/stack/sheet/mineral/uranium
value_per_unit = 0.05
beauty_modifier = 0.3 //It shines so beautiful
armor_modifiers = list("melee" = 1.5, "bullet" = 1.4, "laser" = 0.5, "energy" = 0.5, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 1, "acid" = 1)
/datum/material/uranium/on_applied(atom/source, amount, material_flags)
@@ -88,6 +94,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
sheet_type = /obj/item/stack/sheet/mineral/plasma
value_per_unit = 0.1
beauty_modifier = 0.15
armor_modifiers = list("melee" = 1.4, "bullet" = 0.7, "laser" = 0, "energy" = 1.2, "bomb" = 0, "bio" = 1.2, "rad" = 1, "fire" = 0, "acid" = 0.5)
/datum/material/plasma/on_applied(atom/source, amount, material_flags)
@@ -109,6 +116,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
color = list(119/255, 217/255, 396/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
alpha = 200
categories = list(MAT_CATEGORY_ORE = TRUE)
beauty_modifier = 0.5
sheet_type = /obj/item/stack/sheet/bluespace_crystal
value_per_unit = 0.15
@@ -121,6 +129,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
sheet_type = /obj/item/stack/sheet/mineral/bananium
value_per_unit = 0.5
beauty_modifier = 0.5
armor_modifiers = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 100, "bio" = 0, "rad" = 0, "fire" = 10, "acid" = 0) //Clowns cant be blown away
/datum/material/bananium/on_applied(atom/source, amount, material_flags)
@@ -144,6 +153,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
sheet_type = /obj/item/stack/sheet/mineral/titanium
value_per_unit = 0.0625
beauty_modifier = 0.05
armor_modifiers = list("melee" = 1.35, "bullet" = 1.3, "laser" = 1.3, "energy" = 1.25, "bomb" = 1.25, "bio" = 1, "rad" = 1, "fire" = 0.7, "acid" = 1)
/datum/material/runite
@@ -154,6 +164,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
strength_modifier = 1.3
categories = list(MAT_CATEGORY_RIGID = TRUE)
sheet_type = /obj/item/stack/sheet/mineral/runite
beauty_modifier = 0.5
armor_modifiers = list("melee" = 1.35, "bullet" = 2, "laser" = 0.5, "energy" = 1.25, "bomb" = 1.25, "bio" = 1, "rad" = 1, "fire" = 1.4, "acid" = 1) //rune is weak against magic lasers but strong against bullets. This is the combat triangle.
///Force decrease
@@ -165,6 +176,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
strength_modifier = 0.85
sheet_type = /obj/item/stack/sheet/plastic
value_per_unit = 0.0125
beauty_modifier = -0.01
armor_modifiers = list("melee" = 1.5, "bullet" = 1.1, "laser" = 0.3, "energy" = 0.5, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 1.1, "acid" = 1)
///Force decrease and mushy sound effect. (Not yet implemented)
@@ -176,6 +188,30 @@ Unless you know what you're doing, only use the first three numbers. They're in
strength_modifier = 0.8
value_per_unit = 0.025
/datum/material/wood
name = "wood"
id = "wood"
desc = "Flexible, durable, but flamable. Hard to come across in space."
color = "#bb8e53"
strength_modifier = 0.5
sheet_type = /obj/item/stack/sheet/mineral/wood
categories = list(MAT_CATEGORY_RIGID = TRUE)
value_per_unit = 0.06
beauty_modifier = 0.1
armor_modifiers = list("melee" = 1.1, "bullet" = 1.1, "laser" = 0.4, "energy" = 0.4, "bomb" = 1, "bio" = 0.2, "rad" = 0, "fire" = 0, "acid" = 0.3)
/datum/material/wood/on_applied_obj(obj/source, amount, material_flags)
. = ..()
if(material_flags & MATERIAL_AFFECT_STATISTICS)
var/obj/wooden = source
wooden.resistance_flags |= FLAMMABLE
/datum/material/wood/on_removed_obj(obj/source, material_flags)
. = ..()
if(material_flags & MATERIAL_AFFECT_STATISTICS)
var/obj/wooden = source
wooden.resistance_flags &= ~FLAMMABLE
///Stronk force increase
/datum/material/adamantine
name = "adamantine"
@@ -186,6 +222,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
categories = list(MAT_CATEGORY_RIGID = TRUE)
sheet_type = /obj/item/stack/sheet/mineral/adamantine
value_per_unit = 0.25
beauty_modifier = 0.4
armor_modifiers = list("melee" = 1.5, "bullet" = 1.5, "laser" = 1.3, "energy" = 1.3, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 2.5, "acid" = 1)
///RPG Magic. (Admin only)
@@ -197,6 +234,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
categories = list(MAT_CATEGORY_RIGID = TRUE)
sheet_type = /obj/item/stack/sheet/mineral/mythril
value_per_unit = 0.75
beauty_modifier = 0.5
armor_modifiers = list("melee" = 2, "bullet" = 2, "laser" = 2, "energy" = 2, "bomb" = 2, "bio" = 2, "rad" = 2, "fire" = 2, "acid" = 2)
/datum/material/mythril/on_applied_obj(atom/source, amount, material_flags)
-3
View File
@@ -97,9 +97,6 @@
if(current) // remove ourself from our old body's mind variable
current.mind = null
SStgui.on_transfer(current, new_character)
if(iscarbon(current))
var/mob/living/carbon/C = current
C.disable_intentional_combat_mode(TRUE)
if(key)
if(new_character.key != key) //if we're transferring into a body with a key associated which is not ours
@@ -153,7 +153,13 @@
mood_change = -4
timeout = 2400
/datum/mood_event/graverobbing
description ="<span class='boldwarning'>I just desecrated someone's grave... I can't believe I did that...</span>\n"
mood_change = -8
timeout = 3 MINUTES
//These are unused so far but I want to remember them to use them later
/datum/mood_event/cloned_corpse
description = "<span class='boldwarning'>I recently saw my own corpse...</span>\n"
mood_change = -6
@@ -162,6 +168,8 @@
description = "<span class='boldwarning'>HE'S CUTTING ME OPEN!!</span>\n"
mood_change = -8
//End unused
/datum/mood_event/sad_empath
description = "<span class='warning'>Someone seems upset...</span>\n"
mood_change = -2
@@ -199,6 +207,8 @@
mood_change = -2
timeout = 1 MINUTES
//Cursed stuff end.
/datum/mood_event/vampcandle
description = "<span class='umbra'>Something is making your mind feel... loose...</span>\n"
mood_change = -15
+9 -1
View File
@@ -250,4 +250,12 @@
cost = 5
placement_weight = 3
always_place = TRUE
allow_duplicates = TRUE
allow_duplicates = TRUE
/datum/map_template/ruin/lavaland/elephant_graveyard
name = "Elephant Graveyard"
id = "Graveyard"
description = "An abandoned graveyard, calling to those unable to continue."
suffix = "lavaland_surface_elephant_graveyard.dmm"
allow_duplicates = FALSE
cost = 10
+19
View File
@@ -1,3 +1,6 @@
/datum/tgs_event_handler/impl
var/datum/timedevent/reattach_timer
/datum/tgs_event_handler/impl/HandleEvent(event_code, ...)
switch(event_code)
if(TGS_EVENT_REBOOT_MODE_CHANGE)
@@ -18,3 +21,19 @@
if(TGS_EVENT_DEPLOYMENT_COMPLETE)
message_admins("TGS: Deployment complete!")
to_chat(world, "<span class='boldannounce'>Server updated, changes will be applied on the next round...</span>")
if(TGS_EVENT_WATCHDOG_DETACH)
message_admins("TGS restarting...")
reattach_timer = addtimer(CALLBACK(src, .proc/LateOnReattach), 1 MINUTES)
if(TGS_EVENT_WATCHDOG_REATTACH)
var/datum/tgs_version/old_version = world.TgsVersion()
var/datum/tgs_version/new_version = args[2]
if(!old_version.Equals(new_version))
to_chat(world, "<span class='boldannounce'>TGS updated to v[old_version.deprefixed_parameter]</span>")
else
message_admins("TGS: Back online")
if(reattach_timer)
deltimer(reattach_timer)
reattach_timer = null
/datum/tgs_event_handler/impl/proc/LateOnReattach()
message_admins("Warning: TGS hasn't notified us of it coming back for a full minute! Is there a problem?")
+9
View File
@@ -10,6 +10,15 @@
lose_text = "<span class='notice'>You can taste again!</span>"
medical_record_text = "Patient suffers from ageusia and is incapable of tasting food or reagents."
/datum/quirk/snob
name = "Snob"
desc = "You care about the finer things, if a room doesn't look nice its just not really worth it, is it?"
value = 0
gain_text = "<span class='notice'>You feel like you understand what things should look like.</span>"
lose_text = "<span class='notice'>Well who cares about deco anyways?</span>"
medical_record_text = "Patient seems to be rather stuck up."
mob_trait = TRAIT_SNOB
/datum/quirk/pineapple_liker
name = "Ananas Affinity"
desc = "You find yourself greatly enjoying fruits of the ananas genus. You can't seem to ever get enough of their sweet goodness!"
-3
View File
@@ -11,9 +11,6 @@
if(A.attachable)
return TRUE
/atom
var/datum/wires/wires = null
/atom/proc/attempt_wire_interaction(mob/user)
if(!wires)
return WIRE_INTERACTION_FAIL