Skip to content

Commit

Permalink
Merge branch 'NebulaSS13:dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
Legendaxe committed Jul 2, 2024
2 parents 2749122 + c227742 commit da23970
Show file tree
Hide file tree
Showing 228 changed files with 47,567 additions and 1,148 deletions.
18 changes: 17 additions & 1 deletion code/__defines/directions.dm
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#define N_NORTHEAST 32
#define N_NORTHWEST 512
#define N_SOUTHEAST 64
#define N_SOUTHWEST 1024
#define N_SOUTHWEST 1024

#define CORNER_NONE 0
#define CORNER_COUNTERCLOCKWISE 1
Expand Down Expand Up @@ -43,6 +43,22 @@

return ret

/proc/corner_states_to_dirs(list/corners)
if(!istype(corners)) return

var/list/ret = list(NORTHWEST, SOUTHEAST, NORTHEAST, SOUTHWEST)
. = list()

for(var/i = 1 to ret.len)
var/dir = ret[i]
var/corner = text2num(corners[i])
if(corner & CORNER_DIAGONAL)
. |= dir
if(corner & CORNER_COUNTERCLOCKWISE)
. |= turn(dir, 45)
if(corner & CORNER_CLOCKWISE)
. |= turn(dir, -45)

// Similar to dirs_to_corner_states(), but returns an *ordered* list, requiring (in order), dir=NORTH, SOUTH, EAST, WEST
// Note that this means this proc can be used as:

Expand Down
3 changes: 2 additions & 1 deletion code/__defines/subsystem-priority.dm
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
#define SS_PRIORITY_PLANTS 90 // Plant processing, slow ticks.
#define SS_PRIORITY_VINES 50 // Spreading vine effects.
#define SS_PRIORITY_PSYCHICS 45 // Psychic complexus processing.
#define SS_PRIORITY_AI 45 // Artificial Intelligence on mobs processing.
#define SS_PRIORITY_MOB_AI 45 // Mob AI logic; finding targets, attacking, etc.
#define SS_PRIORITY_AUTO_MOVE 42 // Automated atom movement, fires much more frequently than MOB_AI.
#define SS_PRIORITY_NANO 40 // Updates to nanoui uis.
#define SS_PRIORITY_TURF 30 // Radioactive walls/blob.
#define SS_PRIORITY_EVAC 30 // Processes the evac controller.
Expand Down
15 changes: 3 additions & 12 deletions code/_helpers/emissive.dm
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
/proc/emissive_overlay(var/icon, var/icon_state, var/loc, var/dir, var/color)
var/image/emissive/I = new(icon, icon_state)
if(!isnull(loc))
I.loc = loc
if(!isnull(dir))
I.dir = dir
if(!isnull(color))
I.color = color
var/image/I = image(icon, loc, icon_state, EMISSIVE_LAYER, dir)
I.plane = EMISSIVE_PLANE
I.color = color
return I

/image/emissive/New()
..()
layer = EMISSIVE_LAYER
plane = EMISSIVE_PLANE
2 changes: 1 addition & 1 deletion code/_helpers/time.dm
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ var/global/round_start_time = 0
return last_round_duration

var/mills = round_duration_in_ticks // 1/10 of a second, not real milliseconds but whatever
//var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for refrence.. or something
//var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for reference or something
var/mins = round((mills % 36000) / 600)
var/hours = round(mills / 36000)

Expand Down
10 changes: 4 additions & 6 deletions code/_onclick/click.dm
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,13 @@
//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.
var/sdepth = A.storage_depth(src)
var/check_dexterity_val = A.storage ? DEXTERITY_NONE : (istype(holding) ? holding.needs_attack_dexterity : DEXTERITY_WIELD_ITEM)
var/can_wield_item = holding && (!check_dexterity_val || check_dexterity(check_dexterity_val))
if((!isturf(A) && A == loc) || (sdepth != -1 && sdepth <= 1))
if(can_wield_item)
if(holding)
var/resolved = holding.resolve_attackby(A, src, params)
if(!resolved && A && holding)
holding.afterattack(A, src, 1, params) // 1 indicates adjacency
setClickCooldown(DEFAULT_QUICK_COOLDOWN)
else if(!holding)
else
if(ismob(A)) // No instant mob attacking
setClickCooldown(DEFAULT_QUICK_COOLDOWN)
UnarmedAttack(A, TRUE)
Expand All @@ -138,13 +136,13 @@
sdepth = A.storage_depth_turf()
if(isturf(A) || isturf(A.loc) || (sdepth != -1 && sdepth <= 1))
if(A.Adjacent(src)) // see adjacent.dm
if(can_wield_item)
if(holding)
// Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
var/resolved = holding.resolve_attackby(A,src, params)
if(!resolved && A && holding)
holding.afterattack(A, src, 1, params) // 1: clicking something Adjacent
setClickCooldown(DEFAULT_QUICK_COOLDOWN)
else if(!holding)
else
if(ismob(A)) // No instant mob attacking
setClickCooldown(DEFAULT_QUICK_COOLDOWN)
UnarmedAttack(A, TRUE)
Expand Down
5 changes: 0 additions & 5 deletions code/_onclick/cyborg.dm
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,6 @@
holding.attack_self(src)
return

