Conflicts galore
This commit is contained in:
@@ -83,10 +83,3 @@
|
||||
|
||||
#define SPAM_TRIGGER_WARNING 5 //Number of identical messages required before the spam-prevention will warn you to stfu
|
||||
#define SPAM_TRIGGER_AUTOMUTE 10 //Number of identical messages required before the spam-prevention will automute you
|
||||
|
||||
///Max length of a keypress command before it's considered to be a forged packet/bogus command
|
||||
#define MAX_KEYPRESS_COMMANDLENGTH 16
|
||||
///Max amount of keypress messages per second over two seconds before client is autokicked
|
||||
#define MAX_KEYPRESS_AUTOKICK 100
|
||||
///Length of max held keys
|
||||
#define MAX_HELD_KEYS 15
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// Defines for managed input/keybinding system.
|
||||
/// Max length of a keypress command before it's considered to be a forged packet/bogus command
|
||||
#define MAX_KEYPRESS_COMMANDLENGTH 16
|
||||
/// Maximum keys that can be bound to one button
|
||||
#define MAX_COMMANDS_PER_KEY 5
|
||||
/// Maximum keys per keybind
|
||||
#define MAX_KEYS_PER_KEYBIND 3
|
||||
/// Max amount of keypress messages per second over two seconds before client is autokicked
|
||||
#define MAX_KEYPRESS_AUTOKICK 100
|
||||
/// Max keys that can be held down at once by a client
|
||||
#define MAX_HELD_KEYS 15
|
||||
|
||||
/// Macroset name of hotkeys/keybind only/modern mode
|
||||
#define SKIN_MACROSET_HOTKEYS "hotkeys"
|
||||
/// Macroset name of classic hotkey mode
|
||||
#define SKIN_MACROSET_CLASSIC_HOTKEYS "oldhotkeys"
|
||||
/// Macroset name of classic input mode
|
||||
#define SKIN_MACROSET_CLASSIC_INPUT "oldinput"
|
||||
@@ -103,4 +103,9 @@
|
||||
#define RCD_COMPUTER 16
|
||||
|
||||
#define RCD_UPGRADE_FRAMES 1
|
||||
#define RCD_UPGRADE_SIMPLE_CIRCUITS 2
|
||||
#define RCD_UPGRADE_SIMPLE_CIRCUITS 2
|
||||
|
||||
//Electrochromatic window defines.
|
||||
#define NOT_ELECTROCHROMATIC 0
|
||||
#define ELECTROCHROMATIC_OFF 1
|
||||
#define ELECTROCHROMATIC_DIMMED 2
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
#define COMSIG_EXIT_AREA "exit_area" //from base of area/Exited(): (/area)
|
||||
|
||||
#define COMSIG_CLICK "atom_click" //from base of atom/Click(): (location, control, params, mob/user)
|
||||
#define COMSIG_CLICK_SHIFT "shift_click" //from base of atom/ShiftClick(): (/mob)
|
||||
#define COMSIG_CLICK_SHIFT "shift_click" //from base of atom/ShiftClick(): (/mob), return flags also used by other signals.
|
||||
#define COMPONENT_ALLOW_EXAMINATE 1
|
||||
#define COMPONENT_DENY_EXAMINATE 2 //Higher priority compared to the above one
|
||||
|
||||
@@ -141,13 +141,17 @@
|
||||
#define HEARING_SOURCE 8*/
|
||||
#define COMSIG_MOVABLE_DISPOSING "movable_disposing" //called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source)
|
||||
#define COMSIG_MOVABLE_TELEPORTED "movable_teleported" //from base of do_teleport(): (channel, turf/origin, turf/destination)
|
||||
|
||||
// /mind signals
|
||||
#define COMSIG_PRE_MIND_TRANSFER "pre_mind_transfer" //from base of mind/transfer_to() before it's done: (new_character, old_character)
|
||||
#define COMPONENT_STOP_MIND_TRANSFER 1 //stops the mind transfer from happening.
|
||||
#define COMSIG_MIND_TRANSFER "mind_transfer" //from base of mind/transfer_to() when it's done: (new_character, old_character)
|
||||
|
||||
// /mob signals
|
||||
#define COMSIG_MOB_EXAMINATE "mob_examinate" //from base of /mob/verb/examinate(): (atom/A)
|
||||
#define COMSIG_MOB_CLICKED_SHIFT_ON "mob_shift_click_on" //from base of /atom/ShiftClick(): (atom/A), for return values, see COMSIG_CLICK_SHIFT
|
||||
#define COMSIG_MOB_FOV_VIEW "mob_visible_atoms" //from base of mob/fov_view(): (list/visible_atoms)
|
||||
#define COMSIG_MOB_EXAMINATE "mob_examinate" //from base of /mob/verb/examinate(): (atom/A), for return values, see COMSIG_CLICK_SHIFT
|
||||
#define COMPONENT_EXAMINATE_BLIND 3 //outputs the "something is there but you can't see it" message.
|
||||
#define COMSIG_MOB_DEATH "mob_death" //from base of mob/death(): (gibbed)
|
||||
#define COMPONENT_BLOCK_DEATH_BROADCAST 1 //stops the death from being broadcasted in deadchat.
|
||||
#define COMSIG_MOB_CLICKON "mob_clickon" //from base of mob/clickon(): (atom/A, params)
|
||||
@@ -181,30 +185,14 @@
|
||||
#define SPEECH_LANGUAGE 5
|
||||
// #define SPEECH_IGNORE_SPAM 6
|
||||
// #define SPEECH_FORCED 7
|
||||
#define COMSIG_MOB_FOV_VIEWER "mob_is_viewer" //from base of /fov_viewers(): (atom/center, depth, viewers_list)
|
||||
#define COMSIG_MOB_GET_VISIBLE_MESSAGE "mob_get_visible_message" //from base of atom/visible_message(): (atom/A, msg, range, ignored_mobs)
|
||||
#define COMPONENT_NO_VISIBLE_MESSAGE 1 //exactly what's said on the tin.
|
||||
#define COMSIG_MOB_ANTAG_ON_GAIN "mob_antag_on_gain" //from base of /datum/antagonist/on_gain(): (antag_datum)
|
||||
|
||||
#define COMSIG_MOB_SPELL_CAN_CAST "mob_spell_can_cast" //from base of /obj/effect/proc_holder/spell/can_cast(): (spell)
|
||||
|
||||
#define COMSIG_MOB_ACTION_SKILL_MOD "mob_action_skill_mod" //from base of /datum/skill_holder/action_skills_mod() : (proc args list, list/mod_values)
|
||||
#define ACTION_SKILL_MOD_SKILL 1 //redundancy.
|
||||
#define ACTION_SKILL_MOD_VALUE 2
|
||||
#define ACTION_SKILL_MOD_THRESHOLD 3
|
||||
#define ACTION_SKILL_MOD_IS_MULTI 4
|
||||
//other mod values, kept separate from the args
|
||||
#define MOD_VALUES_SKILL_MOD 1
|
||||
|
||||
#define COMSIG_MOB_ITEM_ACTION_SKILLS_MOD "mob_item_action_skills_mod" //from base of /datum/skill_holder/item_action_skills_mod() : (proc args list, mod_values)
|
||||
#define ITEM_SKILLS_MOD_ITEM 1 //redundancy
|
||||
#define ITEM_SKILLS_MOD_VALUE 2
|
||||
#define ITEM_SKILLS_MOD_FLAGS 3
|
||||
#define ITEM_SKILLS_MOD_BAD_FLAGS 4
|
||||
#define ITEM_SKILLS_MOD_IS_MULTI 5
|
||||
//other mod values, kept separate from the args
|
||||
#define MOD_VALUES_ITEM_SKILLS_SUM 1
|
||||
#define MOD_VALUES_ITEM_SKILLS_DIV 2
|
||||
#define MOD_VALUES_ITEM_SKILLS_CHECKED 3
|
||||
|
||||
#define COMSIG_MOB_SKILL_GET_AFFINITY "mob_skill_get_affinity" //from base of /datum/skill_holder/get_skill_affinity(): (skill_path, list/return_value)
|
||||
#define COMSIG_ROBOT_UPDATE_ICONS "robot_update_icons" //from base of robot/update_icons(): ()
|
||||
|
||||
// /mob/living signals
|
||||
#define COMSIG_LIVING_REGENERATE_LIMBS "living_regenerate_limbs" //from base of /mob/living/regenerate_limbs(): (noheal, excluded_limbs)
|
||||
@@ -214,9 +202,13 @@
|
||||
#define COMSIG_LIVING_ELECTROCUTE_ACT "living_electrocute_act" //from base of mob/living/electrocute_act(): (shock_damage, source, siemens_coeff, flags)
|
||||
#define COMSIG_LIVING_MINOR_SHOCK "living_minor_shock" //sent by stuff like stunbatons and tasers: ()
|
||||
#define COMSIG_LIVING_REVIVE "living_revive" //from base of mob/living/revive() (full_heal, admin_revive)
|
||||
#define COMSIG_MOB_CLIENT_LOGIN "comsig_mob_client_login" //sent when a mob/login() finishes: (client)
|
||||
#define COMSIG_MOB_CLIENT_LOGOUT "comsig_mob_client_logout" //sent when a mob/logout() starts: (client)
|
||||
#define COMSIG_MOB_CLIENT_MOVE "comsig_mob_client_move" //sent when client/Move() finishes with no early returns: (client, direction, n, oldloc)
|
||||
|
||||
#define COMSIG_MOB_CLIENT_LOGIN "mob_client_login" //sent when a mob/login() finishes: (client)
|
||||
#define COMSIG_MOB_CLIENT_LOGOUT "mob_client_logout" //sent when a mob/logout() starts: (client)
|
||||
#define COMSIG_MOB_CLIENT_MOVE "mob_client_move" //sent when client/Move() finishes with no early returns: (client, direction, n, oldloc)
|
||||
#define COMSIG_MOB_CLIENT_CHANGE_VIEW "mob_client_change_view" //from base of /client/change_view(): (client, old_view, view)
|
||||
|
||||
#define COMSIG_MOB_RESET_PERSPECTIVE "mob_reset_perspective" //from base of /mob/reset_perspective(): (atom/target)
|
||||
#define COMSIG_LIVING_GUN_PROCESS_FIRE "living_gun_process_fire" //from base of /obj/item/gun/proc/process_fire(): (atom/target, params, zone_override)
|
||||
// This returns flags as defined for block in __DEFINES/combat.dm!
|
||||
#define COMSIG_LIVING_RUN_BLOCK "living_do_run_block" //from base of mob/living/do_run_block(): (real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone)
|
||||
@@ -277,6 +269,9 @@
|
||||
// THE FOLLOWING TWO BLOCKS SHOULD RETURN BLOCK FLAGS AS DEFINED IN __DEFINES/combat.dm!
|
||||
#define COMSIG_ITEM_CHECK_BLOCK "check_block" //from base of obj/item/check_block(): (mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
#define COMSIG_ITEM_RUN_BLOCK "run_block" //from base of obj/item/run_block(): (mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
// Item mouse siganls
|
||||
#define COMSIG_ITEM_MOUSE_EXIT "item_mouse_exit" //from base of obj/item/MouseExited(): (location, control, params)
|
||||
#define COMSIG_ITEM_MOUSE_ENTER "item_mouse_enter" //from base of obj/item/MouseEntered(): (location, control, params)
|
||||
#define COMSIG_ITEM_DECONSTRUCTOR_DEEPSCAN "deconstructor_deepscan" //Called by deconstructive analyzers deepscanning an item: (obj/machinery/rnd/destructive_analyzer/analyzer_machine, mob/user, list/information_list)
|
||||
// Uncovered information
|
||||
#define COMPONENT_DEEPSCAN_UNCOVERED_INFORMATION 1
|
||||
@@ -323,6 +318,9 @@
|
||||
#define COMSIG_SPECIES_GAIN "species_gain" //from datum/species/on_species_gain(): (datum/species/new_species, datum/species/old_species)
|
||||
#define COMSIG_SPECIES_LOSS "species_loss" //from datum/species/on_species_loss(): (datum/species/lost_species)
|
||||
|
||||
// /datum/mutation signals
|
||||
#define COMSIG_HUMAN_MUTATION_LOSS "human_mutation_loss" //from datum/mutation/human/on_losing(): (datum/mutation/human/lost_mutation)
|
||||
|
||||
/*******Component Specific Signals*******/
|
||||
//Janitor
|
||||
#define COMSIG_TURF_IS_WET "check_turf_wet" //(): Returns bitflags of wet values.
|
||||
|
||||
+38
-22
@@ -20,26 +20,41 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
|
||||
#define DF_ISPROCESSING (1<<2)
|
||||
|
||||
//FLAGS BITMASK
|
||||
|
||||
#define HEAR_1 (1<<3) // This flag is what recursive_hear_check() uses to determine wether to add an item to the hearer list or not.
|
||||
#define CHECK_RICOCHET_1 (1<<4) // Projectiels will check ricochet on things impacted that have this.
|
||||
#define CONDUCT_1 (1<<5) // conducts electricity (metal etc.)
|
||||
#define NODECONSTRUCT_1 (1<<7) // For machines and structures that should not break into parts, eg, holodeck stuff
|
||||
#define OVERLAY_QUEUED_1 (1<<8) // atom queued to SSoverlay
|
||||
#define ON_BORDER_1 (1<<9) // item has priority to check when entering or leaving
|
||||
#define PREVENT_CLICK_UNDER_1 (1<<11) //Prevent clicking things below it on the same turf eg. doors/ fulltile windows
|
||||
///This flag is what recursive_hear_check() uses to determine wether to add an item to the hearer list or not.
|
||||
#define HEAR_1 (1<<3)
|
||||
///Projectiels will check ricochet on things impacted that have this.
|
||||
#define CHECK_RICOCHET_1 (1<<4)
|
||||
///Conducts electricity (metal etc.).
|
||||
#define CONDUCT_1 (1<<5)
|
||||
///For machines and structures that should not break into parts, eg, holodeck stuff.
|
||||
#define NODECONSTRUCT_1 (1<<7)
|
||||
///Atom queued to SSoverlay.
|
||||
#define OVERLAY_QUEUED_1 (1<<8)
|
||||
///Item has priority to check when entering or leaving.
|
||||
#define ON_BORDER_1 (1<<9)
|
||||
///Prevent clicking things below it on the same turf eg. doors/ fulltile windows.
|
||||
#define PREVENT_CLICK_UNDER_1 (1<<11)
|
||||
#define HOLOGRAM_1 (1<<12)
|
||||
#define TESLA_IGNORE_1 (1<<13) // TESLA_IGNORE grants immunity from being targeted by tesla-style electricity
|
||||
#define INITIALIZED_1 (1<<14) //Whether /atom/Initialize() has already run for the object
|
||||
#define ADMIN_SPAWNED_1 (1<<15) //was this spawned by an admin? used for stat tracking stuff.
|
||||
#define PREVENT_CONTENTS_EXPLOSION_1 (1<<16) /// should not get harmed if this gets caught by an explosion?
|
||||
///Prevents mobs from getting chainshocked by teslas and the supermatter.
|
||||
#define SHOCKED_1 (1<<13)
|
||||
///Whether /atom/Initialize() has already run for the object.
|
||||
#define INITIALIZED_1 (1<<14)
|
||||
///was this spawned by an admin? used for stat tracking stuff.
|
||||
#define ADMIN_SPAWNED_1 (1<<15)
|
||||
/// should not get harmed if this gets caught by an explosion?
|
||||
#define PREVENT_CONTENTS_EXPLOSION_1 (1<<16)
|
||||
/// Early returns mob.face_atom()
|
||||
#define BLOCK_FACE_ATOM_1 (1<<17)
|
||||
|
||||
//turf-only flags
|
||||
#define NOJAUNT_1 (1<<0)
|
||||
#define UNUSED_RESERVATION_TURF_1 (1<<1)
|
||||
#define CAN_BE_DIRTY_1 (1<<2) // If a turf can be made dirty at roundstart. This is also used in areas.
|
||||
#define NO_LAVA_GEN_1 (1<<6) //Blocks lava rivers being generated on the turf
|
||||
#define NO_RUINS_1 (1<<10) //Blocks ruins spawning on the turf
|
||||
///If a turf can be made dirty at roundstart. This is also used in areas.
|
||||
#define CAN_BE_DIRTY_1 (1<<2)
|
||||
///Blocks lava rivers being generated on the turf.
|
||||
#define NO_LAVA_GEN_1 (1<<6)
|
||||
///Blocks ruins spawning on the turf.
|
||||
#define NO_RUINS_1 (1<<10)
|
||||
|
||||
/*
|
||||
These defines are used specifically with the atom/pass_flags bitmask
|
||||
@@ -75,14 +90,15 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
|
||||
#define GOLIATH_WEAKNESS (1<<9) //CIT CHANGE
|
||||
|
||||
//tesla_zap
|
||||
#define TESLA_MACHINE_EXPLOSIVE (1<<0)
|
||||
#define TESLA_ALLOW_DUPLICATES (1<<1)
|
||||
#define TESLA_OBJ_DAMAGE (1<<2)
|
||||
#define TESLA_MOB_DAMAGE (1<<3)
|
||||
#define TESLA_MOB_STUN (1<<4)
|
||||
#define ZAP_MACHINE_EXPLOSIVE (1<<0)
|
||||
#define ZAP_ALLOW_DUPLICATES (1<<1)
|
||||
#define ZAP_OBJ_DAMAGE (1<<2)
|
||||
#define ZAP_MOB_DAMAGE (1<<3)
|
||||
#define ZAP_MOB_STUN (1<<4)
|
||||
|
||||
#define TESLA_DEFAULT_FLAGS ALL
|
||||
#define TESLA_FUSION_FLAGS TESLA_OBJ_DAMAGE | TESLA_MOB_DAMAGE | TESLA_MOB_STUN
|
||||
#define ZAP_DEFAULT_FLAGS ALL
|
||||
#define ZAP_FUSION_FLAGS ZAP_OBJ_DAMAGE | ZAP_MOB_DAMAGE | ZAP_MOB_STUN
|
||||
#define ZAP_SUPERMATTER_FLAGS NONE
|
||||
|
||||
//EMP protection
|
||||
#define EMP_PROTECT_SELF (1<<0)
|
||||
|
||||
@@ -24,6 +24,15 @@
|
||||
#define FOOTPRINT_SNAKE "snake"
|
||||
#define FOOTPRINT_DRAG "drag"
|
||||
|
||||
//footstep mob defines
|
||||
#define FOOTSTEP_MOB_CLAW 1
|
||||
#define FOOTSTEP_MOB_BAREFOOT 2
|
||||
#define FOOTSTEP_MOB_HEAVY 3
|
||||
#define FOOTSTEP_MOB_SHOE 4
|
||||
#define FOOTSTEP_MOB_HUMAN 5 //Warning: Only works on /mob/living/carbon/human
|
||||
#define FOOTSTEP_MOB_SLIME 6
|
||||
#define FOOTSTEP_MOB_CRAWL 7
|
||||
|
||||
/*
|
||||
|
||||
id = list(
|
||||
|
||||
@@ -148,50 +148,6 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
|
||||
|
||||
#define isclown(A) (istype(A, /mob/living/simple_animal/hostile/retaliate/clown))
|
||||
|
||||
GLOBAL_LIST_INIT(shoefootmob, typecacheof(list(
|
||||
/mob/living/carbon/human/,
|
||||
/mob/living/simple_animal/cow,
|
||||
/mob/living/simple_animal/hostile/cat_butcherer,
|
||||
/mob/living/simple_animal/hostile/faithless,
|
||||
/mob/living/simple_animal/hostile/nanotrasen,
|
||||
/mob/living/simple_animal/hostile/pirate,
|
||||
/mob/living/simple_animal/hostile/russian,
|
||||
/mob/living/simple_animal/hostile/syndicate,
|
||||
/mob/living/simple_animal/hostile/wizard,
|
||||
/mob/living/simple_animal/hostile/zombie,
|
||||
/mob/living/simple_animal/hostile/retaliate/clown,
|
||||
/mob/living/simple_animal/hostile/retaliate/spaceman,
|
||||
/mob/living/simple_animal/hostile/retaliate/nanotrasenpeace,
|
||||
/mob/living/simple_animal/hostile/retaliate/goat,
|
||||
/mob/living/carbon/true_devil,
|
||||
)))
|
||||
|
||||
GLOBAL_LIST_INIT(clawfootmob, typecacheof(list(
|
||||
/mob/living/carbon/alien/humanoid,
|
||||
/mob/living/simple_animal/hostile/alien,
|
||||
/mob/living/simple_animal/pet/cat,
|
||||
/mob/living/simple_animal/pet/dog,
|
||||
/mob/living/simple_animal/pet/fox,
|
||||
/mob/living/simple_animal/chicken,
|
||||
/mob/living/simple_animal/hostile/bear,
|
||||
/mob/living/simple_animal/hostile/jungle/mega_arachnid,
|
||||
/mob/living/simple_animal/hostile/asteroid/ice_whelp,
|
||||
/mob/living/simple_animal/hostile/asteroid/wolf,
|
||||
/mob/living/simple_animal/hostile/asteroid/polarbear
|
||||
)))
|
||||
|
||||
GLOBAL_LIST_INIT(barefootmob, typecacheof(list(
|
||||
/mob/living/carbon/monkey,
|
||||
/mob/living/simple_animal/pet/penguin,
|
||||
/mob/living/simple_animal/hostile/gorilla,
|
||||
/mob/living/simple_animal/hostile/jungle/mook
|
||||
)))
|
||||
|
||||
GLOBAL_LIST_INIT(heavyfootmob, typecacheof(list(
|
||||
/mob/living/simple_animal/hostile/megafauna,
|
||||
/mob/living/simple_animal/hostile/jungle/leaper
|
||||
)))
|
||||
|
||||
//Misc mobs
|
||||
#define isobserver(A) (istype(A, /mob/dead/observer))
|
||||
|
||||
|
||||
@@ -11,16 +11,38 @@
|
||||
#define PLANE_SPACE_PARALLAX_RENDER_TARGET "PLANE_SPACE_PARALLAX"
|
||||
|
||||
#define OPENSPACE_LAYER 17 //Openspace layer over all
|
||||
#define OPENSPACE_PLANE -4 //Openspace plane below all turfs
|
||||
#define OPENSPACE_BACKDROP_PLANE -3 //Black square just over openspace plane to guaranteed cover all in openspace turf
|
||||
#define OPENSPACE_PLANE -10 //Openspace plane below all turfs
|
||||
#define OPENSPACE_BACKDROP_PLANE -9 //Black square just over openspace plane to guaranteed cover all in openspace turf
|
||||
|
||||
#define FLOOR_PLANE -2
|
||||
#define FLOOR_PLANE -8
|
||||
#define FLOOR_PLANE_RENDER_TARGET "FLOOR_PLANE"
|
||||
#define GAME_PLANE -1
|
||||
|
||||
#define WALL_PLANE -7
|
||||
#define WALL_PLANE_RENDER_TARGET "WALL_PLANE"
|
||||
|
||||
#define ABOVE_WALL_PLANE -6
|
||||
#define ABOVE_WALL_PLANE_RENDER_TARGET "ABOVE_WALL_PLANE"
|
||||
|
||||
#define FIELD_OF_VISION_BLOCKER_PLANE -5
|
||||
#define FIELD_OF_VISION_BLOCKER_RENDER_TARGET "*FIELD_OF_VISION_BLOCKER_PLANE"
|
||||
|
||||
#define FIELD_OF_VISION_PLANE -4
|
||||
#define FIELD_OF_VISION_RENDER_TARGET "*FIELD_OF_VISION_PLANE"
|
||||
#define FIELD_OF_VISION_LAYER 17 //used to place the visual (not the mask) shadow cone above any other floor plane stuff.
|
||||
|
||||
#define GAME_PLANE -3
|
||||
#define GAME_PLANE_RENDER_TARGET "GAME_PLANE"
|
||||
|
||||
#define FIELD_OF_VISION_VISUAL_PLANE -2 //Yea, FoV does require quite a few planes to work with 513 filters to a decent degree.
|
||||
#define FIELD_OF_VISION_VISUAL_RENDER_TARGET "FIELD_OF_VISION_VISUAL_PLANE"
|
||||
|
||||
#define CHAT_PLANE -1 //We don't want heard messages to be hidden by FoV.
|
||||
#define CHAT_LAYER 12.1 //Legacy, it doesn't matter that much because we are displayed above the game plane anyway.
|
||||
|
||||
#define BLACKNESS_PLANE 0 //To keep from conflicts with SEE_BLACKNESS internals
|
||||
#define BLACKNESS_PLANE_RENDER_TARGET "BLACKNESS_PLANE"
|
||||
|
||||
///Layers most often used by atoms of plane lower than GAME_PLANE
|
||||
#define SPACE_LAYER 1.8
|
||||
//#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define
|
||||
#define MID_TURF_LAYER 2.02
|
||||
@@ -40,11 +62,12 @@
|
||||
#define GAS_PIPE_VISIBLE_LAYER 2.47
|
||||
#define GAS_FILTER_LAYER 2.48
|
||||
#define GAS_PUMP_LAYER 2.49
|
||||
|
||||
#define LOW_OBJ_LAYER 2.5
|
||||
#define LOW_SIGIL_LAYER 2.52
|
||||
#define SIGIL_LAYER 2.54
|
||||
#define HIGH_SIGIL_LAYER 2.56
|
||||
|
||||
///Layers most often used by atoms of plane equal or higher than GAME_PLANE
|
||||
#define BELOW_OPEN_DOOR_LAYER 2.6
|
||||
#define BLASTDOOR_LAYER 2.65
|
||||
#define OPEN_DOOR_LAYER 2.7
|
||||
@@ -80,8 +103,9 @@
|
||||
#define SPACEVINE_LAYER 4.8
|
||||
#define SPACEVINE_MOB_LAYER 4.9
|
||||
//#define FLY_LAYER 5 //For easy recordkeeping; this is a byond define
|
||||
#define GASFIRE_LAYER 5.05
|
||||
#define RIPPLE_LAYER 5.1
|
||||
#define ABOVE_FLY_LAYER 5.1
|
||||
#define GASFIRE_LAYER 5.2
|
||||
#define RIPPLE_LAYER 5.3
|
||||
|
||||
#define GHOST_LAYER 6
|
||||
#define LOW_LANDMARK_LAYER 9
|
||||
@@ -91,8 +115,6 @@
|
||||
#define MASSIVE_OBJ_LAYER 11
|
||||
#define POINT_LAYER 12
|
||||
|
||||
#define CHAT_LAYER 12.1
|
||||
|
||||
#define EMISSIVE_BLOCKER_PLANE 12
|
||||
#define EMISSIVE_BLOCKER_LAYER 12
|
||||
#define EMISSIVE_BLOCKER_RENDER_TARGET "*EMISSIVE_BLOCKER_PLANE"
|
||||
@@ -136,19 +158,20 @@
|
||||
#define HUD_LAYER 21
|
||||
#define HUD_RENDER_TARGET "HUD_PLANE"
|
||||
|
||||
#define VOLUMETRIC_STORAGE_BOX_PLANE 23
|
||||
#define VOLUMETRIC_STORAGE_BOX_LAYER 23
|
||||
#define VOLUMETRIC_STORAGE_BOX_PLANE 22
|
||||
#define VOLUMETRIC_STORAGE_BOX_LAYER 22
|
||||
#define VOLUMETRIC_STORAGE_BOX_RENDER_TARGET "VOLUME_STORAGE_BOX_PLANE"
|
||||
|
||||
#define VOLUMETRIC_STORAGE_ITEM_PLANE 24
|
||||
#define VOLUMETRIC_STORAGE_ITEM_LAYER 24
|
||||
#define VOLUMETRIC_STORAGE_ITEM_PLANE 23
|
||||
#define VOLUMETRIC_STORAGE_ITEM_LAYER 23
|
||||
#define VOLUMETRIC_STORAGE_ACTIVE_ITEM_LAYER 25
|
||||
#define VOLUMETRIC_STORAGE_ACTIVE_ITEM_PLANE 25
|
||||
#define VOLUMETRIC_STORAGE_ITEM_RENDER_TARGET "VOLUME_STORAGE_ITEM_PLANE"
|
||||
|
||||
#define ABOVE_HUD_PLANE 25
|
||||
#define ABOVE_HUD_LAYER 25
|
||||
#define ABOVE_HUD_PLANE 30
|
||||
#define ABOVE_HUD_LAYER 30
|
||||
#define ABOVE_HUD_RENDER_TARGET "ABOVE_HUD_PLANE"
|
||||
|
||||
#define SPLASHSCREEN_LAYER 30
|
||||
#define SPLASHSCREEN_PLANE 30
|
||||
#define SPLASHSCREEN_LAYER 90
|
||||
#define SPLASHSCREEN_PLANE 90
|
||||
#define SPLASHSCREEN_RENDER_TARGET "SPLASHSCREEN_PLANE"
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#define INVESTIGATE_CIRCUIT "circuit"
|
||||
#define INVESTIGATE_FERMICHEM "fermichem"
|
||||
#define INVESTIGATE_RCD "rcd"
|
||||
#define INVESTIGATE_CRYOGENICS "cryogenics"
|
||||
|
||||
// Logging types for log_message()
|
||||
#define LOG_ATTACK (1 << 0)
|
||||
|
||||
@@ -463,7 +463,7 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
|
||||
#define PDAIMG(what) {"<span class="pda16x16 [#what]"></span>"}
|
||||
|
||||
//Filters
|
||||
#define AMBIENT_OCCLUSION list("type"="drop_shadow","x"=0,"y"=-2,"size"=4,"color"="#04080FAA")
|
||||
#define AMBIENT_OCCLUSION(_size, _color) list("type"="drop_shadow","x"=0,"y"=-2,"size"=_size,"color"=_color)
|
||||
#define EYE_BLUR(size) list("type"="blur", "size"=size)
|
||||
#define GRAVITY_MOTION_BLUR list("type"="motion_blur","x"=0,"y"=0)
|
||||
|
||||
|
||||
@@ -290,8 +290,15 @@
|
||||
|
||||
#define HUMAN_FIRE_STACK_ICON_NUM 3
|
||||
|
||||
#define TYPING_INDICATOR_TIMEOUT 5 MINUTES
|
||||
|
||||
#define GRAB_PIXEL_SHIFT_PASSIVE 6
|
||||
#define GRAB_PIXEL_SHIFT_AGGRESSIVE 12
|
||||
#define GRAB_PIXEL_SHIFT_NECK 16
|
||||
|
||||
#define SLEEP_CHECK_DEATH(X) sleep(X); if(QDELETED(src) || stat == DEAD) return;
|
||||
|
||||
/// Field of vision defines.
|
||||
#define FOV_90_DEGREES 90
|
||||
#define FOV_180_DEGREES 180
|
||||
#define FOV_270_DEGREES 270
|
||||
|
||||
@@ -51,6 +51,19 @@
|
||||
#define ASSEMBLY_FOURTH_STEP 3
|
||||
#define ASSEMBLY_FIFTH_STEP 4
|
||||
|
||||
//Bot Upgrade defines
|
||||
#define UPGRADE_CLEANER_ADVANCED_MOP (1<<0)
|
||||
#define UPGRADE_CLEANER_BROOM (1<<1)
|
||||
|
||||
#define UPGRADE_MEDICAL_HYPOSPRAY (1<<0)
|
||||
#define UPGRADE_MEDICAL_CHEM_BOARD (1<<1)
|
||||
#define UPGRADE_MEDICAL_CRYO_BOARD (1<<2)
|
||||
#define UPGRADE_MEDICAL_CHEM_MASTER (1<<3)
|
||||
#define UPGRADE_MEDICAL_SLEEP_BOARD (1<<4)
|
||||
#define UPGRADE_MEDICAL_PIERERCING (1<<5)
|
||||
|
||||
#define UPGRADE_FLOOR_ARTBOX (1<<0)
|
||||
#define UPGRADE_FLOOR_SYNDIBOX (1<<1)
|
||||
|
||||
//Checks to determine borg availability depending on the server's config. These are defines in the interest of reducing copypasta
|
||||
#define BORG_SEC_AVAILABLE (!CONFIG_GET(flag/disable_secborg) && GLOB.security_level >= CONFIG_GET(number/minimum_secborg_alert))
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
#define RUSTG_OVERRIDE_BUILTINS
|
||||
@@ -1,11 +1,27 @@
|
||||
// rust_g.dm - DM API for rust_g extension library
|
||||
#define RUST_G "rust_g"
|
||||
|
||||
#define RUSTG_JOB_NO_RESULTS_YET "NO RESULTS YET"
|
||||
#define RUSTG_JOB_NO_SUCH_JOB "NO SUCH JOB"
|
||||
#define RUSTG_JOB_ERROR "JOB PANICKED"
|
||||
|
||||
#define rustg_dmi_strip_metadata(fname) call(RUST_G, "dmi_strip_metadata")(fname)
|
||||
#define rustg_dmi_create_png(fname,width,height,data) call(RUST_G, "dmi_create_png")(fname,width,height,data)
|
||||
|
||||
#define rustg_git_revparse(rev) call(RUST_G, "rg_git_revparse")(rev)
|
||||
#define rustg_git_commit_date(rev) call(RUST_G, "rg_git_commit_date")(rev)
|
||||
|
||||
#define rustg_log_write(fname, text) call(RUST_G, "log_write")(fname, text)
|
||||
#define rustg_log_write(fname, text, format) call(RUST_G, "log_write")(fname, text, format)
|
||||
/proc/rustg_log_close_all() return call(RUST_G, "log_close_all")()
|
||||
|
||||
// RUST-G defines & procs for HTTP component
|
||||
#define RUSTG_HTTP_METHOD_GET "get"
|
||||
#define RUSTG_HTTP_METHOD_POST "post"
|
||||
#define RUSTG_HTTP_METHOD_PUT "put"
|
||||
#define RUSTG_HTTP_METHOD_DELETE "delete"
|
||||
#define RUSTG_HTTP_METHOD_PATCH "patch"
|
||||
#define RUSTG_HTTP_METHOD_HEAD "head"
|
||||
|
||||
#define rustg_http_request_blocking(method, url, body, headers) call(RUST_G, "http_request_blocking")(method, url, body, headers)
|
||||
#define rustg_http_request_async(method, url, body, headers) call(RUST_G, "http_request_async")(method, url, body, headers)
|
||||
#define rustg_http_check_request(req_id) call(RUST_G, "http_check_request")(req_id)
|
||||
|
||||
@@ -20,34 +20,34 @@
|
||||
|
||||
// Standard values for job starting skill affinities
|
||||
|
||||
#define STARTING_SKILL_AFFINITY_SURGERY_MEDICAL 1.2
|
||||
|
||||
#define STARTING_SKILL_AFFINITY_WIRING_ENGI_ROBO 1.2
|
||||
#define STARTING_SKILL_AFFINITY_DEF_JOB 1.2
|
||||
|
||||
// Standard values for skill gain (this is multiplied by affinity)
|
||||
|
||||
#define DEF_SKILL_GAIN 1
|
||||
#define SKILL_GAIN_SURGERY_PER_STEP 0.25
|
||||
|
||||
#define SKILL_AFFINITY_MOOD_BONUS 1.25
|
||||
//An extra point for each few seconds of delay when using a tool. Before the multiplier.
|
||||
#define SKILL_GAIN_DELAY_DIVISOR 3 SECONDS
|
||||
|
||||
///Items skill_flags and other defines
|
||||
#define SKILL_USE_TOOL (1<<0)
|
||||
#define SKILL_TRAINING_TOOL (1<<1)
|
||||
#define SKILL_ATTACK_MOB (1<<2)
|
||||
#define SKILL_TRAIN_ATTACK_MOB (1<<3)
|
||||
#define SKILL_ATTACK_OBJ (1<<4)
|
||||
#define SKILL_TRAIN_ATTACK_OBJ (1<<5)
|
||||
#define SKILL_STAMINA_COST (1<<6) //Influences the stamina cost from weapon usage.
|
||||
#define SKILL_THROW_STAM_COST (1<<7)
|
||||
#define SKILL_COMBAT_MODE (1<<8) //The user must have combat mode on.
|
||||
#define SKILL_USE_MOOD (1<<9) //Is the skill negatively affected by bad mood.
|
||||
#define SKILL_TRAIN_MOOD (1<<10) //Is this skill training affected by good mood.
|
||||
///Items skill_traits and other defines
|
||||
#define SKILL_USE_TOOL "use_tool"
|
||||
#define SKILL_TRAINING_TOOL "training_tool"
|
||||
#define SKILL_ATTACK_MOB "attack_mob"
|
||||
#define SKILL_TRAIN_ATTACK_MOB "train_attack_mob"
|
||||
#define SKILL_ATTACK_OBJ "attack_obj"
|
||||
#define SKILL_TRAIN_ATTACK_OBJ "train_attack_obj"
|
||||
#define SKILL_STAMINA_COST "stamina_cost" //Influences the stamina cost from weapon usage.
|
||||
#define SKILL_THROW_STAM_COST "throw_stam_cost"
|
||||
#define SKILL_COMBAT_MODE "combat_mode" //The user must have combat mode on.
|
||||
#define SKILL_SANITY "sanity" //Is the skill affected by (in)sanity.
|
||||
#define SKILL_INTELLIGENCE "intelligence" //Is the skill affected by brain damage?
|
||||
|
||||
///competency_threshold index defines
|
||||
#define THRESHOLD_COMPETENT 1
|
||||
#define THRESHOLD_EXPERT 2
|
||||
#define THRESHOLD_MASTER 3
|
||||
///competency_threshold defines
|
||||
#define THRESHOLD_UNTRAINED "untrained"
|
||||
#define THRESHOLD_COMPETENT "competent"
|
||||
#define THRESHOLD_EXPERT "expert"
|
||||
#define THRESHOLD_MASTER "master"
|
||||
|
||||
/// Level/Experience skills defines.
|
||||
#define STD_XP_LVL_UP 100
|
||||
@@ -75,3 +75,29 @@
|
||||
#define DORF_SKILL_COMPETENT 3
|
||||
#define DORF_SKILL_EXPERT 8
|
||||
#define DORF_SKILL_MASTER 12
|
||||
|
||||
/// Skill modifier defines and flags.
|
||||
#define MODIFIER_SKILL_VALUE (1<<0)
|
||||
#define MODIFIER_SKILL_AFFINITY (1<<1)
|
||||
#define MODIFIER_SKILL_LEVEL (1<<2)
|
||||
///makes the skill modifier a multiplier, not an addendum.
|
||||
#define MODIFIER_SKILL_MULT (1<<3)
|
||||
///Sets the skill to the defined value if lower than that. Highly reccomended you don't use it with MODIFIER_SKILL_MULT.
|
||||
#define MODIFIER_SKILL_VIRTUE (1<<4)
|
||||
///Does the opposite of the above. combining both effectively results in the skill being locked to the specified value.
|
||||
#define MODIFIER_SKILL_HANDICAP (1<<5)
|
||||
///Makes it untransferred by mind.transfer_to()
|
||||
#define MODIFIER_SKILL_BODYBOUND (1<<6)
|
||||
///Adds the difference of the current value and the value stored at the time the modifier was added to the result.
|
||||
#define MODIFIER_SKILL_ORIGIN_DIFF (1<<7)
|
||||
///Will this skill use competency thresholds instead of preset values
|
||||
#define MODIFIER_USE_THRESHOLDS (1<<8)
|
||||
|
||||
#define MODIFIER_TARGET_VALUE "value"
|
||||
#define MODIFIER_TARGET_LEVEL "level"
|
||||
#define MODIFIER_TARGET_AFFINITY "affinity"
|
||||
|
||||
///Ascending priority defines.
|
||||
#define MODIFIER_SKILL_PRIORITY_LOW 100
|
||||
#define MODIFIER_SKILL_PRIORITY_DEF 50
|
||||
#define MODIFIER_SKILL_PRIORITY_MAX 1 //max priority, meant for job/antag modifiers so they don't null out other (de)buffs
|
||||
@@ -6,3 +6,43 @@
|
||||
//More experience value getter macros
|
||||
#define GET_STANDARD_LVL(lvl) XP_LEVEL(STD_XP_LVL_UP, STD_XP_LVL_MULTI, lvl)
|
||||
#define GET_DORF_LVL(lvl) DORF_XP_LEVEL(DORF_XP_LVL_UP, DORF_XP_LVL_MULTI, lvl)
|
||||
|
||||
#define IS_SKILL_VALUE_GREATER(path, existing, new_value) GLOB.skill_datums[path].is_value_greater(existing, new_value)
|
||||
|
||||
#define SANITIZE_SKILL_VALUE(path, value) GLOB.skill_datums[path].sanitize_value(value)
|
||||
|
||||
///Doesn't automatically round the value.
|
||||
#define SANITIZE_SKILL_LEVEL(path, lvl) clamp(lvl, 0, GLOB.skill_datums[path].max_levels)
|
||||
|
||||
/// Simple generic identifier macro.
|
||||
#define GET_SKILL_MOD_ID(path, id) (id ? "[path]&[id]" : path)
|
||||
|
||||
/**
|
||||
* A simple universal comsig for body bound skill modifiers.
|
||||
* Technically they are still bound to the mind, but other signal procs will take care of adding and removing the modifier
|
||||
* from/to new/old minds.
|
||||
*/
|
||||
#define ADD_SKILL_MODIFIER_BODY(path, id, body, prototype) \
|
||||
prototype = GLOB.skill_modifiers[GET_SKILL_MOD_ID(path, id)] || new path(id, TRUE);\
|
||||
if(body.mind){\
|
||||
body.mind.add_skill_modifier(prototype.identifier)\
|
||||
} else {\
|
||||
prototype.RegisterSignal(body, COMSIG_MOB_ON_NEW_MIND, /datum/skill_modifier.proc/on_mob_new_mind, TRUE)\
|
||||
}
|
||||
|
||||
/// Same as above but to remove the skill modifier.
|
||||
#define REMOVE_SKILL_MODIFIER_BODY(path, id, body) \
|
||||
if(GLOB.skill_modifiers[GET_SKILL_MOD_ID(path, id)]){\
|
||||
if(body.mind){\
|
||||
body.mind.remove_skill_modifier(GET_SKILL_MOD_ID(path, id))\
|
||||
} else {\
|
||||
GLOB.skill_modifiers[GET_SKILL_MOD_ID(path, id)].UnregisterSignal(body, COMSIG_MOB_ON_NEW_MIND)\
|
||||
}\
|
||||
}
|
||||
|
||||
///Macro used when adding generic singleton skill modifiers.
|
||||
#define ADD_SINGLETON_SKILL_MODIFIER(mind, path, id) \
|
||||
if(!GLOB.skill_modifiers[GET_SKILL_MOD_ID(path, id)]){\
|
||||
new path(id, TRUE)\
|
||||
};\
|
||||
mind.add_skill_modifier(GET_SKILL_MOD_ID(path, id))
|
||||
|
||||
@@ -11,7 +11,21 @@
|
||||
#define STORAGE_LIMIT_MAX_W_CLASS (1<<3)
|
||||
|
||||
#define STORAGE_FLAGS_LEGACY_DEFAULT (STORAGE_LIMIT_MAX_ITEMS | STORAGE_LIMIT_COMBINED_W_CLASS | STORAGE_LIMIT_MAX_W_CLASS)
|
||||
#define STORAGE_FLAGS_VOLUME_DEFAULT (STORAGE_LIMIT_MAX_ITEMS | STORAGE_LIMIT_VOLUME | STORAGE_LIMIT_MAX_W_CLASS)
|
||||
#define STORAGE_FLAGS_VOLUME_DEFAULT (STORAGE_LIMIT_VOLUME | STORAGE_LIMIT_MAX_W_CLASS)
|
||||
|
||||
// UI defines
|
||||
/// Size of volumetric box icon
|
||||
#define VOLUMETRIC_STORAGE_BOX_ICON_SIZE 32
|
||||
/// Size of EACH left/right border icon for volumetric boxes
|
||||
#define VOLUMETRIC_STORAGE_BOX_BORDER_SIZE 1
|
||||
/// Minimum pixels an item must have in volumetric scaled storage UI
|
||||
#define MINIMUM_PIXELS_PER_ITEM 8
|
||||
/// Maximum number of objects that will be allowed to be displayed using the volumetric display system. Arbitrary number to prevent server lockups.
|
||||
#define MAXIMUM_VOLUMETRIC_ITEMS 256
|
||||
/// How much padding to give between items
|
||||
#define VOLUMETRIC_STORAGE_ITEM_PADDING 4
|
||||
/// How much padding to give to edges
|
||||
#define VOLUMETRIC_STORAGE_EDGE_PADDING 1
|
||||
|
||||
//ITEM INVENTORY WEIGHT, FOR w_class
|
||||
/// Usually items smaller then a human hand, ex: Playing Cards, Lighter, Scalpel, Coins/Money
|
||||
@@ -26,22 +40,3 @@
|
||||
#define WEIGHT_CLASS_HUGE 5
|
||||
/// Essentially means it cannot be picked up or placed in an inventory, ex: Mech Parts, Safe - Can not fit in Boh
|
||||
#define WEIGHT_CLASS_GIGANTIC 6
|
||||
|
||||
/// Macro for automatically getting the volume of an item from its w_class.
|
||||
#define AUTO_SCALE_VOLUME(w_class) (2 ** w_class)
|
||||
/// Macro for automatically getting the volume of a storage item from its max_w_class and max_combined_w_class.
|
||||
#define AUTO_SCALE_STORAGE_VOLUME(w_class, max_combined_w_class) (AUTO_SCALE_VOLUME(w_class) * (max_combined_w_class / w_class))
|
||||
|
||||
// UI defines
|
||||
/// Size of volumetric box icon
|
||||
#define VOLUMETRIC_STORAGE_BOX_ICON_SIZE 32
|
||||
/// Size of EACH left/right border icon for volumetric boxes
|
||||
#define VOLUMETRIC_STORAGE_BOX_BORDER_SIZE 1
|
||||
/// Minimum pixels an item must have in volumetric scaled storage UI
|
||||
#define MINIMUM_PIXELS_PER_ITEM 6
|
||||
/// Maximum number of objects that will be allowed to be displayed using the volumetric display system. Arbitrary number to prevent server lockups.
|
||||
#define MAXIMUM_VOLUMETRIC_ITEMS 256
|
||||
/// How much padding to give between items
|
||||
#define VOLUMETRIC_STORAGE_ITEM_PADDING 1
|
||||
/// How much padding to give to edges
|
||||
#define VOLUMETRIC_STORAGE_EDGE_PADDING 1
|
||||
@@ -0,0 +1,39 @@
|
||||
// PLEASE KEEP ALL VOLUME DEFINES IN THIS FILE, it's going to be hell to keep track of them later.
|
||||
|
||||
#define DEFAULT_VOLUME_TINY 2
|
||||
#define DEFAULT_VOLUME_SMALL 3
|
||||
#define DEFAULT_VOLUME_NORMAL 4
|
||||
#define DEFAULT_VOLUME_BULKY 8
|
||||
#define DEFAULT_VOLUME_HUGE 16
|
||||
#define DEFAULT_VOLUME_GIGANTIC 32
|
||||
|
||||
GLOBAL_LIST_INIT(default_weight_class_to_volume, list(
|
||||
"[WEIGHT_CLASS_TINY]" = DEFAULT_VOLUME_TINY,
|
||||
"[WEIGHT_CLASS_SMALL]" = DEFAULT_VOLUME_SMALL,
|
||||
"[WEIGHT_CLASS_NORMAL]" = DEFAULT_VOLUME_NORMAL,
|
||||
"[WEIGHT_CLASS_BULKY]" = DEFAULT_VOLUME_BULKY,
|
||||
"[WEIGHT_CLASS_HUGE]" = DEFAULT_VOLUME_HUGE,
|
||||
"[WEIGHT_CLASS_GIGANTIC]" = DEFAULT_VOLUME_GIGANTIC
|
||||
))
|
||||
|
||||
/// Macro for automatically getting the volume of an item from its w_class.
|
||||
#define AUTO_SCALE_VOLUME(w_class) (GLOB.default_weight_class_to_volume["[w_class]"])
|
||||
/// Macro for automatically getting the volume of a storage item from its max_w_class and max_combined_w_class.
|
||||
#define AUTO_SCALE_STORAGE_VOLUME(w_class, max_combined_w_class) (AUTO_SCALE_VOLUME(w_class) * (max_combined_w_class / w_class))
|
||||
|
||||
// Let's keep all of this in one place. given what we put above anyways..
|
||||
|
||||
// volume amount for items
|
||||
#define ITEM_VOLUME_DISK DEFAULT_VOLUME_TINY
|
||||
|
||||
// #define SAMPLE_VOLUME_AMOUNT 2
|
||||
|
||||
// max_weight_class for storages
|
||||
#define MAX_WEIGHT_CLASS_BACKPACK WEIGHT_CLASS_NORMAL
|
||||
#define MAX_WEIGHT_CLASS_BAG_OF_HOLDING WEIGHT_CLASS_BULKY
|
||||
|
||||
// max_volume for storages
|
||||
#define STORAGE_VOLUME_BACKPACK (DEFAULT_VOLUME_NORMAL * 7)
|
||||
#define STORAGE_VOLUME_DUFFLEBAG (DEFAULT_VOLUME_NORMAL * 10)
|
||||
#define STORAGE_VOLUME_BAG_OF_HOLDING (DEFAULT_VOLUME_NORMAL * 20)
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
#define TGS_READ_GLOBAL(Name) GLOB.##Name
|
||||
#define TGS_WRITE_GLOBAL(Name, Value) GLOB.##Name = ##Value
|
||||
#define TGS_WORLD_ANNOUNCE(message) to_chat(world, "<span class='boldannounce'>[html_encode(##message)]</span>")
|
||||
#define TGS_INFO_LOG(message) log_world("TGS: Info: [##message]")
|
||||
#define TGS_ERROR_LOG(message) log_world("TGS: Error: [##message]")
|
||||
#define TGS_INFO_LOG(message) log_world("TGS Info: [##message]")
|
||||
#define TGS_WARNING_LOG(message) log_world("TGS Warn: [##message]")
|
||||
#define TGS_ERROR_LOG(message) log_world("TGS Error: [##message]")
|
||||
#define TGS_NOTIFY_ADMINS(event) message_admins(##event)
|
||||
#define TGS_CLIENT_COUNT GLOB.clients.len
|
||||
#define TGS_PROTECT_DATUM(Path) GENERAL_PROTECT_DATUM(##Path)
|
||||
|
||||
+56
-35
@@ -1,5 +1,7 @@
|
||||
//tgstation-server DMAPI
|
||||
|
||||
#define TGS_DMAPI_VERSION "5.1.1"
|
||||
|
||||
//All functions and datums outside this document are subject to change with any version and should not be relied on
|
||||
|
||||
//CONFIGURATION
|
||||
@@ -17,7 +19,6 @@
|
||||
//Required interfaces (fill in with your codebase equivalent):
|
||||
|
||||
//create a global variable named `Name` and set it to `Value`
|
||||
//These globals must not be modifiable from anywhere outside of the server tools
|
||||
#define TGS_DEFINE_AND_SET_GLOBAL(Name, Value)
|
||||
|
||||
//Read the value in the global variable `Name`
|
||||
@@ -26,10 +27,10 @@
|
||||
//Set the value in the global variable `Name` to `Value`
|
||||
#define TGS_WRITE_GLOBAL(Name, Value)
|
||||
|
||||
//Disallow ANYONE from reflecting a given `path`, security measure to prevent in-game priveledge escalation
|
||||
//Disallow ANYONE from reflecting a given `path`, security measure to prevent in-game use of DD -> TGS capabilities
|
||||
#define TGS_PROTECT_DATUM(Path)
|
||||
|
||||
//display an announcement `message` from the server to all players
|
||||
//Display an announcement `message` from the server to all players
|
||||
#define TGS_WORLD_ANNOUNCE(message)
|
||||
|
||||
//Notify current in-game administrators of a string `event`
|
||||
@@ -38,6 +39,9 @@
|
||||
//Write an info `message` to a server log
|
||||
#define TGS_INFO_LOG(message)
|
||||
|
||||
//Write an warning `message` to a server log
|
||||
#define TGS_WARNING_LOG(message)
|
||||
|
||||
//Write an error `message` to a server log
|
||||
#define TGS_ERROR_LOG(message)
|
||||
|
||||
@@ -48,10 +52,12 @@
|
||||
|
||||
//EVENT CODES
|
||||
|
||||
#define TGS_EVENT_PORT_SWAP -2 //before a port change is about to happen, extra parameter is new port
|
||||
#define TGS_EVENT_REBOOT_MODE_CHANGE -1 //before a reboot mode change, extras parameters are the current and new reboot mode enums
|
||||
#define TGS_EVENT_REBOOT_MODE_CHANGE -1 //Before a reboot mode change, extras parameters are the current and new reboot mode enums
|
||||
#define TGS_EVENT_PORT_SWAP -2 //Before a port change is about to happen, extra parameters is new port
|
||||
#define TGS_EVENT_INSTANCE_RENAMED -3 //Before the instance is renamed, extra parameter is the new name
|
||||
#define TGS_EVENT_WATCHDOG_REATTACH -4 //After the watchdog reattaches to DD, extra parameter is the new /datum/tgs_version of the server
|
||||
|
||||
//See the descriptions for these codes here: https://github.com/tgstation/tgstation-server/blob/master/src/Tgstation.Server.Host/Components/EventType.cs
|
||||
//See the descriptions for the parameters of these codes here: https://github.com/tgstation/tgstation-server/blob/master/src/Tgstation.Server.Host/Components/EventType.cs
|
||||
#define TGS_EVENT_REPO_RESET_ORIGIN 0
|
||||
#define TGS_EVENT_REPO_CHECKOUT 1
|
||||
#define TGS_EVENT_REPO_FETCH 2
|
||||
@@ -63,9 +69,12 @@
|
||||
#define TGS_EVENT_COMPILE_START 8
|
||||
#define TGS_EVENT_COMPILE_CANCELLED 9
|
||||
#define TGS_EVENT_COMPILE_FAILURE 10
|
||||
#define TGS_EVENT_COMPILE_COMPLETE 11
|
||||
#define TGS_EVENT_COMPILE_COMPLETE 11 // Note, this event fires before the new .dmb is loaded into the watchdog. Consider using the TGS_EVENT_DEPLOYMENT_COMPLETE instead
|
||||
#define TGS_EVENT_INSTANCE_AUTO_UPDATE_START 12
|
||||
#define TGS_EVENT_REPO_MERGE_CONFLICT 13
|
||||
#define TGS_EVENT_DEPLOYMENT_COMPLETE 14
|
||||
#define TGS_EVENT_WATCHDOG_SHUTDOWN 15
|
||||
#define TGS_EVENT_WATCHDOG_DETACH 16
|
||||
|
||||
//OTHER ENUMS
|
||||
|
||||
@@ -80,6 +89,7 @@
|
||||
//REQUIRED HOOKS
|
||||
|
||||
//Call this somewhere in /world/New() that is always run
|
||||
//IMPORTANT: This function may sleep!
|
||||
//event_handler: optional user defined event handler. The default behaviour is to broadcast the event in english to all connected admin channels
|
||||
//minimum_required_security_level: The minimum required security level to run the game in which the DMAPI is integrated
|
||||
/world/proc/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE)
|
||||
@@ -109,12 +119,12 @@
|
||||
|
||||
//represents a version of tgstation-server
|
||||
/datum/tgs_version
|
||||
var/suite //The suite version, can be >=3
|
||||
var/suite //The suite/major version, can be >=3
|
||||
|
||||
//this group of variables can be null to represent a wild card
|
||||
var/major //The major version
|
||||
var/minor //The minor version
|
||||
var/patch //The patch version
|
||||
var/deprecated_patch //The legacy version
|
||||
|
||||
var/raw_parameter //The unparsed parameter
|
||||
var/deprefixed_parameter //The version only bit of raw_parameter
|
||||
@@ -123,6 +133,10 @@
|
||||
/datum/tgs_version/proc/Wildcard()
|
||||
return
|
||||
|
||||
//if the tgs_version equals some other_version
|
||||
/datum/tgs_version/proc/Equals(datum/tgs_version/other_version)
|
||||
return
|
||||
|
||||
//represents a merge of a GitHub pull request
|
||||
/datum/tgs_revision_information/test_merge
|
||||
var/number //pull request number
|
||||
@@ -179,14 +193,45 @@
|
||||
return
|
||||
|
||||
//Returns TRUE if the world was launched under the server tools and the API matches, FALSE otherwise
|
||||
//No function below this succeeds if it returns FALSE
|
||||
//No function below this succeeds if it returns FALSE or if TgsNew() has yet to be called
|
||||
/world/proc/TgsAvailable()
|
||||
return
|
||||
|
||||
//Forces a hard reboot of BYOND by ending the process
|
||||
//unlike del(world) clients will try to reconnect
|
||||
//If the service has not requested a shutdown, the next server will take over
|
||||
/world/proc/TgsEndProcess()
|
||||
return
|
||||
|
||||
//Send a message to non-admin connected chats
|
||||
//message: The message to send
|
||||
//admin_only: If TRUE, message will instead be sent to only admin connected chats
|
||||
/world/proc/TgsTargetedChatBroadcast(message, admin_only)
|
||||
return
|
||||
|
||||
//Send a private message to a specific user
|
||||
//message: The message to send
|
||||
//user: The /datum/tgs_chat_user to send to
|
||||
/world/proc/TgsChatPrivateMessage(message, datum/tgs_chat_user/user)
|
||||
return
|
||||
|
||||
//The following functions will sleep if a call to TgsNew() is sleeping
|
||||
|
||||
//Sends a message to connected game chats
|
||||
//message: The message to send
|
||||
//channels: optional channels to limit the broadcast to
|
||||
/world/proc/TgsChatBroadcast(message, list/channels)
|
||||
return
|
||||
|
||||
//Gets the current /datum/tgs_version of the server tools running the server
|
||||
/world/proc/TgsVersion()
|
||||
return
|
||||
|
||||
//Gets the current /datum/tgs_version of the DMAPI being used
|
||||
/world/proc/TgsApiVersion()
|
||||
return
|
||||
|
||||
//Gets the name of the TGS instance running the game
|
||||
/world/proc/TgsInstanceName()
|
||||
return
|
||||
|
||||
@@ -202,34 +247,10 @@
|
||||
/world/proc/TgsTestMerges()
|
||||
return
|
||||
|
||||
//Forces a hard reboot of BYOND by ending the process
|
||||
//unlike del(world) clients will try to reconnect
|
||||
//If the service has not requested a shutdown, the next server will take over
|
||||
/world/proc/TgsEndProcess()
|
||||
return
|
||||
|
||||
//Gets a list of connected tgs_chat_channel
|
||||
/world/proc/TgsChatChannelInfo()
|
||||
return
|
||||
|
||||
//Sends a message to connected game chats
|
||||
//message: The message to send
|
||||
//channels: optional channels to limit the broadcast to
|
||||
/world/proc/TgsChatBroadcast(message, list/channels)
|
||||
return
|
||||
|
||||
//Send a message to non-admin connected chats
|
||||
//message: The message to send
|
||||
//admin_only: If TRUE, message will instead be sent to only admin connected chats
|
||||
/world/proc/TgsTargetedChatBroadcast(message, admin_only)
|
||||
return
|
||||
|
||||
//Send a private message to a specific user
|
||||
//message: The message to send
|
||||
//user: The /datum/tgs_chat_user to send to
|
||||
/world/proc/TgsChatPrivateMessage(message, datum/tgs_chat_user/user)
|
||||
return
|
||||
|
||||
/*
|
||||
The MIT License
|
||||
|
||||
@@ -255,4 +276,4 @@ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
*/
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
#define TRAIT_SLEEPIMMUNE "sleep_immunity"
|
||||
#define TRAIT_PUSHIMMUNE "push_immunity"
|
||||
#define TRAIT_SHOCKIMMUNE "shock_immunity"
|
||||
#define TRAIT_TESLA_SHOCKIMMUNE "tesla_shock_immunity"
|
||||
#define TRAIT_STABLEHEART "stable_heart"
|
||||
#define TRAIT_STABLELIVER "stable_liver"
|
||||
#define TRAIT_RESISTHEAT "resist_heat"
|
||||
|
||||
@@ -123,3 +123,6 @@
|
||||
// misc
|
||||
#define VV_HK_SPACEVINE_PURGE "spacevine_purge"
|
||||
#define VV_HK_REMOVE_PAINTING "remove_painting"
|
||||
|
||||
// paintings
|
||||
#define VV_HK_REMOVE_PAINTING "remove_painting"
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
//THIS FILE CONTAINS CONSTANTS, PROCS, AND OTHER THINGS//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/mob/proc/setClickCooldown(var/timeout)
|
||||
next_move = max(world.time + timeout, next_move)
|
||||
|
||||
/proc/get_matrix_largest()
|
||||
var/matrix/mtrx=new()
|
||||
return mtrx.Scale(2)
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
* TYPECONT: The typepath of the contents of the list
|
||||
* COMPARE: The object to compare against, usualy the same as INPUT
|
||||
* COMPARISON: The variable on the objects to compare
|
||||
* COMPTYPE: How the current bin item to compare against COMPARE is fetched. By key or value.
|
||||
*/
|
||||
#define BINARY_INSERT(INPUT, LIST, TYPECONT, COMPARE, COMPARISON, COMPTYPE) \
|
||||
do {\
|
||||
@@ -670,3 +671,13 @@
|
||||
for(var/key in input)
|
||||
ret += key
|
||||
return ret
|
||||
|
||||
/proc/is_type_in_ref_list(path, list/L)
|
||||
if(!ispath(path))//not a path
|
||||
return
|
||||
for(var/i in L)
|
||||
var/datum/D = i
|
||||
if(!istype(D))//not an usable reference
|
||||
continue
|
||||
if(istype(D, path))
|
||||
return TRUE
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
#define SEND_SOUND(target, sound) DIRECT_OUTPUT(target, sound)
|
||||
#define SEND_TEXT(target, text) DIRECT_OUTPUT(target, text)
|
||||
#define WRITE_FILE(file, text) DIRECT_OUTPUT(file, text)
|
||||
#define WRITE_LOG(log, text) rustg_log_write(log, text)
|
||||
//This is an external call, "true" and "false" are how rust parses out booleans
|
||||
#define WRITE_LOG(log, text) rustg_log_write(log, text, "true")
|
||||
#define WRITE_LOG_NO_FORMAT(log, text) rustg_log_write(log, text, "false")
|
||||
|
||||
//print a warning message to world.log
|
||||
#define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [UNLINT(src)] usr: [usr].")
|
||||
|
||||
@@ -270,6 +270,15 @@
|
||||
SEND_SIGNAL(A, COMSIG_ATOM_HEARER_IN_VIEW, processing, .)
|
||||
processing += A.contents
|
||||
|
||||
//viewers() but with a signal, for blacklisting.
|
||||
/proc/fov_viewers(depth = world.view, atom/center)
|
||||
if(!center)
|
||||
return
|
||||
. = viewers(depth, center)
|
||||
for(var/k in .)
|
||||
var/mob/M = k
|
||||
SEND_SIGNAL(M, COMSIG_MOB_FOV_VIEWER, center, depth, .)
|
||||
|
||||
/proc/get_mobs_in_radio_ranges(list/obj/item/radio/radios)
|
||||
. = list()
|
||||
// Returns a list of mobs who can hear any of the radios given in @radios
|
||||
|
||||
@@ -75,6 +75,8 @@
|
||||
var/datum/emote/E = new path()
|
||||
E.emote_list[E.key] = E
|
||||
|
||||
init_keybindings()
|
||||
|
||||
//Uplink Items
|
||||
for(var/path in subtypesof(/datum/uplink_item))
|
||||
var/datum/uplink_item/I = path
|
||||
|
||||
@@ -18,6 +18,12 @@
|
||||
return text
|
||||
return default
|
||||
|
||||
/proc/sanitize_islist(value, default)
|
||||
if(islist(value) && length(value))
|
||||
return value
|
||||
if(default)
|
||||
return default
|
||||
|
||||
/proc/sanitize_inlist(value, list/List, default)
|
||||
if(value in List)
|
||||
return value
|
||||
|
||||
@@ -629,3 +629,45 @@
|
||||
return null
|
||||
r += ascii2text(c)
|
||||
return r
|
||||
|
||||
/proc/slot_to_string(slot)
|
||||
switch(slot)
|
||||
if(SLOT_BACK)
|
||||
return "Backpack"
|
||||
if(SLOT_WEAR_MASK)
|
||||
return "Mask"
|
||||
if(SLOT_HANDS)
|
||||
return "Hands"
|
||||
if(SLOT_BELT)
|
||||
return "Belt"
|
||||
if(SLOT_EARS)
|
||||
return "Ears"
|
||||
if(SLOT_GLASSES)
|
||||
return "Glasses"
|
||||
if(SLOT_GLOVES)
|
||||
return "Gloves"
|
||||
if(SLOT_NECK)
|
||||
return "Neck"
|
||||
if(SLOT_HEAD)
|
||||
return "Head"
|
||||
if(SLOT_SHOES)
|
||||
return "Shoes"
|
||||
if(SLOT_WEAR_SUIT)
|
||||
return "Suit"
|
||||
if(SLOT_W_UNIFORM)
|
||||
return "Uniform"
|
||||
if(SLOT_IN_BACKPACK)
|
||||
return "In backpack"
|
||||
|
||||
/proc/tg_ui_icon_to_cit_ui(ui_style)
|
||||
switch(ui_style)
|
||||
if('icons/mob/screen_plasmafire.dmi')
|
||||
return 'modular_citadel/icons/ui/screen_plasmafire.dmi'
|
||||
if('icons/mob/screen_slimecore.dmi')
|
||||
return 'modular_citadel/icons/ui/screen_slimecore.dmi'
|
||||
if('icons/mob/screen_operative.dmi')
|
||||
return 'modular_citadel/icons/ui/screen_operative.dmi'
|
||||
if('icons/mob/screen_clockwork.dmi')
|
||||
return 'modular_citadel/icons/ui/screen_clockwork.dmi'
|
||||
else
|
||||
return 'modular_citadel/icons/ui/screen_midnight.dmi'
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
/*
|
||||
* A large number of misc global procs.
|
||||
*/
|
||||
@@ -391,6 +389,16 @@ Turf and target are separate in case you want to teleport some distance from a t
|
||||
break
|
||||
return loc
|
||||
|
||||
//Returns a list of all locations the target is within.
|
||||
/proc/get_nested_locs(atom/movable/M, include_turf = FALSE)
|
||||
. = list()
|
||||
var/atom/A = M.loc
|
||||
while(A && !isturf(A))
|
||||
. += A
|
||||
A = A.loc
|
||||
if(A && include_turf) //At this point, only the turf is left.
|
||||
. += A
|
||||
|
||||
// returns the turf located at the map edge in the specified direction relative to A
|
||||
// used for mass driver
|
||||
/proc/get_edge_target_turf(atom/A, direction)
|
||||
@@ -1594,8 +1602,13 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
|
||||
//empty string - use TgsTargetBroadcast with admin_only = FALSE
|
||||
//other string - use TgsChatBroadcast with the tag that matches config_setting, only works with TGS4, if using TGS3 the above method is used
|
||||
/proc/send2chat(message, config_setting)
|
||||
if(config_setting == null || !world.TgsAvailable())
|
||||
if(config_setting == null)
|
||||
return
|
||||
|
||||
UNTIL(GLOB.tgs_initialized)
|
||||
if(!world.TgsAvailable())
|
||||
return
|
||||
|
||||
var/datum/tgs_version/version = world.TgsVersion()
|
||||
if(config_setting == "" || version.suite == 3)
|
||||
world.TgsTargetedChatBroadcast(message, FALSE)
|
||||
|
||||
@@ -132,9 +132,11 @@ GLOBAL_LIST_INIT(bitfields, list(
|
||||
"NO_RUINS_1" = NO_RUINS_1,
|
||||
"PREVENT_CLICK_UNDER_1" = PREVENT_CLICK_UNDER_1,
|
||||
"HOLOGRAM_1" = HOLOGRAM_1,
|
||||
"TESLA_IGNORE_1" = TESLA_IGNORE_1,
|
||||
"SHOCKED_1" = SHOCKED_1,
|
||||
"INITIALIZED_1" = INITIALIZED_1,
|
||||
"ADMIN_SPAWNED_1" = ADMIN_SPAWNED_1,
|
||||
"BLOCK_FACE_ATOM_1" = BLOCK_FACE_ATOM_1,
|
||||
"PREVENT_CONTENTS_EXPLOSION_1" = PREVENT_CONTENTS_EXPLOSION_1
|
||||
),
|
||||
"clothing_flags" = list(
|
||||
"LAVAPROTECT" = LAVAPROTECT,
|
||||
@@ -148,12 +150,12 @@ GLOBAL_LIST_INIT(bitfields, list(
|
||||
"IGNORE_HAT_TOSS" = IGNORE_HAT_TOSS,
|
||||
"SCAN_REAGENTS" = SCAN_REAGENTS
|
||||
),
|
||||
"tesla_flags" = list(
|
||||
"TESLA_MOB_DAMAGE" = TESLA_MOB_DAMAGE,
|
||||
"TESLA_OBJ_DAMAGE" = TESLA_OBJ_DAMAGE,
|
||||
"TESLA_MOB_STUN" = TESLA_MOB_STUN,
|
||||
"TESLA_ALLOW_DUPLICATES" = TESLA_ALLOW_DUPLICATES,
|
||||
"TESLA_MACHINE_EXPLOSIVE" = TESLA_MACHINE_EXPLOSIVE,
|
||||
"zap_flags" = list(
|
||||
"ZAP_MOB_DAMAGE" = ZAP_MOB_DAMAGE,
|
||||
"ZAP_OBJ_DAMAGE" = ZAP_OBJ_DAMAGE,
|
||||
"ZAP_MOB_STUN" = ZAP_MOB_STUN,
|
||||
"ZAP_ALLOW_DUPLICATES" = ZAP_ALLOW_DUPLICATES,
|
||||
"ZAP_MACHINE_EXPLOSIVE" = ZAP_MACHINE_EXPLOSIVE,
|
||||
),
|
||||
"smooth" = list(
|
||||
"SMOOTH_TRUE" = SMOOTH_TRUE,
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
GLOBAL_LIST_EMPTY(classic_keybinding_list_by_key)
|
||||
GLOBAL_LIST_EMPTY(hotkey_keybinding_list_by_key)
|
||||
GLOBAL_LIST_EMPTY(keybindings_by_name)
|
||||
|
||||
// This is a mapping from JS keys to Byond - ref: https://keycode.info/
|
||||
GLOBAL_LIST_INIT(_kbMap, list(
|
||||
"UP" = "North",
|
||||
"RIGHT" = "East",
|
||||
"DOWN" = "South",
|
||||
"LEFT" = "West",
|
||||
"INSERT" = "Insert",
|
||||
"HOME" = "Northwest",
|
||||
"PAGEUP" = "Northeast",
|
||||
"DEL" = "Delete",
|
||||
"END" = "Southwest",
|
||||
"PAGEDOWN" = "Southeast",
|
||||
"SPACEBAR" = "Space",
|
||||
"ALT" = "Alt",
|
||||
"SHIFT" = "Shift",
|
||||
"CONTROL" = "Ctrl"
|
||||
))
|
||||
@@ -0,0 +1,31 @@
|
||||
/// Creates and sorts all the keybinding datums
|
||||
/proc/init_keybindings()
|
||||
for(var/KB in subtypesof(/datum/keybinding))
|
||||
var/datum/keybinding/keybinding = KB
|
||||
if(!initial(keybinding.hotkey_keys))
|
||||
continue
|
||||
add_keybinding(new keybinding)
|
||||
// init_emote_keybinds() - Disabled - I don't particularly want this.
|
||||
|
||||
/// Adds an instanced keybinding to the global tracker
|
||||
/proc/add_keybinding(datum/keybinding/instance)
|
||||
GLOB.keybindings_by_name[instance.name] = instance
|
||||
|
||||
// Classic
|
||||
if(LAZYLEN(instance.classic_keys))
|
||||
for(var/bound_key in instance.classic_keys)
|
||||
LAZYADD(GLOB.classic_keybinding_list_by_key[bound_key], list(instance.name))
|
||||
|
||||
// Hotkey
|
||||
if(LAZYLEN(instance.hotkey_keys))
|
||||
for(var/bound_key in instance.hotkey_keys)
|
||||
LAZYADD(GLOB.hotkey_keybinding_list_by_key[bound_key], list(instance.name))
|
||||
|
||||
/proc/init_emote_keybinds()
|
||||
for(var/i in subtypesof(/datum/emote))
|
||||
var/datum/emote/faketype = i
|
||||
if(!initial(faketype.key))
|
||||
continue
|
||||
var/datum/keybinding/emote/emote_kb = new
|
||||
emote_kb.link_to_emote(faketype)
|
||||
add_keybinding(emote_kb)
|
||||
@@ -29,6 +29,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_SLEEPIMMUNE" = TRAIT_SLEEPIMMUNE,
|
||||
"TRAIT_PUSHIMMUNE" = TRAIT_PUSHIMMUNE,
|
||||
"TRAIT_SHOCKIMMUNE" = TRAIT_SHOCKIMMUNE,
|
||||
"TRAIT_TESLA_SHOCKIMMUNE" = TRAIT_TESLA_SHOCKIMMUNE,
|
||||
"TRAIT_STABLEHEART" = TRAIT_STABLEHEART,
|
||||
"TRAIT_STABLELIVER" = TRAIT_STABLELIVER,
|
||||
"TRAIT_RESISTHEAT" = TRAIT_RESISTHEAT,
|
||||
|
||||
+18
-15
@@ -77,7 +77,7 @@
|
||||
|
||||
if(SEND_SIGNAL(src, COMSIG_MOB_CLICKON, A, params) & COMSIG_MOB_CANCEL_CLICKON)
|
||||
return
|
||||
|
||||
|
||||
var/list/modifiers = params2list(params)
|
||||
if(modifiers["shift"] && modifiers["middle"])
|
||||
ShiftMiddleClickOn(A)
|
||||
@@ -324,10 +324,9 @@
|
||||
return
|
||||
|
||||
/atom/proc/ShiftClick(mob/user)
|
||||
var/flags = SEND_SIGNAL(src, COMSIG_CLICK_SHIFT, user)
|
||||
var/flags = SEND_SIGNAL(src, COMSIG_CLICK_SHIFT, user) | SEND_SIGNAL(user, COMSIG_MOB_CLICKED_SHIFT_ON, src)
|
||||
if(!(flags & COMPONENT_DENY_EXAMINATE) && user.client && (user.client.eye == user || user.client.eye == user.loc || flags & COMPONENT_ALLOW_EXAMINATE))
|
||||
user.examinate(src)
|
||||
return
|
||||
|
||||
/*
|
||||
Ctrl click
|
||||
@@ -424,32 +423,36 @@
|
||||
LE.fire()
|
||||
|
||||
// Simple helper to face what you clicked on, in case it should be needed in more than one place
|
||||
/mob/proc/face_atom(atom/A)
|
||||
if( buckled || stat != CONSCIOUS || !A || !x || !y || !A.x || !A.y )
|
||||
/mob/proc/face_atom(atom/A, ismousemovement = FALSE)
|
||||
if( buckled || stat != CONSCIOUS || !loc || !A || !A.x || !A.y )
|
||||
return
|
||||
var/dx = A.x - x
|
||||
var/dy = A.y - y
|
||||
var/atom/L = loc
|
||||
if(L.flags_1 & BLOCK_FACE_ATOM_1)
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
var/dx = A.x - T.x
|
||||
var/dy = A.y - T.y
|
||||
if(!dx && !dy) // Wall items are graphically shifted but on the floor
|
||||
if(A.pixel_y > 16)
|
||||
setDir(NORTH)
|
||||
setDir(NORTH, ismousemovement)
|
||||
else if(A.pixel_y < -16)
|
||||
setDir(SOUTH)
|
||||
setDir(SOUTH, ismousemovement)
|
||||
else if(A.pixel_x > 16)
|
||||
setDir(EAST)
|
||||
setDir(EAST, ismousemovement)
|
||||
else if(A.pixel_x < -16)
|
||||
setDir(WEST)
|
||||
setDir(WEST, ismousemovement)
|
||||
return
|
||||
|
||||
if(abs(dx) < abs(dy))
|
||||
if(dy > 0)
|
||||
setDir(NORTH)
|
||||
setDir(NORTH, ismousemovement)
|
||||
else
|
||||
setDir(SOUTH)
|
||||
setDir(SOUTH, ismousemovement)
|
||||
else
|
||||
if(dx > 0)
|
||||
setDir(EAST)
|
||||
setDir(EAST, ismousemovement)
|
||||
else
|
||||
setDir(WEST)
|
||||
setDir(WEST, ismousemovement)
|
||||
|
||||
//debug
|
||||
/obj/screen/proc/scale_to(x1,y1)
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
blend_mode = BLEND_MULTIPLY
|
||||
alpha = 255
|
||||
|
||||
/obj/screen/plane_master/openspace/Initialize()
|
||||
. = ..()
|
||||
filters += filter(type="alpha", render_source=FIELD_OF_VISION_RENDER_TARGET, flags=MASK_INVERSE)
|
||||
|
||||
/obj/screen/plane_master/openspace/backdrop(mob/mymob)
|
||||
filters = list()
|
||||
filters += filter(type = "drop_shadow", color = "#04080FAA", size = -10)
|
||||
@@ -46,6 +50,32 @@
|
||||
appearance_flags = PLANE_MASTER
|
||||
blend_mode = BLEND_OVERLAY
|
||||
|
||||
/obj/screen/plane_master/wall
|
||||
name = "wall plane master"
|
||||
plane = WALL_PLANE
|
||||
appearance_flags = PLANE_MASTER
|
||||
|
||||
/obj/screen/plane_master/wall/backdrop(mob/mymob)
|
||||
if(mymob?.client?.prefs.ambientocclusion)
|
||||
add_filter("ambient_occlusion", 0, AMBIENT_OCCLUSION(4, "#04080FAA"))
|
||||
else
|
||||
remove_filter("ambient_occlusion")
|
||||
|
||||
/obj/screen/plane_master/above_wall
|
||||
name = "above wall plane master"
|
||||
plane = ABOVE_WALL_PLANE
|
||||
appearance_flags = PLANE_MASTER
|
||||
|
||||
/obj/screen/plane_master/above_wall/Initialize()
|
||||
. = ..()
|
||||
add_filter("vision_cone", 100, list(type="alpha", render_source=FIELD_OF_VISION_RENDER_TARGET, flags=MASK_INVERSE))
|
||||
|
||||
/obj/screen/plane_master/above_wall/backdrop(mob/mymob)
|
||||
if(mymob?.client?.prefs.ambientocclusion)
|
||||
add_filter("ambient_occlusion", 0, AMBIENT_OCCLUSION(3, "#04080F64"))
|
||||
else
|
||||
remove_filter("ambient_occlusion")
|
||||
|
||||
///Contains most things in the game world
|
||||
/obj/screen/plane_master/game_world
|
||||
name = "game world plane master"
|
||||
@@ -53,12 +83,50 @@
|
||||
appearance_flags = PLANE_MASTER //should use client color
|
||||
blend_mode = BLEND_OVERLAY
|
||||
|
||||
/obj/screen/plane_master/game_world/Initialize()
|
||||
. = ..()
|
||||
add_filter("vision_cone", 100, list(type="alpha", render_source=FIELD_OF_VISION_RENDER_TARGET, flags=MASK_INVERSE))
|
||||
|
||||
/obj/screen/plane_master/game_world/backdrop(mob/mymob)
|
||||
if(istype(mymob) && mymob.client && mymob.client.prefs && mymob.client.prefs.ambientocclusion)
|
||||
add_filter("ambient_occlusion", 0, AMBIENT_OCCLUSION)
|
||||
if(mymob?.client?.prefs.ambientocclusion)
|
||||
add_filter("ambient_occlusion", 0, AMBIENT_OCCLUSION(4, "#04080FAA"))
|
||||
else
|
||||
remove_filter("ambient_occlusion")
|
||||
update_filters()
|
||||
|
||||
//Reserved to chat messages, so they are still displayed above the field of vision masking.
|
||||
/obj/screen/plane_master/chat_messages
|
||||
name = "chat messages plane master"
|
||||
plane = CHAT_PLANE
|
||||
appearance_flags = PLANE_MASTER
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
|
||||
///Contains all shadow cone masks, whose image overrides are displayed only to their respective owners.
|
||||
/obj/screen/plane_master/field_of_vision
|
||||
name = "field of vision mask plane master"
|
||||
plane = FIELD_OF_VISION_PLANE
|
||||
render_target = FIELD_OF_VISION_RENDER_TARGET
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
|
||||
/obj/screen/plane_master/field_of_vision/Initialize()
|
||||
. = ..()
|
||||
filters += filter(type="alpha", render_source=FIELD_OF_VISION_BLOCKER_RENDER_TARGET, flags=MASK_INVERSE)
|
||||
|
||||
///Used to display the owner and its adjacent surroundings through the FoV plane mask.
|
||||
/obj/screen/plane_master/field_of_vision_blocker
|
||||
name = "field of vision blocker plane master"
|
||||
plane = FIELD_OF_VISION_BLOCKER_PLANE
|
||||
render_target = FIELD_OF_VISION_BLOCKER_RENDER_TARGET
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
|
||||
///Stores the visible portion of the FoV shadow cone.
|
||||
/obj/screen/plane_master/field_of_vision_visual
|
||||
name = "field of vision visual plane master"
|
||||
plane = FIELD_OF_VISION_VISUAL_PLANE
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
|
||||
/obj/screen/plane_master/field_of_vision_visual/Initialize()
|
||||
. = ..()
|
||||
filters += filter(type="alpha", render_source=FIELD_OF_VISION_BLOCKER_RENDER_TARGET, flags=MASK_INVERSE)
|
||||
|
||||
///Contains all lighting objects
|
||||
/obj/screen/plane_master/lighting
|
||||
@@ -87,11 +155,12 @@
|
||||
/obj/screen/plane_master/emissive/Initialize()
|
||||
. = ..()
|
||||
filters += filter(type="alpha", render_source=EMISSIVE_BLOCKER_RENDER_TARGET, flags=MASK_INVERSE)
|
||||
filters += filter(type="alpha", render_source=FIELD_OF_VISION_RENDER_TARGET, flags=MASK_INVERSE)
|
||||
|
||||
/**
|
||||
* Things placed on this always mask the lighting plane. Doesn't render directly.
|
||||
*
|
||||
* Always masks the light plane, isn't blocked by anything. Use for on mob glows,
|
||||
* Always masks the light plane, isn't blocked by anything (except Field of Vision). Use for on mob glows,
|
||||
* magic stuff, etc.
|
||||
*/
|
||||
|
||||
@@ -101,6 +170,10 @@
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
render_target = EMISSIVE_UNBLOCKABLE_RENDER_TARGET
|
||||
|
||||
/obj/screen/plane_master/emissive_unblockable/Initialize()
|
||||
. = ..()
|
||||
filters += filter(type="alpha", render_source=FIELD_OF_VISION_RENDER_TARGET, flags=MASK_INVERSE)
|
||||
|
||||
/**
|
||||
* Things placed on this layer mask the emissive layer. Doesn't render directly
|
||||
*
|
||||
|
||||
@@ -238,6 +238,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
|
||||
var/mutable_appearance/MA = new /mutable_appearance(E)
|
||||
if(MA)
|
||||
MA.layer = ABOVE_HUD_LAYER
|
||||
MA.plane = ABOVE_HUD_PLANE
|
||||
MA.appearance_flags |= RESET_TRANSFORM
|
||||
return MA
|
||||
|
||||
|
||||
@@ -54,10 +54,14 @@
|
||||
|
||||
/obj/screen/storage/volumetric_box
|
||||
icon_state = "stored_continue"
|
||||
layer = VOLUMETRIC_STORAGE_BOX_LAYER
|
||||
plane = VOLUMETRIC_STORAGE_BOX_PLANE
|
||||
var/obj/item/our_item
|
||||
|
||||
/obj/screen/storage/volumetric_box/Initialize(mapload, new_master, our_item)
|
||||
/obj/screen/storage/volumetric_box/Initialize(mapload, new_master, obj/item/our_item)
|
||||
src.our_item = our_item
|
||||
RegisterSignal(our_item, COMSIG_ITEM_MOUSE_ENTER, .proc/on_item_mouse_enter)
|
||||
RegisterSignal(our_item, COMSIG_ITEM_MOUSE_EXIT, .proc/on_item_mouse_exit)
|
||||
return ..()
|
||||
|
||||
/obj/screen/storage/volumetric_box/Destroy()
|
||||
@@ -70,10 +74,30 @@
|
||||
/obj/screen/storage/volumetric_box/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params)
|
||||
return our_item.MouseDrop(over, src_location, over_location, src_control, over_control, params)
|
||||
|
||||
/obj/screen/storage/volumetric_box/MouseExited(location, control, params)
|
||||
makeItemInactive()
|
||||
|
||||
/obj/screen/storage/volumetric_box/MouseEntered(location, control, params)
|
||||
makeItemActive()
|
||||
|
||||
/obj/screen/storage/volumetric_box/proc/on_item_mouse_enter()
|
||||
makeItemActive()
|
||||
|
||||
/obj/screen/storage/volumetric_box/proc/on_item_mouse_exit()
|
||||
makeItemInactive()
|
||||
|
||||
/obj/screen/storage/volumetric_box/proc/makeItemInactive()
|
||||
our_item.layer = VOLUMETRIC_STORAGE_ITEM_LAYER
|
||||
our_item.plane = VOLUMETRIC_STORAGE_ITEM_PLANE
|
||||
|
||||
/obj/screen/storage/volumetric_box/proc/makeItemActive()
|
||||
our_item.layer = VOLUMETRIC_STORAGE_ACTIVE_ITEM_LAYER //make sure we display infront of the others!
|
||||
our_item.plane = VOLUMETRIC_STORAGE_ACTIVE_ITEM_PLANE
|
||||
|
||||
/obj/screen/storage/volumetric_box/center
|
||||
icon_state = "stored_continue"
|
||||
var/obj/screen/storage/stored_left/left
|
||||
var/obj/screen/storage/stored_right/right
|
||||
var/obj/screen/storage/volumetric_edge/stored_left/left
|
||||
var/obj/screen/storage/volumetric_edge/stored_right/right
|
||||
var/pixel_size
|
||||
|
||||
/obj/screen/storage/volumetric_box/center/Initialize(mapload, new_master, our_item)
|
||||
@@ -87,7 +111,7 @@
|
||||
return ..()
|
||||
|
||||
/obj/screen/storage/volumetric_box/center/proc/on_screen_objects()
|
||||
return list(src, left, right)
|
||||
return list(src)
|
||||
|
||||
/**
|
||||
* Sets the size of this box screen object and regenerates its left/right borders. This includes the actual border's size!
|
||||
@@ -96,18 +120,38 @@
|
||||
if(pixel_size == pixels)
|
||||
return
|
||||
pixel_size = pixels
|
||||
cut_overlays()
|
||||
cut_overlays(TRUE)
|
||||
//our icon size is 32 pixels.
|
||||
transform = matrix((pixels - (VOLUMETRIC_STORAGE_BOX_BORDER_SIZE * 2)) / VOLUMETRIC_STORAGE_BOX_ICON_SIZE, 0, 0, 0, 1, 0)
|
||||
left.pixel_x = -((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) - VOLUMETRIC_STORAGE_BOX_BORDER_SIZE
|
||||
right.pixel_x = ((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) + VOLUMETRIC_STORAGE_BOX_BORDER_SIZE
|
||||
add_overlay(left)
|
||||
add_overlay(right)
|
||||
add_overlay(left, TRUE)
|
||||
add_overlay(right, TRUE)
|
||||
|
||||
/obj/screen/storage/stored_left
|
||||
/obj/screen/storage/volumetric_edge
|
||||
layer = VOLUMETRIC_STORAGE_BOX_LAYER
|
||||
plane = VOLUMETRIC_STORAGE_BOX_PLANE
|
||||
|
||||
/obj/screen/storage/volumetric_edge/Initialize(mapload, master, our_item)
|
||||
src.master = master
|
||||
return ..()
|
||||
|
||||
/obj/screen/storage/volumetric_edge/Click(location, control, params)
|
||||
return master.Click(location, control, params)
|
||||
|
||||
/obj/screen/storage/volumetric_edge/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params)
|
||||
return master.MouseDrop(over, src_location, over_location, src_control, over_control, params)
|
||||
|
||||
/obj/screen/storage/volumetric_edge/MouseExited(location, control, params)
|
||||
return master.MouseExited(location, control, params)
|
||||
|
||||
/obj/screen/storage/volumetric_edge/MouseEntered(location, control, params)
|
||||
return master.MouseEntered(location, control, params)
|
||||
|
||||
/obj/screen/storage/volumetric_edge/stored_left
|
||||
icon_state = "stored_start"
|
||||
appearance_flags = APPEARANCE_UI | KEEP_APART | RESET_TRANSFORM // Yes I know RESET_TRANSFORM is in APPEARANCE_UI but we're hard-asserting this incase someone changes it.
|
||||
|
||||
/obj/screen/storage/stored_right
|
||||
/obj/screen/storage/volumetric_edge/stored_right
|
||||
icon_state = "stored_end"
|
||||
appearance_flags = APPEARANCE_UI | KEEP_APART | RESET_TRANSFORM
|
||||
|
||||
@@ -112,17 +112,17 @@
|
||||
|
||||
/obj/attacked_by(obj/item/I, mob/living/user)
|
||||
var/totitemdamage = I.force
|
||||
var/bad_flag = NONE
|
||||
var/bad_trait
|
||||
if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && iscarbon(user))
|
||||
totitemdamage *= 0.5
|
||||
bad_flag |= SKILL_COMBAT_MODE //blacklist combat skills.
|
||||
bad_trait = SKILL_COMBAT_MODE //blacklist combat skills.
|
||||
if(I.used_skills && user.mind)
|
||||
if(totitemdamage)
|
||||
totitemdamage = user.mind.skill_holder.item_action_skills_mod(I, totitemdamage, I.skill_difficulty, SKILL_ATTACK_OBJ, bad_flag)
|
||||
totitemdamage = user.mind.item_action_skills_mod(I, totitemdamage, I.skill_difficulty, SKILL_ATTACK_OBJ, bad_trait)
|
||||
for(var/skill in I.used_skills)
|
||||
if(!(I.used_skills[skill] & SKILL_TRAIN_ATTACK_OBJ))
|
||||
continue
|
||||
user.mind.skill_holder.auto_gain_experience(skill, I.skill_gain)
|
||||
user.mind.auto_gain_experience(skill, I.skill_gain)
|
||||
if(totitemdamage)
|
||||
visible_message("<span class='danger'>[user] has hit [src] with [I]!</span>", null, null, COMBAT_MESSAGE_RANGE)
|
||||
//only witnesses close by and the victim see a hit message.
|
||||
@@ -154,20 +154,20 @@
|
||||
|
||||
/mob/living/proc/pre_attacked_by(obj/item/I, mob/living/user)
|
||||
. = I.force
|
||||
var/bad_flag = NONE
|
||||
var/bad_trait
|
||||
if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && iscarbon(user))
|
||||
. *= 0.5
|
||||
bad_flag |= SKILL_COMBAT_MODE //blacklist combat skills.
|
||||
bad_trait = SKILL_COMBAT_MODE //blacklist combat skills.
|
||||
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
|
||||
. *= 0.5
|
||||
if(!user.mind || !I.used_skills)
|
||||
return
|
||||
if(.)
|
||||
. = user.mind.skill_holder.item_action_skills_mod(I, ., I.skill_difficulty, SKILL_ATTACK_MOB, bad_flag)
|
||||
. = user.mind.item_action_skills_mod(I, ., I.skill_difficulty, SKILL_ATTACK_MOB, bad_trait)
|
||||
for(var/skill in I.used_skills)
|
||||
if(!(I.used_skills[skill] & SKILL_TRAIN_ATTACK_MOB))
|
||||
continue
|
||||
user.mind.skill_holder.auto_gain_experience(skill, I.skill_gain)
|
||||
user.mind.auto_gain_experience(skill, I.skill_gain)
|
||||
|
||||
/mob/living/carbon/pre_attacked_by(obj/item/I, mob/living/user)
|
||||
. = ..()
|
||||
@@ -207,16 +207,16 @@
|
||||
return 1
|
||||
|
||||
/// How much stamina this takes to swing this is not for realism purposes hecc off.
|
||||
/obj/item/proc/getweight(mob/living/user, multiplier = 1, flags = SKILL_STAMINA_COST)
|
||||
/obj/item/proc/getweight(mob/living/user, multiplier = 1, trait = SKILL_STAMINA_COST)
|
||||
. = (total_mass || w_class * STAM_COST_W_CLASS_MULT) * multiplier
|
||||
if(!user)
|
||||
return
|
||||
var/bad_flag = NONE
|
||||
var/bad_trait
|
||||
if(iscarbon(user) && !(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
|
||||
. *= STAM_COST_NO_COMBAT_MULT
|
||||
bad_flag |= SKILL_COMBAT_MODE
|
||||
bad_trait = SKILL_COMBAT_MODE
|
||||
if(used_skills && user.mind)
|
||||
. = user.mind.skill_holder.item_action_skills_mod(src, ., skill_difficulty, flags, bad_flag, FALSE)
|
||||
. = user.mind.item_action_skills_mod(src, ., skill_difficulty, trait, bad_trait, FALSE)
|
||||
|
||||
/// How long this staggers for. 0 and negatives supported.
|
||||
/obj/item/proc/melee_stagger_duration(force_override)
|
||||
|
||||
@@ -507,3 +507,13 @@
|
||||
|
||||
//Allows players to set a hexadecimal color of their choice as skin tone, on top of the standard ones.
|
||||
/datum/config_entry/flag/allow_custom_skintones
|
||||
|
||||
///Initial loadout points
|
||||
/datum/config_entry/number/initial_gear_points
|
||||
config_entry_value = 10
|
||||
|
||||
/**
|
||||
* Enables the FoV component, which hides objects and mobs behind the parent from their sight, unless they turn around, duh.
|
||||
* Camera mobs, AIs, ghosts and some other are of course exempt from this. This also doesn't influence simplemob AI, for the best.
|
||||
*/
|
||||
/datum/config_entry/flag/use_field_of_vision
|
||||
|
||||
@@ -6,13 +6,20 @@ SUBSYSTEM_DEF(input)
|
||||
priority = FIRE_PRIORITY_INPUT
|
||||
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
|
||||
|
||||
var/list/macro_sets
|
||||
var/list/movement_keys
|
||||
/// Classic mode input focused macro set. Manually set because we can't define ANY or ANY+UP for classic.
|
||||
var/static/list/macroset_classic_input
|
||||
/// Classic mode map focused macro set. Manually set because it needs to be clientside and go to macroset_classic_input.
|
||||
var/static/list/macroset_classic_hotkey
|
||||
/// New hotkey mode macro set. All input goes into map, game keeps incessently setting your focus to map, we can use ANY all we want here; we don't care about the input bar, the user has to force the input bar every time they want to type.
|
||||
var/static/list/macroset_hotkey
|
||||
|
||||
/// Macro set for hotkeys
|
||||
var/list/hotkey_mode_macros
|
||||
/// Macro set for classic.
|
||||
var/list/input_mode_macros
|
||||
|
||||
/datum/controller/subsystem/input/Initialize()
|
||||
setup_default_macro_sets()
|
||||
|
||||
setup_default_movement_keys()
|
||||
setup_macrosets()
|
||||
|
||||
initialized = TRUE
|
||||
|
||||
@@ -20,90 +27,68 @@ SUBSYSTEM_DEF(input)
|
||||
|
||||
return ..()
|
||||
|
||||
// This is for when macro sets are eventualy datumized
|
||||
/datum/controller/subsystem/input/proc/setup_default_macro_sets()
|
||||
var/list/static/default_macro_sets
|
||||
|
||||
if(default_macro_sets)
|
||||
macro_sets = default_macro_sets
|
||||
return
|
||||
|
||||
default_macro_sets = list(
|
||||
"default" = list(
|
||||
"Tab" = "\".winset \\\"input.focus=true?map.focus=true input.background-color=[COLOR_INPUT_DISABLED]:input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"",
|
||||
"O" = "ooc",
|
||||
"Ctrl+O" = "looc",
|
||||
"T" = "say",
|
||||
"Ctrl+T" = "whisper",
|
||||
"M" = "me",
|
||||
"Ctrl+M" = "subtle",
|
||||
"Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", // This makes it so backspace can remove default inputs
|
||||
"Any" = "\"KeyDown \[\[*\]\]\"",
|
||||
"Any+UP" = "\"KeyUp \[\[*\]\]\"",
|
||||
),
|
||||
"old_default" = list(
|
||||
"Tab" = "\".winset \\\"mainwindow.macro=old_hotkeys map.focus=true input.background-color=[COLOR_INPUT_DISABLED]\\\"\"",
|
||||
"Ctrl+T" = "say",
|
||||
"Ctrl+O" = "ooc",
|
||||
),
|
||||
"old_hotkeys" = list(
|
||||
"Tab" = "\".winset \\\"mainwindow.macro=old_default input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"",
|
||||
"O" = "ooc",
|
||||
"L" = "looc",
|
||||
"T" = "say",
|
||||
"M" = "me",
|
||||
"Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", // This makes it so backspace can remove default inputs
|
||||
"Any" = "\"KeyDown \[\[*\]\]\"",
|
||||
"Any+UP" = "\"KeyUp \[\[*\]\]\"",
|
||||
),
|
||||
)
|
||||
|
||||
// Because i'm lazy and don't want to type all these out twice
|
||||
var/list/old_default = default_macro_sets["old_default"]
|
||||
|
||||
var/list/static/oldmode_keys = list(
|
||||
/// Sets up the key list for classic mode for when badmins screw up vv's.
|
||||
/datum/controller/subsystem/input/proc/setup_macrosets()
|
||||
// First, let's do the snowflake keyset!
|
||||
macroset_classic_input = list()
|
||||
var/list/classic_mode_keys = list(
|
||||
"North", "East", "South", "West",
|
||||
"Northeast", "Southeast", "Northwest", "Southwest",
|
||||
"Insert", "Delete", "Ctrl", "Alt",
|
||||
"Insert", "Delete", "Ctrl", "Alt", "Shift",
|
||||
"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
|
||||
)
|
||||
for(var/key in classic_mode_keys)
|
||||
macroset_classic_input[key] = "\"KeyDown [key]\""
|
||||
macroset_classic_input["[key]+UP"] = "\"KeyUp [key]\""
|
||||
// LET'S PLAY THE BIND EVERY KEY GAME!
|
||||
// oh except for Backspace and Enter; if you want to use those you shouldn't have used oldmode!
|
||||
var/list/classic_ctrl_override_keys = list(
|
||||
"\[", "\]", "\\", ";", "'", ",", ".", "/", "-", "\\=", "`"
|
||||
)
|
||||
// i'm lazy let's play the list iteration game of numbers
|
||||
for(var/i in 0 to 9)
|
||||
classic_ctrl_override_keys += "[i]"
|
||||
// let's play the ascii game of A to Z (UPPERCASE)
|
||||
for(var/i in 65 to 90)
|
||||
classic_ctrl_override_keys += ascii2text(i)
|
||||
// let's play the game of clientside bind overrides!
|
||||
classic_ctrl_override_keys -= list("T", "O", "M", "L")
|
||||
macroset_classic_input["Ctrl+T"] = "say"
|
||||
macroset_classic_input["Ctrl+O"] = "ooc"
|
||||
macroset_classic_input["Ctrl+L"] = "looc"
|
||||
// let's play the list iteration game x2
|
||||
for(var/key in classic_ctrl_override_keys)
|
||||
macroset_classic_input["Ctrl+[key]"] = "\"KeyDown [key]\""
|
||||
macroset_classic_input["Ctrl+[key]+UP"] = "\"KeyUp [key]\""
|
||||
// Misc
|
||||
macroset_classic_input["Tab"] = "\".winset \\\"mainwindow.macro=[SKIN_MACROSET_CLASSIC_HOTKEYS] map.focus=true input.background-color=[COLOR_INPUT_DISABLED]\\\"\""
|
||||
macroset_classic_input["Escape"] = "\".winset \\\"input.text=\\\"\\\"\\\"\""
|
||||
|
||||
for(var/i in 1 to oldmode_keys.len)
|
||||
var/key = oldmode_keys[i]
|
||||
old_default[key] = "\"KeyDown [key]\""
|
||||
old_default["[key]+UP"] = "\"KeyUp [key]\""
|
||||
// FINALLY, WE CAN DO SOMETHING MORE NORMAL FOR THE SNOWFLAKE-BUT-LESS KEYSET.
|
||||
macroset_classic_hotkey = list(
|
||||
"Any" = "\"KeyDown \[\[*\]\]\"",
|
||||
"Any+UP" = "\"KeyUp \[\[*\]\]\"",
|
||||
"Tab" = "\".winset \\\"mainwindow.macro=[SKIN_MACROSET_CLASSIC_INPUT] input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"",
|
||||
"Escape" = "\".winset \\\"input.text=\\\"\\\"\\\"\"",
|
||||
"Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"",
|
||||
"O" = "ooc",
|
||||
"T" = "say",
|
||||
"L" = "looc",
|
||||
"M" = "me"
|
||||
)
|
||||
|
||||
var/list/static/oldmode_ctrl_override_keys = list(
|
||||
"W" = "W", "A" = "A", "S" = "S", "D" = "D", // movement
|
||||
"1" = "1", "2" = "2", "3" = "3", "4" = "4", // intent
|
||||
"B" = "B", // resist
|
||||
"E" = "E", // quick equip
|
||||
"F" = "F", // intent left
|
||||
"G" = "G", // intent right
|
||||
"H" = "H", // stop pulling
|
||||
"Q" = "Q", // drop
|
||||
"R" = "R", // throw
|
||||
"X" = "X", // switch hands
|
||||
"Y" = "Y", // activate item
|
||||
"Z" = "Z", // activate item
|
||||
)
|
||||
|
||||
for(var/i in 1 to oldmode_ctrl_override_keys.len)
|
||||
var/key = oldmode_ctrl_override_keys[i]
|
||||
var/override = oldmode_ctrl_override_keys[key]
|
||||
old_default["Ctrl+[key]"] = "\"KeyDown [override]\""
|
||||
old_default["Ctrl+[key]+UP"] = "\"KeyUp [override]\""
|
||||
|
||||
macro_sets = default_macro_sets
|
||||
|
||||
// For initially setting up or resetting to default the movement keys
|
||||
/datum/controller/subsystem/input/proc/setup_default_movement_keys()
|
||||
var/static/list/default_movement_keys = list(
|
||||
"W" = NORTH, "A" = WEST, "S" = SOUTH, "D" = EAST, // WASD
|
||||
"North" = NORTH, "West" = WEST, "South" = SOUTH, "East" = EAST, // Arrow keys & Numpad
|
||||
)
|
||||
|
||||
movement_keys = default_movement_keys.Copy()
|
||||
// And finally, the modern set.
|
||||
macroset_hotkey = list(
|
||||
"Any" = "\"KeyDown \[\[*\]\]\"",
|
||||
"Any+UP" = "\"KeyUp \[\[*\]\]\"",
|
||||
"Tab" = "\".winset \\\"input.focus=true?map.focus=true input.background-color=[COLOR_INPUT_DISABLED]:input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"",
|
||||
"Escape" = "\".winset \\\"input.text=\\\"\\\"\\\"\"",
|
||||
"Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"",
|
||||
"O" = "ooc",
|
||||
"T" = "say",
|
||||
"L" = "looc",
|
||||
"M" = "me"
|
||||
)
|
||||
|
||||
// Badmins just wanna have fun ♪
|
||||
/datum/controller/subsystem/input/proc/refresh_client_macro_sets()
|
||||
@@ -111,9 +96,10 @@ SUBSYSTEM_DEF(input)
|
||||
for(var/i in 1 to clients.len)
|
||||
var/client/user = clients[i]
|
||||
user.set_macros()
|
||||
user.update_movement_keys()
|
||||
|
||||
/datum/controller/subsystem/input/fire()
|
||||
var/list/clients = GLOB.clients // Let's sing the list cache song
|
||||
for(var/i in 1 to length(clients))
|
||||
for(var/i in 1 to clients.len)
|
||||
var/client/C = clients[i]
|
||||
C.keyLoop()
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
PROCESSING_SUBSYSTEM_DEF(mood)
|
||||
name = "Mood"
|
||||
flags = SS_NO_INIT | SS_BACKGROUND
|
||||
priority = 20
|
||||
@@ -267,6 +267,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
CollectAntagReputation()
|
||||
SaveRandomizedRecipes()
|
||||
SavePanicBunker()
|
||||
SavePaintings()
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadPanicBunker()
|
||||
var/bunker_path = file("data/bunker_passthrough.json")
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
icon_icon = 'icons/mob/actions/actions_spells.dmi'
|
||||
|
||||
/datum/action/item_action/ninjaboost
|
||||
check_flags = NONE
|
||||
name = "Adrenaline Boost"
|
||||
desc = "Inject a secret chemical that will counteract all movement-impairing effect."
|
||||
button_icon_state = "repulse"
|
||||
icon_icon = 'icons/mob/actions/actions_spells.dmi'
|
||||
required_mobility_flags = NONE
|
||||
|
||||
/datum/action/item_action/ninjapulse
|
||||
name = "EM Burst (25E)"
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
return
|
||||
if(world.time > next_check && world.time > next_scare)
|
||||
next_check = world.time + 50
|
||||
var/list/seen_atoms = view(7, owner)
|
||||
var/list/seen_atoms = owner.fov_view(7)
|
||||
|
||||
if(LAZYLEN(trigger_objs))
|
||||
for(var/obj/O in seen_atoms)
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
* * extra_classes - Extra classes to apply to the span that holds the text
|
||||
* * lifespan - The lifespan of the message in deciseconds
|
||||
*/
|
||||
/datum/chatmessage/New(text, atom/target, mob/owner, list/extra_classes = null, lifespan = CHAT_MESSAGE_LIFESPAN)
|
||||
/datum/chatmessage/New(text, atom/target, mob/owner, list/extra_classes = list(), lifespan = CHAT_MESSAGE_LIFESPAN)
|
||||
. = ..()
|
||||
if (!istype(target))
|
||||
CRASH("Invalid target given for chatmessage")
|
||||
@@ -55,6 +55,12 @@
|
||||
message = null
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Calls qdel on the chatmessage when its parent is deleted, used to register qdel signal
|
||||
*/
|
||||
/datum/chatmessage/proc/on_parent_qdel()
|
||||
qdel(src)
|
||||
|
||||
/**
|
||||
* Generates a chat message image representation
|
||||
*
|
||||
@@ -68,7 +74,7 @@
|
||||
/datum/chatmessage/proc/generate_image(text, atom/target, mob/owner, list/extra_classes, lifespan)
|
||||
// Register client who owns this message
|
||||
owned_by = owner.client
|
||||
RegisterSignal(owned_by, COMSIG_PARENT_QDELETING, .proc/qdel, src)
|
||||
RegisterSignal(owned_by, COMSIG_PARENT_QDELETING, .proc/on_parent_qdel)
|
||||
|
||||
// Clip message
|
||||
var/maxlen = owned_by.prefs.max_chat_length
|
||||
@@ -108,7 +114,7 @@
|
||||
// BYOND Bug #2563917
|
||||
// Construct text
|
||||
var/static/regex/html_metachars = new(@"&[A-Za-z]{1,7};", "g")
|
||||
var/complete_text = "<span class='center maptext [extra_classes != null ? extra_classes.Join(" ") : ""]' style='color: [tgt_color]'>[text]</span>"
|
||||
var/complete_text = "<span class='center maptext [extra_classes.Join(" ")]' style='color: [tgt_color]'>[text]</span>"
|
||||
var/mheight = WXH_TO_HEIGHT(owned_by.MeasureText(replacetext(complete_text, html_metachars, "m"), null, CHAT_MESSAGE_WIDTH))
|
||||
approx_lines = max(1, mheight / CHAT_MESSAGE_APPROX_LHEIGHT)
|
||||
|
||||
@@ -129,7 +135,7 @@
|
||||
|
||||
// Build message image
|
||||
message = image(loc = message_loc, layer = CHAT_LAYER)
|
||||
message.plane = GAME_PLANE
|
||||
message.plane = CHAT_PLANE
|
||||
message.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA | KEEP_APART
|
||||
message.alpha = 0
|
||||
message.pixel_y = owner.bound_height * 0.95
|
||||
@@ -166,7 +172,7 @@
|
||||
*/
|
||||
/mob/proc/create_chat_message(atom/movable/speaker, datum/language/message_language, raw_message, list/spans, message_mode)
|
||||
// Ensure the list we are using, if present, is a copy so we don't modify the list provided to us
|
||||
spans = spans?.Copy()
|
||||
spans = spans ? spans.Copy() : list()
|
||||
|
||||
// Check for virtual speakers (aka hearing a message through a radio)
|
||||
var/atom/movable/originalSpeaker = speaker
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
|
||||
#define BAD_ART 12.5
|
||||
#define GOOD_ART 25
|
||||
#define GREAT_ART 50
|
||||
|
||||
/datum/component/art
|
||||
var/impressiveness = 0
|
||||
|
||||
/datum/component/art/Initialize(impress)
|
||||
impressiveness = impress
|
||||
if(isobj(parent))
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_obj_examine)
|
||||
else
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_other_examine)
|
||||
if(isstructure(parent))
|
||||
RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, .proc/on_attack_hand)
|
||||
if(isitem(parent))
|
||||
RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/apply_moodlet)
|
||||
|
||||
/datum/component/art/proc/apply_moodlet(mob/M, impress)
|
||||
M.visible_message("<span class='notice'>[M] stops and looks intently at [parent].</span>", \
|
||||
"<span class='notice'>You stop to take in [parent].</span>")
|
||||
switch(impress)
|
||||
if (0 to BAD_ART)
|
||||
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad)
|
||||
if (BAD_ART to GOOD_ART)
|
||||
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artok", /datum/mood_event/artok)
|
||||
if (GOOD_ART to GREAT_ART)
|
||||
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgood", /datum/mood_event/artgood)
|
||||
if(GREAT_ART to INFINITY)
|
||||
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat)
|
||||
|
||||
|
||||
/datum/component/art/proc/on_other_examine(datum/source, mob/M)
|
||||
apply_moodlet(M, impressiveness)
|
||||
|
||||
/datum/component/art/proc/on_obj_examine(datum/source, mob/M)
|
||||
var/obj/O = parent
|
||||
apply_moodlet(M, impressiveness *(O.obj_integrity/O.max_integrity))
|
||||
|
||||
/datum/component/art/proc/on_attack_hand(datum/source, mob/M)
|
||||
to_chat(M, "<span class='notice'>You start examining [parent]...</span>")
|
||||
if(!do_after(M, 20, target = parent))
|
||||
return
|
||||
on_obj_examine(source, M)
|
||||
|
||||
/datum/component/art/rev
|
||||
|
||||
/datum/component/art/rev/apply_moodlet(mob/M, impress)
|
||||
M.visible_message("<span class='notice'>[M] stops to inspect [parent].</span>", \
|
||||
"<span class='notice'>You take in [parent], inspecting the fine craftsmanship of the proletariat.</span>")
|
||||
|
||||
if(M.mind && M.mind.has_antag_datum(/datum/antagonist/rev))
|
||||
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat)
|
||||
else
|
||||
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad)
|
||||
@@ -74,7 +74,7 @@
|
||||
|
||||
//////////////////////Lens//////////////////////////
|
||||
//Six Steps //
|
||||
//Sells for 1800 cr, takes 15 glass shets //
|
||||
//Sells for 1600 cr, takes 15 glass shets //
|
||||
//Usefull for selling and later crafting //
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
@@ -146,14 +146,14 @@
|
||||
|
||||
/obj/item/glasswork/glass_base/glass_lens_part5
|
||||
name = "Unpolished glass lens"
|
||||
desc = "A small unpolished glass lens. Could be polished with some silk."
|
||||
desc = "A small unpolished glass lens. Could be polished with some cloth."
|
||||
icon = 'icons/obj/glass_ware.dmi'
|
||||
icon_state = "glass_optics"
|
||||
next_step = /obj/item/glasswork/glass_base/glass_lens_part6
|
||||
|
||||
/obj/item/glasswork/glass_base/glass_lens_part5/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(istype(I, /obj/item/stack/sheet/silk))
|
||||
if(istype(I, /obj/item/stack/sheet/cloth))
|
||||
if(do_after(user,10, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
@@ -324,7 +324,7 @@
|
||||
|
||||
//////////////////////Tea Plates////////////////////
|
||||
//Three Steps //
|
||||
//Sells for 1200 cr, takes 5 glass shets //
|
||||
//Sells for 1000 cr, takes 5 glass shets //
|
||||
//Usefull for selling and chemical things //
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
@@ -370,20 +370,20 @@
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_plate3
|
||||
name = "Disk of glass"
|
||||
desc = "A disk of glass that can be cant be used for much. Needs to be polished with some silk."
|
||||
desc = "A disk of glass that can be cant be used for much. Needs to be polished with some cloth."
|
||||
icon_state = "glass_base_half"
|
||||
next_step = /obj/item/tea_plate
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_plate3/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(istype(I, /obj/item/stack/sheet/silk))
|
||||
if(istype(I, /obj/item/stack/sheet/cloth))
|
||||
if(do_after(user,10, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
//////////////////////Tea Cup///////////////////////
|
||||
//Four Steps //
|
||||
//Sells for 1800 cr, takes 6 glass shets //
|
||||
//Sells for 1600 cr, takes 6 glass shets //
|
||||
//Usefull for selling and chemical things //
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
@@ -429,13 +429,13 @@
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_cup3
|
||||
name = "Disk of glass"
|
||||
desc = "A bowl of glass that can be cant be used for much. Needs to be polished with some silk."
|
||||
desc = "A bowl of glass that can be cant be used for much. Needs to be polished with some cloth."
|
||||
icon_state = "glass_base_half"
|
||||
next_step = /obj/item/glasswork/glass_base/tea_cup4
|
||||
|
||||
/obj/item/glasswork/glass_base/cup3/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(istype(I, /obj/item/stack/sheet/silk))
|
||||
if(istype(I, /obj/item/stack/sheet/cloth))
|
||||
if(do_after(user,10, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
//Gun crafting parts til they can be moved elsewhere
|
||||
|
||||
// PARTS //
|
||||
/obj/item/weaponcrafting
|
||||
icon = 'icons/obj/improvised.dmi'
|
||||
|
||||
/obj/item/weaponcrafting/receiver
|
||||
name = "modular receiver"
|
||||
desc = "A prototype modular receiver and trigger assembly for a firearm."
|
||||
icon = 'icons/obj/improvised.dmi'
|
||||
icon_state = "receiver"
|
||||
|
||||
/obj/item/weaponcrafting/stock
|
||||
name = "rifle stock"
|
||||
desc = "A classic rifle stock that doubles as a grip, roughly carved out of wood."
|
||||
icon = 'icons/obj/improvised.dmi'
|
||||
icon_state = "riflestock"
|
||||
|
||||
/obj/item/weaponcrafting/silkstring
|
||||
name = "silkstring"
|
||||
desc = "A long piece of silk with some resemblance to cable coil."
|
||||
icon = 'icons/obj/improvised.dmi'
|
||||
icon_state = "silkstring"
|
||||
/obj/item/weaponcrafting/durathread_string
|
||||
name = "durathread string"
|
||||
desc = "A long piece of durathread with some resemblance to cable coil."
|
||||
icon_state = "durastring"
|
||||
|
||||
@@ -39,14 +39,14 @@
|
||||
time = 10
|
||||
reqs = list(/obj/item/paper = 20)
|
||||
category = CAT_CLOTHING
|
||||
|
||||
|
||||
/datum/crafting_recipe/armwraps
|
||||
name = "Armwraps"
|
||||
result = /obj/item/clothing/gloves/fingerless/pugilist
|
||||
time = 60
|
||||
tools = list(TOOL_WIRECUTTER)
|
||||
reqs = list(/obj/item/stack/sheet/cloth = 4,
|
||||
/obj/item/stack/sheet/silk = 2,
|
||||
/obj/item/stack/sheet/durathread = 2,
|
||||
/obj/item/stack/sheet/leather = 2)
|
||||
category = CAT_CLOTHING
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
/datum/crafting_recipe/goldenbox
|
||||
name = "Gold Plated Toolbox"
|
||||
result = /obj/item/storage/toolbox/gold_fake
|
||||
tools = list(/obj/item/stock_parts/cell/upgraded/plus)
|
||||
tools = list(/obj/item/stock_parts/cell/high)
|
||||
reqs = list(/obj/item/stack/sheet/cardboard = 1, //so we dont null items in crafting
|
||||
/obj/item/stack/cable_coil = 10,
|
||||
/obj/item/stack/sheet/mineral/gold = 1,
|
||||
@@ -184,7 +184,7 @@
|
||||
|
||||
/datum/crafting_recipe/bronze_driver
|
||||
name = "Bronze Plated Screwdriver"
|
||||
tools = list(/obj/item/stock_parts/cell/upgraded/plus)
|
||||
tools = list(/obj/item/stock_parts/cell/high)
|
||||
result = /obj/item/screwdriver/bronze
|
||||
reqs = list(/obj/item/screwdriver = 1,
|
||||
/obj/item/stack/cable_coil = 10,
|
||||
@@ -196,7 +196,7 @@
|
||||
|
||||
/datum/crafting_recipe/bronze_welder
|
||||
name = "Bronze Plated Welding Tool"
|
||||
tools = list(/obj/item/stock_parts/cell/upgraded/plus)
|
||||
tools = list(/obj/item/stock_parts/cell/high)
|
||||
result = /obj/item/weldingtool/bronze
|
||||
reqs = list(/obj/item/weldingtool = 1,
|
||||
/obj/item/stack/cable_coil = 10,
|
||||
@@ -208,7 +208,7 @@
|
||||
|
||||
/datum/crafting_recipe/bronze_wirecutters
|
||||
name = "Bronze Plated Wirecutters"
|
||||
tools = list(/obj/item/stock_parts/cell/upgraded/plus)
|
||||
tools = list(/obj/item/stock_parts/cell/high)
|
||||
result = /obj/item/wirecutters/bronze
|
||||
reqs = list(/obj/item/wirecutters = 1,
|
||||
/obj/item/stack/cable_coil = 10,
|
||||
@@ -220,7 +220,7 @@
|
||||
|
||||
/datum/crafting_recipe/bronze_crowbar
|
||||
name = "Bronze Plated Crowbar"
|
||||
tools = list(/obj/item/stock_parts/cell/upgraded/plus)
|
||||
tools = list(/obj/item/stock_parts/cell/high)
|
||||
result = /obj/item/crowbar/bronze
|
||||
reqs = list(/obj/item/crowbar = 1,
|
||||
/obj/item/stack/cable_coil = 10,
|
||||
@@ -232,7 +232,7 @@
|
||||
|
||||
/datum/crafting_recipe/bronze_wrench
|
||||
name = "Bronze Plated Wrench"
|
||||
tools = list(/obj/item/stock_parts/cell/upgraded/plus)
|
||||
tools = list(/obj/item/stock_parts/cell/high)
|
||||
result = /obj/item/wrench/bronze
|
||||
reqs = list(/obj/item/wrench = 1,
|
||||
/obj/item/stack/cable_coil = 10,
|
||||
|
||||
@@ -192,7 +192,7 @@
|
||||
result = /obj/item/gun/ballistic/bow/pipe
|
||||
reqs = list(/obj/item/pipe = 5,
|
||||
/obj/item/stack/sheet/plastic = 15,
|
||||
/obj/item/weaponcrafting/silkstring = 5)
|
||||
/obj/item/weaponcrafting/durathread_string = 5)
|
||||
time = 450
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
@@ -281,7 +281,7 @@
|
||||
result = /obj/item/ammo_casing/caseless/arrow/wood
|
||||
time = 30
|
||||
reqs = list(/obj/item/stack/sheet/mineral/wood = 1,
|
||||
/obj/item/stack/sheet/silk = 1,
|
||||
/obj/item/stack/sheet/durathread = 1,
|
||||
/obj/item/stack/rods = 1) // 1 metal sheet = 2 rods = 2 arrows
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_AMMO
|
||||
|
||||
@@ -0,0 +1,354 @@
|
||||
#define CENTERED_RENDER_SOURCE(img, atom, FoV) \
|
||||
atom.render_target = atom.render_target || ref(atom);\
|
||||
img.render_source = atom.render_target;\
|
||||
if(atom.icon){\
|
||||
var/_cached_sizes = FoV.width_n_height_offsets[atom.icon];\
|
||||
if(!_cached_sizes){\
|
||||
var/icon/_I = icon(atom.icon);\
|
||||
var/list/L = list();\
|
||||
L += (_I.Width() - world.icon_size)/2;\
|
||||
L += (_I.Height() - world.icon_size)/2;\
|
||||
_cached_sizes = FoV.width_n_height_offsets[atom.icon] = L\
|
||||
}\
|
||||
img.pixel_x = _cached_sizes[1];\
|
||||
img.pixel_y = _cached_sizes[2];\
|
||||
img.loc = atom\
|
||||
}
|
||||
|
||||
#define REGISTER_NESTED_LOCS(source, list, comsig, proc) \
|
||||
for(var/k in get_nested_locs(source)){\
|
||||
var/atom/_A = k;\
|
||||
RegisterSignal(_A, comsig, proc);\
|
||||
list += _A\
|
||||
}
|
||||
|
||||
#define UNREGISTER_NESTED_LOCS(list, comsig, index) \
|
||||
for(var/k in index to length(list)){\
|
||||
var/atom/_A = list[k];\
|
||||
UnregisterSignal(_A, comsig);\
|
||||
list -= _A\
|
||||
}
|
||||
|
||||
/**
|
||||
* Field of Vision component. Does totally what you probably think it does,
|
||||
* ergo preventing players from seeing what's behind them.
|
||||
*/
|
||||
/datum/component/field_of_vision
|
||||
can_transfer = TRUE
|
||||
|
||||
/**
|
||||
* That special invisible, almost neigh indestructible movable
|
||||
* that holds both shadow cone mask and image and follows the player around.
|
||||
*/
|
||||
var/atom/movable/fov_holder/fov
|
||||
///The current screen size this field of vision is meant to fit for.
|
||||
var/current_fov_size = list(15, 15)
|
||||
///How much is the cone rotated clockwise, purely backend. Please use rotate_shadow_cone() if you must.
|
||||
var/angle = 0
|
||||
/// Used to scale the shadow cone when rotating it to fit over the edges of the screen.
|
||||
var/rot_scale = 1
|
||||
/// The inner angle of this cone, right hardset to 90, 180, or 270 degrees, until someone figures out a way to make it dynamic.
|
||||
var/shadow_angle = FOV_90_DEGREES
|
||||
/// The mask portion of the cone, placed on a * render target plane so while not visible it still applies the filter.
|
||||
var/image/shadow_mask
|
||||
/// The visual portion of the cone, placed on the highest layer of the wall plane
|
||||
var/image/visual_shadow
|
||||
/**
|
||||
* An image whose render_source is kept up to date to prevent the mob (or the topmost movable holding it) from being hidden by the mask.
|
||||
* Will make it use vis_contents instead once a few byonds bugs with images and vis contents are fixed.
|
||||
*/
|
||||
var/image/owner_mask
|
||||
/**
|
||||
* A circle image used to somewhat uncover the adjacent portion of the shadow cone, making mobs and objects behind us somewhat visible.
|
||||
* The owner mask is still required for those mob going over the default 32x32 px size btw.
|
||||
*/
|
||||
var/image/adj_mask
|
||||
/// A list of nested locations the mob is in, to ensure the above image works correctly.
|
||||
var/list/nested_locs = list()
|
||||
/**
|
||||
* A static list of offsets based on icon width and height, because render sources are centered unlike most other visuals,
|
||||
* and that gives us some problems when the icon is larger or smaller than world.icon_size
|
||||
*/
|
||||
var/static/list/width_n_height_offsets = list()
|
||||
|
||||
/datum/component/field_of_vision/Initialize(fov_type = FOV_90_DEGREES, _angle = 0)
|
||||
if(!ismob(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
angle = _angle
|
||||
shadow_angle = fov_type
|
||||
|
||||
/datum/component/field_of_vision/RegisterWithParent()
|
||||
. = ..()
|
||||
var/mob/M = parent
|
||||
if(M.client)
|
||||
generate_fov_holder(M, angle)
|
||||
RegisterSignal(M, COMSIG_MOB_CLIENT_LOGIN, .proc/on_mob_login)
|
||||
RegisterSignal(M, COMSIG_MOB_CLIENT_LOGOUT, .proc/on_mob_logout)
|
||||
RegisterSignal(M, COMSIG_MOB_GET_VISIBLE_MESSAGE, .proc/on_visible_message)
|
||||
RegisterSignal(M, COMSIG_MOB_EXAMINATE, .proc/on_examinate)
|
||||
RegisterSignal(M, COMSIG_MOB_FOV_VIEW, .proc/on_fov_view)
|
||||
RegisterSignal(M, COMSIG_MOB_CLIENT_CHANGE_VIEW, .proc/on_change_view)
|
||||
RegisterSignal(M, COMSIG_MOB_RESET_PERSPECTIVE, .proc/on_reset_perspective)
|
||||
RegisterSignal(M, COMSIG_MOB_FOV_VIEWER, .proc/is_viewer)
|
||||
|
||||
/datum/component/field_of_vision/UnregisterFromParent()
|
||||
. = ..()
|
||||
var/mob/M = parent
|
||||
if(!QDELETED(fov))
|
||||
if(M.client)
|
||||
UnregisterSignal(M, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_MOVABLE_MOVED, COMSIG_MOB_DEATH, COMSIG_LIVING_REVIVE))
|
||||
M.client.images -= owner_mask
|
||||
M.client.images -= shadow_mask
|
||||
M.client.images -= visual_shadow
|
||||
M.client.images -= adj_mask
|
||||
qdel(fov, TRUE) // Forced.
|
||||
fov = null
|
||||
QDEL_NULL(owner_mask)
|
||||
QDEL_NULL(adj_mask)
|
||||
if(length(nested_locs))
|
||||
UNREGISTER_NESTED_LOCS(nested_locs, COMSIG_MOVABLE_MOVED, 1)
|
||||
UnregisterSignal(M, list(COMSIG_MOB_CLIENT_LOGIN, COMSIG_MOB_CLIENT_LOGOUT,
|
||||
COMSIG_MOB_GET_VISIBLE_MESSAGE, COMSIG_MOB_EXAMINATE,
|
||||
COMSIG_MOB_FOV_VIEW, COMSIG_MOB_RESET_PERSPECTIVE,
|
||||
COMSIG_MOB_CLIENT_CHANGE_VIEW, COMSIG_MOB_FOV_VIEWER))
|
||||
|
||||
/**
|
||||
* Generates the holder and images (if not generated yet) and adds them to client.images.
|
||||
* Run when the component is registered to a player mob, or upon login.
|
||||
*/
|
||||
/datum/component/field_of_vision/proc/generate_fov_holder(mob/M, _angle = 0)
|
||||
if(QDELETED(fov))
|
||||
fov = new(get_turf(M))
|
||||
fov.icon_state = "[shadow_angle]"
|
||||
fov.dir = M.dir
|
||||
shadow_mask = image('icons/misc/field_of_vision.dmi', fov, "[shadow_angle]", FIELD_OF_VISION_LAYER)
|
||||
shadow_mask.plane = FIELD_OF_VISION_PLANE
|
||||
visual_shadow = image('icons/misc/field_of_vision.dmi', fov, "[shadow_angle]_v", FIELD_OF_VISION_LAYER)
|
||||
visual_shadow.plane = FIELD_OF_VISION_VISUAL_PLANE
|
||||
owner_mask = new
|
||||
owner_mask.appearance_flags = RESET_TRANSFORM
|
||||
owner_mask.plane = FIELD_OF_VISION_BLOCKER_PLANE
|
||||
adj_mask = image('icons/misc/field_of_vision.dmi', fov, "adj_mask", FIELD_OF_VISION_LAYER)
|
||||
adj_mask.appearance_flags = RESET_TRANSFORM
|
||||
adj_mask.plane = FIELD_OF_VISION_BLOCKER_PLANE
|
||||
if(_angle)
|
||||
rotate_shadow_cone(_angle)
|
||||
fov.alpha = M.stat == DEAD ? 0 : 255
|
||||
RegisterSignal(M, COMSIG_MOB_DEATH, .proc/hide_fov)
|
||||
RegisterSignal(M, COMSIG_LIVING_REVIVE, .proc/show_fov)
|
||||
RegisterSignal(M, COMSIG_ATOM_DIR_CHANGE, .proc/on_dir_change)
|
||||
RegisterSignal(M, COMSIG_MOVABLE_MOVED, .proc/on_mob_moved)
|
||||
RegisterSignal(M, COMSIG_ROBOT_UPDATE_ICONS, .proc/manual_centered_render_source)
|
||||
var/atom/A = M
|
||||
if(M.loc && !isturf(M.loc))
|
||||
REGISTER_NESTED_LOCS(M, nested_locs, COMSIG_MOVABLE_MOVED, .proc/on_loc_moved)
|
||||
A = nested_locs[nested_locs.len]
|
||||
CENTERED_RENDER_SOURCE(owner_mask, A, src)
|
||||
M.client.images += shadow_mask
|
||||
M.client.images += visual_shadow
|
||||
M.client.images += owner_mask
|
||||
M.client.images += adj_mask
|
||||
if(M.client.view != "[current_fov_size[1]]x[current_fov_size[2]]")
|
||||
resize_fov(current_fov_size, getviewsize(M.client.view))
|
||||
|
||||
///Rotates the shadow cone to a certain degree. Backend shenanigans.
|
||||
/datum/component/field_of_vision/proc/rotate_shadow_cone(new_angle)
|
||||
var/simple_degrees = SIMPLIFY_DEGREES(new_angle - angle)
|
||||
var/to_scale = cos(simple_degrees) * sin(simple_degrees)
|
||||
if(to_scale)
|
||||
var/old_rot_scale = rot_scale
|
||||
rot_scale = 1 + to_scale
|
||||
if(old_rot_scale != rot_scale)
|
||||
visual_shadow.transform = shadow_mask.transform = shadow_mask.transform.Scale(rot_scale/old_rot_scale)
|
||||
visual_shadow.transform = shadow_mask.transform = shadow_mask.transform.Turn(fov.transform, simple_degrees)
|
||||
|
||||
/**
|
||||
* Resizes the shadow to match the current screen size.
|
||||
* Run when the client view size is changed, or if the player has a viewsize different than "15x15" on login/comp registration.
|
||||
*/
|
||||
/datum/component/field_of_vision/proc/resize_fov(list/old_view, list/view)
|
||||
current_fov_size = view
|
||||
var/old_size = max(old_view[1], old_view[2])
|
||||
var/new_size = max(view[1], view[2])
|
||||
if(old_size == new_size) //longest edges are still of the same length.
|
||||
return
|
||||
visual_shadow.transform = shadow_mask.transform = shadow_mask.transform.Scale(new_size/old_size)
|
||||
|
||||
/datum/component/field_of_vision/proc/on_mob_login(mob/source, client/client)
|
||||
generate_fov_holder(source, angle)
|
||||
|
||||
/datum/component/field_of_vision/proc/on_mob_logout(mob/source, client/client)
|
||||
UnregisterSignal(source, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_MOVABLE_MOVED, COMSIG_MOB_DEATH,
|
||||
COMSIG_LIVING_REVIVE, COMSIG_ROBOT_UPDATE_ICONS))
|
||||
if(length(nested_locs))
|
||||
UNREGISTER_NESTED_LOCS(nested_locs, COMSIG_MOVABLE_MOVED, 1)
|
||||
|
||||
/datum/component/field_of_vision/proc/on_dir_change(mob/source, old_dir, new_dir)
|
||||
fov.dir = new_dir
|
||||
|
||||
///Hides the shadow, other visibility comsig procs will take it into account. Called when the mob dies.
|
||||
/datum/component/field_of_vision/proc/hide_fov(mob/source)
|
||||
fov.alpha = 0
|
||||
|
||||
/// Shows the shadow. Called when the mob is revived.
|
||||
/datum/component/field_of_vision/proc/show_fov(mob/source)
|
||||
fov.alpha = 255
|
||||
|
||||
/// Hides the shadow when looking through other items, shows it otherwise.
|
||||
/datum/component/field_of_vision/proc/on_reset_perspective(mob/source, atom/target)
|
||||
if(source.client.eye == source || source.client.eye == source.loc)
|
||||
fov.alpha = 255
|
||||
else
|
||||
fov.alpha = 0
|
||||
|
||||
/// Called when the client view size is changed.
|
||||
/datum/component/field_of_vision/proc/on_change_view(mob/source, client, list/old_view, list/view)
|
||||
resize_fov(old_view, view)
|
||||
|
||||
/**
|
||||
* Called when the owner mob moves around. Used to keep shadow located right behind us,
|
||||
* As well as modify the owner mask to match the topmost item.
|
||||
*/
|
||||
/datum/component/field_of_vision/proc/on_mob_moved(mob/source, atom/oldloc, dir, forced)
|
||||
var/turf/T
|
||||
if(!isturf(source.loc)) //Recalculate all nested locations.
|
||||
UNREGISTER_NESTED_LOCS( nested_locs, COMSIG_MOVABLE_MOVED, 1)
|
||||
REGISTER_NESTED_LOCS(source, nested_locs, COMSIG_MOVABLE_MOVED, .proc/on_loc_moved)
|
||||
var/atom/movable/topmost = nested_locs[nested_locs.len]
|
||||
T = topmost.loc
|
||||
CENTERED_RENDER_SOURCE(owner_mask, topmost, src)
|
||||
else
|
||||
T = source.loc
|
||||
if(length(nested_locs))
|
||||
UNREGISTER_NESTED_LOCS(nested_locs, COMSIG_MOVABLE_MOVED, 1)
|
||||
CENTERED_RENDER_SOURCE(owner_mask, source, src)
|
||||
if(T)
|
||||
fov.forceMove(T, harderforce = TRUE)
|
||||
|
||||
/// Pretty much like the above, but meant for other movables the mob is stored in (bodybags, boxes, mechs etc).
|
||||
/datum/component/field_of_vision/proc/on_loc_moved(atom/movable/source, atom/oldloc, dir, forced)
|
||||
if(isturf(source.loc) && isturf(oldloc)) //This is the case of the topmost movable loc moving around the world, skip.
|
||||
fov.forceMove(source.loc, harderforce = TRUE)
|
||||
return
|
||||
var/atom/movable/prev_topmost = nested_locs[nested_locs.len]
|
||||
if(prev_topmost != source)
|
||||
UNREGISTER_NESTED_LOCS(nested_locs, COMSIG_MOVABLE_MOVED, nested_locs.Find(source) + 1)
|
||||
REGISTER_NESTED_LOCS(source, nested_locs, COMSIG_MOVABLE_MOVED, .proc/on_loc_moved)
|
||||
var/atom/movable/topmost = nested_locs[nested_locs.len]
|
||||
if(topmost != prev_topmost)
|
||||
CENTERED_RENDER_SOURCE(owner_mask, topmost, src)
|
||||
if(topmost.loc)
|
||||
fov.forceMove(topmost.loc, harderforce = TRUE)
|
||||
|
||||
/// A hacky comsig proc for things that somehow decide to change icon on the go. may make a change_icon_file() proc later but...
|
||||
/datum/component/field_of_vision/proc/manual_centered_render_source(mob/source, old_icon)
|
||||
if(!isturf(source.loc))
|
||||
return
|
||||
CENTERED_RENDER_SOURCE(owner_mask, source, src)
|
||||
|
||||
#undef CENTERED_RENDER_SOURCE
|
||||
#undef REGISTER_NESTED_LOCS
|
||||
#undef UNREGISTER_NESTED_LOCS
|
||||
|
||||
/**
|
||||
* Byond doc is not entirely correct on the integrated arctan() proc.
|
||||
* When both x and y are negative, the output is also negative, cycling clockwise instead of counter-clockwise.
|
||||
* That's also why I am extensively using the SIMPLIFY_DEGREES macro here.
|
||||
*
|
||||
* Overall this is the main macro that calculates wheter a target is within the shadow cone angle or not.
|
||||
*/
|
||||
#define FOV_ANGLE_CHECK(mob, target, zero_x_y_statement, success_statement) \
|
||||
var/turf/T1 = get_turf(target);\
|
||||
var/turf/T2 = get_turf(mob);\
|
||||
if(!T1 || !T2){\
|
||||
zero_x_y_statement\
|
||||
}\
|
||||
var/_x = (T1.x - T2.x);\
|
||||
var/_y = (T1.y - T2.y);\
|
||||
if(ISINRANGE(_x, -1, 1) && ISINRANGE(_y, -1, 1)){\
|
||||
zero_x_y_statement\
|
||||
}\
|
||||
var/dir = (mob.dir & (EAST|WEST)) || mob.dir;\
|
||||
var/_degree = -angle;\
|
||||
var/_half = shadow_angle/2;\
|
||||
switch(dir){\
|
||||
if(EAST){\
|
||||
_degree += 180;\
|
||||
}\
|
||||
if(NORTH){\
|
||||
_degree += 270;\
|
||||
}\
|
||||
if(SOUTH){\
|
||||
_degree += 90;\
|
||||
}\
|
||||
}\
|
||||
var/_min = SIMPLIFY_DEGREES(_degree - _half);\
|
||||
var/_max = SIMPLIFY_DEGREES(_degree + _half);\
|
||||
if((_min > _max) ? !ISINRANGE(SIMPLIFY_DEGREES(arctan(_x, _y)), _max, _min) : ISINRANGE(SIMPLIFY_DEGREES(arctan(_x, _y)), _min, _max)){\
|
||||
success_statement;\
|
||||
}
|
||||
|
||||
/datum/component/field_of_vision/proc/on_examinate(mob/source, atom/target)
|
||||
if(fov.alpha)
|
||||
FOV_ANGLE_CHECK(source, target, return, return COMPONENT_DENY_EXAMINATE|COMPONENT_EXAMINATE_BLIND)
|
||||
|
||||
/datum/component/field_of_vision/proc/on_visible_message(mob/source, atom/target, message, range, list/ignored_mobs)
|
||||
if(fov.alpha)
|
||||
FOV_ANGLE_CHECK(source, target, return, return COMPONENT_NO_VISIBLE_MESSAGE)
|
||||
|
||||
/datum/component/field_of_vision/proc/on_fov_view(mob/source, list/atoms)
|
||||
if(!fov.alpha)
|
||||
return
|
||||
for(var/k in atoms)
|
||||
var/atom/A = k
|
||||
FOV_ANGLE_CHECK(source, A, continue, atoms -= A)
|
||||
|
||||
/datum/component/field_of_vision/proc/is_viewer(mob/source, atom/center, depth, list/viewers_list)
|
||||
if(fov.alpha)
|
||||
FOV_ANGLE_CHECK(source, center, return, viewers_list -= source)
|
||||
|
||||
#undef FOV_ANGLE_CHECK
|
||||
|
||||
/**
|
||||
* The shadow cone's mask and visual images holder which can't locate inside the mob,
|
||||
* lest they inherit the mob opacity and cause a lot of hindrance
|
||||
*/
|
||||
/atom/movable/fov_holder
|
||||
name = "field of vision holder"
|
||||
pixel_x = -224 //the image is about 480x480 px, ergo 15 tiles (480/32) big, and we gotta center it.
|
||||
pixel_y = -224
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
plane = FIELD_OF_VISION_PLANE
|
||||
anchored = TRUE
|
||||
|
||||
/atom/movable/fov_holder/ConveyorMove()
|
||||
return
|
||||
|
||||
/atom/movable/fov_holder/has_gravity(turf/T)
|
||||
return FALSE
|
||||
|
||||
/atom/movable/fov_holder/ex_act(severity)
|
||||
return FALSE
|
||||
|
||||
/atom/movable/fov_holder/singularity_act()
|
||||
return
|
||||
|
||||
/atom/movable/fov_holder/singularity_pull()
|
||||
return
|
||||
|
||||
/atom/movable/fov_holder/blob_act()
|
||||
return
|
||||
|
||||
/atom/movable/fov_holder/onTransitZ()
|
||||
return
|
||||
|
||||
/// Prevents people from moving these after creation, because they shouldn't be.
|
||||
/atom/movable/fov_holder/forceMove(atom/destination, no_tp=FALSE, harderforce = FALSE)
|
||||
if(harderforce)
|
||||
return ..()
|
||||
|
||||
/// Last but not least, these shouldn't be deleted by anything but the component itself
|
||||
/atom/movable/fov_holder/Destroy(force = FALSE)
|
||||
if(!force)
|
||||
return QDEL_HINT_LETMELIVE
|
||||
return ..()
|
||||
@@ -1,26 +1,52 @@
|
||||
///Footstep component. Plays footsteps at parents location when it is appropriate.
|
||||
/datum/component/footstep
|
||||
///How many steps the parent has taken since the last time a footstep was played
|
||||
var/steps = 0
|
||||
///volume determines the extra volume of the footstep. This is multiplied by the base volume, should there be one.
|
||||
var/volume
|
||||
///e_range stands for extra range - aka how far the sound can be heard. This is added to the base value and ignored if there isn't a base value.
|
||||
var/e_range
|
||||
///footstep_type is a define which determines what kind of sounds should get chosen.
|
||||
var/footstep_type
|
||||
///This can be a list OR a soundfile OR null. Determines whatever sound gets played.
|
||||
var/footstep_sounds
|
||||
|
||||
/datum/component/footstep/Initialize(volume_ = 0.5, e_range_ = -1)
|
||||
/datum/component/footstep/Initialize(footstep_type_ = FOOTSTEP_MOB_BAREFOOT, volume_ = 0.5, e_range_ = -1)
|
||||
if(!isliving(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
volume = volume_
|
||||
e_range = e_range_
|
||||
RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/play_footstep)
|
||||
footstep_type = footstep_type_
|
||||
switch(footstep_type)
|
||||
if(FOOTSTEP_MOB_HUMAN)
|
||||
if(!ishuman(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/play_humanstep)
|
||||
return
|
||||
if(FOOTSTEP_MOB_CLAW)
|
||||
footstep_sounds = GLOB.clawfootstep
|
||||
if(FOOTSTEP_MOB_BAREFOOT)
|
||||
footstep_sounds = GLOB.barefootstep
|
||||
if(FOOTSTEP_MOB_HEAVY)
|
||||
footstep_sounds = GLOB.heavyfootstep
|
||||
if(FOOTSTEP_MOB_SHOE)
|
||||
footstep_sounds = GLOB.footstep
|
||||
if(FOOTSTEP_MOB_SLIME)
|
||||
footstep_sounds = 'sound/effects/footstep/slime1.ogg'
|
||||
if(FOOTSTEP_MOB_CRAWL)
|
||||
footstep_sounds = 'sound/effects/footstep/crawl1.ogg'
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/play_simplestep) //Note that this doesn't get called for humans.
|
||||
|
||||
/datum/component/footstep/proc/play_footstep()
|
||||
///Prepares a footstep. Determines if it should get played. Returns the turf it should get played on. Note that it is always a /turf/open
|
||||
/datum/component/footstep/proc/prepare_step()
|
||||
var/turf/open/T = get_turf(parent)
|
||||
if(!istype(T))
|
||||
return
|
||||
|
||||
var/mob/living/LM = parent
|
||||
var/v = volume
|
||||
var/e = e_range
|
||||
if(!T.footstep || LM.buckled || !CHECK_MOBILITY(LM, MOBILITY_STAND) || LM.buckled || LM.throwing || (LM.movement_type & (VENTCRAWLING | FLYING)))
|
||||
if (LM.lying && !LM.buckled && !(!T.footstep || LM.movement_type & (VENTCRAWLING | FLYING))) //play crawling sound if we're lying
|
||||
playsound(T, 'sound/effects/footstep/crawl1.ogg', 15 * v)
|
||||
playsound(T, 'sound/effects/footstep/crawl1.ogg', 15 * volume)
|
||||
return
|
||||
|
||||
if(HAS_TRAIT(LM, TRAIT_SILENT_STEP))
|
||||
@@ -30,79 +56,83 @@
|
||||
var/mob/living/carbon/C = LM
|
||||
if(!C.get_bodypart(BODY_ZONE_L_LEG) && !C.get_bodypart(BODY_ZONE_R_LEG))
|
||||
return
|
||||
if(ishuman(C) && C.m_intent == MOVE_INTENT_WALK)
|
||||
v /= 2
|
||||
e -= 5
|
||||
if(C.m_intent == MOVE_INTENT_WALK)
|
||||
return
|
||||
steps++
|
||||
|
||||
if(steps >= 3)
|
||||
if(steps >= 6)
|
||||
steps = 0
|
||||
|
||||
else
|
||||
if(steps % 2)
|
||||
return
|
||||
|
||||
if(prob(80) && !LM.has_gravity(T)) // don't need to step as often when you hop around
|
||||
if(steps != 0 && !LM.has_gravity(T)) // don't need to step as often when you hop around
|
||||
return
|
||||
return T
|
||||
|
||||
//begin playsound shenanigans//
|
||||
|
||||
//for barefooted non-clawed mobs like monkeys
|
||||
if(isbarefoot(LM))
|
||||
playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
|
||||
GLOB.barefootstep[T.barefootstep][2] * v,
|
||||
TRUE,
|
||||
GLOB.barefootstep[T.barefootstep][3] + e)
|
||||
/datum/component/footstep/proc/play_simplestep()
|
||||
var/turf/open/T = prepare_step()
|
||||
if(!T)
|
||||
return
|
||||
|
||||
//for xenomorphs, dogs, and other clawed mobs
|
||||
if(isclawfoot(LM))
|
||||
if(isalienadult(LM)) //xenos are stealthy and get quieter footsteps
|
||||
v /= 3
|
||||
e -= 5
|
||||
|
||||
playsound(T, pick(GLOB.clawfootstep[T.clawfootstep][1]),
|
||||
GLOB.clawfootstep[T.clawfootstep][2] * v,
|
||||
TRUE,
|
||||
GLOB.clawfootstep[T.clawfootstep][3] + e)
|
||||
if(isfile(footstep_sounds) || istext(footstep_sounds))
|
||||
playsound(T, footstep_sounds, volume)
|
||||
return
|
||||
|
||||
//for megafauna and other large and imtimidating mobs such as the bloodminer
|
||||
if(isheavyfoot(LM))
|
||||
playsound(T, pick(GLOB.heavyfootstep[T.heavyfootstep][1]),
|
||||
GLOB.heavyfootstep[T.heavyfootstep][2] * v,
|
||||
TRUE,
|
||||
GLOB.heavyfootstep[T.heavyfootstep][3] + e)
|
||||
var/turf_footstep
|
||||
switch(footstep_type)
|
||||
if(FOOTSTEP_MOB_CLAW)
|
||||
turf_footstep = T.clawfootstep
|
||||
if(FOOTSTEP_MOB_BAREFOOT)
|
||||
turf_footstep = T.barefootstep
|
||||
if(FOOTSTEP_MOB_HEAVY)
|
||||
turf_footstep = T.heavyfootstep
|
||||
if(FOOTSTEP_MOB_SHOE)
|
||||
turf_footstep = T.footstep
|
||||
if(!turf_footstep)
|
||||
return
|
||||
playsound(T, pick(footstep_sounds[turf_footstep][1]), footstep_sounds[turf_footstep][2] * volume, TRUE, footstep_sounds[turf_footstep][3] + e_range)
|
||||
|
||||
//for slimes
|
||||
if(isslime(LM))
|
||||
playsound(T, 'sound/effects/footstep/slime1.ogg', 15 * v)
|
||||
/datum/component/footstep/proc/play_humanstep()
|
||||
var/turf/open/T = prepare_step()
|
||||
if(!T)
|
||||
return
|
||||
|
||||
//for (simple) humanoid mobs (clowns, russians, pirates, etc.)
|
||||
if(isshoefoot(LM))
|
||||
if(!ishuman(LM))
|
||||
playsound(T, pick(GLOB.footstep[T.footstep][1]),
|
||||
GLOB.footstep[T.footstep][2] * v,
|
||||
TRUE,
|
||||
GLOB.footstep[T.footstep][3] + e)
|
||||
return
|
||||
if(ishuman(LM)) //for proper humans, they're special
|
||||
var/mob/living/carbon/human/H = LM
|
||||
var/feetCover = (H.wear_suit && (H.wear_suit.body_parts_covered & FEET)) || (H.w_uniform && (H.w_uniform.body_parts_covered & FEET) || (H.shoes && (H.shoes.body_parts_covered & FEET)))
|
||||
|
||||
if (H.dna.features["taur"] == "Naga" || H.dna.features["taur"] == "Tentacle") //are we a naga or tentacle taur creature
|
||||
playsound(T, 'sound/effects/footstep/crawl1.ogg', 15 * v)
|
||||
var/mob/living/carbon/human/H = parent
|
||||
var/list/L = GLOB.barefootstep
|
||||
var/turf_footstep = T.barefootstep
|
||||
var/special = FALSE
|
||||
if(H.physiology.footstep_type)
|
||||
switch(H.physiology.footstep_type)
|
||||
if(FOOTSTEP_MOB_CLAW)
|
||||
turf_footstep = T.clawfootstep
|
||||
L = GLOB.clawfootstep
|
||||
if(FOOTSTEP_MOB_BAREFOOT)
|
||||
turf_footstep = T.barefootstep
|
||||
L = GLOB.barefootstep
|
||||
if(FOOTSTEP_MOB_HEAVY)
|
||||
turf_footstep = T.heavyfootstep
|
||||
L = GLOB.heavyfootstep
|
||||
if(FOOTSTEP_MOB_SHOE)
|
||||
turf_footstep = T.footstep
|
||||
L = GLOB.footstep
|
||||
if(FOOTSTEP_MOB_SLIME)
|
||||
playsound(T, 'sound/effects/footstep/slime1.ogg', 50 * volume)
|
||||
return
|
||||
if(FOOTSTEP_MOB_CRAWL)
|
||||
playsound(T, 'sound/effects/footstep/crawl1.ogg', 50 * volume)
|
||||
return
|
||||
special = TRUE
|
||||
else
|
||||
var/feetCover = (H.wear_suit && (H.wear_suit.body_parts_covered & FEET)) || (H.w_uniform && (H.w_uniform.body_parts_covered & FEET) || (H.shoes && (H.shoes.body_parts_covered & FEET)))
|
||||
if(feetCover) //are we wearing shoes
|
||||
playsound(T, pick(GLOB.footstep[T.footstep][1]),
|
||||
GLOB.footstep[T.footstep][2] * volume,
|
||||
TRUE,
|
||||
GLOB.footstep[T.footstep][3] + e_range)
|
||||
return
|
||||
|
||||
if(feetCover) //are we wearing shoes
|
||||
playsound(T, pick(GLOB.footstep[T.footstep][1]),
|
||||
GLOB.footstep[T.footstep][2] * v,
|
||||
TRUE,
|
||||
GLOB.footstep[T.footstep][3] + e)
|
||||
|
||||
if(!feetCover) //are we NOT wearing shoes
|
||||
playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
|
||||
GLOB.barefootstep[T.barefootstep][2] * v,
|
||||
TRUE,
|
||||
GLOB.barefootstep[T.barefootstep][3] + e)
|
||||
if(!special && H.dna.species.special_step_sounds)
|
||||
playsound(T, pick(H.dna.species.special_step_sounds), 50, TRUE)
|
||||
else
|
||||
playsound(T, pick(L[turf_footstep][1]),
|
||||
L[turf_footstep][2] * volume,
|
||||
TRUE,
|
||||
L[turf_footstep][3] + e_range)
|
||||
|
||||
@@ -1,41 +1,52 @@
|
||||
#define ECSTATIC_SANITY_PEN -1
|
||||
#define SLIGHT_INSANITY_PEN 1
|
||||
#define MINOR_INSANITY_PEN 5
|
||||
#define MAJOR_INSANITY_PEN 10
|
||||
#define MOOD_INSANITY_MALUS 0.0054 // per point of sanity below SANITY_DISTURBED, a 40% debuff to skills at rock bottom depression.
|
||||
#define MOOD_INSANITY_MALUS 0.13 // 13% debuff per sanity_level above the default of 4 (higher is worser), overall a 39% debuff to skills at rock bottom depression.
|
||||
|
||||
/datum/component/mood
|
||||
var/mood //Real happiness
|
||||
var/sanity = 100 //Current sanity
|
||||
var/shown_mood //Shown happiness, this is what others can see when they try to examine you, prevents antag checking by noticing traitors are always very happy.
|
||||
var/mood_level = 5 //To track what stage of moodies they're on
|
||||
var/sanity_level = 5 //To track what stage of sanity they're on
|
||||
var/sanity_level = 3 //To track what stage of sanity they're on
|
||||
var/mood_modifier = 1 //Modifier to allow certain mobs to be less affected by moodlets
|
||||
var/list/datum/mood_event/mood_events = list()
|
||||
var/insanity_effect = 0 //is the owner being punished for low mood? If so, how much?
|
||||
var/obj/screen/mood/screen_obj
|
||||
var/datum/skill_modifier/bad_mood/malus
|
||||
var/datum/skill_modifier/great_mood/bonus
|
||||
var/static/malus_id = 0
|
||||
var/static/list/free_maluses = list()
|
||||
|
||||
/datum/component/mood/Initialize()
|
||||
if(!isliving(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
START_PROCESSING(SSmood, src)
|
||||
var/mob/living/owner = parent
|
||||
if(owner.stat != DEAD)
|
||||
START_PROCESSING(SSdcs, src)
|
||||
|
||||
RegisterSignal(parent, COMSIG_ADD_MOOD_EVENT, .proc/add_event)
|
||||
RegisterSignal(parent, COMSIG_CLEAR_MOOD_EVENT, .proc/clear_event)
|
||||
RegisterSignal(parent, COMSIG_MODIFY_SANITY, .proc/modify_sanity)
|
||||
RegisterSignal(parent, COMSIG_LIVING_REVIVE, .proc/on_revive)
|
||||
RegisterSignal(parent, COMSIG_MOB_HUD_CREATED, .proc/modify_hud)
|
||||
var/mob/living/owner = parent
|
||||
RegisterSignal(parent, COMSIG_MOB_DEATH, .proc/stop_processing)
|
||||
|
||||
if(owner.hud_used)
|
||||
modify_hud()
|
||||
var/datum/hud/hud = owner.hud_used
|
||||
hud.show_hud(hud.hud_version)
|
||||
|
||||
/datum/component/mood/Destroy()
|
||||
STOP_PROCESSING(SSmood, src)
|
||||
STOP_PROCESSING(SSdcs, src)
|
||||
unmodify_hud()
|
||||
return ..()
|
||||
|
||||
/datum/component/mood/proc/stop_processing()
|
||||
STOP_PROCESSING(SSdcs, src)
|
||||
|
||||
/datum/component/mood/proc/print_mood(mob/user)
|
||||
var/msg = "<span class='info'>*---------*\n<EM>Your current mood</EM>\n"
|
||||
msg += "<span class='notice'>My mental status: </span>" //Long term
|
||||
@@ -127,7 +138,7 @@
|
||||
else
|
||||
screen_obj.icon_state = "mood[mood_level]"
|
||||
|
||||
/datum/component/mood/process() //Called on SSmood process
|
||||
/datum/component/mood/process() //Called on SSdcs process
|
||||
if(QDELETED(parent)) // workaround to an obnoxious sneaky periodical runtime.
|
||||
qdel(src)
|
||||
return
|
||||
@@ -167,13 +178,13 @@
|
||||
else if(sanity > maximum && amount > sanity - 0.5)
|
||||
amount = sanity - 0.5
|
||||
|
||||
var/old_sanity = sanity
|
||||
// Disturbed stops you from getting any more sane
|
||||
if(HAS_TRAIT(master, TRAIT_UNSTABLE))
|
||||
sanity = min(amount,sanity)
|
||||
else
|
||||
sanity = amount
|
||||
|
||||
var/old_sanity_level = sanity_level
|
||||
switch(sanity)
|
||||
if(-INFINITY to SANITY_CRAZY)
|
||||
setInsanityEffect(MAJOR_INSANITY_PEN)
|
||||
@@ -196,27 +207,43 @@
|
||||
master.remove_movespeed_modifier(MOVESPEED_ID_SANITY)
|
||||
sanity_level = 2
|
||||
if(SANITY_GREAT+1 to INFINITY)
|
||||
setInsanityEffect(0)
|
||||
setInsanityEffect(ECSTATIC_SANITY_PEN) //It's not a penalty but w/e
|
||||
master.remove_movespeed_modifier(MOVESPEED_ID_SANITY)
|
||||
sanity_level = 1
|
||||
|
||||
if(old_sanity > 1 && sanity == 1)
|
||||
RegisterSignal(master, COMSIG_MOB_SKILL_GET_AFFINITY, .proc/on_get_skill_affinity)
|
||||
else if(old_sanity == 1 && sanity > 1)
|
||||
UnregisterSignal(master, COMSIG_MOB_SKILL_GET_AFFINITY)
|
||||
if(sanity_level != old_sanity_level)
|
||||
if(sanity_level >= 4)
|
||||
if(!malus)
|
||||
if(!length(free_maluses))
|
||||
ADD_SKILL_MODIFIER_BODY(/datum/skill_modifier/bad_mood, malus_id++, master, malus)
|
||||
else
|
||||
malus = pick_n_take(free_maluses)
|
||||
if(master.mind)
|
||||
master.mind.add_skill_modifier(malus.identifier)
|
||||
else
|
||||
malus.RegisterSignal(master, COMSIG_MOB_ON_NEW_MIND, /datum/skill_modifier.proc/on_mob_new_mind, TRUE)
|
||||
malus.value_mod = malus.level_mod = 1 - (sanity_level - 3) * MOOD_INSANITY_MALUS
|
||||
else if(malus)
|
||||
if(master.mind)
|
||||
master.mind.remove_skill_modifier(malus.identifier)
|
||||
else
|
||||
malus.UnregisterSignal(master, COMSIG_MOB_ON_NEW_MIND)
|
||||
free_maluses += malus
|
||||
malus = null
|
||||
|
||||
//update_mood_icon()
|
||||
|
||||
/datum/component/mood/proc/setInsanityEffect(newval)//More code so that the previous proc works
|
||||
if(newval == insanity_effect)
|
||||
return
|
||||
//var/mob/living/master = parent
|
||||
//master.crit_threshold = (master.crit_threshold - insanity_effect) + newval
|
||||
if(!insanity_effect && newval)
|
||||
RegisterSignal(parent, COMSIG_MOB_ACTION_SKILL_MOD, .proc/on_mob_action_skill_mod)
|
||||
RegisterSignal(parent, COMSIG_MOB_ITEM_ACTION_SKILLS_MOD, .proc/on_item_action_skills_mod)
|
||||
else if(insanity_effect && !newval)
|
||||
UnregisterSignal(parent, list(COMSIG_MOB_ACTION_SKILL_MOD, COMSIG_MOB_ITEM_ACTION_SKILLS_MOD))
|
||||
|
||||
var/mob/living/L = parent
|
||||
if(newval == ECSTATIC_SANITY_PEN && !bonus)
|
||||
ADD_SKILL_MODIFIER_BODY(/datum/skill_modifier/great_mood, null, L, bonus)
|
||||
else if(bonus)
|
||||
REMOVE_SKILL_MODIFIER_BODY(/datum/skill_modifier/great_mood, null, L)
|
||||
bonus = null
|
||||
|
||||
insanity_effect = newval
|
||||
|
||||
/datum/component/mood/proc/modify_sanity(datum/source, amount, minimum = SANITY_INSANE, maximum = SANITY_AMAZING)
|
||||
@@ -294,46 +321,15 @@
|
||||
if(0 to NUTRITION_LEVEL_STARVING)
|
||||
add_event(null, "nutrition", /datum/mood_event/starving)
|
||||
|
||||
///Called when parent is ahealed.
|
||||
///Called when parent is revived.
|
||||
/datum/component/mood/proc/on_revive(datum/source, full_heal)
|
||||
START_PROCESSING(SSdcs, src)
|
||||
if(!full_heal)
|
||||
return
|
||||
remove_temp_moods()
|
||||
setSanity(initial(sanity))
|
||||
|
||||
/datum/component/mood/proc/on_mob_action_skill_mod(mob/source, list/skill_args, list/mod_values)
|
||||
var/datum/skill/S = GLOB.skill_datums[skill_args[ACTION_SKILL_MOD_SKILL]]
|
||||
if(!(S.skill_flags & SKILL_USE_MOOD))
|
||||
return
|
||||
var/debuff = 1 - (SANITY_DISTURBED - sanity) * MOOD_INSANITY_MALUS
|
||||
mod_values[MOD_VALUES_SKILL_MOD] *= skill_args[ACTION_SKILL_MOD_IS_MULTI] ? debuff : 1/debuff
|
||||
|
||||
/datum/component/mood/proc/on_item_action_skills_mod(mob/source, list/skill_args, list/mod_values)
|
||||
if(skill_args[ITEM_SKILLS_MOD_BAD_FLAGS] & SKILL_USE_MOOD)
|
||||
return
|
||||
var/divisor = mod_values[MOD_VALUES_ITEM_SKILLS_DIV]
|
||||
if(!divisor)
|
||||
return
|
||||
var/obj/item/I = skill_args[ITEM_SKILLS_MOD_ITEM]
|
||||
var/list/L = mod_values[MOD_VALUES_ITEM_SKILLS_CHECKED]
|
||||
var/skills_len = length(L)
|
||||
var/affected_skills = skills_len
|
||||
for(var/k in L)
|
||||
var/datum/skill/S = k
|
||||
var/our_flags = I.used_skills[S.type]|S.skill_flags
|
||||
if(!(our_flags & SKILL_USE_MOOD))
|
||||
affected_skills--
|
||||
if(!affected_skills)
|
||||
return
|
||||
var/debuff = 1 - (SANITY_DISTURBED - sanity) * MOOD_INSANITY_MALUS * (affected_skills/skills_len)
|
||||
mod_values[MOD_VALUES_ITEM_SKILLS_SUM] *= skill_args[ITEM_SKILLS_MOD_IS_MULTI] ? debuff : 1/debuff
|
||||
|
||||
/datum/component/mood/proc/on_get_skill_affinity(mob/source, skill_path, list/return_value)
|
||||
var/datum/skill/S = GLOB.skill_datums[skill_path]
|
||||
if(!S || !(S.skill_flags & SKILL_TRAIN_MOOD))
|
||||
return
|
||||
return_value[1] *= SKILL_AFFINITY_MOOD_BONUS
|
||||
|
||||
#undef ECSTATIC_SANITY_PEN
|
||||
#undef SLIGHT_INSANITY_PEN
|
||||
#undef MINOR_INSANITY_PEN
|
||||
#undef MAJOR_INSANITY_PEN
|
||||
|
||||
@@ -353,8 +353,12 @@
|
||||
/datum/component/storage/proc/_remove_and_refresh(datum/source, atom/movable/thing)
|
||||
_removal_reset(thing)
|
||||
if(LAZYACCESS(ui_item_blocks, thing))
|
||||
qdel(ui_item_blocks[thing])
|
||||
var/obj/screen/storage/volumetric_box/center/C = ui_item_blocks[thing]
|
||||
for(var/i in can_see_contents()) //runtimes result if mobs can access post deletion.
|
||||
var/mob/M = i
|
||||
M.client?.screen -= C.on_screen_objects()
|
||||
ui_item_blocks -= thing
|
||||
qdel(C)
|
||||
refresh_mob_views()
|
||||
|
||||
//Call this proc to handle the removal of an item from the storage item. The item will be moved to the new_location target, if that is null it's being deleted
|
||||
@@ -567,10 +571,9 @@
|
||||
return
|
||||
if(rustle_sound)
|
||||
playsound(parent, "rustle", 50, 1, -5)
|
||||
for(var/mob/viewing in viewers(user, null))
|
||||
if(M == viewing)
|
||||
to_chat(usr, "<span class='notice'>You put [I] [insert_preposition]to [parent].</span>")
|
||||
else if(in_range(M, viewing)) //If someone is standing close enough, they can tell what it is...
|
||||
to_chat(user, "<span class='notice'>You put [I] [insert_preposition]to [parent].</span>")
|
||||
for(var/mob/viewing in fov_viewers(world.view, user)-M)
|
||||
if(in_range(M, viewing)) //If someone is standing close enough, they can tell what it is...
|
||||
viewing.show_message("<span class='notice'>[M] puts [I] [insert_preposition]to [parent].</span>", MSG_VISUAL)
|
||||
else if(I && I.w_class >= 3) //Otherwise they can only see large or normal items from a distance...
|
||||
viewing.show_message("<span class='notice'>[M] puts [I] [insert_preposition]to [parent].</span>", MSG_VISUAL)
|
||||
|
||||
@@ -92,6 +92,8 @@
|
||||
var/list/volume_by_item = list()
|
||||
var/list/percentage_by_item = list()
|
||||
for(var/obj/item/I in contents)
|
||||
if(QDELETED(I))
|
||||
continue
|
||||
volume = I.get_w_volume()
|
||||
used += volume
|
||||
volume_by_item[I] = volume
|
||||
@@ -123,6 +125,7 @@
|
||||
var/obj/item/I
|
||||
// start at this pixel from screen_start_x.
|
||||
var/current_pixel = VOLUMETRIC_STORAGE_EDGE_PADDING
|
||||
var/first = TRUE
|
||||
var/row = 1
|
||||
|
||||
LAZYINITLIST(ui_item_blocks)
|
||||
@@ -140,10 +143,10 @@
|
||||
addrow = TRUE
|
||||
|
||||
// now that we have pixels_to_use, place our thing and add it to the returned list.
|
||||
|
||||
B.screen_loc = I.screen_loc = "[screen_start_x]:[round(current_pixel + (pixels_to_use * 0.5) + VOLUMETRIC_STORAGE_ITEM_PADDING, 1)],[screen_start_y+row-1]:[screen_pixel_y]"
|
||||
B.screen_loc = I.screen_loc = "[screen_start_x]:[round(current_pixel + (pixels_to_use * 0.5) + (first? 0 : VOLUMETRIC_STORAGE_ITEM_PADDING), 1)],[screen_start_y+row-1]:[screen_pixel_y]"
|
||||
// add the used pixels to pixel after we place the object
|
||||
current_pixel += pixels_to_use + VOLUMETRIC_STORAGE_ITEM_PADDING
|
||||
current_pixel += pixels_to_use + (first? 0 : VOLUMETRIC_STORAGE_ITEM_PADDING)
|
||||
first = FALSE //apply padding to everything after this
|
||||
|
||||
// set various things
|
||||
B.set_pixel_size(pixels_to_use)
|
||||
@@ -163,6 +166,7 @@
|
||||
// go up a row if needed
|
||||
if(addrow)
|
||||
row++
|
||||
first = TRUE //first in the row, don't apply between-item padding.
|
||||
current_pixel = VOLUMETRIC_STORAGE_EDGE_PADDING
|
||||
|
||||
// Then, continuous section.
|
||||
@@ -233,7 +237,7 @@
|
||||
if(!M.client)
|
||||
return TRUE
|
||||
UnregisterSignal(M, COMSIG_MOB_CLIENT_LOGOUT)
|
||||
M.client.screen -= list(ui_boxes, ui_close, ui_left, ui_continuous) + get_ui_item_objects_hide()
|
||||
M.client.screen -= list(ui_boxes, ui_close, ui_left, ui_continuous) + get_ui_item_objects_hide(M)
|
||||
if(M.active_storage == src)
|
||||
M.active_storage = null
|
||||
LAZYREMOVE(is_using, M)
|
||||
@@ -249,8 +253,8 @@
|
||||
/**
|
||||
* Gets the ui item objects to ui_hide.
|
||||
*/
|
||||
/datum/component/storage/proc/get_ui_item_objects_hide()
|
||||
if(!volumetric_ui())
|
||||
/datum/component/storage/proc/get_ui_item_objects_hide(mob/M)
|
||||
if(!volumetric_ui() || M.client?.prefs?.no_tetris_storage)
|
||||
var/atom/real_location = real_location()
|
||||
return real_location.contents
|
||||
else
|
||||
|
||||
@@ -145,4 +145,10 @@
|
||||
return !is_mouth_covered()
|
||||
|
||||
/mob/living/carbon/CanSpreadAirborneDisease()
|
||||
return !((head && (head.flags_cover & HEADCOVERSMOUTH) && (head.armor.getRating("bio") >= 25)) || (wear_mask && (wear_mask.flags_cover & MASKCOVERSMOUTH) && (wear_mask.armor.getRating("bio") >= 25)))
|
||||
return !((head && (head.flags_cover & HEADCOVERSMOUTH) && (head.armor.getRating("bio") >= 25)) || (wear_mask && (wear_mask.flags_cover & MASKCOVERSMOUTH) && (wear_mask.armor.getRating("bio") >= 25)))
|
||||
|
||||
/mob/living/proc/set_shocked()
|
||||
flags_1 |= SHOCKED_1
|
||||
|
||||
/mob/living/proc/reset_shocked()
|
||||
flags_1 &= ~ SHOCKED_1
|
||||
+12
-1
@@ -48,8 +48,8 @@
|
||||
destination.dna.uni_identity = uni_identity
|
||||
destination.dna.blood_type = blood_type
|
||||
destination.dna.skin_tone_override = skin_tone_override
|
||||
destination.set_species(species.type, icon_update=0)
|
||||
destination.dna.features = features.Copy()
|
||||
destination.set_species(species.type, icon_update=0)
|
||||
destination.dna.real_name = real_name
|
||||
destination.dna.nameless = nameless
|
||||
destination.dna.custom_species = custom_species
|
||||
@@ -252,6 +252,17 @@
|
||||
construct_block(GLOB.mam_body_markings_list.Find(features["mam_body_markings"]), GLOB.mam_body_markings_list.len)
|
||||
if(DNA_TAUR_BLOCK)
|
||||
construct_block(GLOB.taur_list.Find(features["taur"]), GLOB.taur_list.len)
|
||||
if(species.mutant_bodyparts["taur"] && ishuman(holder))
|
||||
var/datum/sprite_accessory/taur/T = GLOB.taur_list[features["taur"]]
|
||||
switch(T?.taur_mode)
|
||||
if(STYLE_HOOF_TAURIC)
|
||||
H.physiology.footstep_type = FOOTSTEP_MOB_SHOE
|
||||
if(STYLE_PAW_TAURIC)
|
||||
H.physiology.footstep_type = FOOTSTEP_MOB_CLAW
|
||||
if(STYLE_SNEK_TAURIC)
|
||||
H.physiology.footstep_type = FOOTSTEP_MOB_CRAWL
|
||||
else
|
||||
H.physiology.footstep_type = null
|
||||
|
||||
//Please use add_mutation or activate_mutation instead
|
||||
/datum/dna/proc/force_give(datum/mutation/human/HM)
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
#define SHORT 4/5
|
||||
#define TALL 5/4
|
||||
|
||||
///Very similar to squish, but for dwarves and shorties
|
||||
/datum/element/dwarfism
|
||||
element_flags = ELEMENT_DETACH|ELEMENT_BESPOKE
|
||||
id_arg_index = 2
|
||||
var/comsig
|
||||
var/list/attached_targets = list()
|
||||
|
||||
/datum/element/dwarfism/Attach(datum/target, comsig, comsig_target)
|
||||
. = ..()
|
||||
if(!isliving(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
|
||||
src.comsig = comsig
|
||||
|
||||
var/mob/living/L = target
|
||||
if(L.lying != 0)
|
||||
L.transform = L.transform.Scale(SHORT, 1)
|
||||
else
|
||||
L.transform = L.transform.Scale(1, SHORT)
|
||||
attached_targets[target] = comsig_target
|
||||
RegisterSignal(target, comsig, .proc/check_loss) //Second arg of the signal will be checked against the comsig_target.
|
||||
|
||||
/datum/element/dwarfism/proc/check_loss(mob/living/L, comsig_target)
|
||||
if(attached_targets[L] == comsig_target)
|
||||
Detach(L)
|
||||
|
||||
/datum/element/dwarfism/Detach(mob/living/L)
|
||||
. = ..()
|
||||
if(QDELETED(L))
|
||||
return
|
||||
if(L.lying != 0)
|
||||
L.transform = L.transform.Scale(TALL, 1)
|
||||
else
|
||||
L.transform = L.transform.Scale(1, TALL)
|
||||
UnregisterSignal(L, comsig)
|
||||
attached_targets -= L
|
||||
|
||||
#undef SHORT
|
||||
#undef TALL
|
||||
@@ -41,7 +41,7 @@
|
||||
return
|
||||
//we want to delay the effect to be displayed after the mob is petted, not before.
|
||||
switch(user.a_intent)
|
||||
if(INTENT_HARM, INTENT_DISARM)
|
||||
if(INTENT_HARM)
|
||||
addtimer(CALLBACK(src, .proc/kick_the_dog, source, user), 1)
|
||||
if(INTENT_HELP)
|
||||
addtimer(CALLBACK(src, .proc/pet_the_dog, source, user), 1)
|
||||
|
||||
@@ -5,16 +5,18 @@
|
||||
var/list/testmerge = list()
|
||||
|
||||
/datum/getrev/New()
|
||||
commit = rustg_git_revparse("HEAD")
|
||||
if(commit)
|
||||
date = rustg_git_commit_date(commit)
|
||||
originmastercommit = rustg_git_revparse("origin/master")
|
||||
|
||||
/datum/getrev/proc/load_tgs_info()
|
||||
testmerge = world.TgsTestMerges()
|
||||
var/datum/tgs_revision_information/revinfo = world.TgsRevision()
|
||||
if(revinfo)
|
||||
commit = revinfo.commit
|
||||
originmastercommit = revinfo.origin_commit
|
||||
else
|
||||
commit = rustg_git_revparse("HEAD")
|
||||
if(commit)
|
||||
date = rustg_git_commit_date(commit)
|
||||
originmastercommit = rustg_git_revparse("origin/master")
|
||||
date = rustg_git_commit_date(commit)
|
||||
|
||||
// goes to DD log and config_error.txt
|
||||
log_world(get_log_message())
|
||||
@@ -77,7 +79,9 @@
|
||||
msg += "No commit information"
|
||||
if(world.TgsAvailable())
|
||||
var/datum/tgs_version/version = world.TgsVersion()
|
||||
msg += "Server tools version: [version.raw_parameter]"
|
||||
msg += "TGS version: [version.raw_parameter]"
|
||||
var/datum/tgs_version/api_version = world.TgsApiVersion()
|
||||
msg += "DMAPI version: [api_version.raw_parameter]"
|
||||
|
||||
// Game mode odds
|
||||
msg += "<br><b>Current Informational Settings:</b>"
|
||||
@@ -121,4 +125,4 @@
|
||||
if(probabilities[ctag] > 0)
|
||||
var/percentage = round(probabilities[ctag] / sum * 100, 0.1)
|
||||
msg += "[ctag] [percentage]%"
|
||||
to_chat(src, msg.Join("<br>"))
|
||||
to_chat(src, msg.Join("<br>"))
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@
|
||||
var/datum/skill_holder/skill_holder
|
||||
|
||||
/datum/mind/New(var/key)
|
||||
skill_holder = new(src)
|
||||
skill_holder = new()
|
||||
src.key = key
|
||||
soulOwner = src
|
||||
martial_art = default_martial_art
|
||||
|
||||
@@ -248,7 +248,7 @@
|
||||
description = "<span class='boldwarning'>Something I recently ate was horrifyingly disgusting.</span>\n"
|
||||
mood_change = -5
|
||||
timeout = 5 MINUTES
|
||||
|
||||
|
||||
/datum/mood_event/nanite_sadness
|
||||
description = "<span class='warning robot'>+++++++HAPPINESS SUPPRESSION+++++++</span>\n"
|
||||
mood_change = -7
|
||||
@@ -256,3 +256,7 @@
|
||||
/datum/mood_event/nanite_sadness/add_effects(message)
|
||||
description = "<span class='warning robot'>+++++++[message]+++++++</span>\n"
|
||||
|
||||
/datum/mood_event/artbad
|
||||
description = "<span class='warning'>I've produced better art than that from my ass.</span>\n"
|
||||
mood_change = -2
|
||||
timeout = 1200
|
||||
|
||||
@@ -182,3 +182,17 @@
|
||||
description = "<span class='nicegreen'>What a peculiar emblem. It makes me feel hopeful for my future.</span>\n"
|
||||
mood_change = 5
|
||||
|
||||
/datum/mood_event/artok
|
||||
description = "<span class='nicegreen'>It's nice to see people are making art around here.</span>\n"
|
||||
mood_change = 2
|
||||
timeout = 2 MINUTES
|
||||
|
||||
/datum/mood_event/artgood
|
||||
description = "<span class='nicegreen'>What a thought-provoking piece of art. I'll remember that for a while.</span>\n"
|
||||
mood_change = 3
|
||||
timeout = 3 MINUTES
|
||||
|
||||
/datum/mood_event/artgreat
|
||||
description = "<span class='nicegreen'>That work of art was so great it made me believe in the goodness of humanity. Says a lot in a place like this.</span>\n"
|
||||
mood_change = 4
|
||||
timeout = 4 MINUTES
|
||||
|
||||
@@ -117,7 +117,8 @@
|
||||
owner.apply_overlay(layer_used)
|
||||
if(power)
|
||||
owner.RemoveSpell(power)
|
||||
qdel(src)
|
||||
qdel(power)
|
||||
SEND_SIGNAL(owner, COMSIG_HUMAN_MUTATION_LOSS, src)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
if(..())
|
||||
return
|
||||
ADD_TRAIT(owner, TRAIT_DWARF, GENETIC_MUTATION)
|
||||
owner.transform = owner.transform.Scale(1, 0.8)
|
||||
AddElement(/datum/element/dwarfism, COMSIG_HUMAN_MUTATION_LOSS, src)
|
||||
passtable_on(owner, GENETIC_MUTATION)
|
||||
owner.visible_message("<span class='danger'>[owner] suddenly shrinks!</span>", "<span class='notice'>Everything around you seems to grow..</span>")
|
||||
|
||||
|
||||
@@ -12,5 +12,5 @@
|
||||
to_chat(usr, "<span class='warning'>How do you check the skills of [(usr == src)? "yourself when you are" : "something"] without the capability for skills? (PROBABLY A BUG, PRESS F1.)</span>")
|
||||
return
|
||||
var/datum/browser/B = new(usr, "skilldisplay_[REF(src)]", "Skills of [src]")
|
||||
B.set_content(mind.skill_holder.html_readout())
|
||||
B.set_content(mind.skill_html_readout())
|
||||
B.open()
|
||||
|
||||
@@ -9,19 +9,10 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
|
||||
S = new path
|
||||
.[S.type] = S
|
||||
|
||||
/proc/sanitize_skill_value(path, value)
|
||||
var/datum/skill/S = GLOB.skill_datums[path]
|
||||
// don't check, if we runtime let it happen.
|
||||
return S.sanitize_value(value)
|
||||
|
||||
/proc/is_skill_value_greater(path, existing, new_value)
|
||||
var/datum/skill/S = GLOB.skill_datums[path]
|
||||
// don't check, if we runtime let it happen.
|
||||
return S.is_value_greater(existing, new_value)
|
||||
|
||||
/**
|
||||
* Skill datums
|
||||
*/
|
||||
|
||||
/datum/skill
|
||||
/// Our name
|
||||
var/name
|
||||
@@ -29,16 +20,20 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
|
||||
var/desc
|
||||
/// Color of the name as shown in the html readout
|
||||
var/name_color = "#F0F0F0" // White on dark surface.
|
||||
/// Our progression type
|
||||
/// Our progression type. These are mostly used to skip typechecks overhead, don't go around messing with these.
|
||||
var/progression_type
|
||||
/// Abstract type
|
||||
var/abstract_type = /datum/skill
|
||||
/// skill threshold used in generic skill modifiers calculations.
|
||||
var/list/competency_thresholds = list(0, 0, 0)
|
||||
/// Multiplier of the difference of the holder skill value and the selected threshold.
|
||||
var/list/competency_mults = list(0, 0, 0)
|
||||
/// In which way this skil can affect or be affected through actions.
|
||||
var/skill_flags = SKILL_USE_MOOD|SKILL_TRAIN_MOOD
|
||||
/// List of max levels. Only used in level skills, but present here for helper macros.
|
||||
var/max_levels = INFINITY
|
||||
/// skill threshold used in generic skill competency operations.
|
||||
var/list/competency_thresholds
|
||||
/// Base multiplier used in skill competency operations.
|
||||
var/base_multiplier = 1
|
||||
/// Value added to the base multiplier depending on overall competency compared to maximum value/level.
|
||||
var/competency_multiplier = 1
|
||||
/// A list of ways this skill can affect or be affected through actions and skill modifiers.
|
||||
var/list/skill_traits = list(SKILL_SANITY, SKILL_INTELLIGENCE)
|
||||
|
||||
/**
|
||||
* Ensures what someone's setting as a value for this skill is valid.
|
||||
@@ -73,8 +68,7 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
|
||||
/datum/skill/binary
|
||||
abstract_type = /datum/skill/binary
|
||||
progression_type = SKILL_PROGRESSION_BINARY
|
||||
competency_thresholds = list(FALSE, TRUE, TRUE)
|
||||
competency_mults = list(0.5, 0.5, 0.5)
|
||||
competency_thresholds = list(THRESHOLD_COMPETENT = FALSE, THRESHOLD_EXPERT = TRUE, THRESHOLD_MASTER = TRUE)
|
||||
|
||||
/datum/skill/binary/sanitize_value(new_value)
|
||||
return new_value? TRUE : FALSE
|
||||
@@ -85,6 +79,7 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
|
||||
/datum/skill/numerical
|
||||
abstract_type = /datum/skill/numerical
|
||||
progression_type = SKILL_PROGRESSION_NUMERICAL
|
||||
competency_thresholds = list(THRESHOLD_COMPETENT = 25, THRESHOLD_EXPERT = 50, THRESHOLD_MASTER = 75)
|
||||
/// Max value of this skill
|
||||
var/max_value = 100
|
||||
/// Min value of this skill
|
||||
@@ -114,9 +109,9 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
|
||||
/datum/skill/level
|
||||
abstract_type = /datum/skill/level
|
||||
progression_type = SKILL_PROGRESSION_LEVEL
|
||||
max_levels = STD_MAX_LVL
|
||||
var/standard_xp_lvl_up = STD_XP_LVL_UP //the standard required to level up. def: 100
|
||||
var/xp_lvl_multiplier = STD_XP_LVL_MULTI //standard required level up exp multiplier. def: 2 (100, 200, 400, 800 etc.)
|
||||
var/max_levels = STD_MAX_LVL
|
||||
var/level_up_method = STANDARD_LEVEL_UP //how levels are calculated.
|
||||
var/list/levels = list() //level thresholds, if associative, these will be preceded by tiers such as "novice" or "trained"
|
||||
var/associative = FALSE //See above.
|
||||
@@ -177,18 +172,17 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
|
||||
var/current_lvl_xp_sum = 0
|
||||
if(level)
|
||||
current_lvl_xp_sum = associative ? levels[levels[level]] : levels[level]
|
||||
var/next_index = max(max_levels, level+1)
|
||||
var/next_index = min(max_levels, level+1)
|
||||
var/next_lvl_xp = associative ? levels[levels[next_index]] : levels[next_index]
|
||||
if(next_lvl_xp > current_lvl_xp_sum)
|
||||
next_lvl_xp -= current_lvl_xp_sum
|
||||
|
||||
|
||||
return "[associative ? current_lvl : "Lvl. [current_lvl]"] ([value - current_lvl_xp_sum]/[next_lvl_xp])[level == max_levels ? " \[MAX!\]" : ""]"
|
||||
|
||||
/datum/skill/level/job
|
||||
abstract_type = /datum/skill/level/job
|
||||
levels = list("Basic", "Trained", "Experienced", "Master")
|
||||
competency_thresholds = list(JOB_SKILL_TRAINED, JOB_SKILL_EXPERT, JOB_SKILL_MASTER)
|
||||
competency_mults = list(0.15, 0.1, 0.1)
|
||||
competency_thresholds = list(THRESHOLD_COMPETENT = JOB_SKILL_TRAINED, THRESHOLD_EXPERT = JOB_SKILL_EXPERT, THRESHOLD_MASTER = JOB_SKILL_MASTER)
|
||||
associative = TRUE
|
||||
|
||||
//quite the reference, no?
|
||||
@@ -202,7 +196,6 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
|
||||
"Proficient", "Talented", "Adept", "Expert",
|
||||
"Professional", "Accomplished", "Great", "Master",
|
||||
"High Master", "Grand Master", "Legendary")
|
||||
competency_thresholds = list(DORF_SKILL_COMPETENT, DORF_SKILL_EXPERT, DORF_SKILL_MASTER)
|
||||
competency_mults = list(0.15, 0.1, 0.08)
|
||||
competency_thresholds = list(THRESHOLD_COMPETENT = DORF_SKILL_COMPETENT, THRESHOLD_EXPERT = DORF_SKILL_EXPERT, THRESHOLD_MASTER = DORF_SKILL_MASTER)
|
||||
associative = TRUE
|
||||
unskilled_tier = "Dabbling"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* Skill holder datums
|
||||
* All procs are tied to the mind, since they are always expected to have a skill holder anyway.
|
||||
*/
|
||||
/datum/skill_holder
|
||||
var/datum/mind/owner
|
||||
/// Our list of skills and values. Lazylist. Associative. Keys are datum typepaths to the skill.
|
||||
var/list/skills
|
||||
/// Same as [skills] but affinities, which are multiplied to increase amount when gaining skills.
|
||||
@@ -10,66 +10,87 @@
|
||||
/// Let's say we want to get a specific skill "level" without looping through a proc everytime.
|
||||
/// Only supported by skills with tiers or levels.
|
||||
var/list/skill_levels
|
||||
|
||||
/datum/skill_holder/New(datum/mind/M)
|
||||
. = ..()
|
||||
owner = M
|
||||
/// current skill modifiers lists, per value, affinity, level.
|
||||
var/list/skill_value_mods
|
||||
var/list/skill_affinity_mods
|
||||
var/list/skill_level_mods
|
||||
/// List of all current skill modifiers, so we don't add the same ones twice.
|
||||
var/list/all_current_skill_modifiers
|
||||
/// List of original values stored at the time a modifier with the MODIFIER_SKILL_ORIGIN_DIFF enabled was added.
|
||||
var/list/original_values
|
||||
var/list/original_affinities
|
||||
var/list/original_levels
|
||||
|
||||
/**
|
||||
* Grabs the value of a skill.
|
||||
*/
|
||||
/datum/skill_holder/proc/get_skill_value(skill)
|
||||
/datum/mind/proc/get_skill_value(skill, apply_modifiers = TRUE)
|
||||
if(!ispath(skill))
|
||||
CRASH("Invalid get_skill_value call. Use typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this.
|
||||
if(!skills)
|
||||
return null
|
||||
return skills[skill]
|
||||
if(!skill_holder.skills)
|
||||
. = 0
|
||||
else
|
||||
. = skill_holder.skills[skill] || 0
|
||||
if(apply_modifiers && skill_holder.skill_value_mods)
|
||||
var/L = LAZYACCESS(skill_holder.skill_value_mods, skill)
|
||||
for(var/k in L)
|
||||
var/datum/skill_modifier/M = GLOB.skill_modifiers[k]
|
||||
. = M.apply_modifier(., skill, skill_holder, MODIFIER_TARGET_VALUE)
|
||||
|
||||
/**
|
||||
* Grabs the level of a skill. Only supported by skills with tiers or levels.
|
||||
*/
|
||||
/datum/skill_holder/proc/get_skill_level(skill)
|
||||
/datum/mind/proc/get_skill_level(skill, apply_modifiers = TRUE, round = FALSE)
|
||||
if(!ispath(skill, /datum/skill))
|
||||
CRASH("Invalid get_skill_value call. Use skill typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this.
|
||||
if(!skill_levels)
|
||||
return 0
|
||||
return skill_levels[skill]
|
||||
if(!skill_holder.skill_levels)
|
||||
. = 0
|
||||
else
|
||||
. = skill_holder.skill_levels[skill] || 0
|
||||
if(apply_modifiers && skill_holder.skill_level_mods)
|
||||
var/L = LAZYACCESS(skill_holder.skill_level_mods, skill)
|
||||
for(var/k in L)
|
||||
var/datum/skill_modifier/M = GLOB.skill_modifiers[k]
|
||||
. = M.apply_modifier(., skill, skill_holder, MODIFIER_TARGET_LEVEL)
|
||||
. = SANITIZE_SKILL_LEVEL(skill, round ? round(., 1) : .)
|
||||
|
||||
/**
|
||||
* Grabs our affinity for a skill. !!This is a multiplier!!
|
||||
*/
|
||||
/datum/skill_holder/proc/get_skill_affinity(skill)
|
||||
/datum/mind/proc/get_skill_affinity(skill, apply_modifiers = TRUE)
|
||||
. = 1
|
||||
if(!ispath(skill, /datum/skill))
|
||||
CRASH("Invalid get_skill_affinity call. Use skill typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this.
|
||||
var/affinity = LAZYACCESS(skill_affinities, skill)
|
||||
var/affinity = LAZYACCESS(skill_holder.skill_affinities, skill)
|
||||
if(!isnull(affinity))
|
||||
. = affinity
|
||||
var/list/wrapped = list(.)
|
||||
SEND_SIGNAL(owner.current, COMSIG_MOB_SKILL_GET_AFFINITY, skill, wrapped)
|
||||
. = wrapped[1]
|
||||
if(apply_modifiers && skill_holder.skill_affinity_mods)
|
||||
var/L = LAZYACCESS(skill_holder.skill_affinity_mods, skill)
|
||||
for(var/k in L)
|
||||
var/datum/skill_modifier/M = GLOB.skill_modifiers[k]
|
||||
. = M.apply_modifier(., skill, skill_holder, MODIFIER_TARGET_AFFINITY)
|
||||
|
||||
|
||||
/**
|
||||
* Sets the value of a skill.
|
||||
*/
|
||||
/datum/skill_holder/proc/set_skill_value(skill, value, silent = FALSE)
|
||||
/datum/mind/proc/set_skill_value(skill, value, silent = FALSE)
|
||||
if(!ispath(skill, /datum/skill))
|
||||
CRASH("Invalid set_skill_value call. Use skill typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this.
|
||||
var/datum/skill/S = GLOB.skill_datums[skill]
|
||||
value = S.sanitize_value(value)
|
||||
if(!isnull(value))
|
||||
LAZYINITLIST(skills)
|
||||
S.set_skill_value(src, value, owner, silent)
|
||||
LAZYINITLIST(skill_holder.skills)
|
||||
S.set_skill_value(skill_holder, value, src, silent)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Boosts a skill to a value if not aobve
|
||||
*/
|
||||
/datum/skill_holder/proc/boost_skill_value_to(skill, value, silent = FALSE)
|
||||
var/current = get_skill_value(skill)
|
||||
if(!is_skill_value_greater(skill, current, value))
|
||||
/datum/mind/proc/boost_skill_value_to(skill, value, silent = FALSE, current)
|
||||
current = current || get_skill_value(skill, FALSE)
|
||||
if(!IS_SKILL_VALUE_GREATER(skill, current, value))
|
||||
return FALSE
|
||||
set_skill_value(skill, value, silent)
|
||||
return TRUE
|
||||
@@ -78,20 +99,20 @@
|
||||
* Automatic skill increase, multiplied by skill affinity if existing.
|
||||
* Only works if skill is numerical.
|
||||
*/
|
||||
/datum/skill_holder/proc/auto_gain_experience(skill, value, maximum, silent = FALSE)
|
||||
/datum/mind/proc/auto_gain_experience(skill, value, maximum, silent = FALSE)
|
||||
if(!ispath(skill, /datum/skill))
|
||||
CRASH("Invalid set_skill_value call. Use skill typepaths.")
|
||||
var/datum/skill/S = GLOB.skill_datums[skill]
|
||||
if(S.progression_type != SKILL_PROGRESSION_NUMERICAL && S.progression_type != SKILL_PROGRESSION_LEVEL)
|
||||
CRASH("You cannot auto increment a non numerical(experience skill!")
|
||||
var/current = get_skill_value(skill)
|
||||
var/current = get_skill_value(skill, FALSE)
|
||||
var/affinity = get_skill_affinity(skill)
|
||||
var/target_value = current + (value * affinity)
|
||||
if(maximum)
|
||||
target_value = max(target_value, maximum)
|
||||
target_value = min(target_value, maximum)
|
||||
if(target_value == maximum) //no more experience to gain, early return.
|
||||
return
|
||||
boost_skill_value_to(skill, target_value, silent)
|
||||
boost_skill_value_to(skill, target_value, silent, current)
|
||||
|
||||
/**
|
||||
* Generic value modifier proc that uses one skill.
|
||||
@@ -100,22 +121,23 @@
|
||||
* * threshold : The difficulty of the action, in short. Refer to __DEFINES/skills/defines.dm for the defines.
|
||||
* * modifier_is_multiplier : wheter the modifier is a multiplier or a divisor.
|
||||
*/
|
||||
/datum/skill_holder/proc/action_skills_mod(skill, value, threshold, modifier_is_multiplier = TRUE)
|
||||
var/mod
|
||||
/datum/mind/proc/action_skill_mod(skill, value, threshold, modifier_is_multiplier = TRUE)
|
||||
var/datum/skill/S = GLOB.skill_datums[skill]
|
||||
if(!S)
|
||||
return
|
||||
return value
|
||||
var/mod = S.base_multiplier
|
||||
switch(S.progression_type)
|
||||
if(SKILL_PROGRESSION_LEVEL)
|
||||
mod = LAZYACCESS(skill_levels, S.type)
|
||||
var/datum/skill/level/L = S
|
||||
var/skill_lvl = get_skill_level(L.type)
|
||||
mod += skill_lvl/(L.max_levels+max(L.competency_thresholds[threshold]-skill_lvl, 0))*L.competency_multiplier
|
||||
if(SKILL_PROGRESSION_NUMERICAL)
|
||||
var/datum/skill/numerical/N = S
|
||||
var/skill_val = get_skill_value(N.type)
|
||||
mod += skill_val/(N.max_value+max(N.competency_thresholds[threshold]-skill_val, 0))*N.competency_multiplier
|
||||
else
|
||||
mod = LAZYACCESS(skills, S.type)
|
||||
mod = (1+(mod-S.competency_thresholds[threshold])*S.competency_mults[threshold])
|
||||
|
||||
var/list/comsig_values = list(mod)
|
||||
SEND_SIGNAL(owner.current, COMSIG_MOB_ACTION_SKILL_MOD, args, comsig_values)
|
||||
mod = comsig_values[MOD_VALUES_SKILL_MOD]
|
||||
|
||||
var/comp_threshold = S.competency_thresholds[threshold]
|
||||
mod += (comp_threshold ? (get_skill_value(S.type) / comp_threshold) : get_skill_value(S.type))*S.competency_multiplier
|
||||
. = modifier_is_multiplier ? value*mod : value/mod
|
||||
|
||||
/**
|
||||
@@ -123,37 +145,40 @@
|
||||
* Args:
|
||||
* * item/I : the item used in this action. its used_skills list variable contains the skills exercised with it.
|
||||
* * value : the value to modify, may be a delay, damage, probability.
|
||||
* * flags : the required flags that each skill (either in I.used_skills or the skill datum skill_flags) must have to influence
|
||||
* * traits : the required traits each skill (either in I.used_skills or the skill datum skill_traits) must have to influence
|
||||
* * the value.
|
||||
* * bad_flags : the opposite of the above, skills that must not be present to impact the value.
|
||||
* * bad_traits : the opposite of the above.
|
||||
* * modifier_is_multiplier : wheter the modifier is a multiplier or a divisor.
|
||||
*/
|
||||
/datum/skill_holder/proc/item_action_skills_mod(obj/item/I, value, flags = NONE, bad_flags = NONE, modifier_is_multiplier = TRUE)
|
||||
/datum/mind/proc/item_action_skills_mod(obj/item/I, value, traits, bad_traits, modifier_is_multiplier = TRUE)
|
||||
. = value
|
||||
var/sum = 0
|
||||
var/divisor = 0
|
||||
var/list/checked_skills
|
||||
for(var/k in I.used_skills)
|
||||
var/datum/skill/S = GLOB.skill_datums[k]
|
||||
if(!S)
|
||||
continue
|
||||
var/our_flags = (I.used_skills[k]|S.skill_flags)
|
||||
if((flags && !(our_flags & flags)) || (bad_flags && our_flags & bad_flags))
|
||||
var/our_traits = S.skill_traits
|
||||
var/item_traits = I.used_skills[k]
|
||||
if(item_traits)
|
||||
our_traits |= item_traits
|
||||
if((traits && !(our_traits[traits] || length(our_traits & traits))) || (bad_traits && (our_traits[bad_traits] || length(our_traits & bad_traits))))
|
||||
continue
|
||||
var/mod
|
||||
var/mod = S.base_multiplier
|
||||
switch(S.progression_type)
|
||||
if(SKILL_PROGRESSION_LEVEL)
|
||||
mod = LAZYACCESS(skill_levels, S.type)
|
||||
var/datum/skill/level/L = S
|
||||
var/skill_lvl = get_skill_level(L.type)
|
||||
mod += skill_lvl/(L.max_levels+max(L.competency_thresholds[I.skill_difficulty]-skill_lvl, 0))*L.competency_multiplier
|
||||
if(SKILL_PROGRESSION_NUMERICAL)
|
||||
var/datum/skill/numerical/N = S
|
||||
var/skill_val = get_skill_value(N.type)
|
||||
mod += skill_val/(N.max_value+max(N.competency_thresholds[I.skill_difficulty]-skill_val, 0))*N.competency_multiplier
|
||||
else
|
||||
mod = LAZYACCESS(skills, S.type)
|
||||
sum += 1+(mod - S.competency_thresholds[I.skill_difficulty])*S.competency_mults[I.skill_difficulty]
|
||||
LAZYADD(checked_skills, S)
|
||||
|
||||
var/list/comsig_values = list(sum, divisor, checked_skills)
|
||||
SEND_SIGNAL(owner.current, COMSIG_MOB_ITEM_ACTION_SKILLS_MOD, args, comsig_values)
|
||||
sum = comsig_values[MOD_VALUES_ITEM_SKILLS_SUM]
|
||||
divisor = comsig_values[MOD_VALUES_ITEM_SKILLS_DIV]
|
||||
|
||||
var/comp_threshold = S.competency_thresholds[I.skill_difficulty]
|
||||
mod += (comp_threshold ? (get_skill_value(S.type) / comp_threshold) : get_skill_value(S.type))*S.competency_multiplier
|
||||
sum += mod
|
||||
divisor++
|
||||
if(divisor)
|
||||
. = modifier_is_multiplier ? value*(sum/divisor) : value/(sum/divisor)
|
||||
|
||||
@@ -161,11 +186,13 @@
|
||||
* Generates a HTML readout of our skills.
|
||||
* Port to tgui-next when?
|
||||
*/
|
||||
/datum/skill_holder/proc/html_readout()
|
||||
/datum/mind/proc/skill_html_readout()
|
||||
var/list/out = list("<center><h1>Skills</h1></center><hr>")
|
||||
out += "<table style=\"width:100%\"><tr><th><b>Skill</b><th><b>Value</b></tr>"
|
||||
for(var/path in skills)
|
||||
for(var/path in skill_holder.skills|skill_holder.skill_value_mods|skill_holder.skill_level_mods)
|
||||
var/datum/skill/S = GLOB.skill_datums[path]
|
||||
out += "<tr><td><font color='[S.name_color]'>[S.name]</font></td><td>[S.standard_render_value(skills[path], LAZYACCESS(skill_levels, path) || 0)]</td></tr>"
|
||||
var/skill_value = get_skill_value(path)
|
||||
var/skill_level = get_skill_level(path, round = TRUE)
|
||||
out += "<tr><td><font color='[S.name_color]'>[S.name]</font></td><td>[S.standard_render_value(skill_value, skill_level)]</td></tr>"
|
||||
out += "</table>"
|
||||
return out.Join("")
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
GLOBAL_LIST_EMPTY_TYPED(skill_modifiers, /datum/skill_modifier)
|
||||
GLOBAL_LIST_EMPTY(potential_skills_per_mod)
|
||||
GLOBAL_LIST_EMPTY(potential_mods_per_skill)
|
||||
|
||||
/**
|
||||
* Base skill modifier datum, used to modify a player skills without directly touching their values, levels and affinity
|
||||
* and cause lots of edge cases. These are fairly simple overall... make a subtype though, don't use this one.
|
||||
*/
|
||||
/datum/skill_modifier
|
||||
/// flags for this skill modifier.
|
||||
var/modifier_flags = NONE
|
||||
/// target skills, can be a specific skill typepath or a list of skill traits.
|
||||
var/target_skills = /datum/skill
|
||||
/// the GLOB.potential_skills_per_mod key generated on runtime. You shouldn't be var-editing it.
|
||||
var/target_skills_key
|
||||
/// The identifier key this skill modifier is associated with.
|
||||
var/identifier
|
||||
/// skill affinity modifier, can be a multiplier or addendum, depending on the modifier_flags.
|
||||
var/affinity_mod = 1
|
||||
/// skill value modifier, see above.
|
||||
var/value_mod = 1
|
||||
/// skill level modifier, see above.
|
||||
var/level_mod = 1
|
||||
/// Priority of this skill modifier compared to other ones.
|
||||
var/priority = MODIFIER_SKILL_PRIORITY_DEF
|
||||
|
||||
/datum/skill_modifier/New(id, register = FALSE)
|
||||
identifier = GET_SKILL_MOD_ID(type, id)
|
||||
if(id)
|
||||
var/former_id = identifier
|
||||
var/dupe = 0
|
||||
while(GLOB.skill_modifiers[identifier])
|
||||
identifier = "[former_id][++dupe]"
|
||||
|
||||
if(register)
|
||||
register()
|
||||
|
||||
/datum/skill_modifier/proc/register()
|
||||
if(GLOB.skill_modifiers[identifier])
|
||||
CRASH("Skill modifier identifier \"[identifier]\" already taken.")
|
||||
GLOB.skill_modifiers[identifier] = src
|
||||
if(ispath(target_skills))
|
||||
target_skills_key = target_skills
|
||||
var/list/mod_L = GLOB.potential_mods_per_skill[target_skills]
|
||||
if(!mod_L)
|
||||
mod_L = GLOB.potential_mods_per_skill[target_skills] = list()
|
||||
else
|
||||
BINARY_INSERT(identifier, mod_L, datum/skill_modifier, src, priority, COMPARE_VALUE)
|
||||
mod_L[identifier] = src
|
||||
GLOB.potential_skills_per_mod[target_skills_key] = list(target_skills)
|
||||
else //Should be a list.
|
||||
var/list/T = target_skills
|
||||
T = sortTim(target_skills, /proc/cmp_text_asc) //Sort the list contents alphabetically.
|
||||
target_skills_key = T.Join("-")
|
||||
var/list/L = GLOB.potential_skills_per_mod[target_skills_key]
|
||||
if(!L)
|
||||
L = list()
|
||||
for(var/path in GLOB.skill_datums)
|
||||
if(GLOB.skill_datums[path].skill_traits & target_skills)
|
||||
L += path
|
||||
GLOB.potential_skills_per_mod[target_skills_key] = L
|
||||
for(var/path in L)
|
||||
var/list/mod_L = GLOB.potential_mods_per_skill[path]
|
||||
if(!mod_L)
|
||||
mod_L = GLOB.potential_mods_per_skill[path] = list()
|
||||
else
|
||||
BINARY_INSERT(identifier, mod_L, datum/skill_modifier, src, priority, COMPARE_VALUE)
|
||||
mod_L[identifier] = src
|
||||
|
||||
/datum/skill_modifier/Destroy()
|
||||
for(var/path in GLOB.potential_skills_per_mod[target_skills_key])
|
||||
var/mod_L = GLOB.potential_mods_per_skill[path]
|
||||
mod_L -= identifier
|
||||
if(!length(mod_L))
|
||||
GLOB.potential_mods_per_skill -= path
|
||||
GLOB.skill_modifiers -= identifier
|
||||
return ..()
|
||||
|
||||
#define ADD_MOD_STEP(L, P, O, G) \
|
||||
var/__L = L[P];\
|
||||
if(!__L){\
|
||||
L[P] = list(id)\
|
||||
} else {\
|
||||
L[P] = GLOB.potential_mods_per_skill[P] & (__L + id)\
|
||||
}\
|
||||
if(M.modifier_flags & MODIFIER_SKILL_ORIGIN_DIFF){\
|
||||
LAZYADDASSOC(O, id, "[P]" = G)\
|
||||
}
|
||||
|
||||
/datum/mind/proc/add_skill_modifier(id)
|
||||
if(LAZYACCESS(skill_holder.all_current_skill_modifiers, id))
|
||||
return
|
||||
var/datum/skill_modifier/M = GLOB.skill_modifiers[id]
|
||||
if(!M)
|
||||
CRASH("Invalid add_skill_modifier id: [id].")
|
||||
if(M.modifier_flags & MODIFIER_SKILL_BODYBOUND && !current)
|
||||
CRASH("Body-bound skill modifier [M] was tried to be added to a mob-less mind.")
|
||||
|
||||
if(M.modifier_flags & MODIFIER_SKILL_VALUE)
|
||||
LAZYINITLIST(skill_holder.skill_value_mods)
|
||||
if(M.modifier_flags & MODIFIER_SKILL_AFFINITY)
|
||||
LAZYINITLIST(skill_holder.skill_affinity_mods)
|
||||
if(M.modifier_flags & MODIFIER_SKILL_LEVEL)
|
||||
LAZYINITLIST(skill_holder.skill_level_mods)
|
||||
for(var/path in GLOB.potential_skills_per_mod[M.target_skills_key])
|
||||
if(M.modifier_flags & MODIFIER_SKILL_VALUE)
|
||||
ADD_MOD_STEP(skill_holder.skill_value_mods, path, skill_holder.original_values, get_skill_value(path, FALSE))
|
||||
if(M.modifier_flags & MODIFIER_SKILL_AFFINITY)
|
||||
ADD_MOD_STEP(skill_holder.skill_affinity_mods, path, skill_holder.original_affinities, get_skill_affinity(path, FALSE))
|
||||
if(M.modifier_flags & MODIFIER_SKILL_LEVEL)
|
||||
ADD_MOD_STEP(skill_holder.skill_level_mods, path, skill_holder.original_levels, get_skill_level(path, FALSE))
|
||||
LAZYSET(skill_holder.all_current_skill_modifiers, id, TRUE)
|
||||
|
||||
if(M.modifier_flags & MODIFIER_SKILL_BODYBOUND)
|
||||
M.RegisterSignal(src, COMSIG_MIND_TRANSFER, /datum/skill_modifier.proc/on_mind_transfer)
|
||||
M.RegisterSignal(current, COMSIG_MOB_ON_NEW_MIND, /datum/skill_modifier.proc/on_mob_new_mind, TRUE)
|
||||
RegisterSignal(M, COMSIG_PARENT_PREQDELETED, .proc/on_skill_modifier_deletion)
|
||||
|
||||
#undef ADD_MOD_STEP
|
||||
|
||||
#define REMOVE_MOD_STEP(L, P, O)\
|
||||
LAZYREMOVEASSOC(L, P, id);\
|
||||
if(M.modifier_flags & MODIFIER_SKILL_ORIGIN_DIFF){\
|
||||
LAZYREMOVEASSOC(O, id, "[P]")\
|
||||
}
|
||||
|
||||
/datum/mind/proc/remove_skill_modifier(id, mind_transfer = FALSE)
|
||||
if(!LAZYACCESS(skill_holder.all_current_skill_modifiers, id))
|
||||
return
|
||||
var/datum/skill_modifier/M = GLOB.skill_modifiers[id]
|
||||
if(!M)
|
||||
CRASH("Invalid remove_skill_modifier id: [id].")
|
||||
|
||||
if(!skill_holder.skill_value_mods && !skill_holder.skill_affinity_mods && !skill_holder.skill_level_mods)
|
||||
return
|
||||
for(var/path in GLOB.potential_skills_per_mod[M.target_skills_key])
|
||||
if(M.modifier_flags & MODIFIER_SKILL_VALUE && skill_holder.skill_value_mods)
|
||||
REMOVE_MOD_STEP(skill_holder.skill_value_mods, path, skill_holder.original_values)
|
||||
if(M.modifier_flags & MODIFIER_SKILL_AFFINITY && skill_holder.skill_affinity_mods)
|
||||
REMOVE_MOD_STEP(skill_holder.skill_affinity_mods, path, skill_holder.original_affinities)
|
||||
if(M.modifier_flags & MODIFIER_SKILL_LEVEL && skill_holder.skill_level_mods)
|
||||
REMOVE_MOD_STEP(skill_holder.skill_level_mods, path, skill_holder.original_levels)
|
||||
LAZYREMOVE(skill_holder.all_current_skill_modifiers, id)
|
||||
|
||||
if(!mind_transfer && M.modifier_flags & MODIFIER_SKILL_BODYBOUND)
|
||||
M.UnregisterSignal(src, COMSIG_MIND_TRANSFER)
|
||||
M.UnregisterSignal(current, list(COMSIG_MOB_ON_NEW_MIND))
|
||||
UnregisterSignal(M, COMSIG_PARENT_PREQDELETED)
|
||||
|
||||
#undef REMOVE_MOD_STEP
|
||||
|
||||
/datum/mind/proc/on_skill_modifier_deletion(datum/skill_modifier/source)
|
||||
remove_skill_modifier(source.identifier)
|
||||
|
||||
/datum/skill_modifier/proc/apply_modifier(value, skillpath, datum/skill_holder/H, method = MODIFIER_TARGET_VALUE)
|
||||
. = value
|
||||
var/mod = value_mod
|
||||
switch(method)
|
||||
if(MODIFIER_TARGET_LEVEL)
|
||||
mod = level_mod
|
||||
if(MODIFIER_TARGET_AFFINITY)
|
||||
mod = affinity_mod
|
||||
|
||||
if(modifier_flags & MODIFIER_USE_THRESHOLDS && istext(mod))
|
||||
var/datum/skill/S = GLOB.skill_datums[skillpath]
|
||||
if(method == MODIFIER_TARGET_VALUE && S.progression_type == SKILL_PROGRESSION_LEVEL)
|
||||
var/datum/skill/level/L = S
|
||||
switch(L.level_up_method)
|
||||
if(STANDARD_LEVEL_UP)
|
||||
mod = XP_LEVEL(L.standard_xp_lvl_up, L.xp_lvl_multiplier, S.competency_thresholds[mod])
|
||||
if(DWARFY_LEVEL_UP)
|
||||
mod = DORF_XP_LEVEL(L.standard_xp_lvl_up, L.xp_lvl_multiplier, S.competency_thresholds[mod])
|
||||
else
|
||||
mod = S.competency_thresholds[mod]
|
||||
|
||||
var/diff = 0
|
||||
if(modifier_flags & (MODIFIER_SKILL_VIRTUE|MODIFIER_SKILL_HANDICAP))
|
||||
if(modifier_flags & MODIFIER_SKILL_VIRTUE)
|
||||
. = max(., mod)
|
||||
if(modifier_flags & MODIFIER_SKILL_HANDICAP)
|
||||
. = min(., mod)
|
||||
diff = . - mod
|
||||
else if(modifier_flags & MODIFIER_SKILL_MULT)
|
||||
. *= mod
|
||||
else
|
||||
. += mod
|
||||
|
||||
if(modifier_flags & MODIFIER_SKILL_ORIGIN_DIFF)
|
||||
var/list/to_access = H.original_values
|
||||
switch(method)
|
||||
if(MODIFIER_TARGET_LEVEL)
|
||||
to_access = H.original_levels
|
||||
if(MODIFIER_TARGET_AFFINITY)
|
||||
to_access = H.original_affinities
|
||||
. += value - diff - LAZYACCESS(to_access[identifier], "[skillpath]")
|
||||
|
||||
///Body bound modifier signal procs.
|
||||
/datum/skill_modifier/proc/on_mind_transfer(datum/mind/source, mob/new_character, mob/old_character)
|
||||
source.remove_skill_modifier(identifier, TRUE)
|
||||
UnregisterSignal(source, COMSIG_MIND_TRANSFER)
|
||||
|
||||
/datum/skill_modifier/proc/on_mob_new_mind(mob/source)
|
||||
source.mind.add_skill_modifier(identifier)
|
||||
RegisterSignal(source.mind, COMSIG_MIND_TRANSFER, /datum/skill_modifier.proc/on_mind_transfer)
|
||||
@@ -2,5 +2,4 @@
|
||||
name = "Wiring"
|
||||
desc = "How proficient and knowledged you are at wiring beyond laying cables on the floor."
|
||||
name_color = COLOR_PALE_ORANGE
|
||||
competency_thresholds = list(JOB_SKILL_BASIC, JOB_SKILL_EXPERT, JOB_SKILL_MASTER)
|
||||
skill_flags = SKILL_USE_MOOD|SKILL_TRAIN_MOOD|SKILL_USE_TOOL|SKILL_TRAINING_TOOL
|
||||
skill_traits = list(SKILL_SANITY, SKILL_INTELLIGENCE, SKILL_USE_TOOL, SKILL_TRAINING_TOOL)
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
name = "Surgery"
|
||||
desc = "How proficient you are at doing surgery."
|
||||
name_color = COLOR_PALE_BLUE_GRAY
|
||||
competency_mults = list(0.025, 0.025, 0.025) // 60% surgery speed up at max value of 100.
|
||||
competency_multiplier = 1.5 // 60% surgery speed up at max value of 100, considering the base multiplier.
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/// Jobbie skill modifiers.
|
||||
|
||||
/datum/skill_modifier/job
|
||||
modifier_flags = MODIFIER_SKILL_VALUE|MODIFIER_SKILL_VIRTUE|MODIFIER_SKILL_ORIGIN_DIFF
|
||||
priority = MODIFIER_SKILL_PRIORITY_MAX
|
||||
|
||||
/datum/skill_modifier/job/surgery
|
||||
target_skills = /datum/skill/numerical/surgery
|
||||
value_mod = STARTING_SKILL_SURGERY_MEDICAL
|
||||
|
||||
/datum/skill_modifier/job/affinity
|
||||
modifier_flags = MODIFIER_SKILL_AFFINITY|MODIFIER_SKILL_VIRTUE
|
||||
affinity_mod = STARTING_SKILL_AFFINITY_DEF_JOB
|
||||
|
||||
/datum/skill_modifier/job/affinity/surgery
|
||||
target_skills = /datum/skill/numerical/surgery
|
||||
|
||||
/datum/skill_modifier/job/affinity/wiring
|
||||
target_skills = /datum/skill/level/job/wiring
|
||||
|
||||
/// Level skill modifiers below.
|
||||
/datum/skill_modifier/job/level
|
||||
modifier_flags = MODIFIER_SKILL_VALUE|MODIFIER_SKILL_LEVEL|MODIFIER_SKILL_VIRTUE|MODIFIER_SKILL_ORIGIN_DIFF
|
||||
level_mod = JOB_SKILL_TRAINED
|
||||
|
||||
/datum/skill_modifier/job/level/New(id)
|
||||
if(level_mod)
|
||||
value_mod = GET_STANDARD_LVL(level_mod)
|
||||
..()
|
||||
|
||||
/datum/skill_modifier/job/level/wiring
|
||||
target_skills = /datum/skill/level/job/wiring
|
||||
|
||||
/datum/skill_modifier/job/level/wiring/basic
|
||||
level_mod = JOB_SKILL_BASIC
|
||||
@@ -0,0 +1,8 @@
|
||||
/datum/skill_modifier/bad_mood
|
||||
modifier_flags = MODIFIER_SKILL_VALUE|MODIFIER_SKILL_LEVEL|MODIFIER_SKILL_MULT|MODIFIER_SKILL_BODYBOUND
|
||||
target_skills = list(SKILL_SANITY)
|
||||
|
||||
/datum/skill_modifier/great_mood
|
||||
modifier_flags = MODIFIER_SKILL_AFFINITY|MODIFIER_SKILL_MULT|MODIFIER_SKILL_BODYBOUND
|
||||
target_skills = list(SKILL_SANITY)
|
||||
affinity_mod = 1.2
|
||||
@@ -0,0 +1,13 @@
|
||||
/datum/skill_modifier/brain_damage
|
||||
target_skills = list(SKILL_INTELLIGENCE)
|
||||
modifier_flags = MODIFIER_SKILL_VALUE|MODIFIER_SKILL_AFFINITY|MODIFIER_SKILL_LEVEL|MODIFIER_SKILL_MULT|MODIFIER_SKILL_BODYBOUND
|
||||
value_mod = 0.85
|
||||
level_mod = 0.85
|
||||
affinity_mod = 0.85
|
||||
|
||||
/datum/skill_modifier/heavy_brain_damage
|
||||
target_skills = list(SKILL_INTELLIGENCE)
|
||||
modifier_flags = MODIFIER_SKILL_VALUE|MODIFIER_SKILL_AFFINITY|MODIFIER_SKILL_LEVEL|MODIFIER_SKILL_BODYBOUND|MODIFIER_SKILL_HANDICAP|MODIFIER_USE_THRESHOLDS
|
||||
priority = MODIFIER_SKILL_PRIORITY_LOW
|
||||
value_mod = THRESHOLD_COMPETENT
|
||||
level_mod = THRESHOLD_COMPETENT
|
||||
@@ -0,0 +1,20 @@
|
||||
/datum/tgs_event_handler/impl/HandleEvent(event_code, ...)
|
||||
switch(event_code)
|
||||
if(TGS_EVENT_REBOOT_MODE_CHANGE)
|
||||
var/list/reboot_mode_lookup = list ("[TGS_REBOOT_MODE_NORMAL]" = "be normal", "[TGS_REBOOT_MODE_SHUTDOWN]" = "shutdown the server", "[TGS_REBOOT_MODE_RESTART]" = "hard restart the server")
|
||||
var old_reboot_mode = args[2]
|
||||
var new_reboot_mode = args[3]
|
||||
message_admins("TGS: Reboot will no longer [reboot_mode_lookup["[old_reboot_mode]"]], it will instead [reboot_mode_lookup["[new_reboot_mode]"]]")
|
||||
if(TGS_EVENT_PORT_SWAP)
|
||||
message_admins("TGS: Changing port from [world.port] to [args[2]]")
|
||||
if(TGS_EVENT_INSTANCE_RENAMED)
|
||||
message_admins("TGS: Instance renamed to from [world.TgsInstanceName()] to [args[2]]")
|
||||
if(TGS_EVENT_COMPILE_START)
|
||||
message_admins("TGS: Deployment started, new game version incoming...")
|
||||
if(TGS_EVENT_COMPILE_CANCELLED)
|
||||
message_admins("TGS: Deployment cancelled!")
|
||||
if(TGS_EVENT_COMPILE_FAILURE)
|
||||
message_admins("TGS: Deployment failed!")
|
||||
if(TGS_EVENT_DEPLOYMENT_COMPLETE)
|
||||
message_admins("TGS: Deployment complete!")
|
||||
to_chat(world, "<span class='boldannounce'>Server updated, changes will be applied on the next round...</span>")
|
||||
@@ -138,7 +138,7 @@
|
||||
if(current_users[user])
|
||||
return FALSE
|
||||
if(req_skill && user?.mind)
|
||||
var/level_diff = req_skill - user.mind.skill_holder.get_skill_level(/datum/skill/level/job/wiring)
|
||||
var/level_diff = req_skill - user.mind.get_skill_level(/datum/skill/level/job/wiring, round = TRUE)
|
||||
if(level_diff > 0)
|
||||
LAZYSET(current_users, user, TRUE)
|
||||
to_chat(user, "<span class='notice'>You begin cutting [holder]'s [color] wire...</span>")
|
||||
@@ -167,7 +167,7 @@
|
||||
if(current_users[user])
|
||||
return FALSE
|
||||
if(req_skill && user?.mind)
|
||||
var/level_diff = req_skill - user.mind.skill_holder.get_skill_level(/datum/skill/level/job/wiring)
|
||||
var/level_diff = req_skill - user.mind.get_skill_level(/datum/skill/level/job/wiring, round = TRUE)
|
||||
if(level_diff > 0)
|
||||
LAZYSET(current_users, user, TRUE)
|
||||
to_chat(user, "<span class='notice'>You begin pulsing [holder]'s [color] wire...</span>")
|
||||
@@ -255,7 +255,7 @@
|
||||
var/reveal_wires = FALSE
|
||||
|
||||
// Admin ghost can see a purpose of each wire.
|
||||
if(IsAdminGhost(user) || user.mind.skill_holder.get_skill_level(/datum/skill/level/job/wiring) >= req_knowledge)
|
||||
if(IsAdminGhost(user) || user.mind.get_skill_level(/datum/skill/level/job/wiring) >= req_knowledge)
|
||||
reveal_wires = TRUE
|
||||
|
||||
// Same for anyone with an abductor multitool.
|
||||
|
||||
@@ -129,7 +129,26 @@
|
||||
icon_state = "crew_quarters"
|
||||
|
||||
|
||||
//Ruin of Space Diner
|
||||
|
||||
/area/ruin/space/diner
|
||||
name = "Space Diner"
|
||||
|
||||
/area/ruin/space/diner/interior
|
||||
name = "Space Diner"
|
||||
icon_state = "maintbar"
|
||||
has_gravity = STANDARD_GRAVITY
|
||||
blob_allowed = FALSE //Nope, no winning in the diner as a blob. Gotta eat the main station.
|
||||
|
||||
/area/ruin/space/diner/solars
|
||||
requires_power = FALSE
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_IFSTARLIGHT
|
||||
valid_territory = FALSE
|
||||
blob_allowed = FALSE
|
||||
flags_1 = NONE
|
||||
ambientsounds = ENGINEERING
|
||||
name = "Space Diner Solar Array"
|
||||
icon_state = "yellow"
|
||||
|
||||
//Ruin of Derelict Oupost
|
||||
|
||||
|
||||
+12
-4
@@ -581,6 +581,14 @@
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_RCD_ACT, user, the_rcd, passed_mode)
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Respond to a electric bolt action on our item
|
||||
*
|
||||
* Default behaviour is to return, we define here to allow for cleaner code later on
|
||||
*/
|
||||
/atom/proc/zap_act(power, zap_flags, shocked_targets)
|
||||
return
|
||||
|
||||
/atom/proc/storage_contents_dump_act(obj/item/storage/src_object, mob/user)
|
||||
if(GetComponent(/datum/component/storage))
|
||||
return component_storage_contents_dump_act(src_object, user)
|
||||
@@ -932,14 +940,14 @@ Proc for attack log creation, because really why not
|
||||
target.log_message(reverse_message, LOG_ATTACK, color="orange", log_globally=FALSE)
|
||||
|
||||
// Filter stuff
|
||||
/atom/movable/proc/add_filter(name,priority,list/params)
|
||||
/atom/proc/add_filter(name,priority,list/params)
|
||||
LAZYINITLIST(filter_data)
|
||||
var/list/p = params.Copy()
|
||||
p["priority"] = priority
|
||||
filter_data[name] = p
|
||||
update_filters()
|
||||
|
||||
/atom/movable/proc/update_filters()
|
||||
/atom/proc/update_filters()
|
||||
filters = null
|
||||
filter_data = sortTim(filter_data, /proc/cmp_filter_data_priority, TRUE)
|
||||
for(var/f in filter_data)
|
||||
@@ -948,11 +956,11 @@ Proc for attack log creation, because really why not
|
||||
arguments -= "priority"
|
||||
filters += filter(arglist(arguments))
|
||||
|
||||
/atom/movable/proc/get_filter(name)
|
||||
/atom/proc/get_filter(name)
|
||||
if(filter_data && filter_data[name])
|
||||
return filters[filter_data.Find(name)]
|
||||
|
||||
/atom/movable/proc/remove_filter(name)
|
||||
/atom/proc/remove_filter(name)
|
||||
if(filter_data && filter_data[name])
|
||||
filter_data -= name
|
||||
update_filters()
|
||||
|
||||
+18
-16
@@ -37,6 +37,8 @@
|
||||
var/throwforce = 0
|
||||
var/datum/component/orbiter/orbiting
|
||||
var/can_be_z_moved = TRUE
|
||||
///If we were without gravity and another animation happened, the bouncing will stop, and we need to restart it in next life().
|
||||
var/floating_need_update = FALSE
|
||||
|
||||
var/zfalling = FALSE
|
||||
|
||||
@@ -56,10 +58,6 @@
|
||||
em_block = new(src, render_target)
|
||||
vis_contents += em_block
|
||||
|
||||
/atom/movable/Destroy()
|
||||
QDEL_NULL(em_block)
|
||||
return ..()
|
||||
|
||||
/atom/movable/proc/update_emissive_block()
|
||||
if(blocks_emissive != EMISSIVE_BLOCK_GENERIC)
|
||||
return
|
||||
@@ -183,14 +181,15 @@
|
||||
return TRUE
|
||||
|
||||
/atom/movable/proc/stop_pulling()
|
||||
if(pulling)
|
||||
pulling.pulledby = null
|
||||
var/mob/living/ex_pulled = pulling
|
||||
pulling = null
|
||||
setGrabState(0)
|
||||
if(isliving(ex_pulled))
|
||||
var/mob/living/L = ex_pulled
|
||||
L.update_mobility()// mob gets up if it was lyng down in a chokehold
|
||||
if(!pulling)
|
||||
return
|
||||
pulling.pulledby = null
|
||||
var/mob/living/ex_pulled = pulling
|
||||
pulling = null
|
||||
setGrabState(0)
|
||||
if(isliving(ex_pulled))
|
||||
var/mob/living/L = ex_pulled
|
||||
L.update_mobility()// mob gets up if it was lyng down in a chokehold
|
||||
|
||||
/atom/movable/proc/Move_Pulled(atom/A)
|
||||
if(!pulling)
|
||||
@@ -232,10 +231,12 @@
|
||||
/atom/movable/Destroy(force)
|
||||
QDEL_NULL(proximity_monitor)
|
||||
QDEL_NULL(language_holder)
|
||||
QDEL_NULL(em_block)
|
||||
|
||||
unbuckle_all_mobs(force=1)
|
||||
|
||||
. = ..()
|
||||
|
||||
if(loc)
|
||||
//Restore air flow if we were blocking it (movables with ATMOS_PASS_PROC will need to do this manually if necessary)
|
||||
if(((CanAtmosPass == ATMOS_PASS_DENSITY && density) || CanAtmosPass == ATMOS_PASS_NO) && isturf(loc))
|
||||
@@ -493,15 +494,16 @@
|
||||
/atom/movable/proc/float(on)
|
||||
if(throwing)
|
||||
return
|
||||
if(on && !(movement_type & FLOATING))
|
||||
if(on && (!(movement_type & FLOATING) || floating_need_update))
|
||||
animate(src, pixel_y = pixel_y + 2, time = 10, loop = -1)
|
||||
sleep(10)
|
||||
animate(src, pixel_y = pixel_y - 2, time = 10, loop = -1)
|
||||
setMovetype(movement_type | FLOATING)
|
||||
else if (!on && (movement_type & FLOATING))
|
||||
if(!(movement_type & FLOATING))
|
||||
setMovetype(movement_type | FLOATING)
|
||||
else if (!on && movement_type & FLOATING)
|
||||
animate(src, pixel_y = initial(pixel_y), time = 10)
|
||||
setMovetype(movement_type & ~FLOATING)
|
||||
|
||||
floating_need_update = FALSE
|
||||
|
||||
/* Language procs
|
||||
* Unless you are doing something very specific, these are the ones you want to use.
|
||||
|
||||
@@ -48,9 +48,6 @@
|
||||
/obj/machinery/dominator/hulk_damage()
|
||||
return (max_integrity - integrity_failure) / DOM_HULK_HITS_REQUIRED
|
||||
|
||||
/obj/machinery/dominator/tesla_act()
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/dominator/update_icon()
|
||||
cut_overlays()
|
||||
if(stat & BROKEN)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/obj/effect/decal/cleanable/crayon/gang
|
||||
icon = 'icons/effects/crayondecal.dmi'
|
||||
layer = ABOVE_NORMAL_TURF_LAYER //Harder to hide
|
||||
plane = GAME_PLANE
|
||||
plane = ABOVE_WALL_PLANE
|
||||
do_icon_rotate = FALSE //These are designed to always face south, so no rotation please.
|
||||
var/datum/team/gang/gang
|
||||
|
||||
|
||||
@@ -37,6 +37,11 @@
|
||||
reset_chem_buttons()
|
||||
RefreshParts()
|
||||
add_inital_chems()
|
||||
new_occupant_dir = dir
|
||||
|
||||
/obj/machinery/sleeper/setDir(newdir)
|
||||
. = ..()
|
||||
new_occupant_dir = dir
|
||||
|
||||
/obj/machinery/sleeper/on_deconstruction()
|
||||
var/obj/item/reagent_containers/sleeper_buffer/buffer = new (loc)
|
||||
|
||||
@@ -110,7 +110,8 @@ Class Procs:
|
||||
var/state_open = FALSE
|
||||
var/critical_machine = FALSE //If this machine is critical to station operation and should have the area be excempted from power failures.
|
||||
var/list/occupant_typecache //if set, turned into typecache in Initialize, other wise, defaults to mob/living typecache
|
||||
var/atom/movable/occupant = null
|
||||
var/atom/movable/occupant
|
||||
var/new_occupant_dir = SOUTH //The direction the occupant will be set to look at when entering the machine.
|
||||
var/speed_process = FALSE // Process as fast as possible?
|
||||
var/obj/item/circuitboard/circuit // Circuit to be created and inserted when the machinery is created
|
||||
// For storing and overriding ui id and dimensions
|
||||
@@ -217,6 +218,7 @@ Class Procs:
|
||||
if(target && !target.has_buckled_mobs() && (!isliving(target) || !mobtarget.buckled))
|
||||
occupant = target
|
||||
target.forceMove(src)
|
||||
target.setDir(new_occupant_dir)
|
||||
updateUsrDialog()
|
||||
update_icon()
|
||||
|
||||
@@ -520,11 +522,11 @@ Class Procs:
|
||||
/obj/machinery/proc/can_be_overridden()
|
||||
. = 1
|
||||
|
||||
/obj/machinery/tesla_act(power, tesla_flags, shocked_objects)
|
||||
..()
|
||||
if(prob(85) && (tesla_flags & TESLA_MACHINE_EXPLOSIVE))
|
||||
/obj/machinery/zap_act(power, zap_flags, shocked_objects)
|
||||
. = ..()
|
||||
if(prob(85) && (zap_flags & ZAP_MACHINE_EXPLOSIVE))
|
||||
explosion(src, 1, 2, 4, flame_range = 2, adminlog = FALSE, smoke = FALSE)
|
||||
if(tesla_flags & TESLA_OBJ_DAMAGE)
|
||||
else if(zap_flags & ZAP_OBJ_DAMAGE)
|
||||
take_damage(power/2000, BURN, "energy")
|
||||
if(prob(40))
|
||||
emp_act(EMP_LIGHT)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
desc = "A remote control switch."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "doorctrl"
|
||||
plane = ABOVE_WALL_PLANE
|
||||
var/skin = "doorctrl"
|
||||
power_channel = ENVIRON
|
||||
var/obj/item/assembly/device
|
||||
@@ -17,7 +18,7 @@
|
||||
|
||||
/obj/machinery/button/Initialize(mapload, ndir = 0, built = 0)
|
||||
if(istext(id) && mapload)
|
||||
if(copytext(id, 1, 2) == "!")
|
||||
if(id[1] == "!")
|
||||
id = SSmapping.get_obfuscated_id(id)
|
||||
. = ..()
|
||||
if(built)
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
desc = "Used for watching an empty arena."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "telescreen"
|
||||
layer = SIGN_LAYER
|
||||
plane = ABOVE_WALL_PLANE
|
||||
network = list("thunder")
|
||||
density = FALSE
|
||||
circuit = null
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
if((isnull(user) || istype(user)) && state_open && !panel_open)
|
||||
..(user)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
investigate_log("Cryogenics machine closed with occupant [key_name(occupant)] by user [key_name(user)].", INVESTIGATE_CRYOGENICS)
|
||||
if(mob_occupant && mob_occupant.stat != DEAD)
|
||||
to_chat(occupant, "<span class='boldnotice'>You feel cool air surround you. You go numb as your senses turn inward.</span>")
|
||||
if(mob_occupant.client)//if they're logged in
|
||||
@@ -251,12 +252,15 @@
|
||||
icon_state = "cryopod"
|
||||
|
||||
/obj/machinery/cryopod/open_machine()
|
||||
if(occupant)
|
||||
investigate_log("Cryogenics machine opened with occupant [key_name(occupant)] inside.", INVESTIGATE_CRYOGENICS)
|
||||
..()
|
||||
icon_state = "cryopod-open"
|
||||
density = TRUE
|
||||
name = initial(name)
|
||||
|
||||
/obj/machinery/cryopod/container_resist(mob/living/user)
|
||||
investigate_log("Cryogenics machine container resisted by [key_name(user)] with occupant [key_name(occupant)].", INVESTIGATE_CRYOGENICS)
|
||||
visible_message("<span class='notice'>[occupant] emerges from [src]!</span>",
|
||||
"<span class='notice'>You climb out of [src]!</span>")
|
||||
open_machine()
|
||||
@@ -304,6 +308,8 @@
|
||||
|
||||
var/mob/living/mob_occupant = occupant
|
||||
var/list/obj/item/cryo_items = list()
|
||||
|
||||
investigate_log("Despawning [key_name(mob_occupant)].", INVESTIGATE_CRYOGENICS)
|
||||
|
||||
//Handle Borg stuff first
|
||||
if(iscyborg(mob_occupant))
|
||||
|
||||
@@ -474,15 +474,15 @@
|
||||
if(welded)
|
||||
weld_overlay = get_airlock_overlay("welded", overlays_file)
|
||||
if(obj_integrity < integrity_failure * max_integrity)
|
||||
damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE)
|
||||
else if(obj_integrity < (0.75 * max_integrity))
|
||||
damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE)
|
||||
if(lights && hasPower())
|
||||
|
||||
if(locked)
|
||||
lights_overlay = get_airlock_overlay("lights_bolts", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
lights_overlay = get_airlock_overlay("lights_bolts", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE)
|
||||
else if(emergency)
|
||||
lights_overlay = get_airlock_overlay("lights_emergency", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
lights_overlay = get_airlock_overlay("lights_emergency", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE)
|
||||
if(note)
|
||||
note_overlay = get_airlock_overlay(notetype, note_overlay_file)
|
||||
|
||||
@@ -500,18 +500,18 @@
|
||||
else
|
||||
panel_overlay = get_airlock_overlay("panel_closed", overlays_file)
|
||||
if(obj_integrity < integrity_failure * max_integrity)
|
||||
damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE)
|
||||
else if(obj_integrity < (0.75 * max_integrity))
|
||||
damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE)
|
||||
if(welded)
|
||||
weld_overlay = get_airlock_overlay("welded", overlays_file)
|
||||
lights_overlay = get_airlock_overlay("lights_denied", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
lights_overlay = get_airlock_overlay("lights_denied", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE)
|
||||
if(note)
|
||||
note_overlay = get_airlock_overlay(notetype, note_overlay_file)
|
||||
|
||||
if(AIRLOCK_EMAG)
|
||||
frame_overlay = get_airlock_overlay("closed", icon)
|
||||
sparks_overlay = get_airlock_overlay("sparks", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
sparks_overlay = get_airlock_overlay("sparks", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE)
|
||||
if(airlock_material)
|
||||
filling_overlay = get_airlock_overlay("[airlock_material]_closed", overlays_file)
|
||||
else
|
||||
@@ -522,9 +522,9 @@
|
||||
else
|
||||
panel_overlay = get_airlock_overlay("panel_closed", overlays_file)
|
||||
if(obj_integrity < integrity_failure * max_integrity)
|
||||
damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE)
|
||||
else if(obj_integrity < (0.75 * max_integrity))
|
||||
damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE)
|
||||
if(welded)
|
||||
weld_overlay = get_airlock_overlay("welded", overlays_file)
|
||||
if(note)
|
||||
@@ -537,7 +537,7 @@
|
||||
else
|
||||
filling_overlay = get_airlock_overlay("fill_closing", icon)
|
||||
if(lights && hasPower())
|
||||
lights_overlay = get_airlock_overlay("lights_closing", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
lights_overlay = get_airlock_overlay("lights_closing", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE)
|
||||
if(panel_open)
|
||||
if(security_level)
|
||||
panel_overlay = get_airlock_overlay("panel_closing_protected", overlays_file)
|
||||
@@ -558,7 +558,7 @@
|
||||
else
|
||||
panel_overlay = get_airlock_overlay("panel_open", overlays_file)
|
||||
if(obj_integrity < (0.75 * max_integrity))
|
||||
damag_overlay = get_airlock_overlay("sparks_open", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
damag_overlay = get_airlock_overlay("sparks_open", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE)
|
||||
if(note)
|
||||
note_overlay = get_airlock_overlay("[notetype]_open", note_overlay_file)
|
||||
|
||||
@@ -569,7 +569,7 @@
|
||||
else
|
||||
filling_overlay = get_airlock_overlay("fill_opening", icon)
|
||||
if(lights && hasPower())
|
||||
lights_overlay = get_airlock_overlay("lights_opening", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
lights_overlay = get_airlock_overlay("lights_opening", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE)
|
||||
if(panel_open)
|
||||
if(security_level)
|
||||
panel_overlay = get_airlock_overlay("panel_opening_protected", overlays_file)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
icon = 'icons/obj/status_display.dmi'
|
||||
icon_state = "frame"
|
||||
desc = "A remote control for a door."
|
||||
plane = ABOVE_WALL_PLANE
|
||||
req_access = list(ACCESS_SECURITY)
|
||||
density = FALSE
|
||||
var/id // id of linked machinery/lockers
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
/obj/machinery/embedded_controller/radio/simple_vent_controller
|
||||
icon = 'icons/obj/airlock_machines.dmi'
|
||||
icon_state = "airlock_control_standby"
|
||||
|
||||
plane = ABOVE_WALL_PLANE
|
||||
name = "vent controller"
|
||||
density = FALSE
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
desc = "<i>\"Pull this in case of emergency\"</i>. Thus, keep pulling it forever."
|
||||
icon = 'icons/obj/monitors.dmi'
|
||||
icon_state = "fire0"
|
||||
plane = ABOVE_WALL_PLANE
|
||||
max_integrity = 250
|
||||
integrity_failure = 0.4
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 30)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
desc = "A wall-mounted flashbulb device."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "mflash1"
|
||||
plane = ABOVE_WALL_PLANE
|
||||
max_integrity = 250
|
||||
integrity_failure = 0.4
|
||||
light_color = LIGHT_COLOR_WHITE
|
||||
@@ -20,6 +21,7 @@
|
||||
name = "portable flasher"
|
||||
desc = "A portable flashing device. Wrench to activate and deactivate. Cannot detect slow movements."
|
||||
icon_state = "pflash1-p"
|
||||
plane = GAME_PLANE
|
||||
strength = 80
|
||||
anchored = FALSE
|
||||
base_state = "pflash"
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
. = ..()
|
||||
if(prob(1))
|
||||
name = "auto-autopsy"
|
||||
new_occupant_dir = dir
|
||||
|
||||
/obj/machinery/harvester/setDir(newdir)
|
||||
. = ..()
|
||||
new_occupant_dir = dir
|
||||
|
||||
/obj/machinery/harvester/RefreshParts()
|
||||
interval = 0
|
||||
|
||||
@@ -34,7 +34,7 @@ GLOBAL_LIST_EMPTY(network_holopads)
|
||||
desc = "It's a floor-mounted device for projecting holographic images."
|
||||
icon_state = "holopad0"
|
||||
layer = LOW_OBJ_LAYER
|
||||
plane = FLOOR_PLANE
|
||||
plane = ABOVE_WALL_PLANE
|
||||
flags_1 = HEAR_1
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 5
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
name = "light switch"
|
||||
icon = 'icons/obj/power.dmi'
|
||||
icon_state = "light1"
|
||||
plane = ABOVE_WALL_PLANE
|
||||
desc = "Make dark."
|
||||
var/on = TRUE
|
||||
var/area/area = null
|
||||
|
||||
@@ -16,6 +16,7 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
desc = "A console intended to send requests to different departments on the station."
|
||||
icon = 'icons/obj/terminals.dmi'
|
||||
icon_state = "req_comp0"
|
||||
plane = ABOVE_WALL_PLANE
|
||||
var/department = "Unknown" //The list of all departments on the station (Determined from this variable on each unit) Set this to the same thing if you want several consoles in one department
|
||||
var/list/messages = list() //List of all messages
|
||||
var/departmentType = 0
|
||||
|
||||
@@ -115,8 +115,8 @@
|
||||
return PROCESS_KILL
|
||||
|
||||
/obj/machinery/space_heater/RefreshParts()
|
||||
var/laser = 0
|
||||
var/cap = 0
|
||||
var/laser = 2
|
||||
var/cap = 1
|
||||
for(var/obj/item/stock_parts/micro_laser/M in component_parts)
|
||||
laser += M.rating
|
||||
for(var/obj/item/stock_parts/capacitor/M in component_parts)
|
||||
@@ -166,6 +166,11 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/space_heater/wrench_act(mob/living/user, obj/item/I)
|
||||
..()
|
||||
default_unfasten_wrench(user, I, 5)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/space_heater/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
desc = null
|
||||
icon = 'icons/obj/status_display.dmi'
|
||||
icon_state = "frame"
|
||||
plane = ABOVE_WALL_PLANE
|
||||
density = FALSE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
|
||||
@@ -11,9 +11,6 @@
|
||||
var/insisting = 0
|
||||
|
||||
/obj/machinery/wish_granter/attack_hand(mob/living/carbon/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(charges <= 0)
|
||||
to_chat(user, "The Wish Granter lies silent.")
|
||||
return
|
||||
@@ -22,22 +19,116 @@
|
||||
to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.")
|
||||
return
|
||||
|
||||
else if(is_special_character(user))
|
||||
to_chat(user, "Even to a heart as dark as yours, you know nothing good will come of this. Something instinctual makes you pull away.")
|
||||
|
||||
else if (!insisting)
|
||||
to_chat(user, "Your first touch makes the Wish Granter stir, listening to you. Are you really sure you want to do this?")
|
||||
insisting++
|
||||
|
||||
else
|
||||
to_chat(user, "You speak. [pick("I want the station to disappear","Humanity is corrupt, mankind must be destroyed","I want to be rich", "I want to rule the world","I want immortality.")]. The Wish Granter answers.")
|
||||
to_chat(user, "Your head pounds for a moment, before your vision clears. You are the avatar of the Wish Granter, and your power is LIMITLESS! And it's all yours. You need to make sure no one can take it from you. No one can know, first.")
|
||||
if(is_special_character(user))
|
||||
to_chat(user, "You speak. [pick("I want power","Humanity is corrupt, mankind must be destroyed", "I want to rule the world","I want immortality")]. The Wish Granter answers.")
|
||||
to_chat(user, "Your head pounds for a moment, before your vision clears. The Wish Granter, sensing the darkness in your heart, has given you limitless power, and it's all yours!")
|
||||
user.dna.add_mutation(HULK)
|
||||
user.dna.add_mutation(XRAY)
|
||||
user.dna.add_mutation(SPACEMUT)
|
||||
user.dna.add_mutation(TK)
|
||||
user.next_move_modifier *= 0.5 //half the delay between attacks!
|
||||
to_chat(user, "Things around you feel slower!")
|
||||
charges--
|
||||
insisting = FALSE
|
||||
to_chat(user, "You have a very great feeling about this!")
|
||||
else
|
||||
to_chat(user, "The Wish Granter awaits your wish.")
|
||||
var/wish = input("You want...","Wish") as null|anything in list("Power","Wealth","The Station To Disappear","To Kill","Nothing")
|
||||
switch(wish)
|
||||
if("Power") //Gives infinite power in exchange for infinite power going off in your face!
|
||||
if(charges <= 0)
|
||||
return
|
||||
to_chat(user, "<B>Your wish is granted, but at a terrible cost...</B>")
|
||||
to_chat(user, "The Wish Granter punishes you for your selfishness, warping itself into a delaminating supermatter shard!")
|
||||
var/obj/item/stock_parts/cell/infinite/powah = new /obj/item/stock_parts/cell/infinite(get_turf(user))
|
||||
if(user.put_in_hands(powah))
|
||||
to_chat(user, "[powah] materializes into your hands!")
|
||||
else
|
||||
to_chat(user, "[powah] materializes onto the floor.")
|
||||
var/obj/machinery/power/supermatter_crystal/powerwish = new /obj/machinery/power/supermatter_crystal(loc)
|
||||
powerwish.damage = 700 //right at the emergency threshold
|
||||
powerwish.produces_gas = FALSE
|
||||
charges--
|
||||
insisting = FALSE
|
||||
if(!charges)
|
||||
qdel(src)
|
||||
if("Wealth") //Gives 1 million space bucks in exchange for being turned into gold!
|
||||
if(charges <= 0)
|
||||
return
|
||||
to_chat(user, "<B>Your wish is granted, but at a cost...</B>")
|
||||
to_chat(user, "The Wish Granter punishes you for your selfishness, warping your body to match the greed in your heart.")
|
||||
new /obj/structure/closet/crate/trashcart/moneywish(loc)
|
||||
new /obj/structure/closet/crate/trashcart/moneywish(loc)
|
||||
user.set_species(/datum/species/golem/gold)
|
||||
charges--
|
||||
insisting = FALSE
|
||||
if(!charges)
|
||||
qdel(src)
|
||||
if("The Station To Disappear") //teleports you to the station and makes you blind, making the station disappear for you!
|
||||
if(charges <= 0)
|
||||
return
|
||||
to_chat(user, "<B>Your wish is 'granted', but at a terrible cost...</B>")
|
||||
to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your eyes to match the darkness in your heart.")
|
||||
user.dna.add_mutation(BLINDMUT)
|
||||
var/obj/item/organ/eyes/eyes = user.getorganslot(ORGAN_SLOT_EYES)
|
||||
if(eyes)
|
||||
eyes.applyOrganDamage(eyes.maxHealth)
|
||||
var/list/destinations = list()
|
||||
for(var/obj/item/beacon/B in GLOB.teleportbeacons)
|
||||
var/turf/T = get_turf(B)
|
||||
if(is_station_level(T.z))
|
||||
destinations += B
|
||||
var/chosen_beacon = pick(destinations)
|
||||
var/obj/effect/portal/jaunt_tunnel/J = new (get_turf(src), src, 100, null, FALSE, get_turf(chosen_beacon))
|
||||
try_move_adjacent(J)
|
||||
playsound(src,'sound/effects/sparks4.ogg',50,1)
|
||||
charges--
|
||||
insisting = FALSE
|
||||
if(!charges)
|
||||
qdel(src)
|
||||
if("To Kill") //Makes you kill things in exchange for rewards!
|
||||
if(charges <= 0)
|
||||
return
|
||||
to_chat(user, "<B>Your wish is granted, but at a terrible cost...</B>")
|
||||
to_chat(user, "The Wish Granter punishes you for your wickedness, warping itself into a dastardly creature for you to kill! ...but it almost seems to reward you for this.")
|
||||
var/obj/item/melee/transforming/energy/sword/cx/killreward = new /obj/item/melee/transforming/energy/sword/cx(get_turf(user))
|
||||
if(user.put_in_hands(killreward))
|
||||
to_chat(user, "[killreward] materializes into your hands!")
|
||||
else
|
||||
to_chat(user, "[killreward] materializes onto the floor.")
|
||||
user.next_move_modifier *= 0.8 //20% less delay between attacks!
|
||||
to_chat(user, "Things around you feel slightly slower!")
|
||||
var/mob/living/simple_animal/hostile/venus_human_trap/killwish = new /mob/living/simple_animal/hostile/venus_human_trap(loc)
|
||||
killwish.maxHealth = 1500
|
||||
killwish.health = killwish.maxHealth
|
||||
killwish.vine_grab_distance = 6
|
||||
killwish.melee_damage_upper = 30
|
||||
killwish.loot = list(/obj/item/twohanded/dualsaber/hypereutactic)
|
||||
charges--
|
||||
insisting = FALSE
|
||||
if(!charges)
|
||||
qdel(src)
|
||||
if("Nothing") //Makes the wish granter disappear
|
||||
if(charges <= 0)
|
||||
return
|
||||
to_chat(user, "<B>The Wish Granter vanishes from sight!</B>")
|
||||
to_chat(user, "You feel as if you just narrowly avoided a terrible fate...")
|
||||
charges--
|
||||
insisting = FALSE
|
||||
qdel(src)
|
||||
|
||||
charges--
|
||||
insisting = 0
|
||||
//ITEMS THAT IT USES
|
||||
|
||||
user.mind.add_antag_datum(/datum/antagonist/wishgranter)
|
||||
/obj/structure/closet/crate/trashcart/moneywish
|
||||
desc = "A heavy, metal trashcart with wheels. Filled with cash."
|
||||
name = "loaded trash cart"
|
||||
|
||||
to_chat(user, "You have a very bad feeling about this.")
|
||||
|
||||
return
|
||||
/obj/structure/closet/crate/trashcart/moneywish/PopulateContents() //25*20*1000=500,000
|
||||
for(var/i in 1 to 25)
|
||||
var/obj/item/stack/spacecash/c1000/lodsamoney = new /obj/item/stack/spacecash/c1000(src)
|
||||
lodsamoney.amount = lodsamoney.max_amount
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user