mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-26 22:50:26 +01:00
Merge pull request #32751 from ninjanomnom/keybindings
In-code key handling system, Take 2
This commit is contained in:
@@ -21,25 +21,26 @@
|
||||
usr.loc = O
|
||||
usr.real_name = O.name
|
||||
usr.name = O.name
|
||||
usr.client.eye = O
|
||||
usr.reset_perspective(O)
|
||||
usr.control_object = O
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Possess Object") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/proc/release(obj/O in world)
|
||||
/proc/release()
|
||||
set name = "Release Obj"
|
||||
set category = "Object"
|
||||
//usr.loc = get_turf(usr)
|
||||
|
||||
if(usr.control_object && usr.name_archive) //if you have a name archived and if you are actually relassing an object
|
||||
usr.real_name = usr.name_archive
|
||||
usr.name_archive = ""
|
||||
usr.name = usr.real_name
|
||||
if(ishuman(usr))
|
||||
var/mob/living/carbon/human/H = usr
|
||||
H.name = H.get_visible_name()
|
||||
// usr.regenerate_icons() //So the name is updated properly
|
||||
|
||||
usr.loc = O.loc
|
||||
usr.client.eye = usr
|
||||
|
||||
usr.loc = get_turf(usr.control_object)
|
||||
usr.reset_perspective()
|
||||
usr.control_object = null
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Release Object") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
|
||||
@@ -68,11 +68,10 @@
|
||||
a_right.on_found(finder)
|
||||
|
||||
/obj/item/device/assembly_holder/Move()
|
||||
..()
|
||||
. = ..()
|
||||
if(a_left && a_right)
|
||||
a_left.holder_movement()
|
||||
a_right.holder_movement()
|
||||
return
|
||||
|
||||
/obj/item/device/assembly_holder/attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess
|
||||
if(a_left && a_right)
|
||||
|
||||
@@ -83,10 +83,9 @@
|
||||
|
||||
/obj/item/device/assembly/infra/Move()
|
||||
var/t = dir
|
||||
..()
|
||||
. = ..()
|
||||
setDir(t)
|
||||
qdel(first)
|
||||
return
|
||||
|
||||
/obj/item/device/assembly/infra/holder_movement()
|
||||
if(!holder)
|
||||
|
||||
@@ -195,7 +195,6 @@ GLOBAL_LIST(external_rsc_urls)
|
||||
prefs.last_id = computer_id //these are gonna be used for banning
|
||||
if(world.byond_version >= 511 && byond_version >= 511 && prefs.clientfps)
|
||||
vars["fps"] = prefs.clientfps
|
||||
sethotkeys(1) //set hoykeys from preferences (from_pref = 1)
|
||||
|
||||
log_access("Login: [key_name(src)] from [address ? address : "localhost"]-[computer_id] || BYOND v[byond_version]")
|
||||
var/alert_mob_dupe_login = FALSE
|
||||
@@ -223,6 +222,8 @@ GLOBAL_LIST(external_rsc_urls)
|
||||
|
||||
. = ..() //calls mob.Login()
|
||||
|
||||
set_macros()
|
||||
|
||||
chatOutput.start() // Starts the chat
|
||||
|
||||
if(alert_mob_dupe_login)
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/client/verb/sethotkeys(from_pref = 0 as num)
|
||||
set name = "Set Hotkeys"
|
||||
set hidden = TRUE
|
||||
set waitfor = FALSE
|
||||
set desc = "Used to set mob-specific hotkeys or load hoykey mode from preferences"
|
||||
|
||||
var/hotkey_default = "default"
|
||||
var/hotkey_macro = "hotkeys"
|
||||
var/current_setting
|
||||
|
||||
var/list/default_macros = list("default", "robot-default")
|
||||
|
||||
if(from_pref)
|
||||
current_setting = (prefs.hotkeys ? hotkey_macro : hotkey_default)
|
||||
else
|
||||
current_setting = winget(src, "mainwindow", "macro")
|
||||
|
||||
if(mob)
|
||||
hotkey_macro = mob.macro_hotkeys
|
||||
hotkey_default = mob.macro_default
|
||||
|
||||
if(current_setting in default_macros)
|
||||
winset(src, null, "mainwindow.macro=[hotkey_default] input.focus=true input.background-color=#d3b5b5")
|
||||
else
|
||||
winset(src, null, "mainwindow.macro=[hotkey_macro] mapwindow.map.focus=true input.background-color=#e0e0e0")
|
||||
@@ -0,0 +1,15 @@
|
||||
/datum/admins/key_down(_key, client/user)
|
||||
switch(_key)
|
||||
if("F5")
|
||||
user.admin_ghost()
|
||||
return
|
||||
if("F6")
|
||||
player_panel_new()
|
||||
return
|
||||
if("F7")
|
||||
user.cmd_admin_pm_panel()
|
||||
return
|
||||
if("F8")
|
||||
user.invisimin()
|
||||
return
|
||||
..()
|
||||
@@ -0,0 +1,18 @@
|
||||
// You might be wondering why this isn't client level. If focus is null, we don't want you to move.
|
||||
// Only way to do that is to tie the behavior into the focus's keyLoop().
|
||||
|
||||
/atom/movable/keyLoop(client/user)
|
||||
if(!user.keys_held["Ctrl"])
|
||||
var/movement_dir = NONE
|
||||
for(var/_key in user.keys_held)
|
||||
movement_dir |= GLOB.movement_keys[_key]
|
||||
if(user.next_move_dir_add)
|
||||
movement_dir |= user.next_move_dir_add
|
||||
if(user.next_move_dir_sub)
|
||||
movement_dir &= ~user.next_move_dir_sub
|
||||
// Sanity checks in case you hold left and right and up to make sure you only go up
|
||||
if((movement_dir & NORTH) && (movement_dir & SOUTH))
|
||||
movement_dir &= ~(NORTH|SOUTH)
|
||||
if((movement_dir & EAST) && (movement_dir & WEST))
|
||||
movement_dir &= ~(EAST|WEST)
|
||||
user.Move(get_step(src, movement_dir), movement_dir)
|
||||
@@ -0,0 +1,18 @@
|
||||
/mob/living/carbon/key_down(_key, client/user)
|
||||
switch(_key)
|
||||
if("R", "Southwest") // Southwest is End
|
||||
toggle_throw_mode()
|
||||
return
|
||||
if("1")
|
||||
a_intent_change("help")
|
||||
return
|
||||
if("2")
|
||||
a_intent_change("disarm")
|
||||
return
|
||||
if("3")
|
||||
a_intent_change("grab")
|
||||
return
|
||||
if("4")
|
||||
a_intent_change("harm")
|
||||
return
|
||||
return ..()
|
||||
@@ -0,0 +1,50 @@
|
||||
// Clients aren't datums so we have to define these procs indpendently.
|
||||
// These verbs are called for all key press and release events
|
||||
/client/verb/keyDown(_key as text)
|
||||
set instant = TRUE
|
||||
set hidden = TRUE
|
||||
|
||||
keys_held[_key] = world.time
|
||||
var/movement = GLOB.movement_keys[_key]
|
||||
if(!(next_move_dir_sub & movement))
|
||||
next_move_dir_add |= movement
|
||||
|
||||
// Client-level keybindings are ones anyone should be able to do at any time
|
||||
// Things like taking screenshots, hitting tab, and adminhelps.
|
||||
|
||||
switch(_key)
|
||||
if("F1")
|
||||
if(keys_held["Ctrl"] && keys_held["Shift"]) // Is this command ever used?
|
||||
winset(src, null, "command=.options")
|
||||
else
|
||||
adminhelp()
|
||||
if("F2") // Screenshot. Hold shift to choose a name and location to save in
|
||||
winset(src, null, "command=.screenshot [!keys_held["shift"] ? "auto" : ""]")
|
||||
if("F12") // Toggles minimal HUD
|
||||
mob.button_pressed_F12()
|
||||
|
||||
if(holder)
|
||||
holder.key_down(_key, src)
|
||||
if(mob.focus)
|
||||
mob.focus.key_down(_key, src)
|
||||
|
||||
/client/verb/keyUp(_key as text)
|
||||
set instant = TRUE
|
||||
set hidden = TRUE
|
||||
|
||||
keys_held -= _key
|
||||
var/movement = GLOB.movement_keys[_key]
|
||||
if(!(next_move_dir_add & movement))
|
||||
next_move_dir_sub |= movement
|
||||
|
||||
if(holder)
|
||||
holder.key_up(_key, src)
|
||||
if(mob.focus)
|
||||
mob.focus.key_up(_key, src)
|
||||
|
||||
// Called every game tick
|
||||
/client/keyLoop()
|
||||
if(holder)
|
||||
holder.keyLoop(src)
|
||||
if(mob.focus)
|
||||
mob.focus.keyLoop(src)
|
||||
@@ -0,0 +1,6 @@
|
||||
/mob/living/carbon/human/key_down(_key, client/user)
|
||||
switch(_key)
|
||||
if("E")
|
||||
quick_equip()
|
||||
return
|
||||
return ..()
|
||||
@@ -0,0 +1,7 @@
|
||||
/mob/living/key_down(_key, client/user)
|
||||
switch(_key)
|
||||
if("B")
|
||||
resist()
|
||||
return
|
||||
|
||||
return ..()
|
||||
@@ -0,0 +1,79 @@
|
||||
// Technically the client argument is unncessary here since that SHOULD be src.client but let's not assume things
|
||||
// All it takes is one badmin setting their focus to someone else's client to mess things up
|
||||
// Or we can have NPC's send actual keypresses and detect that by seeing no client
|
||||
|
||||
/mob/key_down(_key, client/user)
|
||||
switch(_key)
|
||||
if("Delete", "H")
|
||||
if(!pulling)
|
||||
to_chat(src, "<span class='notice'>You are not pulling anything.</span>")
|
||||
else
|
||||
stop_pulling()
|
||||
return
|
||||
if("Insert", "G")
|
||||
a_intent_change(INTENT_HOTKEY_RIGHT)
|
||||
return
|
||||
if("F")
|
||||
a_intent_change(INTENT_HOTKEY_LEFT)
|
||||
return
|
||||
if("X", "Northeast") // Northeast is Page-up
|
||||
swap_hand()
|
||||
return
|
||||
if("Y", "Z", "Southeast") // Southeast is Page-down
|
||||
mode() // attack_self(). No idea who came up with "mode()"
|
||||
return
|
||||
if("Q", "Northwest") // Northwest is Home
|
||||
var/obj/item/I = get_active_held_item()
|
||||
if(!I)
|
||||
to_chat(src, "<span class='warning'>You have nothing to drop in your hand!</span>")
|
||||
else
|
||||
dropItemToGround(I)
|
||||
return
|
||||
if("Alt")
|
||||
toggle_move_intent()
|
||||
return
|
||||
//Bodypart selections
|
||||
if("Numpad8")
|
||||
user.body_toggle_head()
|
||||
return
|
||||
if("Numpad4")
|
||||
user.body_r_arm()
|
||||
return
|
||||
if("Numpad5")
|
||||
user.body_chest()
|
||||
return
|
||||
if("Numpad6")
|
||||
user.body_l_arm()
|
||||
return
|
||||
if("Numpad1")
|
||||
user.body_r_leg()
|
||||
return
|
||||
if("Numpad2")
|
||||
user.body_groin()
|
||||
return
|
||||
if("Numpad3")
|
||||
user.body_l_leg()
|
||||
return
|
||||
|
||||
if(client.keys_held["Ctrl"])
|
||||
switch(GLOB.movement_keys[_key])
|
||||
if(NORTH)
|
||||
northface()
|
||||
return
|
||||
if(SOUTH)
|
||||
southface()
|
||||
return
|
||||
if(WEST)
|
||||
westface()
|
||||
return
|
||||
if(EAST)
|
||||
eastface()
|
||||
return
|
||||
return ..()
|
||||
|
||||
/mob/key_up(_key, client/user)
|
||||
switch(_key)
|
||||
if("Alt")
|
||||
toggle_move_intent()
|
||||
return
|
||||
return ..()
|
||||
@@ -0,0 +1,12 @@
|
||||
/mob/living/silicon/robot/key_down(_key, client/user)
|
||||
switch(_key)
|
||||
if("1", "2", "3")
|
||||
toggle_module(text2num(_key))
|
||||
return
|
||||
if("4")
|
||||
a_intent_change(INTENT_HOTKEY_LEFT)
|
||||
return
|
||||
if("Q")
|
||||
uneq_active()
|
||||
return
|
||||
return ..()
|
||||
@@ -0,0 +1,20 @@
|
||||
/datum
|
||||
var/list/focusers //Only initialized when needed. Contains a list of mobs focusing on this.
|
||||
|
||||
/mob
|
||||
var/datum/focus //What receives our keyboard inputs. src by default
|
||||
|
||||
/mob/proc/set_focus(datum/new_focus)
|
||||
if(focus == new_focus)
|
||||
return
|
||||
|
||||
if(new_focus)
|
||||
if(!new_focus.focusers) //Set up the new focus
|
||||
new_focus.focusers = list()
|
||||
new_focus.focusers += src
|
||||
|
||||
if(focus)
|
||||
focus.focusers -= src //Tell the old focus we're done with it
|
||||
|
||||
focus = new_focus
|
||||
reset_perspective(focus) //Maybe this should be done manually? You figure it out, reader
|
||||
@@ -0,0 +1,40 @@
|
||||
# In-code keypress handling system
|
||||
|
||||
This whole system is heavily based off of forum_account's keyboard library.
|
||||
Thanks to forum_account for saving the day, the library can be found [here](http://www.byond.com/developer/Forum_account/Keyboard)!
|
||||
|
||||
.dmf macros have some very serious shortcomings. For example, they do not allow reusing parts
|
||||
of one macro in another, so giving cyborgs their own shortcuts to swap active module couldn't
|
||||
inherit the movement that all mobs should have anyways. The webclient only supports one macro,
|
||||
so having more than one was problematic. Additionally each keybind has to call an actual
|
||||
verb, which meant a lot of hidden verbs that just call one other proc. Also our existing
|
||||
macro was really bad and tied unrelated behavior into `Northeast()`, `Southeast()`, `Northwest()`,
|
||||
and `Southwest()`.
|
||||
|
||||
The basic premise of this system is to not screw with .dmf macro setup at all and handle
|
||||
pressing those keys in the code instead. We have every key call `client.keyDown()`
|
||||
or `client.keyUp()` with the pressed key as an argument. Certain keys get processed
|
||||
directly by the client because they should be doable at any time, then we call
|
||||
`keyDown()` or `keyUp()` on the client's holder and the client's mob's focus.
|
||||
By default `mob.focus` is the mob itself, but you can set it to any datum to give control of a
|
||||
client's keypresses to another object. This would be a good way to handle a menu or driving
|
||||
a mech. You can also set it to null to disregard input from a certain user.
|
||||
|
||||
Movement is handled by having each client call `client.keyLoop()` every game tick.
|
||||
As above, this calls holder and `focus.keyLoop()`. `atom/movable/keyLoop()` handles movement
|
||||
Try to keep the calculations in this proc light. It runs every tick for every client after all!
|
||||
|
||||
You can also tell which keys are being held down now. Each client a list of keys pressed called
|
||||
`keys_held`. Each entry is a key as a text string associated with the world.time when it was
|
||||
pressed.
|
||||
|
||||
No client-set keybindings at this time, but it shouldn't be too hard if someone wants.
|
||||
|
||||
Notes about certain keys
|
||||
`Tab` has client-sided behavior but acts normally
|
||||
`T`, `O`, and `M` move focus to the input when pressed. This fires the keyUp macro right away.
|
||||
`\` needs to be escaped in the dmf so any usage is `\\`
|
||||
|
||||
You cannot `TICK_CHECK` or check `world.tick_usage` inside of procs called by key down and up
|
||||
events. They happen outside of a byond tick and have no meaning there. Key looping
|
||||
works correctly since it's part of a subsystem, not direct input.
|
||||
@@ -0,0 +1,62 @@
|
||||
/client
|
||||
var/list/keys_held = list() // A list of any keys held currently
|
||||
// These next two vars are to apply movement for keypresses and releases made while move delayed.
|
||||
// Because discarding that input makes the game less responsive.
|
||||
var/next_move_dir_add // On next move, add this dir to the move that would otherwise be done
|
||||
var/next_move_dir_sub // On next move, subtract this dir from the move that would otherwise be done
|
||||
|
||||
// Set a client's focus to an object and override these procs on that object to let it handle keypresses
|
||||
|
||||
/datum/proc/key_down(key, client/user) // Called when a key is pressed down initially
|
||||
return
|
||||
/datum/proc/key_up(key, client/user) // Called when a key is released
|
||||
return
|
||||
/datum/proc/keyLoop(client/user) // Called once every frame
|
||||
return
|
||||
|
||||
// Keys used for movement
|
||||
GLOBAL_LIST_INIT(movement_keys, list(
|
||||
"W" = NORTH, "A" = WEST, "S" = SOUTH, "D" = EAST, // WASD
|
||||
"North" = NORTH, "West" = WEST, "South" = SOUTH, "East" = EAST, // Arrow keys & Numpad
|
||||
))
|
||||
|
||||
/*
|
||||
A horrific battle against shitcode was fought here to find out some use details of winset
|
||||
Aparently you need to wrap the entire proc + args in quotes if you intend on using args
|
||||
But you don't need the quote wrappings to just call on a proc with no args
|
||||
ex. winset(src, "default-Any", "command=keyDown \[\[*\]\]") fail: command = keyDown
|
||||
ex. winset(src, "default-Any", "command=keyDown \"\[\[*\]\]\"") fail: same
|
||||
ex. winset(src, "default-T", "command=say") works fine
|
||||
ex. winset(src, "default-Any", "command=\"keyDown \[\[*\]\]\"") works fine
|
||||
Thanks for the useful errors lummox ~ninjanomnom
|
||||
*/
|
||||
GLOBAL_LIST_INIT(default_macros, list(
|
||||
"Tab" = "\".winset \\\"input.focus=true?map.focus=true input.background-color=#F0F0F0:input.focus=true input.background-color=#D3B5B5\\\"\"",
|
||||
"O" = "ooc",
|
||||
"T" = "say",
|
||||
"M" = "me",
|
||||
"Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", // This makes it so backspace can remove default inputs
|
||||
"Any" = "\"KeyDown \[\[*\]\]\"",
|
||||
"Any+UP" = "\"KeyUp \[\[*\]\]\"",
|
||||
))
|
||||
|
||||
/client/proc/set_macros()
|
||||
set waitfor = FALSE
|
||||
|
||||
winset(src, null, "reset=true")
|
||||
winset(src, null, "mainwindow.macro=default")
|
||||
var/list/default = params2list(winget(src, "default.*", "command"))
|
||||
for(var/i in 1 to length(default))
|
||||
var/id = default[i]
|
||||
winset(src, id, "parent=none")
|
||||
|
||||
var/list/default_macros = GLOB.default_macros
|
||||
for(var/i in 1 to length(default_macros))
|
||||
var/input = default_macros[i]
|
||||
var/output = default_macros[input]
|
||||
winset(src, "default-[input]", "parent=default;name=[input];command=[output]")
|
||||
|
||||
if(prefs.hotkeys)
|
||||
winset(src, null, "mapwindow.map.focus=true input.background-color=#e0e0e0")
|
||||
else
|
||||
winset(src, null, "input.focus=true input.background-color=#d3b5b5")
|
||||
@@ -16,6 +16,7 @@ INITIALIZE_IMMEDIATE(/mob/dead)
|
||||
|
||||
if(CONFIG_GET(string/cross_server_address))
|
||||
verbs += /mob/dead/proc/server_hop
|
||||
set_focus(src)
|
||||
return INITIALIZE_HINT_NORMAL
|
||||
|
||||
/mob/dead/dust() //ghosts can't be vaporised.
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
..()
|
||||
|
||||
/mob/living/carbon/alien/humanoid/hunter/movement_delay()
|
||||
. = -1 //hunters are sanic
|
||||
. = -1 //hunters are sanic
|
||||
. += ..() //but they still need to slow down on stun
|
||||
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
icon_state = "robot"
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
macro_default = "robot-default"
|
||||
macro_hotkeys = "robot-hotkeys"
|
||||
bubble_icon = "robot"
|
||||
designation = "Default" //used for displaying the prefix & getting the current module of cyborg
|
||||
has_limbs = 1
|
||||
@@ -247,17 +245,6 @@
|
||||
return //won't work if dead
|
||||
robot_alerts()
|
||||
|
||||
//for borg hotkeys, here module refers to borg inv slot, not core module
|
||||
/mob/living/silicon/robot/verb/cmd_toggle_module(module as num)
|
||||
set name = "Toggle Module"
|
||||
set hidden = 1
|
||||
toggle_module(module)
|
||||
|
||||
/mob/living/silicon/robot/verb/cmd_unequip_module()
|
||||
set name = "Unequip Module"
|
||||
set hidden = 1
|
||||
uneq_active()
|
||||
|
||||
/mob/living/silicon/robot/proc/robot_alerts()
|
||||
var/dat = ""
|
||||
for (var/cat in alarms)
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
src.visible_message("<span class='danger'>[src] gets an evil-looking gleam in [p_their()] eye.</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/Move()
|
||||
..()
|
||||
. = ..()
|
||||
if(!stat)
|
||||
eat_plants()
|
||||
|
||||
|
||||
@@ -283,9 +283,8 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/mecha_pilot/Move(NewLoc,Dir=0,step_x=0,step_y=0)
|
||||
if(mecha && loc == mecha)
|
||||
mecha.relaymove(src, Dir)
|
||||
return
|
||||
..()
|
||||
return mecha.relaymove(src, Dir)
|
||||
return ..()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/mecha_pilot/Goto(target, delay, minimum_distance)
|
||||
|
||||
@@ -33,8 +33,6 @@
|
||||
|
||||
sync_mind()
|
||||
|
||||
client.sethotkeys() //set mob specific hotkeys
|
||||
|
||||
update_client_colour()
|
||||
if(client)
|
||||
client.click_intercept = null
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
GLOB.dead_mob_list += src
|
||||
else
|
||||
GLOB.alive_mob_list += src
|
||||
set_focus(src)
|
||||
prepare_huds()
|
||||
for(var/v in GLOB.active_alternate_appearances)
|
||||
if(!v)
|
||||
|
||||
@@ -21,9 +21,6 @@
|
||||
*/
|
||||
var/zone_selected = null
|
||||
|
||||
var/macro_default = "default"
|
||||
var/macro_hotkeys = "hotkeys"
|
||||
|
||||
var/damageoverlaytemp = 0
|
||||
var/computer_id = null
|
||||
var/lastattacker = null
|
||||
|
||||
@@ -11,94 +11,12 @@
|
||||
return (!mover.density || !density || lying)
|
||||
|
||||
|
||||
//The byond version of these verbs wait for the next tick before acting.
|
||||
// instant verbs however can run mid tick or even during the time between ticks.
|
||||
/client/verb/moveup()
|
||||
set name = ".moveup"
|
||||
set instant = 1
|
||||
Move(get_step(mob, NORTH), NORTH)
|
||||
|
||||
/client/verb/movedown()
|
||||
set name = ".movedown"
|
||||
set instant = 1
|
||||
Move(get_step(mob, SOUTH), SOUTH)
|
||||
|
||||
/client/verb/moveright()
|
||||
set name = ".moveright"
|
||||
set instant = 1
|
||||
Move(get_step(mob, EAST), EAST)
|
||||
|
||||
/client/verb/moveleft()
|
||||
set name = ".moveleft"
|
||||
set instant = 1
|
||||
Move(get_step(mob, WEST), WEST)
|
||||
|
||||
/client/Northeast()
|
||||
swap_hand()
|
||||
return
|
||||
|
||||
|
||||
/client/Southeast()
|
||||
attack_self()
|
||||
return
|
||||
|
||||
|
||||
/client/Southwest()
|
||||
if(iscarbon(usr))
|
||||
var/mob/living/carbon/C = usr
|
||||
C.toggle_throw_mode()
|
||||
else
|
||||
to_chat(usr, "<span class='danger'>This mob type cannot throw items.</span>")
|
||||
return
|
||||
|
||||
|
||||
/client/Northwest()
|
||||
var/obj/item/I = usr.get_active_held_item()
|
||||
if(!I)
|
||||
to_chat(usr, "<span class='warning'>You have nothing to drop in your hand!</span>")
|
||||
return
|
||||
usr.dropItemToGround(I)
|
||||
|
||||
//This gets called when you press the delete button.
|
||||
/client/verb/delete_key_pressed()
|
||||
set hidden = 1
|
||||
|
||||
if(!isliving(usr))
|
||||
return
|
||||
if(!usr.pulling)
|
||||
to_chat(usr, "<span class='notice'>You are not pulling anything.</span>")
|
||||
return
|
||||
usr.stop_pulling()
|
||||
|
||||
/client/verb/swap_hand()
|
||||
set category = "IC"
|
||||
set name = "Swap hands"
|
||||
|
||||
if(mob)
|
||||
mob.swap_hand()
|
||||
|
||||
/client/verb/attack_self()
|
||||
set hidden = 1
|
||||
if(mob)
|
||||
mob.mode()
|
||||
return
|
||||
|
||||
|
||||
/client/verb/drop_item()
|
||||
set hidden = 1
|
||||
if(!iscyborg(mob) && mob.stat == CONSCIOUS)
|
||||
mob.dropItemToGround(mob.get_active_held_item())
|
||||
return
|
||||
|
||||
|
||||
/client/Center()
|
||||
if(isobj(mob.loc))
|
||||
var/obj/O = mob.loc
|
||||
if(mob.canmove)
|
||||
return O.relaymove(mob, 0)
|
||||
return
|
||||
|
||||
|
||||
/client/proc/Move_object(direct)
|
||||
if(mob && mob.control_object)
|
||||
if(mob.control_object.density)
|
||||
@@ -114,19 +32,23 @@
|
||||
#define MOVEMENT_DELAY_BUFFER_DELTA 1.25
|
||||
|
||||
/client/Move(n, direct)
|
||||
if(world.time < move_delay)
|
||||
if(world.time < move_delay) //do not move anything ahead of this check please
|
||||
return FALSE
|
||||
else
|
||||
next_move_dir_add = 0
|
||||
next_move_dir_sub = 0
|
||||
var/old_move_delay = move_delay
|
||||
move_delay = world.time+world.tick_lag //this is here because Move() can now be called mutiple times per tick
|
||||
if(!mob || !mob.loc)
|
||||
return FALSE
|
||||
var/oldloc = mob.loc
|
||||
if(!n || !direct)
|
||||
return FALSE
|
||||
if(mob.notransform)
|
||||
return FALSE //This is sota the goto stop mobs from moving var
|
||||
if(mob.control_object)
|
||||
return Move_object(direct)
|
||||
if(!isliving(mob))
|
||||
return mob.Move(n,direct)
|
||||
return mob.Move(n, direct)
|
||||
if(mob.stat == DEAD)
|
||||
mob.ghostize()
|
||||
return FALSE
|
||||
@@ -159,26 +81,32 @@
|
||||
|
||||
if(!mob.Process_Spacemove(direct))
|
||||
return FALSE
|
||||
|
||||
//We are now going to move
|
||||
var/delay = mob.movement_delay()
|
||||
if(old_move_delay + (delay*MOVEMENT_DELAY_BUFFER_DELTA) + MOVEMENT_DELAY_BUFFER > world.time)
|
||||
move_delay = old_move_delay + delay
|
||||
var/add_delay = mob.movement_delay()
|
||||
if(old_move_delay + (add_delay*MOVEMENT_DELAY_BUFFER_DELTA) + MOVEMENT_DELAY_BUFFER > world.time)
|
||||
move_delay = old_move_delay
|
||||
else
|
||||
move_delay = delay + world.time
|
||||
move_delay = world.time
|
||||
var/oldloc = mob.loc
|
||||
|
||||
if(mob.confused)
|
||||
var/newdir = 0
|
||||
if(mob.confused > 40)
|
||||
step(mob, pick(GLOB.cardinals))
|
||||
newdir = pick(GLOB.alldirs)
|
||||
else if(prob(mob.confused * 1.5))
|
||||
step(mob, angle2dir(dir2angle(direct) + pick(90, -90)))
|
||||
newdir = angle2dir(dir2angle(direct) + pick(90, -90))
|
||||
else if(prob(mob.confused * 3))
|
||||
step(mob, angle2dir(dir2angle(direct) + pick(45, -45)))
|
||||
else
|
||||
step(mob, direct)
|
||||
else
|
||||
. = ..()
|
||||
newdir = angle2dir(dir2angle(direct) + pick(45, -45))
|
||||
if(newdir)
|
||||
direct = newdir
|
||||
n = get_step(mob, direct)
|
||||
|
||||
. = ..()
|
||||
|
||||
if((direct & (direct - 1)) && mob.loc == n) //moved diagonally successfully
|
||||
add_delay *= 2
|
||||
if(mob.loc != oldloc)
|
||||
move_delay += add_delay
|
||||
if(.) // If mob is null here, we deserve the runtime
|
||||
if(mob.throwing)
|
||||
mob.throwing.finalize(FALSE)
|
||||
|
||||
@@ -5,7 +5,10 @@
|
||||
if(GLOB.say_disabled) //This is here to try to identify lag problems
|
||||
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
|
||||
return
|
||||
usr.say(message)
|
||||
if(!message)
|
||||
message = input(src, "What do you want to say?", "Speech") as null|text
|
||||
if(message)
|
||||
say(message)
|
||||
|
||||
|
||||
/mob/verb/whisper_verb(message as text)
|
||||
|
||||
@@ -53,7 +53,7 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne
|
||||
|
||||
// You aren't allowed to move.
|
||||
/obj/machinery/gravity_generator/Move()
|
||||
..()
|
||||
. = ..()
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/gravity_generator/proc/set_broken()
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
|
||||
/obj/machinery/field/containment/Move()
|
||||
qdel(src)
|
||||
return FALSE
|
||||
|
||||
|
||||
// Abstract Field Class
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/particle_accelerator/Move()
|
||||
..()
|
||||
. = ..()
|
||||
if(master && master.active)
|
||||
master.toggle_power()
|
||||
investigate_log("was moved whilst active; it <font color='red'>powered down</font>.", INVESTIGATE_SINGULO)
|
||||
|
||||
Reference in New Issue
Block a user