var/check_dexterity_val = A.storage ? DEXTERITY_NONE : (istype(holding) ? holding.needs_attack_dexterity : DEXTERITY_WIELD_ITEM)
var/can_wield_item = (!check_dexterity_val || check_dexterity(check_dexterity_val))
if(!can_wield_item)
return

if(A == loc || (A in loc) || (A in contents))
// No adjacency checks
var/resolved = holding.resolve_attackby(A, src, params)
Expand Down
11 changes: 9 additions & 2 deletions code/_onclick/hud/animal.dm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@
hud_used = /datum/hud/animal

/datum/hud/animal/FinalizeInstantiation()
action_intent = new(null, mymob, get_ui_style_data(), get_ui_color(), get_ui_alpha(), UI_ICON_INTENT)

var/ui_style = get_ui_style_data()
var/ui_color = get_ui_color()
var/ui_alpha = get_ui_alpha()

move_intent = new(null, mymob, ui_style, ui_color, ui_alpha, UI_ICON_MOVEMENT)
move_intent.icon_state = mymob.move_intent.hud_icon_state
adding += move_intent
action_intent = new(null, mymob, ui_style, ui_color, ui_alpha, UI_ICON_INTENT)
adding += action_intent
..()

21 changes: 14 additions & 7 deletions code/_onclick/item_attack.dm
Original file line number Diff line number Diff line change
Expand Up @@ -44,22 +44,24 @@ avoid code duplication. This includes items that may sometimes act as a standard
if(!.)
return bash(W,user)

/atom/movable/proc/bash(obj/item/W, mob/user)
/atom/movable/proc/bash(obj/item/weapon, mob/user)
if(isliving(user) && user.a_intent == I_HELP)
return FALSE
if(W.item_flags & ITEM_FLAG_NO_BLUDGEON)
if(!weapon.user_can_wield(user))
return FALSE
visible_message("<span class='danger'>[src] has been hit by [user] with [W].</span>")
if(weapon.item_flags & ITEM_FLAG_NO_BLUDGEON)
return FALSE
visible_message(SPAN_DANGER("[src] has been hit by [user] with [weapon]."))
return TRUE

/mob/living/attackby(obj/item/I, mob/user)
/mob/living/attackby(obj/item/used_item, mob/user)
if(!ismob(user))
return TRUE
if(can_operate(src,user) != OPERATE_DENY && I.do_surgery(src,user)) //Surgery
if(can_operate(src, user) != OPERATE_DENY && used_item.do_surgery(src,user)) //Surgery
return TRUE
if(try_butcher_in_place(user, I))
if(try_butcher_in_place(user, used_item))
return TRUE
return I.use_on_mob(src, user)
return used_item.use_on_mob(src, user)

/mob/living/human/attackby(obj/item/I, mob/user)

Expand Down Expand Up @@ -96,6 +98,11 @@ avoid code duplication. This includes items that may sometimes act as a standard
//I would prefer to rename this attack_as_weapon(), but that would involve touching hundreds of files.
/obj/item/proc/use_on_mob(mob/living/target, mob/living/user, animate = TRUE)

// TODO: revisit if this should be a silent failure/parent call instead, for mob-level storage interactions?
// like a horse with a saddlebag or something
if(!user_can_wield(user))
return TRUE // skip other interactions

if(squash_item())
return TRUE

