Refactors Mousepointers + Code improvements (#29960)

* blah

* tweaks

* refactor

* awesome

* put everything in mouse_icons folder

* make spells work

* update twin

* tweak

* woop woop

* remove dynamic mousepointers

* bam
This commit is contained in:
Contrabang
2025-09-02 20:47:56 +00:00
committed by GitHub
parent 7162b71b4a
commit 7125897ebb
26 changed files with 80 additions and 77 deletions
+7
View File
@@ -394,3 +394,10 @@
#define NPC_DEFAULT_MIN_TEMP 250
/// Default maximum body temperature mobs can exist in before taking damage
#define NPC_DEFAULT_MAX_TEMP 350
#define MP_SPELL_PRIORITY 1
#define MP_THROW_MODE_PRIORITY 2
#define MP_GIVE_MODE_PRIORITY 3
#define MP_AUTO_GUN_PRIORITY 4
#define MP_CLOWN_CAR_PRIORITY 5
#define MP_MECHA_PRIORITY 6
-4
View File
@@ -53,8 +53,6 @@ to inform the game this action was expected and its fine
if(QDELETED(object)) // Yep, you can click on qdeleted things before they have time to nullspace. Fun.
return
SEND_SIGNAL(src, COMSIG_CLIENT_MOUSEDOWN, object, location, control, params)
if(mouse_down_icon)
mouse_pointer_icon = mouse_down_icon
var/delay = mob.CanMobAutoclick(object, location, params)
if(delay)
selected_target[1] = object
@@ -66,8 +64,6 @@ to inform the game this action was expected and its fine
/client/MouseUp(object, location, control, params)
if(SEND_SIGNAL(src, COMSIG_CLIENT_MOUSEUP, object, location, control, params) & COMPONENT_CLIENT_MOUSEUP_INTERCEPT)
click_intercept_time = world.time
if(mouse_up_icon)
mouse_pointer_icon = mouse_up_icon
selected_target[1] = null
/mob/proc/CanMobAutoclick(object, location, params)
+3 -4
View File
@@ -97,6 +97,7 @@
if(!QDELETED(clicker))
UnregisterSignal(clicker, list(COMSIG_CLIENT_MOUSEDOWN, COMSIG_CLIENT_MOUSEUP, COMSIG_CLIENT_MOUSEDRAG))
clicker.mob.remove_mousepointer(MP_AUTO_GUN_PRIORITY)
mouse_status = AUTOFIRE_MOUSEUP // In regards to the component there's no click anymore to care about.
clicker = null
if(!QDELETED(shooter))
@@ -164,8 +165,7 @@
return
autofire_stat = AUTOFIRE_STAT_FIRING
clicker.mouse_override_icon = 'icons/effects/mouse_pointers/weapon_pointer.dmi'
clicker.mouse_pointer_icon = clicker.mouse_override_icon
clicker.mob.add_mousepointer(MP_AUTO_GUN_PRIORITY, 'icons/mouse_icons/weapon_pointer.dmi')
if(mouse_status == AUTOFIRE_MOUSEUP) // See mouse_status definition for the reason for this.
RegisterSignal(clicker, COMSIG_CLIENT_MOUSEUP, PROC_REF(on_mouse_up))
@@ -206,8 +206,7 @@
STOP_PROCESSING(SSprojectiles, src)
autofire_stat = AUTOFIRE_STAT_ALERT
if(clicker)
clicker.mouse_override_icon = null
clicker.mouse_pointer_icon = clicker.mouse_override_icon
clicker.mob.remove_mousepointer(MP_AUTO_GUN_PRIORITY)
UnregisterSignal(clicker, COMSIG_CLIENT_MOUSEDRAG)
if(!QDELETED(shooter))
UnregisterSignal(shooter, COMSIG_MOB_SWAPPED_HANDS)
+8 -8
View File
@@ -136,7 +136,7 @@ GLOBAL_LIST_INIT(spells, typesof(/datum/spell))
user.ranged_ability = src
ranged_ability_user = user
user.client.click_intercept = new /datum/click_intercept/proc_holder(user.client, user.ranged_ability)
add_mousepointer(user.client)
add_mousepointer(user)
active = TRUE
if(msg)
to_chat(user, msg)
@@ -145,13 +145,13 @@ GLOBAL_LIST_INIT(spells, typesof(/datum/spell))
/datum/spell/proc/update_spell_icon()
return
/datum/spell/proc/add_mousepointer(client/C)
if(C && ranged_mousepointer && C.mouse_pointer_icon == initial(C.mouse_pointer_icon))
C.mouse_pointer_icon = ranged_mousepointer
/datum/spell/proc/add_mousepointer(mob/user)
if(ranged_mousepointer)
user.add_mousepointer(MP_SPELL_PRIORITY, ranged_mousepointer)
/datum/spell/proc/remove_mousepointer(client/C)
if(C && ranged_mousepointer && C.mouse_pointer_icon == ranged_mousepointer)
C.mouse_pointer_icon = initial(C.mouse_pointer_icon)
/datum/spell/proc/remove_mousepointer(mob/user)
if(ranged_mousepointer)
user.remove_mousepointer(MP_SPELL_PRIORITY)
/datum/spell/proc/remove_ranged_ability(mob/user, msg)
if(!user || (user.ranged_ability && user.ranged_ability != src)) //To avoid removing the wrong ability
@@ -162,7 +162,7 @@ GLOBAL_LIST_INIT(spells, typesof(/datum/spell))
if(user.client)
qdel(user.client.click_intercept)
user.client.click_intercept = null
remove_mousepointer(user.client)
remove_mousepointer(user)
if(msg)
to_chat(user, msg)
update_spell_icon()
+1 -1
View File
@@ -271,7 +271,7 @@
return TRUE
/datum/spell/horror
ranged_mousepointer = 'icons/effects/cult_target.dmi'
ranged_mousepointer = 'icons/mouse_icons/cult_target.dmi'
var/datum/action/innate/cult/blood_spell/attached_action
/datum/spell/horror/Destroy()
@@ -490,7 +490,7 @@
desc = "Overheats a machine, causing a moderately-sized explosion after a short time."
action_icon_state = "overload_machine"
uses = 4
ranged_mousepointer = 'icons/effects/cult_target.dmi'
ranged_mousepointer = 'icons/mouse_icons/cult_target.dmi'
selection_activated_message = "<span class='notice'>You tap into the station's powernet. Click on a machine to detonate it, or use the ability again to cancel.</span>"
selection_deactivated_message = "<span class='notice'>You release your hold on the powernet.</span>"
@@ -531,7 +531,7 @@
desc = "Animates a targeted machine, causing it to attack anyone nearby."
action_icon_state = "override_machine"
uses = 4
ranged_mousepointer = 'icons/effects/override_machine_target.dmi'
ranged_mousepointer = 'icons/mouse_icons/override_machine_target.dmi'
selection_activated_message = "<span class='notice'>You tap into the station's powernet. Click on a machine to animate it, or use the ability again to cancel.</span>"
selection_deactivated_message = "<span class='notice'>You release your hold on the powernet.</span>"
@@ -888,7 +888,7 @@
desc = "Shocks a cyborg back to 'life' after a short delay."
action_icon_state = "overload_machine"
uses = 2
ranged_mousepointer = 'icons/effects/overload_machine_target.dmi'
ranged_mousepointer = 'icons/mouse_icons/explode_machine_target.dmi'
selection_activated_message = "<span class='notice'>Call to address 0FFFFFFF in APC logic thread, awaiting user response.</span>"
selection_deactivated_message = "<span class='notice'>APC logic thread restarting...</span>"
var/is_active = FALSE
@@ -934,7 +934,7 @@
name = "Roll Over"
action_icon_state = "roll_over"
desc = "Allows you to roll over in the direction of your choosing, crushing anything in your way."
ranged_mousepointer = 'icons/effects/cult_target.dmi'
ranged_mousepointer = 'icons/mouse_icons/cult_target.dmi'
selection_activated_message = "<span class='notice'>Your inner servos shift as you prepare to roll around. Click adjacent tiles to roll into them!</span>"
selection_deactivated_message = "<span class='notice'>You disengage your rolling protocols.</span>"
COOLDOWN_DECLARE(time_til_next_tilt)
+8 -15
View File
@@ -5,24 +5,17 @@
armor = list(MELEE = 30, BULLET = 30, LASER = 15, ENERGY = 20, BOMB = 20, RAD = 0, FIRE = 100)
destruction_sleep_duration = 4 SECONDS
/obj/mecha/combat/moved_inside(mob/living/carbon/human/H as mob)
/obj/mecha/combat/moved_inside(mob/living/carbon/human/H)
if(..())
if(H.client)
H.client.mouse_pointer_icon = file("icons/mecha/mecha_mouse.dmi")
return 1
else
return 0
H.add_mousepointer(MP_MECHA_PRIORITY, 'icons/mouse_icons/mecha_mouse.dmi')
return TRUE
/obj/mecha/combat/mmi_moved_inside(obj/item/mmi/mmi_as_oc as obj, mob/user as mob)
/obj/mecha/combat/mmi_moved_inside(obj/item/mmi/mmi_as_oc, mob/user as mob)
if(..())
if(occupant.client)
occupant.client.mouse_pointer_icon = file("icons/mecha/mecha_mouse.dmi")
return 1
else
return 0
occupant.add_mousepointer(MP_MECHA_PRIORITY, 'icons/mouse_icons/mecha_mouse.dmi')
return TRUE
/obj/mecha/combat/go_out()
if(occupant && occupant.client)
occupant.client.mouse_pointer_icon = initial(occupant.client.mouse_pointer_icon)
if(occupant)
occupant.remove_mousepointer(MP_MECHA_PRIORITY)
..()
+3
View File
@@ -1076,3 +1076,6 @@ GLOBAL_DATUM_INIT(welding_sparks, /mutable_appearance, mutable_appearance('icons
if(iscarbon(user))
var/mob/living/carbon/C = user
C.update_hands_hud()
/obj/item/proc/on_hands_swap(mob/user, in_active_hand)
return
-7
View File
@@ -134,13 +134,6 @@
/// The client's movement keybindings to directions, which work regardless of modifiers.
var/list/movement_kb_dirs = list()
/// Used to make a special mouse cursor, this one for mouse up icon
var/mouse_up_icon = null
/// Used to make a special mouse cursor, this one for mouse up icon
var/mouse_down_icon = null
/// Used to override the mouse cursor so it doesnt get reset
var/mouse_override_icon = null
/// Autoclick list of two elements, first being the clicked thing, second being the parameters.
var/list/atom/selected_target[2]
/// Used in MouseDrag to preserve the original mouse click parameters
@@ -233,6 +233,8 @@
return
hand = !hand
update_hands_hud()
r_hand?.on_hands_swap(src, hand == HAND_BOOL_RIGHT)
l_hand?.on_hands_swap(src, hand == HAND_BOOL_LEFT)
SEND_SIGNAL(src, COMSIG_CARBON_SWAP_HANDS)
@@ -706,24 +708,18 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
if(I)
SEND_SIGNAL(I, COMSIG_CARBON_TOGGLE_THROW, in_throw_mode)
#define THROW_MODE_ICON 'icons/effects/cult_target.dmi'
/mob/living/carbon/proc/throw_mode_off()
in_throw_mode = FALSE
if(throw_icon) //in case we don't have the HUD and we use the hotkey
throw_icon.icon_state = "act_throw_off"
if(client?.mouse_pointer_icon == THROW_MODE_ICON)
client.mouse_pointer_icon = initial(client.mouse_pointer_icon)
remove_mousepointer(MP_THROW_MODE_PRIORITY)
/mob/living/carbon/proc/throw_mode_on()
SIGNAL_HANDLER //This signal is here so we can turn throw mode back on via carp when an object is caught
in_throw_mode = TRUE
if(throw_icon)
throw_icon.icon_state = "act_throw_on"
if(client?.mouse_pointer_icon == initial(client.mouse_pointer_icon))
client.mouse_pointer_icon = THROW_MODE_ICON
#undef THROW_MODE_ICON
add_mousepointer(MP_THROW_MODE_PRIORITY, 'icons/mouse_icons/cult_target.dmi')
/mob/proc/throw_item(atom/target)
return
+2 -2
View File
@@ -70,14 +70,14 @@
/datum/click_intercept/give/New(client/C)
..()
holder.mouse_pointer_icon = 'icons/mouse_icons/give_item.dmi'
holder.mob.add_mousepointer(MP_GIVE_MODE_PRIORITY, 'icons/mouse_icons/give_item.dmi')
to_chat(holder, "<span class='notice'>You can now left click on someone to give them your held item.</span>")
RegisterSignal(holder.mob.get_active_hand(), list(COMSIG_PARENT_QDELETING, COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED), PROC_REF(signal_qdel))
RegisterSignal(holder.mob, list(SIGNAL_ADDTRAIT(TRAIT_HANDS_BLOCKED), COMSIG_CARBON_SWAP_HANDS), PROC_REF(signal_qdel))
/datum/click_intercept/give/Destroy(force = FALSE, ...)
holder.mouse_pointer_icon = initial(holder.mouse_pointer_icon)
holder.mob.remove_mousepointer(MP_GIVE_MODE_PRIORITY)
if(!item_offered)
to_chat(holder.mob, "<span class='notice'>You're no longer trying to give someone your held item.</span>")
return ..()
-4
View File
@@ -62,11 +62,7 @@
return ..()
/mob/living/ghostize(can_reenter_corpse = 1)
var/prev_client = client
. = ..()
if(.)
if(ranged_ability && prev_client)
ranged_ability.remove_mousepointer(prev_client)
SEND_SIGNAL(src, COMSIG_LIVING_GHOSTIZED)
/// Legacy method for simplemobs to handle turning off their AI.
-2
View File
@@ -1,7 +1,5 @@
/mob/living/Logout()
update_z(null)
if(ranged_ability && client)
ranged_ability.remove_mousepointer(client)
if(isobj(loc))
var/obj/our_location = loc
if(length(our_location.client_mobs_in_contents))
@@ -295,7 +295,7 @@
desc = "Changes the color of a selected light."
action_icon = 'icons/effects/random_spawners.dmi'
action_icon_state = "glowstick"
ranged_mousepointer = 'icons/mecha/mecha_mouse.dmi'
ranged_mousepointer = 'icons/mouse_icons/mecha_mouse.dmi'
base_cooldown = 30 SECONDS
cooldown_min = 5 SECONDS
level_max = 5
@@ -367,7 +367,7 @@
desc = "Recharge an APC, Borg, or Mech with power directly from your SMES."
action_icon = 'icons/obj/power.dmi'
action_icon_state = "smes-o"
ranged_mousepointer = 'icons/mecha/mecha_mouse.dmi'
ranged_mousepointer = 'icons/mouse_icons/mecha_mouse.dmi'
base_cooldown = 120 SECONDS
cooldown_min = 30 SECONDS
level_max = 7
@@ -448,7 +448,7 @@
desc = "Repair an APC, Borg, or Mech with large numbers of robotic nanomachines!"
action_icon = 'icons/obj/surgery.dmi'
action_icon_state = "tube"
ranged_mousepointer = 'icons/mecha/mecha_mouse.dmi'
ranged_mousepointer = 'icons/mouse_icons/mecha_mouse.dmi'
base_cooldown = 150 SECONDS
cooldown_min = 30 SECONDS
level_max = 7
@@ -550,7 +550,7 @@
desc = "Repair the wires in an airlock that still has an intact AI control wire."
action_icon = 'icons/obj/doors/doorint.dmi'
action_icon_state = "door_closed"
ranged_mousepointer = 'icons/mecha/mecha_mouse.dmi'
ranged_mousepointer = 'icons/mouse_icons/mecha_mouse.dmi'
base_cooldown = 60 SECONDS
cooldown_min = 60 SECONDS
level_max = 5
@@ -615,7 +615,7 @@
desc = "Deploy a nanofrost globule to a target to rapidly extinguish plasmafires."
action_icon = 'icons/effects/effects.dmi'
action_icon_state = "frozen_smoke_capsule"
ranged_mousepointer = 'icons/mecha/mecha_mouse.dmi'
ranged_mousepointer = 'icons/mouse_icons/mecha_mouse.dmi'
base_cooldown = 60 SECONDS
cooldown_min = 30 SECONDS
level_max = 3
@@ -731,7 +731,7 @@
desc = "Replace damaged or missing lightbulbs."
action_icon = 'icons/obj/janitor.dmi'
action_icon_state = "lightreplacer0"
ranged_mousepointer = 'icons/mecha/mecha_mouse.dmi'
ranged_mousepointer = 'icons/mouse_icons/mecha_mouse.dmi'
base_cooldown = 30 SECONDS
cooldown_min = 5 SECONDS
level_max = 5
@@ -788,7 +788,7 @@
desc = "Heal a crew member with large numbers of robotic nanomachines!"
action_icon = 'icons/obj/surgery.dmi'
action_icon_state = "scalpel_laser1_on"
ranged_mousepointer = 'icons/mecha/mecha_mouse.dmi'
ranged_mousepointer = 'icons/mouse_icons/mecha_mouse.dmi'
base_cooldown = 150 SECONDS
cooldown_min = 30 SECONDS
level_max = 10
@@ -930,7 +930,7 @@
desc = "Deploy an area of metal foam to rapidly repair and seal hull breaches."
action_icon = 'icons/obj/structures.dmi'
action_icon_state = "reinforced"
ranged_mousepointer = 'icons/mecha/mecha_mouse.dmi'
ranged_mousepointer = 'icons/mouse_icons/mecha_mouse.dmi'
base_cooldown = 180 SECONDS
cooldown_min = 30 SECONDS
level_max = 5
@@ -983,7 +983,7 @@
desc = "Deploy a holographic sign to alert crewmembers to potential hazards."
action_icon = 'icons/obj/device.dmi'
action_icon_state = "signmaker"
ranged_mousepointer = 'icons/mecha/mecha_mouse.dmi'
ranged_mousepointer = 'icons/mouse_icons/mecha_mouse.dmi'
base_cooldown = 30 SECONDS
cooldown_min = 30 SECONDS
level_max = 8
@@ -1052,7 +1052,7 @@
desc = "Download a program from Clowns.NT to be able to play bike horn sounds on demand."
action_icon = 'icons/obj/items.dmi'
action_icon_state = "bike_horn"
ranged_mousepointer = 'icons/mecha/mecha_mouse.dmi'
ranged_mousepointer = 'icons/mouse_icons/mecha_mouse.dmi'
base_cooldown = 30 SECONDS
cooldown_min = 15 SECONDS
level_max = 10
@@ -1170,7 +1170,7 @@
desc = "Illuminate a hologram to notify or beckon crew."
action_icon = 'icons/mob/telegraphing/telegraph_holographic.dmi'
action_icon_state = "target_circle"
ranged_mousepointer = 'icons/mecha/mecha_mouse.dmi'
ranged_mousepointer = 'icons/mouse_icons/mecha_mouse.dmi'
base_cooldown = 15 SECONDS
cooldown_min = 15 SECONDS
level_max = 1
@@ -153,7 +153,6 @@
else
inventory.deactivate()
update_icons()
return
//deselect_module(module) - Deselects the module slot specified by "module"
/mob/living/silicon/robot/proc/deselect_module(module) //Module is 1-3
@@ -164,7 +163,6 @@
var/atom/movable/screen/robot/active_module/inventory = inventory_screens[i]
inventory.deactivate()
update_icons()
return
//toggle_module(module) - Toggles the selection of the module slot specified by "module".
/mob/living/silicon/robot/proc/toggle_module(module) //Module is 1-3
@@ -27,7 +27,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
/// A reference to the type of cyborg it is, i.e. Engineering, Security, Medical etc.
var/obj/item/robot_module/module = null
/// The item the borg currently has selected, or null if nothing is selected
var/selected_item
var/obj/item/selected_item
/// The list of up to 3 items the borg can have "equipped". The contents will either be CYBORG_EMPTY_MODULE for nothing, or the item selected
var/list/all_active_items = list(CYBORG_EMPTY_MODULE, CYBORG_EMPTY_MODULE, CYBORG_EMPTY_MODULE)
+21
View File
@@ -1625,3 +1625,24 @@ GLOBAL_LIST_INIT(holy_areas, typecacheof(list(
. = STATUS_UPDATE_HEALTH
if(updating_health)
updatehealth()
/mob/proc/add_mousepointer(priority = INFINITY, new_icon)
mousepointers["[priority]"] = new_icon
update_mousepointer()
/mob/proc/remove_mousepointer(priority)
mousepointers -= "[priority]"
update_mousepointer()
/mob/proc/update_mousepointer()
if(!client)
return
var/lowest_prio = INFINITY
for(var/prio in mousepointers)
prio = text2num(prio)
if(prio < lowest_prio)
lowest_prio = prio
if(lowest_prio == INFINITY)
client.mouse_pointer_icon = null
return
client.mouse_pointer_icon = mousepointers["[lowest_prio]"]
+2
View File
@@ -85,3 +85,5 @@
client.init_verbs()
SEND_SIGNAL(src, COMSIG_MOB_LOGIN)
SEND_SIGNAL(src, COMSIG_MOB_CLIENT_LOGIN, client)
update_mousepointer()
+2
View File
@@ -259,3 +259,5 @@
/// For storing what do_after's something has, key = string, value = amount of interactions of that type happening.
var/list/do_afters
new_attack_chain = TRUE
var/list/mousepointers = list()
@@ -273,19 +273,18 @@
/// Finalizes cannon activation
/obj/tgvehicle/sealed/car/clowncar/proc/activate_cannon()
var/mouse_pointer = 'icons/effects/mouse_pointers/weapon_pointer.dmi'
var/mouse_pointer = 'icons/mouse_icons/weapon_pointer.dmi'
cannonmode = CLOWN_CANNON_READY
for(var/mob/living/driver as anything in return_controllers_with_flag(VEHICLE_CONTROL_DRIVE))
REMOVE_TRAIT(driver, TRAIT_HANDS_BLOCKED, VEHICLE_TRAIT)
if(driver.client.mouse_pointer_icon == initial(driver.client.mouse_pointer_icon))
driver.client.mouse_pointer_icon = mouse_pointer
driver.add_mousepointer(MP_CLOWN_CAR_PRIORITY, mouse_pointer)
/// Finalizes cannon deactivation
/obj/tgvehicle/sealed/car/clowncar/proc/deactivate_cannon()
canmove = TRUE
cannonmode = CLOWN_CANNON_INACTIVE
for(var/mob/living/driver as anything in return_controllers_with_flag(VEHICLE_CONTROL_DRIVE))
driver.client.mouse_pointer_icon = initial(driver.client.mouse_pointer_icon)
driver.remove_mousepointer(MP_CLOWN_CAR_PRIORITY)
ADD_TRAIT(driver, TRAIT_HANDS_BLOCKED, VEHICLE_TRAIT)
/// Fires the cannon where the user clicks
Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

Before

Width:  |  Height:  |  Size: 770 B

After

Width:  |  Height:  |  Size: 770 B

Before

Width:  |  Height:  |  Size: 441 B

After

Width:  |  Height:  |  Size: 441 B

Before

Width:  |  Height:  |  Size: 234 B

After

Width:  |  Height:  |  Size: 234 B

Before

Width:  |  Height:  |  Size: 371 B

After

Width:  |  Height:  |  Size: 371 B

Before

Width:  |  Height:  |  Size: 232 B

After

Width:  |  Height:  |  Size: 232 B