diff --git a/code/__defines/targeting.dm b/code/__defines/targeting.dm
new file mode 100644
index 00000000000..4bbe7345920
--- /dev/null
+++ b/code/__defines/targeting.dm
@@ -0,0 +1,4 @@
+#define TARGET_CAN_MOVE 1
+#define TARGET_CAN_RUN 2
+#define TARGET_CAN_CLICK 4
+#define TARGET_CAN_RADIO 8
\ No newline at end of file
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 797f0385d42..42d815205ac 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -38,8 +38,10 @@
* mob/RangedAttack(atom,params) - used only ranged, only used for tk and laser eyes but could be changed
*/
/mob/proc/ClickOn(var/atom/A, var/params)
+
if(world.time <= next_click) // Hard check, before anything else, to avoid crashing
return
+
next_click = world.time + 1
if(client.buildmode)
@@ -49,19 +51,19 @@
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
- return
+ return 1
if(modifiers["middle"])
MiddleClickOn(A)
- return
+ return 1
if(modifiers["shift"])
ShiftClickOn(A)
- return
+ return 0
if(modifiers["alt"]) // alt and alt-gr (rightalt)
AltClickOn(A)
- return
+ return 1
if(modifiers["ctrl"])
CtrlClickOn(A)
- return
+ return 1
if(stat || paralysis || stunned || weakened)
return
@@ -80,17 +82,14 @@
if(restrained())
setClickCooldown(10)
RestrainedClickOn(A)
- return
+ return 1
if(in_throw_mode)
if(isturf(A) || isturf(A.loc))
throw_item(A)
- return
+ return 1
throw_mode_off()
- if(!istype(A, /obj/item/weapon/gun) && !isturf(A) && !istype(A, /obj/screen))
- last_target_click = world.time
-
var/obj/item/W = get_active_hand()
if(W == A) // Handle attack_self
@@ -99,7 +98,7 @@
update_inv_l_hand(0)
else
update_inv_r_hand(0)
- return
+ return 1
//Atoms on your person
// A is your location but is not a turf; or is on you (backpack); or is on something on you (box in backpack); sdepth is needed here because contents depth does not equate inventory storage depth.
@@ -117,7 +116,7 @@
if(ismob(A)) // No instant mob attacking
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
UnarmedAttack(A, 1)
- return
+ return 1
if(!isturf(loc)) // This is going to stop you from telekinesing from inside a closet, but I don't shed many tears for that
return
@@ -144,8 +143,7 @@
W.afterattack(A, src, 0, params) // 0: not Adjacent
else
RangedAttack(A, params)
-
- return
+ return 1
/mob/proc/setClickCooldown(var/timeout)
next_move = max(world.time + timeout, next_move)
diff --git a/code/_onclick/hud/gun_mode.dm b/code/_onclick/hud/gun_mode.dm
new file mode 100644
index 00000000000..e5d1fbce37d
--- /dev/null
+++ b/code/_onclick/hud/gun_mode.dm
@@ -0,0 +1,66 @@
+/obj/screen/gun
+ name = "gun"
+ icon = 'icons/mob/screen1.dmi'
+ master = null
+ dir = 2
+
+/obj/screen/gun/Click(location, control, params)
+ if(!usr)
+ return
+ return 1
+
+/obj/screen/gun/move
+ name = "Allow Movement"
+ icon_state = "no_walk0"
+ screen_loc = ui_gun2
+
+/obj/screen/gun/move/Click(location, control, params)
+ if(..())
+ var/mob/living/user = usr
+ if(istype(user))
+ if(!user.aiming) user.aiming = new(user)
+ user.aiming.toggle_permission(TARGET_CAN_MOVE)
+ return 1
+ return 0
+
+/obj/screen/gun/item
+ name = "Allow Item Use"
+ icon_state = "no_item0"
+ screen_loc = ui_gun1
+
+/obj/screen/gun/item/Click(location, control, params)
+ if(..())
+ var/mob/living/user = usr
+ if(istype(user))
+ if(!user.aiming) user.aiming = new(user)
+ user.aiming.toggle_permission(TARGET_CAN_CLICK)
+ return 1
+ return 0
+
+/obj/screen/gun/mode
+ name = "Toggle Gun Mode"
+ icon_state = "gun0"
+ screen_loc = ui_gun_select
+
+/obj/screen/gun/mode/Click(location, control, params)
+ if(..())
+ var/mob/living/user = usr
+ if(istype(user))
+ if(!user.aiming) user.aiming = new(user)
+ user.aiming.toggle_active()
+ return 1
+ return 0
+
+/obj/screen/gun/radio
+ name = "Allow Radio Use"
+ icon_state = "no_radio0"
+ screen_loc = ui_gun4
+
+/obj/screen/gun/radio/Click(location, control, params)
+ if(..())
+ var/mob/living/user = usr
+ if(istype(user))
+ if(!user.aiming) user.aiming = new(user)
+ user.aiming.toggle_permission(TARGET_CAN_RADIO)
+ return 1
+ return 0
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 5a9b45bfca3..a73779ef722 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -257,8 +257,6 @@ datum/hud/New(mob/owner)
human_hud(ui_style, ui_color, ui_alpha, mymob) // Pass the player the UI style chosen in preferences
else if(isrobot(mymob))
robot_hud()
- else if(issmall(mymob))
- monkey_hud(ui_style, ui_color, ui_alpha)
else if(isbrain(mymob))
brain_hud(ui_style)
else if(isalien(mymob))
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index ab5d0f6a123..2ee17dedced 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -1,5 +1,7 @@
-/datum/hud/proc/human_hud(var/ui_style='icons/mob/screen1_White.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255, var/mob/living/carbon/human/target)
+/mob/living/carbon/human/instantiate_hud(var/datum/hud/HUD, var/ui_style, var/ui_color, var/ui_alpha)
+ HUD.human_hud(ui_style, ui_color, ui_alpha, src)
+/datum/hud/proc/human_hud(var/ui_style='icons/mob/screen1_White.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255, var/mob/living/carbon/human/target)
var/datum/hud_data/hud_data
if(!istype(target))
hud_data = new()
@@ -354,17 +356,11 @@
mymob.gun_move_icon.color = ui_color
mymob.gun_move_icon.alpha = ui_alpha
- mymob.gun_run_icon = new /obj/screen/gun/run(null)
- mymob.gun_run_icon.icon = ui_style
- mymob.gun_run_icon.color = ui_color
- mymob.gun_run_icon.alpha = ui_alpha
-
mymob.radio_use_icon = new /obj/screen/gun/radio(null)
mymob.radio_use_icon.icon = ui_style
mymob.radio_use_icon.color = ui_color
mymob.radio_use_icon.alpha = ui_alpha
-
mymob.client.screen = null
mymob.client.screen += hud_elements
diff --git a/code/_onclick/hud/monkey.dm b/code/_onclick/hud/monkey.dm
deleted file mode 100644
index d24d9322a56..00000000000
--- a/code/_onclick/hud/monkey.dm
+++ /dev/null
@@ -1,282 +0,0 @@
-/datum/hud/proc/monkey_hud(var/ui_style='icons/mob/screen1_old.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255)
-
- src.adding = list()
- src.other = list()
-
- var/obj/screen/using
- var/obj/screen/inventory/inv_box
-
- using = new /obj/screen()
- using.name = "act_intent"
- using.icon = ui_style
- using.color = ui_color
- using.alpha = ui_alpha
- using.icon_state = mymob.a_intent
- using.screen_loc = ui_acti
- using.layer = 20
- src.adding += using
- action_intent = using
-
-//intent small hud objects
- var/icon/ico
-
- ico = new(ui_style, "black")
- ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
- ico.DrawBox(rgb(255,255,255,1),1,ico.Height()/2,ico.Width()/2,ico.Height())
- using = new /obj/screen( src )
- using.name = I_HELP
- using.icon = ico
- using.screen_loc = ui_acti
- using.layer = 21
- src.adding += using
- help_intent = using
-
- ico = new(ui_style, "black")
- ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
- ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,ico.Height()/2,ico.Width(),ico.Height())
- using = new /obj/screen( src )
- using.name = I_DISARM
- using.icon = ico
- using.screen_loc = ui_acti
- using.layer = 21
- src.adding += using
- disarm_intent = using
-
- ico = new(ui_style, "black")
- ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
- ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,1,ico.Width(),ico.Height()/2)
- using = new /obj/screen( src )
- using.name = I_GRAB
- using.icon = ico
- using.screen_loc = ui_acti
- using.layer = 21
- src.adding += using
- grab_intent = using
-
- ico = new(ui_style, "black")
- ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
- ico.DrawBox(rgb(255,255,255,1),1,1,ico.Width()/2,ico.Height()/2)
- using = new /obj/screen( src )
- using.name = I_HURT
- using.icon = ico
- using.screen_loc = ui_acti
- using.layer = 21
- src.adding += using
- hurt_intent = using
-
-//end intent small hud objects
-
- using = new /obj/screen()
- using.name = "mov_intent"
- using.icon = ui_style
- using.color = ui_color
- using.alpha = ui_alpha
- using.icon_state = (mymob.m_intent == "run" ? "running" : "walking")
- using.screen_loc = ui_movi
- using.layer = 20
- src.adding += using
- move_intent = using
-
- using = new /obj/screen()
- using.name = "drop"
- using.icon = ui_style
- using.color = ui_color
- using.alpha = ui_alpha
- using.icon_state = "act_drop"
- using.screen_loc = ui_drop_throw
- using.layer = 19
- src.adding += using
-
- inv_box = new /obj/screen/inventory()
- inv_box.name = "r_hand"
- inv_box.icon = ui_style
- using.color = ui_color
- using.alpha = ui_alpha
- inv_box.icon_state = "r_hand_inactive"
- if(mymob && !mymob.hand) //This being 0 or null means the right hand is in use
- inv_box.icon_state = "hand_active"
- inv_box.screen_loc = ui_rhand
- inv_box.slot_id = slot_r_hand
- inv_box.layer = 19
- src.r_hand_hud_object = inv_box
- src.adding += inv_box
-
- inv_box = new /obj/screen/inventory()
- inv_box.name = "l_hand"
- inv_box.icon = ui_style
- using.color = ui_color
- using.alpha = ui_alpha
- inv_box.icon_state = "l_hand_inactive"
- if(mymob && mymob.hand) //This being 1 means the left hand is in use
- inv_box.icon_state = "hand_active"
- inv_box.screen_loc = ui_lhand
- inv_box.slot_id = slot_l_hand
- inv_box.layer = 19
- src.l_hand_hud_object = inv_box
- src.adding += inv_box
-
- using = new /obj/screen/inventory()
- using.name = "hand"
- using.icon = ui_style
- using.color = ui_color
- using.alpha = ui_alpha
- using.icon_state = "hand1"
- using.screen_loc = ui_swaphand1
- using.layer = 19
- src.adding += using
-
- using = new /obj/screen/inventory()
- using.name = "hand"
- using.icon = ui_style
- using.color = ui_color
- using.alpha = ui_alpha
- using.icon_state = "hand2"
- using.screen_loc = ui_swaphand2
- using.layer = 19
- src.adding += using
-
- inv_box = new /obj/screen/inventory()
- inv_box.name = "mask"
- inv_box.icon = ui_style
- inv_box.color = ui_color
- inv_box.alpha = ui_alpha
- inv_box.icon_state = "equip"
- inv_box.screen_loc = ui_monkey_mask
- inv_box.slot_id = slot_wear_mask
- inv_box.layer = 19
- src.adding += inv_box
-
- inv_box = new /obj/screen/inventory()
- inv_box.name = "back"
- inv_box.icon = ui_style
- inv_box.color = ui_color
- inv_box.alpha = ui_alpha
- inv_box.icon_state = "equip"
- inv_box.screen_loc = ui_back
- inv_box.slot_id = slot_back
- inv_box.layer = 19
- src.adding += inv_box
-
- mymob.throw_icon = new /obj/screen()
- mymob.throw_icon.icon = ui_style
- mymob.throw_icon.color = ui_color
- mymob.throw_icon.alpha = ui_alpha
- mymob.throw_icon.icon_state = "act_throw_off"
- mymob.throw_icon.name = "throw"
- mymob.throw_icon.screen_loc = ui_drop_throw
-
- mymob.oxygen = new /obj/screen()
- mymob.oxygen.icon = ui_style
- mymob.oxygen.color = ui_color
- mymob.oxygen.alpha = ui_alpha
- mymob.oxygen.icon_state = "oxy0"
- mymob.oxygen.name = "oxygen"
- mymob.oxygen.screen_loc = ui_oxygen
-
- mymob.pressure = new /obj/screen()
- mymob.pressure.icon = ui_style
- mymob.pressure.color = ui_color
- mymob.pressure.alpha = ui_alpha
- mymob.pressure.icon_state = "pressure0"
- mymob.pressure.name = "pressure"
- mymob.pressure.screen_loc = ui_pressure
-
- mymob.toxin = new /obj/screen()
- mymob.toxin.icon = ui_style
- mymob.toxin.color = ui_color
- mymob.toxin.alpha = ui_alpha
- mymob.toxin.icon_state = "tox0"
- mymob.toxin.name = "toxin"
- mymob.toxin.screen_loc = ui_toxin
-
- mymob.internals = new /obj/screen()
- mymob.internals.icon = ui_style
- mymob.internals.color = ui_color
- mymob.internals.alpha = ui_alpha
- mymob.internals.icon_state = "internal0"
- mymob.internals.name = "internal"
- mymob.internals.screen_loc = ui_internal
-
- mymob.fire = new /obj/screen()
- mymob.fire.icon = ui_style
- mymob.fire.color = ui_color
- mymob.fire.alpha = ui_alpha
- mymob.fire.icon_state = "fire0"
- mymob.fire.name = "fire"
- mymob.fire.screen_loc = ui_fire
-
- mymob.bodytemp = new /obj/screen()
- mymob.bodytemp.icon = ui_style
- mymob.bodytemp.color = ui_color
- mymob.bodytemp.alpha = ui_alpha
- mymob.bodytemp.icon_state = "temp1"
- mymob.bodytemp.name = "body temperature"
- mymob.bodytemp.screen_loc = ui_temp
-
- mymob.healths = new /obj/screen()
- mymob.healths.icon = ui_style
- mymob.healths.color = ui_color
- mymob.healths.alpha = ui_alpha
- mymob.healths.icon_state = "health0"
- mymob.healths.name = "health"
- mymob.healths.screen_loc = ui_health
-
- mymob.pullin = new /obj/screen()
- mymob.pullin.icon = ui_style
- mymob.pullin.color = ui_color
- mymob.pullin.alpha = ui_alpha
- mymob.pullin.icon_state = "pull0"
- mymob.pullin.name = "pull"
- mymob.pullin.screen_loc = ui_pull_resist
-
- mymob.blind = new /obj/screen()
- mymob.blind.icon = 'icons/mob/screen1_full.dmi'
- mymob.blind.icon_state = "blackimageoverlay"
- mymob.blind.name = " "
- mymob.blind.screen_loc = "1,1"
- mymob.blind.layer = 0
-
- mymob.flash = new /obj/screen()
- mymob.flash.icon = ui_style
- mymob.flash.icon_state = "blank"
- mymob.flash.name = "flash"
- mymob.flash.screen_loc = ui_entire_screen
- mymob.flash.layer = 17
-
- mymob.zone_sel = new /obj/screen/zone_sel()
- mymob.zone_sel.icon = ui_style
- mymob.zone_sel.color = ui_color
- mymob.zone_sel.alpha = ui_alpha
- mymob.zone_sel.overlays.Cut()
- mymob.zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[mymob.zone_sel.selecting]")
-
- //Handle the gun settings buttons
- mymob.gun_setting_icon = new /obj/screen/gun/mode(null)
- if (mymob.client)
- if (mymob.client.gun_mode) // If in aim mode, correct the sprite
- mymob.gun_setting_icon.set_dir(2)
- for(var/obj/item/weapon/gun/G in mymob) // If targeting someone, display other buttons
- if (G.aim_targets)
- mymob.item_use_icon = new /obj/screen/gun/item(null)
- if (mymob.client.target_can_click)
- mymob.item_use_icon.set_dir(1)
- src.adding += mymob.item_use_icon
- mymob.radio_use_icon = new /obj/screen/gun/radio(null)
- if (mymob.client.target_can_radio)
- mymob.radio_use_icon.set_dir(1)
- src.adding += mymob.radio_use_icon
- mymob.gun_move_icon = new /obj/screen/gun/move(null)
- if (mymob.client.target_can_move)
- mymob.gun_move_icon.set_dir(1)
- mymob.gun_run_icon = new /obj/screen/gun/run(null)
- if (mymob.client.target_can_run)
- mymob.gun_run_icon.set_dir(1)
- src.adding += mymob.gun_run_icon
- src.adding += mymob.gun_move_icon
-
- mymob.client.screen = null
-
- mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.pressure, mymob.toxin, mymob.bodytemp, mymob.internals, mymob.fire, mymob.healths, mymob.pullin, mymob.blind, mymob.flash, mymob.gun_setting_icon) //, mymob.hands, mymob.rest, mymob.sleep, mymob.mach )
- mymob.client.screen += src.adding + src.other
-
- return
diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm
index eb31c7019b5..95f8f3c9d3a 100644
--- a/code/_onclick/hud/robot.dm
+++ b/code/_onclick/hud/robot.dm
@@ -153,31 +153,13 @@ var/obj/screen/robot_inventory
//Handle the gun settings buttons
mymob.gun_setting_icon = new /obj/screen/gun/mode(null)
- if (mymob.client)
- if (mymob.client.gun_mode) // If in aim mode, correct the sprite
- mymob.gun_setting_icon.set_dir(2)
- for(var/obj/item/weapon/gun/G in mymob) // If targeting someone, display other buttons
- if (G.aim_targets)
- mymob.item_use_icon = new /obj/screen/gun/item(null)
- if (mymob.client.target_can_click)
- mymob.item_use_icon.set_dir(1)
- src.adding += mymob.item_use_icon
- mymob.radio_use_icon = new /obj/screen/gun/radio(null)
- if (mymob.client.target_can_radio)
- mymob.radio_use_icon.set_dir(1)
- src.adding += mymob.radio_use_icon
- mymob.gun_move_icon = new /obj/screen/gun/move(null)
- if (mymob.client.target_can_move)
- mymob.gun_move_icon.set_dir(1)
- mymob.gun_run_icon = new /obj/screen/gun/run(null)
- if (mymob.client.target_can_run)
- mymob.gun_run_icon.set_dir(1)
- src.adding += mymob.gun_run_icon
- src.adding += mymob.gun_move_icon
+ mymob.item_use_icon = new /obj/screen/gun/item(null)
+ mymob.gun_move_icon = new /obj/screen/gun/move(null)
+ mymob.radio_use_icon = new /obj/screen/gun/radio(null)
mymob.client.screen = null
- mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.fire, mymob.hands, mymob.healths, mymob:cells, mymob.pullin, mymob.blind, mymob.flash, mymob.gun_setting_icon, robot_inventory) //, mymob.rest, mymob.sleep, mymob.mach )
+ mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.fire, mymob.hands, mymob.healths, mymob:cells, mymob.pullin, mymob.blind, mymob.flash, robot_inventory, mymob.gun_setting_icon)
mymob.client.screen += src.adding + src.other
return
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 1f30726c072..d0904aa4664 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -12,7 +12,6 @@
layer = 20.0
unacidable = 1
var/obj/master = null //A reference to the object in the slot. Grabs or items, generally.
- var/gun_click_time = -100 //I'm lazy.
/obj/screen/Destroy()
master = null
@@ -95,38 +94,6 @@
usr.ClickOn(master)
return 1
-/obj/screen/gun
- name = "gun"
- icon = 'icons/mob/screen1.dmi'
- master = null
- dir = 2
-
- move
- name = "Allow Walking"
- icon_state = "no_walk0"
- screen_loc = ui_gun2
-
- run
- name = "Allow Running"
- icon_state = "no_run0"
- screen_loc = ui_gun3
-
- item
- name = "Allow Item Use"
- icon_state = "no_item0"
- screen_loc = ui_gun1
-
- mode
- name = "Toggle Gun Mode"
- icon_state = "gun0"
- screen_loc = ui_gun_select
- //dir = 1
-
- radio
- name = "Allow Radio Use"
- icon_state = "no_radio0"
- screen_loc = ui_gun4
-
/obj/screen/zone_sel
name = "damage zone"
icon_state = "zone_sel"
@@ -201,7 +168,6 @@
/obj/screen/Click(location, control, params)
if(!usr) return 1
-
switch(name)
if("toggle")
if(usr.hud_used.inventory_shown)
@@ -431,46 +397,6 @@
if("module3")
if(istype(usr, /mob/living/silicon/robot))
usr:toggle_module(3)
-
- if("Allow Walking", "Disallow Walking")
- if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes.
- return
- if(!istype(usr.get_active_hand(),/obj/item/weapon/gun))
- usr << "You need your gun in your active hand to do that!"
- return
- usr.client.AllowTargetMove()
- gun_click_time = world.time
-
- if("Allow Running", "Disallow Running")
- if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes.
- return
- if(!istype(usr.get_active_hand(),/obj/item/weapon/gun))
- usr << "You need your gun in your active hand to do that!"
- return
- usr.client.AllowTargetRun()
- gun_click_time = world.time
-
- if("Allow Item Use", "Disallow Item Use")
- if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes.
- return
- if(!istype(usr.get_active_hand(),/obj/item/weapon/gun))
- usr << "You need your gun in your active hand to do that!"
- return
- usr.client.AllowTargetClick()
- gun_click_time = world.time
-
- if("Toggle Gun Mode")
- usr.client.ToggleGunMode()
-
- if("Allow Radio Use", "Disallow Radio Use")
- if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes.
- return
- if(!istype(usr.get_active_hand(),/obj/item/weapon/gun))
- usr << "You need your gun in your active hand to do that!"
- return
- usr.client.AllowTargetRadio()
- gun_click_time = world.time
-
else
return 0
return 1
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index e0d7ddad3a0..a27dd2d84b3 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -949,7 +949,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
/obj/item/device/pda/proc/create_message(var/mob/living/U = usr, var/obj/item/device/pda/P, var/tap = 1)
if(tap)
U.visible_message("\The [U] taps on \his PDA's screen.")
- U.last_target_click = world.time
var/t = input(U, "Please enter message", P.name, null) as text
t = sanitize(t)
//t = readd_quotes(t)
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index affde77733b..16c810a8a0c 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -273,13 +273,13 @@ var/global/list/default_medbay_channels = list(
// Fix for permacell radios, but kinda eh about actually fixing them.
if(!M || !message) return 0
+ if(istype(M)) M.trigger_aiming(TARGET_CAN_RADIO)
+
// Uncommenting this. To the above comment:
// The permacell radios aren't suppose to be able to transmit, this isn't a bug and this "fix" is just making radio wires useless. -Giacom
if(wires.IsIndexCut(WIRE_TRANSMIT)) // The device has to have all its wires and shit intact
return 0
- M.last_target_radio = world.time // For the projectile targeting system
-
if(!radio_connection)
set_frequency(frequency)
diff --git a/code/modules/client/ui_style.dm b/code/modules/client/ui_style.dm
index 12521a6a1eb..2802d25e60b 100644
--- a/code/modules/client/ui_style.dm
+++ b/code/modules/client/ui_style.dm
@@ -38,7 +38,6 @@
icons.Add(usr.gun_setting_icon)
icons.Add(usr.item_use_icon)
icons.Add(usr.gun_move_icon)
- icons.Add(usr.gun_run_icon)
icons.Add(usr.radio_use_icon)
var/icon/ic = all_ui_styles[UI_style_new]
diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm
index b3d59aaf7d4..f123f17b55c 100644
--- a/code/modules/clothing/spacesuits/rig/rig.dm
+++ b/code/modules/clothing/spacesuits/rig/rig.dm
@@ -851,7 +851,6 @@
return 0
// AIs are a bit slower than regular and ignore move intent.
- wearer.last_move_intent = world.time + ai_controlled_move_delay
wearer_move_delay = world.time + ai_controlled_move_delay
var/tickcomp = 0
diff --git a/code/modules/clothing/under/accessories/holster.dm b/code/modules/clothing/under/accessories/holster.dm
index 5d71a004203..9ba4ffa5e34 100644
--- a/code/modules/clothing/under/accessories/holster.dm
+++ b/code/modules/clothing/under/accessories/holster.dm
@@ -5,8 +5,8 @@
slot = "utility"
var/obj/item/holstered = null
-/obj/item/clothing/accessory/holster/proc/holster(obj/item/I, mob/user as mob)
- if(holstered)
+/obj/item/clothing/accessory/holster/proc/holster(var/obj/item/I, var/mob/living/user)
+ if(holstered && istype(user))
user << "There is already \a [holstered] holstered here!"
return
@@ -14,6 +14,8 @@
user << "[I] won't fit in [src]!"
return
+ if(istype(user))
+ user.stop_aiming(no_message=1)
holstered = I
user.drop_from_inventory(holstered)
holstered.loc = src
diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm
index 7924bd21296..b2e8c3ca0e0 100644
--- a/code/modules/mob/inventory.dm
+++ b/code/modules/mob/inventory.dm
@@ -165,6 +165,7 @@ var/list/slot_equipment_priority = list( \
// Removes an item from inventory and places it in the target atom.
// If canremove or other conditions need to be checked then use unEquip instead.
/mob/proc/drop_from_inventory(var/obj/item/W, var/atom/Target = null)
+
if(W)
if(!Target)
Target = loc
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index 29eff929dce..ca81defe0f9 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -49,6 +49,8 @@
if(shock_stage >= 10) tally += 3
+ if(aiming && aiming.aiming_at) tally += 5 // Iron sights make you slower, it's a well-known fact.
+
if(FAT in src.mutations)
tally += 1.5
if (bodytemperature < 283.222)
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index d89268fe1b9..3e5731543c8 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -429,17 +429,6 @@ var/global/list/damage_icon_parts = list()
overlays_standing[MUTATIONS_LAYER] = null
if(update_icons) update_icons()
-//Call when target overlay should be added/removed
-/mob/living/carbon/human/update_targeted(var/update_icons=1)
- if (targeted_by && target_locked)
- overlays_standing[TARGETED_LAYER] = target_locked
- else if (!targeted_by && target_locked)
- qdel(target_locked)
- if (!targeted_by)
- overlays_standing[TARGETED_LAYER] = null
- if(update_icons) update_icons()
-
-
/* --------------------------------------- */
//For legacy support.
/mob/living/carbon/human/regenerate_icons()
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 93f9e409224..8507053e232 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -703,14 +703,6 @@
icon_state = module_sprites[icontype]
return
-//Call when target overlay should be added/removed
-/mob/living/silicon/robot/update_targeted()
- if(!targeted_by && target_locked)
- qdel(target_locked)
- updateicon()
- if (targeted_by && target_locked)
- overlays += target_locked
-
/mob/living/silicon/robot/proc/installed_modules()
if(weapon_lock)
src << "\red Weapon lock active, unable to use modules! Count:[weaponlock_time]"
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index acce1e39b19..a66f6b772cd 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -365,14 +365,6 @@
return (0)
return 1
-//Call when target overlay should be added/removed
-/mob/living/simple_animal/update_targeted()
- if(!targeted_by && target_locked)
- qdel(target_locked)
- overlays = null
- if (targeted_by && target_locked)
- overlays += target_locked
-
/mob/living/simple_animal/say(var/message)
var/verb = "says"
if(speak_emote.len)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index d26f5242624..d30e23765ee 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -39,7 +39,6 @@
pain = null
item_use_icon = null
gun_move_icon = null
- gun_run_icon = null
gun_setting_icon = null
spell_masters = null
zone_sel = null
@@ -765,8 +764,8 @@
if(lying)
density = 0
- drop_l_hand()
- drop_r_hand()
+ if(l_hand) unEquip(l_hand)
+ if(r_hand) unEquip(r_hand)
else
density = initial(density)
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index d8b8778f420..e946a9df41d 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -265,7 +265,7 @@
return 0
move_delay = world.time//set move delay
- mob.last_move_intent = world.time + 10
+
switch(mob.m_intent)
if("run")
if(mob.drowsyness > 0)
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 733b086669b..ee40394c78c 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -107,7 +107,7 @@
if(process_projectile(P, user, user, pick("l_foot", "r_foot")))
handle_post_fire(user, user)
user.visible_message(
- "[user] shoots \himself in the foot with \the [src]!",
+ "\The [user] shoots \himself in the foot with \the [src]!",
"You shoot yourself in the foot with \the [src]!"
)
M.drop_item()
@@ -123,17 +123,17 @@
/obj/item/weapon/gun/afterattack(atom/A, mob/living/user, adjacent, params)
if(adjacent) return //A is adjacent, is the user, or is on the user's person
- //decide whether to aim or shoot normally
- var/aiming = 0
- if(user && user.client && !(A in aim_targets))
- if(user.client.gun_mode)
- aiming = PreFire(A,user,params) //They're using the new gun system, locate what they're aiming at.
+ if(!user.aiming)
+ user.aiming = new(user)
- if (!aiming)
- if(user && user.a_intent == I_HELP) //regardless of what happens, refuse to shoot if help intent is on
- user << "\red You refrain from firing your [src] as your intent is set to help."
- else
- Fire(A,user,params) //Otherwise, fire normally.
+ if(user && user.client && user.aiming && user.aiming.active && user.aiming.aiming_at != A)
+ PreFire(A,user,params) //They're using the new gun system, locate what they're aiming at.
+ return
+
+ if(user && user.a_intent == I_HELP) //regardless of what happens, refuse to shoot if help intent is on
+ user << "You refrain from firing your [src] as your intent is set to help."
+ else
+ Fire(A,user,params) //Otherwise, fire normally.
/obj/item/weapon/gun/attack(atom/A, mob/living/user, def_zone)
if (A == user && user.zone_sel.selecting == "mouth" && !mouthshoot)
diff --git a/code/modules/projectiles/targeting.dm b/code/modules/projectiles/targeting.dm
deleted file mode 100644
index de9e115b8ec..00000000000
--- a/code/modules/projectiles/targeting.dm
+++ /dev/null
@@ -1,407 +0,0 @@
-/obj/item/weapon/gun/verb/toggle_firerate()
- set name = "Toggle Continue Aiming"
- set category = "Object"
-
- keep_aim = !keep_aim
-
- if (keep_aim)
- loc << "You will now continue firing when your target moves."
- else
- loc << "You will now only fire once, then lower your aim, when your target moves."
-
-/obj/item/weapon/gun/verb/lower_aim()
- set name = "Lower Aim"
- set category = "Object"
- if(aim_targets)
- stop_aim()
- usr.visible_message(" \The [usr] lowers \the [src]...")
-
-//Removing the lock and the buttons.
-/obj/item/weapon/gun/dropped(mob/user as mob)
- stop_aim()
- if(user && user.client)
- user.client.remove_gun_icons()
- return ..()
-
-/obj/item/weapon/gun/equipped(var/mob/user, var/slot)
- if (slot != slot_l_hand && slot != slot_r_hand)
- stop_aim()
- if (user.client)
- user.client.remove_gun_icons()
- return ..()
-
-//Removes lock from all targets
-/obj/item/weapon/gun/proc/stop_aim()
- if(aim_targets)
- for(var/mob/living/M in aim_targets)
- if(M)
- M.NotTargeted(src) //Untargeting people.
- aim_targets = null
-
-//Compute how to fire.....
-//Return 1 if a target was found, 0 otherwise.
-/obj/item/weapon/gun/proc/PreFire(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, params)
- //Lets not spam it.
- if(lock_time > world.time - 2) return
-
- user.set_dir(get_cardinal_dir(src, A))
- if(isliving(A) && !(A in aim_targets))
- Aim(A) //Clicked a mob, aim at them
- return 1
-
- //Didn't click someone, check if there is anyone along that guntrace
- var/mob/living/M = GunTrace(usr.x,usr.y,A.x,A.y,usr.z,usr) //Find dat mob.
- if(isliving(M) && (M in view(user)) && !(M in aim_targets))
- Aim(M) //Aha! Aim at them!
- return 1
-
- return 0
-
-//Aiming at the target mob.
-/obj/item/weapon/gun/proc/Aim(var/mob/living/M)
- if(!aim_targets || !(M in aim_targets))
- admin_attack_log(usr, M, "Pointed a [src] at [M]", "Had a [src] aimed at them, by [usr]", "aims a gun ([src]) (MODE: [src.mode_name]) at")
- lock_time = world.time
- if(aim_targets && !multi_aim) //If they're targeting someone and they have a non multi_aim weapon.
- for(var/mob/living/L in aim_targets)
- if(L)
- L.NotTargeted(src)
- aim_targets = null
- usr.visible_message("[usr] turns \the [src] on [M]!")
- else
- usr.visible_message("[usr] aims \a [src] at [M]!")
- M.Targeted(src)
-
-//HE MOVED, SHOOT HIM!
-/obj/item/weapon/gun/proc/TargetActed(var/mob/living/T)
- var/mob/living/M = loc
- if(M == T) return
- if(!istype(M)) return
- if(src != M.get_active_hand())
- stop_aim()
- return
-
- //reflex firing is disabled when help intent is set
- if (M.a_intent == I_HELP)
- M << "You refrain from firing your [src] as your intent is set to help."
- return
-
- M.last_move_intent = world.time
- var/firing_check = can_hit(T,usr) //0 if it cannot hit them, 1 if it is capable of hitting, and 2 if a special check is preventing it from firing.
- if(firing_check > 0)
- if(firing_check == 1)
- Fire(T,usr, reflex = 1)
- else if(!told_cant_shoot)
- M << "They can't be hit from here!"
- told_cant_shoot = 1
- spawn(30)
- told_cant_shoot = 0
-
- usr.set_dir(get_cardinal_dir(src, T))
-
- if (!keep_aim) // If keep_aim is set to lower aim after one shot, untarget the target
- T.NotTargeted(src)
-
-//Yay, math!
-
-#define SIGN(X) ((X<0)?-1:1)
-
-/proc/GunTrace(X1,Y1,X2,Y2,Z=1,exc_obj,PX1=16,PY1=16,PX2=16,PY2=16)
- //bluh << "Tracin' [X1],[Y1] to [X2],[Y2] on floor [Z]."
- var/turf/T
- var/mob/living/M
- if(X1==X2)
- if(Y1==Y2) return 0 //Light cannot be blocked on same tile
- else
- var/s = SIGN(Y2-Y1)
- Y1+=s
- while(1)
- T = locate(X1,Y1,Z)
- if(!T) return 0
- M = locate() in T
- if(M) return M
- M = locate() in orange(1,T)-exc_obj
- if(M) return M
- Y1+=s
- else
- var
- m=(32*(Y2-Y1)+(PY2-PY1))/(32*(X2-X1)+(PX2-PX1))
- b=(Y1+PY1/32-0.015625)-m*(X1+PX1/32-0.015625) //In tiles
- signX = SIGN(X2-X1)
- signY = SIGN(Y2-Y1)
- if(X1= 5)
- if(ismob(I.loc))
- I.loc << "You can only target 5 people at once!"
- return
- else
- return
- for(var/mob/living/K in viewers(usr))
- K << 'sound/weapons/TargetOn.ogg'
-
- if(!targeted_by) targeted_by = list()
- targeted_by += I
- I.lock_time = world.time + 20 //Target has 2 second to realize they're targeted and stop (or target the opponent).
- src << "((Your character is being targeted. They have 2 seconds to stop any click or move actions. While targeted, they may \
- drag and drop items in or into the map, speak, and click on interface buttons. Clicking on the map objects (floors and walls are fine), their items \
- (other than a weapon to de-target), moving, or talking into a radio will result in being fired upon. The aggressor may also fire manually, \
- so try not to get on their bad side.))"
-
- if(targeted_by.len == 1)
- spawn(0)
- target_locked = image("icon" = 'icons/effects/Targeted.dmi', "icon_state" = "locking")
- overlays += target_locked
- spawn(0)
- sleep(20)
- if(target_locked)
- target_locked = image("icon" = 'icons/effects/Targeted.dmi', "icon_state" = "locked")
- update_targeted()
-
- //Adding the buttons to the controller person
- var/mob/living/T = I.loc
- if(T)
- if(T.client)
- T.client.add_gun_icons()
- else
- I.lower_aim()
- return
- if(iscarbon(src) && m_intent == "run" && T.client.target_can_move == 1 && T.client.target_can_run == 0)
- src << "Your move intent is now set to walk, as your targeter permits it." //Self explanitory.
- set_m_intent("walk")
-
- //Processing the aiming. Should be probably in separate object with process() but lasy.
- while(targeted_by && T.client)
- if(last_move_intent > I.lock_time + 10 && !T.client.target_can_move) //If target moved when not allowed to
- I.TargetActed(src)
- if(I.last_moved_mob == src) //If they were the last ones to move, give them more of a grace period, so that an automatic weapon can hold down a room better.
- I.lock_time = world.time + 5
- I.lock_time = world.time + 5
- I.last_moved_mob = src
- else if(last_move_intent > I.lock_time + 10 && !T.client.target_can_run && m_intent == "run") //If the target ran while targeted
- I.TargetActed(src)
- if(I.last_moved_mob == src) //If they were the last ones to move, give them more of a grace period, so that an automatic weapon can hold down a room better.
- I.lock_time = world.time + 5
- I.lock_time = world.time + 5
- I.last_moved_mob = src
- if(last_target_click > I.lock_time + 10 && !T.client.target_can_click) //If the target clicked the map to pick something up/shoot/etc
- I.TargetActed(src)
- if(I.last_moved_mob == src) //If they were the last ones to move, give them more of a grace period, so that an automatic weapon can hold down a room better.
- I.lock_time = world.time + 5
- I.lock_time = world.time + 5
- I.last_moved_mob = src
- if(last_target_radio > I.lock_time + 10 && !T.client.target_can_radio)
- I.TargetActed(src)
- if(I.last_moved_mob == src) //If they were the last ones to move, give them more of a grace period, so that an automatic weapon can hold down a room better.
- I.lock_time = world.time + 5
- I.lock_time = world.time + 5
- I.last_moved_mob = src
- sleep(1)
-
-/mob/living/proc/NotTargeted(var/obj/item/weapon/gun/I)
- if(!I.silenced)
- for(var/mob/living/M in viewers(src))
- M << 'sound/weapons/TargetOff.ogg'
- targeted_by -= I
- I.aim_targets.Remove(src) //De-target them
- if(!I.aim_targets.len)
- I.aim_targets = null
- var/mob/living/T = I.loc //Remove the targeting icons
- if(T && ismob(T) && !I.aim_targets && T.client)
- T.client.remove_gun_icons()
- if(!targeted_by.len)
- qdel(target_locked) //Remove the overlay
- targeted_by.Cut()
- spawn(1) update_targeted()
-
-/mob/living/Move()
- . = ..()
- for(var/obj/item/weapon/gun/G in targeted_by) //Handle moving out of the gunner's view.
- var/mob/living/M = G.loc
- if(!(M in view(src)))
- NotTargeted(G)
- for(var/obj/item/weapon/gun/G in src) //Handle the gunner loosing sight of their target/s
- if(G.aim_targets)
- for(var/mob/living/M in G.aim_targets)
- if(M && !(M in view(src)))
- M.NotTargeted(G)
-
-//If you move out of range, it isn't going to still stay locked on you any more.
-/client/var
- target_can_move = 0
- target_can_run = 0
- target_can_click = 0
- target_can_radio = 0
- gun_mode = 0
-
-//These are called by the on-screen buttons, adjusting what the victim can and cannot do.
-/client/proc/add_gun_icons()
- if(!usr) return 1 // This can runtime if someone manages to throw a gun out of their hand before the proc is called.
- screen += usr.item_use_icon
- screen += usr.gun_move_icon
- screen += usr.radio_use_icon
- if (target_can_move)
- screen += usr.gun_run_icon
-
-
-
-/client/proc/remove_gun_icons()
- if(!usr) return 1 // Runtime prevention on N00k agents spawning with SMG
- screen -= usr.item_use_icon
- screen -= usr.gun_move_icon
- screen -= usr.radio_use_icon
- if (target_can_move)
- screen -= usr.gun_run_icon
-
-/client/verb/ToggleGunMode()
- set name = "Toggle Gun Mode"
- set hidden = 1
- gun_mode = !gun_mode
- if(gun_mode)
- usr << "You will now take people captive."
- else
- usr << "You will now shoot where you target."
- for(var/obj/item/weapon/gun/G in usr)
- G.stop_aim()
- remove_gun_icons()
- if(usr.gun_setting_icon)
- usr.gun_setting_icon.icon_state = "gun[gun_mode]"
-
-
-/client/verb/AllowTargetMove()
- set hidden=1
-
- //Changing client's permissions
- target_can_move = !target_can_move
- if(target_can_move)
- usr << "Target may now walk."
- //usr.gun_run_icon = new /obj/screen/gun/run(null) //adding icon for running permission
- screen += usr.gun_run_icon
- else
- usr << "Target may no longer move."
- target_can_run = 0
- qdel(usr.gun_run_icon) //no need for icon for running permission
-
- //Updating walking permission button
- if(usr.gun_move_icon)
- usr.gun_move_icon.icon_state = "no_walk[target_can_move]"
- usr.gun_move_icon.name = "[target_can_move ? "Disallow" : "Allow"] Walking"
-
- //Handling change for all the guns on client
- for(var/obj/item/weapon/gun/G in usr)
- G.lock_time = world.time + 5
- if(G.aim_targets)
- for(var/mob/living/M in G.aim_targets)
- if(target_can_move)
- M << "Your character may now walk at the discretion of their targeter."
- if(!target_can_run)
- M << "Your move intent is now set to walk, as your targeter permits it."
- M.set_m_intent("walk")
- else
- M << "Your character will now be shot if they move."
-
-/mob/living/proc/set_m_intent(var/intent)
- if (intent != "walk" && intent != "run")
- return 0
- m_intent = intent
- if(hud_used)
- if (hud_used.move_intent)
- hud_used.move_intent.icon_state = intent == "walk" ? "walking" : "running"
-
-client/verb/AllowTargetRun()
- set hidden=1
-
- //Changing client's permissions
- target_can_run = !target_can_run
- if(target_can_run)
- usr << "Target may now run."
- else
- usr << "Target may no longer run."
-
- //Updating running permission button
- if(usr.gun_run_icon)
- usr.gun_run_icon.icon_state = "no_run[target_can_run]"
- usr.gun_run_icon.name = "[target_can_run ? "Disallow" : "Allow"] Running"
-
- //Handling change for all the guns on client
- for(var/obj/item/weapon/gun/G in src)
- G.lock_time = world.time + 5
- if(G.aim_targets)
- for(var/mob/living/M in G.aim_targets)
- if(target_can_run)
- M << "Your character may now run at the discretion of their targeter."
- else
- M << "Your character will now be shot if they run."
-
-/client/verb/AllowTargetClick()
- set hidden=1
-
- //Changing client's permissions
- target_can_click = !target_can_click
- if(target_can_click)
- usr << "Target may now use items."
- else
- usr << "Target may no longer use items."
-
- if(usr.item_use_icon)
- usr.item_use_icon.icon_state = "no_item[target_can_click]"
- usr.item_use_icon.name = "[target_can_click ? "Disallow" : "Allow"] Item Use"
-
- //Handling change for all the guns on client
- for(var/obj/item/weapon/gun/G in src)
- G.lock_time = world.time + 5
- if(G.aim_targets)
- for(var/mob/living/M in G.aim_targets)
- if(target_can_click)
- M << "Your character may now use items at the discretion of their targeter."
- else
- M << "Your character will now be shot if they use items."
-
-/client/verb/AllowTargetRadio()
- set hidden=1
-
- target_can_radio = !target_can_radio
- if(target_can_radio)
- usr << "Target may now use radio."
- else
- usr << "Target may no longer use radio."
-
- if(usr.radio_use_icon)
- usr.radio_use_icon.icon_state = "no_radio[target_can_radio]"
- usr.radio_use_icon.name = "[target_can_radio ? "Disallow" : "Allow"] Radio Use"
-
- //Handling change for all the guns on client
- for(var/obj/item/weapon/gun/G in src)
- G.lock_time = world.time + 5
- if(G.aim_targets)
- for(var/mob/living/M in G.aim_targets)
- if(target_can_radio)
- M << "Your character may now use the radio at the discretion of their targeter."
- else
- M << "Your character will now be shot if they use the radio."
diff --git a/code/modules/projectiles/targeting/targeting_client.dm b/code/modules/projectiles/targeting/targeting_client.dm
new file mode 100644
index 00000000000..42a0e3e6a1c
--- /dev/null
+++ b/code/modules/projectiles/targeting/targeting_client.dm
@@ -0,0 +1,12 @@
+//These are called by the on-screen buttons, adjusting what the victim can and cannot do.
+/client/proc/add_gun_icons()
+ if(!usr) return 1 // This can runtime if someone manages to throw a gun out of their hand before the proc is called.
+ screen |= usr.item_use_icon
+ screen |= usr.gun_move_icon
+ screen |= usr.radio_use_icon
+
+/client/proc/remove_gun_icons()
+ if(!usr) return 1 // Runtime prevention on N00k agents spawning with SMG
+ screen -= usr.item_use_icon
+ screen -= usr.gun_move_icon
+ screen -= usr.radio_use_icon
diff --git a/code/modules/projectiles/targeting/targeting_gun.dm b/code/modules/projectiles/targeting/targeting_gun.dm
new file mode 100644
index 00000000000..e2ef466255e
--- /dev/null
+++ b/code/modules/projectiles/targeting/targeting_gun.dm
@@ -0,0 +1,21 @@
+//Removing the lock and the buttons.
+/obj/item/weapon/gun/dropped(var/mob/living/user)
+ if(istype(user))
+ user.stop_aiming(src)
+ return ..()
+
+/obj/item/weapon/gun/equipped(var/mob/living/user, var/slot)
+ if(istype(user) && (slot != slot_l_hand && slot != slot_r_hand))
+ user.stop_aiming(src)
+ return ..()
+
+//Compute how to fire.....
+//Return 1 if a target was found, 0 otherwise.
+/obj/item/weapon/gun/proc/PreFire(var/atom/A, var/mob/living/user, var/params)
+ if(!user.aiming)
+ user.aiming = new(user)
+ user.face_atom(A)
+ if(ismob(A) && user.aiming)
+ user.aiming.aim_at(A, src)
+ return 1
+ return 0
\ No newline at end of file
diff --git a/code/modules/projectiles/targeting/targeting_mob.dm b/code/modules/projectiles/targeting/targeting_mob.dm
new file mode 100644
index 00000000000..a89bbc2c9a5
--- /dev/null
+++ b/code/modules/projectiles/targeting/targeting_mob.dm
@@ -0,0 +1,52 @@
+/mob/living/var/obj/aiming_overlay/aiming
+/mob/living/var/list/aimed = list()
+
+/mob/living/proc/stop_aiming(var/obj/item/thing, var/no_message = 0)
+ if(!aiming)
+ aiming = new(src)
+ if(thing && aiming.aiming_with != thing)
+ return
+ aiming.cancel_aiming(no_message)
+
+/mob/living/death(gibbed,deathmessage="seizes up and falls limp...")
+ if(..())
+ stop_aiming(no_message=1)
+
+/mob/living/update_canmove()
+ ..()
+ if(lying)
+ stop_aiming(no_message=1)
+
+/mob/living/Weaken(amount)
+ stop_aiming(no_message=1)
+ ..()
+
+/mob/living/Destroy()
+ if(aiming)
+ qdel(aiming)
+ aiming = null
+ aimed.Cut()
+ return ..()
+
+/turf/Enter(var/mob/living/mover)
+ . = ..()
+ if(istype(mover))
+ if(mover.aiming && mover.aiming.aiming_at)
+ mover.aiming.update_aiming()
+ if(mover.aimed.len)
+ mover.trigger_aiming(TARGET_CAN_MOVE)
+
+/mob/living/forceMove(var/atom/destination)
+ . = ..()
+ if(aiming && aiming.aiming_at)
+ aiming.update_aiming()
+ if(aimed.len)
+ trigger_aiming(TARGET_CAN_MOVE)
+
+/mob/living/proc/set_m_intent(var/intent)
+ if (intent != "walk" && intent != "run")
+ return 0
+ m_intent = intent
+ if(hud_used)
+ if (hud_used.move_intent)
+ hud_used.move_intent.icon_state = intent == "walk" ? "walking" : "running"
\ No newline at end of file
diff --git a/code/modules/projectiles/targeting/targeting_overlay.dm b/code/modules/projectiles/targeting/targeting_overlay.dm
new file mode 100644
index 00000000000..e0a2885a857
--- /dev/null
+++ b/code/modules/projectiles/targeting/targeting_overlay.dm
@@ -0,0 +1,213 @@
+/obj/aiming_overlay
+ name = "target indicator"
+ desc = "Stick 'em up!"
+ icon = 'icons/effects/Targeted.dmi'
+ icon_state = "locking"
+ anchored = 1
+ density = 0
+ opacity = 0
+ layer = FLY_LAYER
+ simulated = 0
+
+ var/mob/living/aiming_at // Who are we currently targeting, if anyone?
+ var/obj/item/aiming_with // What are we targeting with?
+ var/mob/owner // Who do we belong to?
+ var/locked = 0 // Have we locked on?
+ var/lock_time = 0 // When -will- we lock on?
+ var/active = 0 // Is our owner intending to take hostages?
+ var/target_permissions = 0 // Permission bitflags.
+
+/obj/aiming_overlay/New(var/newowner)
+ ..()
+ owner = newowner
+ loc = null
+
+/obj/aiming_overlay/proc/toggle_permission(var/perm)
+
+ if(target_permissions & perm)
+ target_permissions &= ~perm
+ else
+ target_permissions |= perm
+
+ // Update HUD icons.
+ if(owner.gun_move_icon)
+ if(!(target_permissions & TARGET_CAN_MOVE))
+ owner.gun_move_icon.icon_state = "no_walk0"
+ owner.gun_move_icon.name = "Allow Movement"
+ else
+ owner.gun_move_icon.icon_state = "no_walk1"
+ owner.gun_move_icon.name = "Disallow Movement"
+
+ if(owner.item_use_icon)
+ if(!(target_permissions & TARGET_CAN_CLICK))
+ owner.item_use_icon.icon_state = "no_item0"
+ owner.item_use_icon.name = "Allow Item Use"
+ else
+ owner.item_use_icon.icon_state = "no_item1"
+ owner.item_use_icon.name = "Disallow Item Use"
+
+ if(owner.radio_use_icon)
+ if(!(target_permissions & TARGET_CAN_RADIO))
+ owner.radio_use_icon.icon_state = "no_radio0"
+ owner.radio_use_icon.name = "Allow Radio Use"
+ else
+ owner.radio_use_icon.icon_state = "no_radio1"
+ owner.radio_use_icon.name = "Disallow Radio Use"
+
+ var/message = "no longer permitted to "
+ var/use_span = "warning"
+ if(target_permissions & perm)
+ message = "now permitted to "
+ use_span = "notice"
+
+ switch(perm)
+ if(TARGET_CAN_MOVE)
+ message += "move"
+ if(TARGET_CAN_CLICK)
+ message += "use items"
+ if(TARGET_CAN_RADIO)
+ message += "use a radio"
+ else
+ return
+
+ owner << "[aiming_at ? "\The [aiming_at] is" : "Your targets are"] [message]."
+ if(aiming_at)
+ aiming_at << "You are [message]."
+
+/obj/aiming_overlay/process()
+ if(!owner)
+ qdel(src)
+ return
+ ..()
+ update_aiming()
+
+/obj/aiming_overlay/Destroy()
+ if(aiming_at)
+ aiming_at.aimed -= src
+ aiming_at = null
+ owner = null
+ aiming_with = null
+ processing_objects -= src
+ return ..()
+
+obj/aiming_overlay/proc/update_aiming_deferred()
+ set waitfor = 0
+ sleep(0)
+ update_aiming()
+
+/obj/aiming_overlay/proc/update_aiming()
+
+ if(!owner)
+ qdel(src)
+ return
+
+ if(!aiming_at)
+ cancel_aiming()
+ return
+
+ if(!locked && lock_time >= world.time)
+ locked = 1
+ update_icon()
+
+ var/cancel_aim = 1
+ if(!(aiming_with in owner) || (owner.l_hand != aiming_with && owner.r_hand != aiming_with))
+ owner << "You must keep hold of your weapon!"
+ else if(!aiming_at || !istype(aiming_at.loc, /turf))
+ owner << "You have lost sight of your target!"
+ else if(owner.incapacitated() || owner.lying || owner.restrained())
+ owner << "You must be conscious and standing to keep track of your target!"
+ else if(aiming_at.alpha == 0 || (aiming_at.invisibility > owner.see_invisible))
+ owner << "Your target has become invisible!"
+ else if(get_dist(get_turf(owner), get_turf(aiming_at)) > 7) // !(owner in viewers(aiming_at, 7))
+ owner << "Your target is too far away to track!"
+ else
+ cancel_aim = 0
+
+ forceMove(get_turf(aiming_at))
+
+ if(cancel_aim)
+ cancel_aiming()
+ return
+
+ if(!owner.incapacitated() && owner.client)
+ spawn(0)
+ owner.set_dir(get_dir(get_turf(owner), get_turf(src)))
+
+/obj/aiming_overlay/proc/aim_at(var/mob/target, var/obj/thing)
+
+ if(!owner)
+ return
+
+ if(owner.incapacitated())
+ owner << "You cannot aim a gun in your current state."
+ return
+ if(owner.lying)
+ owner << "You cannot aim a gun while prone."
+ return
+ if(owner.restrained())
+ owner << "You cannot aim a gun while handcuffed."
+ return
+
+ if(aiming_at)
+ if(aiming_at == target)
+ return
+ aiming_at.aimed -= src
+ owner.visible_message("\The [owner] turns \the [thing] on \the [target]!")
+ else
+ owner.visible_message("\The [owner] aims \the [thing] at \the [target]!")
+
+ if(owner.client)
+ owner.client.add_gun_icons()
+ target << "You now have a gun pointed at you. No sudden moves!"
+ aiming_with = thing
+ aiming_at = target
+ if(istype(aiming_with, /obj/item/weapon/gun))
+ playsound(get_turf(owner), 'sound/weapons/TargetOn.ogg', 50,1)
+ forceMove(get_turf(target))
+ processing_objects |= src
+
+ aiming_at.aimed |= src
+ toggle_active(1)
+ locked = 0
+ update_icon()
+ lock_time = world.time + 35
+
+/obj/aiming_overlay/update_icon()
+ if(locked)
+ icon_state = "locked"
+ else
+ icon_state = "locking"
+
+/obj/aiming_overlay/proc/toggle_active(var/force_state = null)
+ if(!isnull(force_state))
+ if(active == force_state)
+ return
+ active = force_state
+ else
+ active = !active
+
+ if(!active)
+ cancel_aiming()
+
+ if(owner.client)
+ if(active)
+ owner << "You will now aim rather than fire."
+ owner.client.add_gun_icons()
+ else
+ owner << "You will no longer aim rather than fire."
+ owner.client.remove_gun_icons()
+
+/obj/aiming_overlay/proc/cancel_aiming(var/no_message = 0)
+ if(!aiming_with || !aiming_at)
+ return
+ if(istype(aiming_with, /obj/item/weapon/gun))
+ playsound(get_turf(owner), 'sound/weapons/TargetOff.ogg', 50,1)
+ if(!no_message)
+ owner.visible_message("\The [owner] lowers \the [aiming_with].")
+
+ aiming_with = null
+ aiming_at.aimed -= src
+ aiming_at = null
+ loc = null
+ processing_objects -= src
+
diff --git a/code/modules/projectiles/targeting/targeting_triggers.dm b/code/modules/projectiles/targeting/targeting_triggers.dm
new file mode 100644
index 00000000000..ea18fc3a708
--- /dev/null
+++ b/code/modules/projectiles/targeting/targeting_triggers.dm
@@ -0,0 +1,29 @@
+/mob/living/proc/trigger_aiming(var/trigger_type)
+ if(!aimed.len)
+ return
+ for(var/obj/aiming_overlay/AO in aimed)
+ if(AO.aiming_at == src)
+ AO.update_aiming()
+ if(AO.aiming_at == src)
+ AO.trigger(trigger_type)
+ AO.update_aiming_deferred()
+
+/obj/aiming_overlay/proc/trigger(var/perm)
+ if(!owner || !aiming_with || !aiming_at || !locked)
+ return
+ if(perm && (target_permissions & perm))
+ return
+ if(!owner.canClick())
+ return
+ owner.setClickCooldown(5) // Spam prevention, essentially.
+ if(owner.a_intent == I_HELP)
+ owner << "You refrain from firing \the [aiming_with] as your intent is set to help."
+ return
+ owner.visible_message("\The [owner] pulls the trigger reflexively!")
+ var/obj/item/weapon/gun/G = aiming_with
+ if(istype(G))
+ G.Fire(aiming_at, owner)
+
+/mob/living/ClickOn(var/atom/A, var/params)
+ . = ..()
+ trigger_aiming(TARGET_CAN_CLICK)
diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm
index a11bf15a248..800482df64e 100644
--- a/code/modules/recycling/disposal.dm
+++ b/code/modules/recycling/disposal.dm
@@ -116,7 +116,7 @@
if (GM.client)
GM.client.perspective = EYE_PERSPECTIVE
GM.client.eye = src
- GM.loc = src
+ GM.forceMove(src)
for (var/mob/C in viewers(src))
C.show_message("\red [GM.name] has been placed in the [src] by [user].", 3)
qdel(G)
@@ -132,7 +132,7 @@
user.drop_item()
if(I)
- I.loc = src
+ I.forceMove(src)
user << "You place \the [I] into the [src]."
for(var/mob/M in viewers(src))
@@ -177,7 +177,8 @@
if (target.client)
target.client.perspective = EYE_PERSPECTIVE
target.client.eye = src
- target.loc = src
+
+ target.forceMove(src)
for (var/mob/C in viewers(src))
if(C == user)
@@ -201,7 +202,7 @@
if (user.client)
user.client.eye = user.client.mob
user.client.perspective = MOB_PERSPECTIVE
- user.loc = src.loc
+ user.forceMove(src.loc)
update()
return
@@ -310,7 +311,7 @@
// eject the contents of the disposal unit
/obj/machinery/disposal/proc/eject()
for(var/atom/movable/AM in src)
- AM.loc = src.loc
+ AM.forceMove(src.loc)
AM.pipe_eject(0)
update()
@@ -443,7 +444,7 @@
for(var/atom/movable/AM in H)
target = get_offset_target_turf(src.loc, rand(5)-rand(5), rand(5)-rand(5))
- AM.loc = src.loc
+ AM.forceMove(src.loc)
AM.pipe_eject(0)
if(!istype(AM,/mob/living/silicon/robot/drone)) //Poor drones kept smashing windows and taking system damage being fired out of disposals. ~Z
spawn(1)
@@ -459,7 +460,7 @@
if(istype(I, /obj/item/projectile))
return
if(prob(75))
- I.loc = src
+ I.forceMove(src)
for(var/mob/M in viewers(src))
M.show_message("\The [I] lands in \the [src].", 3)
else
@@ -508,7 +509,7 @@
// now everything inside the disposal gets put into the holder
// note AM since can contain mobs or objs
for(var/atom/movable/AM in D)
- AM.loc = src
+ AM.forceMove(src)
if(istype(AM, /obj/structure/bigDelivery) && !hasmob)
var/obj/structure/bigDelivery/T = AM
src.destinationTag = T.sortTag
@@ -528,7 +529,7 @@
D.expel(src) // no trunk connected, so expel immediately
return
- loc = D.trunk
+ forceMove(D.trunk)
active = 1
set_dir(DOWN)
spawn(1)
@@ -585,7 +586,7 @@
// used when a a holder meets a stuck holder
proc/merge(var/obj/structure/disposalholder/other)
for(var/atom/movable/AM in other)
- AM.loc = src // move everything in other holder to this one
+ AM.forceMove(src) // move everything in other holder to this one
if(ismob(AM))
var/mob/M = AM
if(M.client) // if a client mob, update eye to follow this holder
@@ -671,7 +672,7 @@
// this is unlikely, but just dump out everything into the turf in case
for(var/atom/movable/AM in H)
- AM.loc = T
+ AM.forceMove(T)
AM.pipe_eject(0)
qdel(H)
..()
@@ -702,9 +703,9 @@
if(H2 && !H2.active)
H.merge(H2)
- H.loc = P
+ H.forceMove(P)
else // if wasn't a pipe, then set loc to turf
- H.loc = T
+ H.forceMove(T)
return null
return P
@@ -746,6 +747,7 @@
H.active = 0
H.loc = src
return
+
if(!T.is_plating() && istype(T,/turf/simulated/floor)) //intact floor, pop the tile
var/turf/simulated/floor/F = T
F.break_tile()
@@ -760,7 +762,7 @@
playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
if(H)
for(var/atom/movable/AM in H)
- AM.loc = T
+ AM.forceMove(T)
AM.pipe_eject(direction)
spawn(1)
if(AM)
@@ -775,7 +777,7 @@
for(var/atom/movable/AM in H)
target = get_offset_target_turf(T, rand(5)-rand(5), rand(5)-rand(5))
- AM.loc = T
+ AM.forceMove(T)
AM.pipe_eject(0)
spawn(1)
if(AM)
@@ -808,7 +810,7 @@
// this is unlikely, but just dump out everything into the turf in case
for(var/atom/movable/AM in H)
- AM.loc = T
+ AM.forceMove(T)
AM.pipe_eject(0)
qdel(H)
return
@@ -929,7 +931,7 @@
// this is unlikely, but just dump out everything into the turf in case
for(var/atom/movable/AM in H)
- AM.loc = T
+ AM.forceMove(T)
AM.pipe_eject(0)
qdel(H)
..()
@@ -990,7 +992,7 @@
if(nextdir == 12)
T = GetAbove(src)
if(!T)
- H.loc = loc
+ H.forceMove(loc)
return
else
for(var/obj/structure/disposalpipe/down/F in T)
@@ -1006,9 +1008,9 @@
if(H2 && !H2.active)
H.merge(H2)
- H.loc = P
+ H.forceMove(P)
else // if wasn't a pipe, then set loc to turf
- H.loc = T
+ H.forceMove(T)
return null
return P
@@ -1040,7 +1042,7 @@
if(nextdir == 11)
T = GetBelow(src)
if(!T)
- H.loc = src.loc
+ H.forceMove(src.loc)
return
else
for(var/obj/structure/disposalpipe/up/F in T)
@@ -1056,9 +1058,9 @@
if(H2 && !H2.active)
H.merge(H2)
- H.loc = P
+ H.forceMove(P)
else // if wasn't a pipe, then set loc to turf
- H.loc = T
+ H.forceMove(T)
return null
return P
@@ -1249,9 +1251,9 @@
if(H2 && !H2.active)
H.merge(H2)
- H.loc = P
+ H.forceMove(P)
else // if wasn't a pipe, then set loc to turf
- H.loc = T
+ H.forceMove(T)
return null
return P
@@ -1439,7 +1441,7 @@
if(H)
for(var/atom/movable/AM in H)
- AM.loc = src.loc
+ AM.forceMove(src.loc)
AM.pipe_eject(dir)
if(!istype(AM,/mob/living/silicon/robot/drone)) //Drones keep smashing windows from being fired out of chutes. Bad for the station. ~Z
spawn(5)
diff --git a/html/changelogs/Zuhayr-aiming.yml b/html/changelogs/Zuhayr-aiming.yml
new file mode 100644
index 00000000000..88b4b7f3d54
--- /dev/null
+++ b/html/changelogs/Zuhayr-aiming.yml
@@ -0,0 +1,4 @@
+author: Zuhayr
+delete-after: True
+changes:
+ - tweak: "Aiming has been rewritten, keep an eye out for weird behavior."
diff --git a/polaris.dme b/polaris.dme
index 2acbed414ca..d337865505d 100644
--- a/polaris.dme
+++ b/polaris.dme
@@ -31,6 +31,7 @@
#include "code\__defines\mobs.dm"
#include "code\__defines\research.dm"
#include "code\__defines\species_languages.dm"
+#include "code\__defines\targeting.dm"
#include "code\__defines\turfs.dm"
#include "code\_helpers\atmospherics.dm"
#include "code\_helpers\datum_pool.dm"
@@ -64,9 +65,9 @@
#include "code\_onclick\hud\_defines.dm"
#include "code\_onclick\hud\action.dm"
#include "code\_onclick\hud\alien_larva.dm"
+#include "code\_onclick\hud\gun_mode.dm"
#include "code\_onclick\hud\hud.dm"
#include "code\_onclick\hud\human.dm"
-#include "code\_onclick\hud\monkey.dm"
#include "code\_onclick\hud\movable_screen_objects.dm"
#include "code\_onclick\hud\other_mobs.dm"
#include "code\_onclick\hud\robot.dm"
@@ -1610,7 +1611,6 @@
#include "code\modules\projectiles\effects.dm"
#include "code\modules\projectiles\gun.dm"
#include "code\modules\projectiles\projectile.dm"
-#include "code\modules\projectiles\targeting.dm"
#include "code\modules\projectiles\ammunition\boxes.dm"
#include "code\modules\projectiles\ammunition\bullets.dm"
#include "code\modules\projectiles\guns\alien.dm"
@@ -1641,6 +1641,11 @@
#include "code\modules\projectiles\projectile\energy.dm"
#include "code\modules\projectiles\projectile\force.dm"
#include "code\modules\projectiles\projectile\special.dm"
+#include "code\modules\projectiles\targeting\targeting_client.dm"
+#include "code\modules\projectiles\targeting\targeting_gun.dm"
+#include "code\modules\projectiles\targeting\targeting_mob.dm"
+#include "code\modules\projectiles\targeting\targeting_overlay.dm"
+#include "code\modules\projectiles\targeting\targeting_triggers.dm"
#include "code\modules\random_map\_random_map_setup.dm"
#include "code\modules\random_map\random_map.dm"
#include "code\modules\random_map\random_map_verbs.dm"