mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-20 04:17:33 +01:00
e0aa218843
https://www.youtube.com/watch?v=9mPvZ96pHJI A pull request commissioned by the Synthetic Lore Team to comprehensively rework synthetics (read: IPCs) and how they work in Aurora. The objective is to make IPCs as unique as possible from humans, upgrading the robotic feel and atmosphere, while also preserving a good sense of balance in-game. Key features: - A comprehensive expansion of synthetic organs, all of which now fulfill a purpose: hydraulics, cooling units, power systems, actuators, diagnostics units. - Customizable organs with benefits and drawbacks, such as with cooling units and power systems. - Unique ways to repair the organs and more involved steps. - Unique damage mechanics - every organ has wiring and electronics which affect its functioning, and they are defended by plating which provides natural armour. - Improved and immersive diagnostics. - Unique features, benefits, and drawbacks for every IPC frame. - A rework of the positronic brain, which can be either destroyed or shut down, alongside effects caused by low integrity. - A rework of how EMPs affect IPC organs. - Non-binary damage states for each organ. To-do: - [x] Finish the unique features for each frame. - [x] Look into if mechanical synthskin is possible. - [x] Power system. - [x] Posibrain mechanics. - [ ] Passive cooling expansion. - [x] EMP mechanics. - [x] Repair mechanics. - [x] Mob weight mechanics. - [ ] Gurney for heavy mobs. - [x] New augments. - [ ] IPC tag scanning and flashing. --------- Signed-off-by: Werner <1331699+Arrow768@users.noreply.github.com> Co-authored-by: Matt Atlas <liermattia@gmail.com> Co-authored-by: Geeves <22774890+Geevies@users.noreply.github.com> Co-authored-by: Werner <1331699+Arrow768@users.noreply.github.com>
403 lines
12 KiB
Plaintext
403 lines
12 KiB
Plaintext
/obj
|
|
layer = OBJ_LAYER
|
|
animate_movement = 2
|
|
|
|
/// Used to store information about the contents of the object.
|
|
var/list/matter
|
|
/// Whether the object can be recycled (eaten) by something like the Autolathe
|
|
var/recyclable = FALSE
|
|
/// Size of the object.
|
|
var/w_class
|
|
/// Used by R&D to determine what research bonuses it grants.
|
|
var/list/origin_tech = null
|
|
/// Universal "unacidabliness" var, here so you can use it in any obj.
|
|
var/unacidable = FALSE
|
|
|
|
/// Special flags such as whether or not this object can be rotated.
|
|
var/obj_flags
|
|
/// Integer. Used for varied damage and item volume calculations.
|
|
var/throwforce = 1
|
|
/// Used in attackby() to say how something was attacked "[x] has been [z.attack_verb] by [y] with [z]"
|
|
var/list/attack_verb
|
|
/// Whether this object cuts.
|
|
var/sharp = FALSE
|
|
/// Whether this object is more likely to dismember its poor foes.
|
|
var/edge = FALSE
|
|
/// If we have a user using us, this will be set on. We will check if the user has stopped using us, and thus stop updating and LAGGING EVERYTHING!
|
|
var/in_use = FALSE
|
|
/// Type of damage this object deals.
|
|
var/damtype = DAMAGE_BRUTE
|
|
var/force = 0
|
|
var/armor_penetration = 0
|
|
/// Makes an object not able to slice things.
|
|
var/noslice = FALSE
|
|
|
|
var/being_shocked = 0
|
|
|
|
/// If set, this holds the 3-letter shortname of a species, used for species-specific worn icons.
|
|
var/icon_species_tag = ""
|
|
/// If TRUE, this item will automatically change its species tag to match the wearer's species, given the wearer's species is listed in icon_supported_species_tags.
|
|
var/icon_auto_adapt = FALSE
|
|
|
|
/**
|
|
* A list of strings used with icon_auto_adapt, a list of species which have differing appearances for this item,
|
|
* based on the specie short name
|
|
*/
|
|
var/list/icon_supported_species_tags
|
|
|
|
/// If `TRUE`, will use the `icon_species_tag` var for rendering this item in the left/right hand.
|
|
var/icon_species_in_hand = FALSE
|
|
|
|
var/equip_slot = 0
|
|
/// Played when the item is used, for example tools.
|
|
var/usesound
|
|
|
|
var/toolspeed = 1
|
|
|
|
var/surgerysound
|
|
|
|
/* START BUCKLING VARS */
|
|
var/list/can_buckle
|
|
var/buckle_movable = 0
|
|
var/buckle_dir = 0
|
|
var/buckle_lying = -1 //bed-like behavior, forces mob.lying = buckle_lying if != -1
|
|
var/buckle_require_restraints = 0 //require people to be handcuffed before being able to buckle. eg: pipes
|
|
var/atom/movable/buckled = null
|
|
/**
|
|
* Stores the original layer of a buckled atom.
|
|
*
|
|
* Set in `/obj/proc/buckle` when the atom's layer is adjusted.
|
|
*
|
|
* Used in `/unbuckle()` to restore the original layer.
|
|
*/
|
|
var/buckled_original_layer = null
|
|
var/buckle_delay = 0 //How much extra time to buckle someone to this object.
|
|
/* END BUCKLING VARS */
|
|
|
|
/* START ACCESS VARS */
|
|
var/list/req_access
|
|
var/list/req_one_access
|
|
/* END ACCESS VARS */
|
|
|
|
/* START PERSISTENCE VARS */
|
|
// State check if the subsystem is tracking the object, used for easy state checking without iterating the register
|
|
var/persistence_track_active = FALSE
|
|
// Tracking ID of the object used by the persistence subsystem
|
|
var/persistence_track_id = 0
|
|
// Author ckey of the object used in persistence subsystem
|
|
// Note: Not every type can have an author, like generated dirt for example
|
|
// Additionally, the ckey is only an indicator, for example: A player could pin a paper without having written it
|
|
// This should be considered for any moderation purpose
|
|
var/persistence_author_ckey = null
|
|
// Expiration time used when saving/updating a persistent type, this can be changed depending on the use case by assigning a new value
|
|
var/persistance_expiration_time_days = PERSISTENT_DEFAULT_EXPIRATION_DAYS
|
|
/* END PERSISTENCE VARS */
|
|
|
|
/obj/Destroy()
|
|
if(persistence_track_active) // Prevent hard deletion of references in the persistence register by removing it preemptively
|
|
SSpersistence.deregister_track(src)
|
|
STOP_PROCESSING(SSprocessing, src)
|
|
unbuckle()
|
|
QDEL_NULL(talking_atom)
|
|
return ..()
|
|
|
|
/obj/Topic(href, href_list, var/datum/ui_state/state = GLOB.default_state)
|
|
if(..())
|
|
return 1
|
|
|
|
// In the far future no checks are made in an overriding Topic() beyond if(..()) return
|
|
// Instead any such checks are made in CanUseTopic()
|
|
if(CanUseTopic(usr, state, href_list) == STATUS_INTERACTIVE)
|
|
CouldUseTopic(usr)
|
|
return 0
|
|
|
|
CouldNotUseTopic(usr)
|
|
return 1
|
|
|
|
/obj/CanUseTopic(var/mob/user, var/datum/ui_state/state)
|
|
if(user.CanUseObjTopic(src))
|
|
return ..()
|
|
to_chat(user, SPAN_DANGER("[icon2html(src, user)]Access denied!"))
|
|
return STATUS_CLOSE
|
|
|
|
/mob/living/silicon/CanUseObjTopic(var/obj/O)
|
|
var/id = src.GetIdCard()
|
|
return O.check_access(id)
|
|
|
|
/mob/proc/CanUseObjTopic()
|
|
return 1
|
|
|
|
/obj/proc/CouldUseTopic(var/mob/user)
|
|
user.AddTopicPrint(src)
|
|
|
|
/mob/proc/AddTopicPrint(var/obj/target)
|
|
target.add_hiddenprint(src)
|
|
|
|
/mob/living/AddTopicPrint(var/obj/target)
|
|
if(Adjacent(target))
|
|
target.add_fingerprint(src)
|
|
else
|
|
target.add_hiddenprint(src)
|
|
|
|
/mob/living/silicon/ai/AddTopicPrint(var/obj/target)
|
|
target.add_hiddenprint(src)
|
|
|
|
/obj/proc/CouldNotUseTopic(var/mob/user)
|
|
// Nada
|
|
|
|
/obj/proc/ai_can_interact(var/mob/user)
|
|
if(!Adjacent(user) && within_jamming_range(src, FALSE)) // if not adjacent to it, it uses wireless signal
|
|
to_chat(user, SPAN_WARNING("Something in the area of \the [src] is blocking the remote signal!"))
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/obj/item/proc/is_used_on(obj/O, mob/user)
|
|
|
|
/obj/assume_air(datum/gas_mixture/giver)
|
|
if(loc)
|
|
return loc.assume_air(giver)
|
|
else
|
|
return null
|
|
|
|
/obj/remove_air(amount)
|
|
if(loc)
|
|
return loc.remove_air(amount)
|
|
else
|
|
return null
|
|
|
|
/obj/return_air()
|
|
if(loc)
|
|
return loc.return_air()
|
|
|
|
/obj/proc/updateUsrDialog()
|
|
if(in_use)
|
|
var/is_in_use = 0
|
|
var/list/nearby = viewers(1, src)
|
|
for(var/mob/M in nearby)
|
|
if ((M.client && M.machine == src))
|
|
is_in_use = 1
|
|
src.attack_hand(M)
|
|
if (istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/living/silicon/robot))
|
|
if (!(usr in nearby))
|
|
if (usr.client && usr.machine==src) // && M.machine == src is omitted because if we triggered this by using the dialog, it doesn't matter if our machine changed in between triggering it and this - the dialog is probably still supposed to refresh.
|
|
is_in_use = 1
|
|
src.attack_ai(usr)
|
|
in_use = is_in_use
|
|
|
|
/obj/proc/updateDialog()
|
|
// Check that people are actually using the machine. If not, don't update anymore.
|
|
if(in_use)
|
|
var/list/nearby = viewers(1, src)
|
|
var/is_in_use = 0
|
|
for(var/mob/M in nearby)
|
|
if ((M.client && M.machine == src))
|
|
is_in_use = 1
|
|
src.interact(M)
|
|
var/ai_in_use = AutoUpdateAI(src)
|
|
|
|
if(!ai_in_use && !is_in_use)
|
|
in_use = 0
|
|
|
|
/obj/attack_ghost(mob/user)
|
|
ui_interact(user)
|
|
..()
|
|
|
|
/obj/proc/interact(mob/user)
|
|
return
|
|
|
|
/mob/proc/unset_machine()
|
|
src.machine = null
|
|
|
|
/mob/proc/set_machine(var/obj/O)
|
|
if(src.machine)
|
|
unset_machine()
|
|
src.machine = O
|
|
if(istype(O))
|
|
O.in_use = 1
|
|
|
|
/obj/item/proc/updateSelfDialog()
|
|
var/mob/M = src.loc
|
|
if(istype(M) && M.client && M.machine == src)
|
|
src.attack_self(M)
|
|
|
|
/obj/proc/hide(var/hide)
|
|
set_invisibility(hide ? INVISIBILITY_MAXIMUM : initial(invisibility))
|
|
level = hide ? 1 : initial(level)
|
|
|
|
/obj/proc/hides_under_flooring()
|
|
return level == 1
|
|
|
|
/obj/proc/hear_talk(mob/M as mob, text, verb, datum/language/speaking)
|
|
if(talking_atom)
|
|
talking_atom.catchMessage(text, M)
|
|
|
|
/obj/proc/see_emote(mob/M as mob, text, var/emote_type)
|
|
return
|
|
|
|
/obj/proc/tesla_act(var/power, var/melt = FALSE)
|
|
if(melt)
|
|
visible_message(SPAN_DANGER("\The [src] melts down until ashes are left!"))
|
|
new /obj/effect/decal/cleanable/ash(loc)
|
|
qdel(src)
|
|
return
|
|
being_shocked = 1
|
|
var/power_bounced = power / 2
|
|
tesla_zap(src, 3, power_bounced)
|
|
addtimer(CALLBACK(src, PROC_REF(reset_shocked)), 10)
|
|
|
|
/obj/proc/reset_shocked()
|
|
being_shocked = 0
|
|
|
|
|
|
/obj/show_message(msg, type, alt, alt_type)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2)
|
|
return
|
|
|
|
//To be called from things that spill objects on the floor.
|
|
//Makes an object move around randomly for a couple of tiles
|
|
/obj/proc/tumble(var/dist)
|
|
if (dist >= 1)
|
|
spawn()
|
|
dist += rand(0,1)
|
|
for(var/i = 1, i <= dist, i++)
|
|
if(src)
|
|
step(src, pick(NORTH,SOUTH,EAST,WEST))
|
|
sleep(rand(2,4))
|
|
|
|
/**
|
|
* Sets the `icon_species_tag` on the `/obj` based on the wearer specie, which is
|
|
* then used by the icon generator to select the correct overlay of the object
|
|
*
|
|
* * wearer - A `/mob/living/carbon/human` to adapt the object to the specie of
|
|
*
|
|
* Returns `TRUE` on successful adaptation, `FALSE` otherwise
|
|
*/
|
|
/obj/proc/auto_adapt_species(mob/living/carbon/human/wearer)
|
|
SHOULD_NOT_SLEEP(TRUE)
|
|
if(icon_auto_adapt)
|
|
icon_species_tag = ""
|
|
if(wearer && length(icon_supported_species_tags))
|
|
if(wearer.species.short_name in icon_supported_species_tags)
|
|
icon_species_tag = wearer.species.short_name
|
|
return TRUE
|
|
return FALSE
|
|
|
|
|
|
//This function should be called on an item when it is:
|
|
//Built, autolathed, protolathed, crafted or constructed. At runtime, by players or machines
|
|
|
|
//It should NOT be called on things that:
|
|
//spawn at roundstart, are adminspawned, arrive on shuttles, spawned from vendors, removed from fridges and containers, etc
|
|
//This is useful for setting special behaviour for built items that shouldn't apply to those spawned at roundstart
|
|
/obj/proc/Created()
|
|
return
|
|
|
|
/obj/proc/rotate(var/mob/user, var/anchored_ignore = FALSE)
|
|
if(use_check_and_message(user))
|
|
return
|
|
|
|
if(anchored && !anchored_ignore)
|
|
to_chat(user, SPAN_WARNING("\The [src] is bolted down to the floor!"))
|
|
return
|
|
|
|
set_dir(turn(dir, 90))
|
|
update_icon()
|
|
return TRUE
|
|
|
|
/obj/AltClick(var/mob/user)
|
|
if(obj_flags & OBJ_FLAG_ROTATABLE)
|
|
rotate(user)
|
|
return
|
|
if(obj_flags & OBJ_FLAG_ROTATABLE_ANCHORED)
|
|
rotate(user, TRUE)
|
|
return
|
|
..()
|
|
|
|
/obj/get_examine_text(mob/user, distance, is_adjacent, infix, suffix, get_extended = FALSE)
|
|
. = ..()
|
|
if((obj_flags & OBJ_FLAG_ROTATABLE) || (obj_flags & OBJ_FLAG_ROTATABLE_ANCHORED))
|
|
. += SPAN_SUBTLE("Can be rotated with alt-click.")
|
|
if(contaminated)
|
|
. += SPAN_ALIEN("\The [src] has been contaminated!")
|
|
|
|
// whether mobs can unequip and drop items into us or not
|
|
/obj/proc/can_hold_dropped_items()
|
|
return TRUE
|
|
|
|
/obj/proc/damage_flags()
|
|
. = 0
|
|
if(has_edge(src))
|
|
. |= DAMAGE_FLAG_EDGE
|
|
if(is_sharp(src))
|
|
. |= DAMAGE_FLAG_SHARP
|
|
if(damtype == DAMAGE_BURN)
|
|
. |= DAMAGE_FLAG_LASER
|
|
|
|
/obj/proc/set_pixel_offsets()
|
|
return
|
|
|
|
//wash an object
|
|
/obj/proc/clean()
|
|
clean_blood()
|
|
color = initial(color)
|
|
|
|
/obj/proc/output_spoken_message(var/message, var/message_verb = "transmits", var/display_overhead = TRUE, var/overhead_time = 2 SECONDS)
|
|
audible_message("\The <b>[src.name]</b> [message_verb], \"[message]\"")
|
|
if(display_overhead)
|
|
var/list/hearers = get_hearers_in_view(7, src)
|
|
var/list/clients_in_hearers = list()
|
|
for(var/mob/mob in hearers)
|
|
if(mob.client)
|
|
clients_in_hearers += mob.client
|
|
if(length(clients_in_hearers))
|
|
langchat_speech(message, hearers, GLOB.all_languages, skip_language_check = TRUE)
|
|
|
|
/// Override this to customize the effects an activated signaler has.
|
|
/obj/proc/do_signaler()
|
|
return
|
|
|
|
|
|
/**
|
|
* Called when an access cable - from an IPC or from a roboticist tool - is inserted into an object.
|
|
*/
|
|
/obj/proc/insert_cable(obj/item/access_cable/cable, mob/user)
|
|
user.drop_from_inventory(cable)
|
|
cable.forceMove(src)
|
|
cable.target = src
|
|
|
|
/**
|
|
* Called when an access cable is removed from something, forcibly or not.
|
|
* Override as needed to clear variables up.
|
|
*/
|
|
/obj/proc/remove_cable(obj/item/access_cable/cable)
|
|
SHOULD_CALL_PARENT(TRUE)
|
|
cable.target = null
|
|
|
|
/**
|
|
* Called when an access cable - from an IPC or from a roboticist tool - is used on an object to interact with it.
|
|
* For example, brings up diagnostics for an access port if it's hooked into one.
|
|
*/
|
|
/obj/proc/cable_interact(obj/item/access_cable/cable, mob/user)
|
|
return
|
|
|
|
/*#############################################
|
|
PERSISTENT
|
|
#############################################*/
|
|
|
|
/**
|
|
* Called by the persistence subsystem to retrieve relevant persistent information to be stored in the database.
|
|
* Expected to be overriden by derived objects.
|
|
* RETURN: Associated list with custom information (e.g.: ["test" = "abc", "counter" = 123])
|
|
*/
|
|
/obj/proc/persistence_get_content()
|
|
return
|
|
|
|
/**
|
|
* Called by the persistence subsystem to apply persistent data on the created object.
|
|
* Expected to be overriden by derived objects.
|
|
* PARAMS:
|
|
* content = Associated list with custom information (e.g.: ["test" = "abc", "counter" = 123]).
|
|
* x,y,z = x-y-z coordinates of object, can be null.
|
|
*/
|
|
/obj/proc/persistence_apply_content(content, x, y, z)
|
|
return
|