Expand Down
2 changes: 1 addition & 1 deletion code/_onclick/other_mobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
var/decl/pronouns/G = get_pronouns()
face_atom(A)
if(attack_delay)
walk_to(src, 0) // Cancel any baked-in movement.
stop_automove() // Cancel any baked-in movement.
do_windup_animation(A, attack_delay, no_reset = TRUE)
if(!do_after(src, attack_delay, A) || !Adjacent(A))
visible_message(SPAN_NOTICE("\The [src] misses [G.his] attack on \the [A]!"))
Expand Down
55 changes: 55 additions & 0 deletions code/controllers/subsystems/mob_ai/auto_movement.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
SUBSYSTEM_DEF(automove)
name = "Automated Movement"
wait = 1
flags = SS_NO_INIT
priority = SS_PRIORITY_AUTO_MOVE

var/list/moving_atoms = list()
var/list/moving_metadata = list()
var/list/processing_atoms

/datum/controller/subsystem/automove/proc/unregister_mover(atom/movable/mover)
if(!istype(mover))
CRASH("Invalid parameters to unregister_mover: [mover || "NULL"]")
if(length(moving_atoms))
moving_atoms -= mover
if(length(moving_metadata))
moving_metadata -= mover
if(length(processing_atoms))
processing_atoms -= mover

/datum/controller/subsystem/automove/proc/register_mover(atom/movable/mover, controller_type, datum/automove_metadata/metadata)
if(!istype(mover) || (!ispath(controller_type, /decl/automove_controller) && !istype(controller_type, /decl/automove_controller)))
CRASH("Invalid parameters to register_mover: [controller_type || "NULL"], [mover || "NULL"]")

var/decl/automove_controller/controller = ispath(controller_type) ? GET_DECL(controller_type) : controller_type
moving_atoms[mover] = controller
if(istype(metadata))
moving_metadata[mover] = metadata
else
moving_metadata -= mover

if(suspended)
wake()

/datum/controller/subsystem/automove/fire(resumed = FALSE)

if(!resumed)
processing_atoms = moving_atoms.Copy()

if(!length(processing_atoms))
suspend()
return

var/i = 0
var/atom/movable/mover
var/decl/automove_controller/controller
while(i < processing_atoms.len)
i++
mover = processing_atoms[i]
controller = processing_atoms[mover]
if(controller.handle_mover(mover, moving_metadata[mover]) == PROCESS_KILL && !QDELETED(mover))
mover.stop_automove()
if(MC_TICK_CHECK)
processing_atoms.Cut(1, i+1)
return
3 changes: 3 additions & 0 deletions code/controllers/subsystems/mob_ai/mob_ai.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
PROCESSING_SUBSYSTEM_DEF(mob_ai)
name = "Mob AI"
priority = SS_PRIORITY_MOB_AI
3 changes: 0 additions & 3 deletions code/controllers/subsystems/processing/ai.dm

This file was deleted.

22 changes: 14 additions & 8 deletions code/datums/ai/ai.dm
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
/datum/ai
/datum/mob_controller
var/name
var/mob/living/body // The parent mob we control.
var/expected_type = /mob/living // Type of mob this AI applies to.
var/wait_for = 0 // The next time we can process.
var/run_interval = 1 // How long to wait between processes.

/datum/ai/New(var/mob/living/target_body)
/datum/mob_controller/New(var/mob/living/target_body)
body = target_body
if(expected_type && !istype(body, expected_type))
PRINT_STACK_TRACE("AI datum [type] received a body ([body ? body.type : "NULL"]) of unexpected type ([expected_type]).")
START_PROCESSING(SSai, src)
START_PROCESSING(SSmob_ai, src)

/datum/ai/Destroy()
STOP_PROCESSING(SSai, src)
/datum/mob_controller/Destroy()
STOP_PROCESSING(SSmob_ai, src)
if(body)
if(body.ai == src)
body.ai = null
body = null
. = ..()

/datum/ai/proc/can_process()
/datum/mob_controller/proc/can_process()
if(!body || !body.loc || ((body.client || body.mind) && !(body.status_flags & ENABLE_AI)))
return FALSE
if(wait_for > world.time)
Expand All @@ -28,7 +28,7 @@
return FALSE
return TRUE

/datum/ai/Process()
/datum/mob_controller/Process()
if(!can_process())
return

Expand All @@ -37,5 +37,11 @@
do_process(time_elapsed)

// This is the place to actually do work in the AI.
/datum/ai/proc/do_process(var/time_elapsed)
/datum/mob_controller/proc/do_process(var/time_elapsed)
return

