Files
Bubberstation/code/datums/mutations/sight.dm
MrMelbert 329921639a Rewrites how action buttons icons are generated, makes them layer nicer. Allows observers to see a mob's action buttons. (#71339)
## About The Pull Request

- Rewrites how action button icons are generated.
- Prior, generated an action button icon was fairly simplistic and
didn't allow for many changes. Someone recently added the option for
overlays to be generated over action buttons, but the framework was very
weak.
- Now, action button icon generation is split across multiple procs,
like atom icon updates.
      - The background of action buttons are underlays
- The actual icon of the action button is the icon and icon state of the
action button movable
- The rim / border of the button is an overlay, layered overtop the
button.

- Allows observers to see what action buttons a mob has. They even
update in real time! And no, the observers cannot click on them.

## Why It's Good For The Game

- Runechat text of action buttons are no longer hidden behind the actual
icon. This was very ugly with cooldown actions, as the cooldown text was
hidden behind a lot of spell icons.
- Cuts down on a lot of icon duplication. 
- Gives much finer control over action button icons
- Saves a bit of processing from generating full action button icons
when not necessary. Not implemented in many places, but is in some.


![image](https://user-images.githubusercontent.com/51863163/202816617-342e87e6-2cc6-488e-9af2-4b2053dc3dc6.png)


![image](https://user-images.githubusercontent.com/51863163/202816604-da8d4821-0e2b-45af-b289-7442367f98ce.png)

## Changelog

🆑 Melbert
add: Observers can now see what action buttons an observed mob has. No,
you can't click them. And no it doesn't show EVERY action.
refactor: Refactored how action button icons are generated. Some actions
will now use a colored border when active instead of just turning green.
Cooldown text will also appear on the top layer of actions too. If you
see any funky lookin' icons (namely their borders), let me know.
refactor: Bluespace Golem's teleport action is now a cooldown action.
fix: Construct actions go to the middle of the screen like expected. 
/🆑
2022-12-03 19:01:08 -08:00

198 lines
7.0 KiB
Plaintext

//Nearsightedness restricts your vision by several tiles.
/datum/mutation/human/nearsight
name = "Near Sightness"
desc = "The holder of this mutation has poor eyesight."
quality = MINOR_NEGATIVE
text_gain_indication = "<span class='danger'>You can't see very well.</span>"
/datum/mutation/human/nearsight/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
owner.become_nearsighted(GENETIC_MUTATION)
/datum/mutation/human/nearsight/on_losing(mob/living/carbon/human/owner)
if(..())
return
owner.cure_nearsighted(GENETIC_MUTATION)
///Blind makes you blind. Who knew?
/datum/mutation/human/blind
name = "Blindness"
desc = "Renders the subject completely blind."
quality = NEGATIVE
text_gain_indication = "<span class='danger'>You can't seem to see anything.</span>"
/datum/mutation/human/blind/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
owner.become_blind(GENETIC_MUTATION)
/datum/mutation/human/blind/on_losing(mob/living/carbon/human/owner)
if(..())
return
owner.cure_blind(GENETIC_MUTATION)
///Thermal Vision lets you see mobs through walls
/datum/mutation/human/thermal
name = "Thermal Vision"
desc = "The user of this genome can visually perceive the unique human thermal signature."
quality = POSITIVE
difficulty = 18
text_gain_indication = "<span class='notice'>You can see the heat rising off of your skin...</span>"
text_lose_indication = "<span class='notice'>You can no longer see the heat rising off of your skin...</span>"
instability = 25
synchronizer_coeff = 1
power_coeff = 1
energy_coeff = 1
power_path = /datum/action/cooldown/spell/thermal_vision
/datum/mutation/human/thermal/on_losing(mob/living/carbon/human/owner)
if(..())
return
// Something went wront and we still have the thermal vision from our power, no cheating.
if(HAS_TRAIT_FROM(owner, TRAIT_THERMAL_VISION, GENETIC_MUTATION))
REMOVE_TRAIT(owner, TRAIT_THERMAL_VISION, GENETIC_MUTATION)
owner.update_sight()
/datum/mutation/human/thermal/modify()
. = ..()
var/datum/action/cooldown/spell/thermal_vision/to_modify = .
if(!istype(to_modify)) // null or invalid
return
to_modify.eye_damage = 10 * GET_MUTATION_SYNCHRONIZER(src)
to_modify.thermal_duration = 10 SECONDS * GET_MUTATION_POWER(src)
/datum/action/cooldown/spell/thermal_vision
name = "Activate Thermal Vision"
desc = "You can see thermal signatures, at the cost of your eyesight."
button_icon = 'icons/mob/actions/actions_changeling.dmi'
button_icon_state = "augmented_eyesight"
cooldown_time = 25 SECONDS
spell_requirements = NONE
/// How much eye damage is given on cast
var/eye_damage = 10
/// The duration of the thermal vision
var/thermal_duration = 10 SECONDS
/datum/action/cooldown/spell/thermal_vision/Remove(mob/living/remove_from)
REMOVE_TRAIT(remove_from, TRAIT_THERMAL_VISION, GENETIC_MUTATION)
remove_from.update_sight()
return ..()
/datum/action/cooldown/spell/thermal_vision/is_valid_target(atom/cast_on)
return isliving(cast_on) && !HAS_TRAIT(cast_on, TRAIT_THERMAL_VISION)
/datum/action/cooldown/spell/thermal_vision/cast(mob/living/cast_on)
. = ..()
ADD_TRAIT(cast_on, TRAIT_THERMAL_VISION, GENETIC_MUTATION)
cast_on.update_sight()
to_chat(cast_on, span_info("You focus your eyes intensely, as your vision becomes filled with heat signatures."))
addtimer(CALLBACK(src, PROC_REF(deactivate), cast_on), thermal_duration)
/datum/action/cooldown/spell/thermal_vision/proc/deactivate(mob/living/cast_on)
if(QDELETED(cast_on) || !HAS_TRAIT_FROM(cast_on, TRAIT_THERMAL_VISION, GENETIC_MUTATION))
return
REMOVE_TRAIT(cast_on, TRAIT_THERMAL_VISION, GENETIC_MUTATION)
cast_on.update_sight()
to_chat(cast_on, span_info("You blink a few times, your vision returning to normal as a dull pain settles in your eyes."))
if(iscarbon(cast_on))
var/mob/living/carbon/carbon_cast_on = cast_on
carbon_cast_on.adjustOrganLoss(ORGAN_SLOT_EYES, eye_damage)
///X-ray Vision lets you see through walls.
/datum/mutation/human/xray
name = "X Ray Vision"
desc = "A strange genome that allows the user to see between the spaces of walls." //actual x-ray would mean you'd constantly be blasting rads, wich might be fun for later //hmb
text_gain_indication = "<span class='notice'>The walls suddenly disappear!</span>"
instability = 35
locked = TRUE
/datum/mutation/human/xray/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
ADD_TRAIT(owner, TRAIT_XRAY_VISION, GENETIC_MUTATION)
owner.update_sight()
/datum/mutation/human/xray/on_losing(mob/living/carbon/human/owner)
if(..())
return
REMOVE_TRAIT(owner, TRAIT_XRAY_VISION, GENETIC_MUTATION)
owner.update_sight()
///Laser Eyes lets you shoot lasers from your eyes!
/datum/mutation/human/laser_eyes
name = "Laser Eyes"
desc = "Reflects concentrated light back from the eyes."
quality = POSITIVE
locked = TRUE
difficulty = 16
text_gain_indication = "<span class='notice'>You feel pressure building up behind your eyes.</span>"
layer_used = FRONT_MUTATIONS_LAYER
limb_req = BODY_ZONE_HEAD
/datum/mutation/human/laser_eyes/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
..()
if(!(type in visual_indicators))
visual_indicators[type] = list(mutable_appearance('icons/effects/genetics.dmi', "lasereyes", -FRONT_MUTATIONS_LAYER))
/datum/mutation/human/laser_eyes/on_acquiring(mob/living/carbon/human/H)
. = ..()
if(.)
return
RegisterSignal(H, COMSIG_MOB_ATTACK_RANGED, PROC_REF(on_ranged_attack))
/datum/mutation/human/laser_eyes/on_losing(mob/living/carbon/human/H)
. = ..()
if(.)
return
UnregisterSignal(H, COMSIG_MOB_ATTACK_RANGED)
/datum/mutation/human/laser_eyes/get_visual_indicator()
return visual_indicators[type][1]
///Triggers on COMSIG_MOB_ATTACK_RANGED. Does the projectile shooting.
/datum/mutation/human/laser_eyes/proc/on_ranged_attack(mob/living/carbon/human/source, atom/target, modifiers)
SIGNAL_HANDLER
if(!source.combat_mode)
return
to_chat(source, span_warning("You shoot with your laser eyes!"))
source.changeNext_move(CLICK_CD_RANGE)
source.newtonian_move(get_dir(target, source))
var/obj/projectile/beam/laser_eyes/LE = new(source.loc)
LE.firer = source
LE.def_zone = ran_zone(source.zone_selected)
LE.preparePixelProjectile(target, source, modifiers)
INVOKE_ASYNC(LE, TYPE_PROC_REF(/obj/projectile, fire))
playsound(source, 'sound/weapons/taser2.ogg', 75, TRUE)
///Projectile type used by laser eyes
/obj/projectile/beam/laser_eyes
name = "beam"
icon = 'icons/effects/genetics.dmi'
icon_state = "eyelasers"
/datum/mutation/human/illiterate
name = "Illiterate"
desc = "Causes a severe case of Aphasia that prevents reading or writing."
quality = NEGATIVE
text_gain_indication = "<span class='danger'>You feel unable to read or write.</span>"
text_lose_indication = "<span class='danger'>You feel able to read and write again.</span>"
/datum/mutation/human/illiterate/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
ADD_TRAIT(owner, TRAIT_ILLITERATE, GENETIC_MUTATION)
/datum/mutation/human/illiterate/on_losing(mob/living/carbon/human/owner)
if(..())
return
REMOVE_TRAIT(owner, TRAIT_ILLITERATE, GENETIC_MUTATION)