/datum/mob_controller/proc/get_automove_target(datum/automove_metadata/metadata)
return null

/datum/mob_controller/proc/can_do_automated_move(variant_move_delay)
return body && !body.client
4 changes: 2 additions & 2 deletions code/datums/ai/human.dm
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/datum/ai/human
/datum/mob_controller/human
name = "human"
expected_type = /mob/living/human

/datum/ai/human/do_process(var/time_elapsed)
/datum/mob_controller/human/do_process(var/time_elapsed)
var/mob/living/human/H = body
if(H.stat != CONSCIOUS)
return
Expand Down
4 changes: 2 additions & 2 deletions code/datums/ai/monkey.dm
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/datum/ai/monkey
/datum/mob_controller/monkey
name = "monkey"
expected_type = /mob/living/human
var/list/no_touchie = list(
/obj/item/mirror,
/obj/structure/mirror
)

/datum/ai/monkey/do_process(var/time_elapsed)
/datum/mob_controller/monkey/do_process(var/time_elapsed)
if(body.incapacitated())
return

Expand Down
2 changes: 1 addition & 1 deletion code/datums/config/config_types/config_server.dm
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@

/decl/config/toggle/delist_when_no_admins
uid = "delist_when_no_admins"
desc = "Determines if the server should hide itself from the hub when no admins are online.."
desc = "Determines if the server should hide itself from the hub when no admins are online."

/decl/config/toggle/wait_for_sigusr1_reboot
uid = "wait_for_sigusr1_reboot"
Expand Down
21 changes: 13 additions & 8 deletions code/datums/extensions/lockable.dm
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@
Process keypresses coming from the nanoUI.
*/
/datum/extension/lockable/proc/pressed_key(key_char, mob/user)
if(!user.check_dexterity(DEXTERITY_KEYBOARDS))
return
// Always clear error when pressing a button.
clear_error()

Expand Down Expand Up @@ -318,22 +320,25 @@
/**
Item attack handler for interactions with the host.
*/
/datum/extension/lockable/proc/attackby(obj/item/W, mob/user)
/datum/extension/lockable/proc/attackby(obj/item/used_item, mob/user)
if(!locked)
return
return FALSE

if(!used_item.user_can_wield(user))
return TRUE

//TODO: This probably should be handled in a better way.
if(!is_digital_lock && istype(W, /obj/item/energy_blade))
var/obj/item/energy_blade/blade = W
if(!is_digital_lock && istype(used_item, /obj/item/energy_blade))
var/obj/item/energy_blade/blade = used_item
if(blade.is_special_cutting_tool() && emag_act(INFINITY, user, "You slice through the lock of \the [holder]."))
var/obj/item/A = holder
spark_at(A.loc, amount=5)
playsound(A.loc, 'sound/weapons/blade1.ogg', 50, 1)
return TRUE

if(IS_SCREWDRIVER(W))
if(IS_SCREWDRIVER(used_item))
if(!opening_panel)
var/obj/item/screwdriver/S = W
var/obj/item/screwdriver/S = used_item
opening_panel = TRUE //Make sure we only have one user/attempt to opens the panel at a time.
if(
S.do_tool_interaction(
Expand All @@ -350,8 +355,8 @@
toggle_panel(user)
return TRUE

if(IS_MULTITOOL(W))
try_hack(W, user)
if(IS_MULTITOOL(used_item))
try_hack(used_item, user)
return TRUE

/**
Expand Down
2 changes: 1 addition & 1 deletion code/datums/inventory_slots/inventory_gripper_subtypes.dm
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
overlay_slot = BP_MOUTH
ui_label = "M"
hand_sort_priority = 3
dexterity = DEXTERITY_SIMPLE_MACHINES | DEXTERITY_HOLD_ITEM | DEXTERITY_EQUIP_ITEM | DEXTERITY_KEYBOARDS | DEXTERITY_TOUCHSCREENS
dexterity = DEXTERITY_SIMPLE_MACHINES | DEXTERITY_GRAPPLE | DEXTERITY_HOLD_ITEM | DEXTERITY_EQUIP_ITEM | DEXTERITY_KEYBOARDS | DEXTERITY_TOUCHSCREENS

/datum/inventory_slot/gripper/mouth/simple
requires_organ_tag = null
Expand Down
Loading

0 comments on commit da23970

Please sign in to comment.