Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into DRAKEBORG
This commit is contained in:
@@ -108,6 +108,8 @@
|
||||
#define TR_KEEPSE (1<<5) // changelings shouldn't edit the DNA's SE when turning into a monkey
|
||||
#define TR_DEFAULTMSG (1<<6)
|
||||
#define TR_KEEPORGANS (1<<8)
|
||||
#define TR_KEEPREAGENTS (1<<10)
|
||||
#define TR_KEEPSTUNS (1<<9)
|
||||
|
||||
|
||||
#define CLONER_FRESH_CLONE "fresh"
|
||||
@@ -140,6 +142,11 @@
|
||||
#define CUSTOM_SKINTONE 24 //adds a "_g" suffix to bodypart overlays icon states if a custom skintone is used.
|
||||
#define HORNCOLOR 25
|
||||
#define WINGCOLOR 26
|
||||
#define CAN_SCAR 27 // If this species can be scarred (fleshy)
|
||||
|
||||
/// Used for determining which wounds are applicable to this species.
|
||||
#define HAS_FLESH 28 /// if we have flesh (can suffer slash/piercing/burn wounds, requires they don't have NOBLOOD)
|
||||
#define HAS_BONE 29 /// if we have bones (can suffer bone wounds)
|
||||
|
||||
//organ slots
|
||||
#define ORGAN_SLOT_BRAIN "brain"
|
||||
@@ -184,4 +191,4 @@
|
||||
#define G_MALE 1
|
||||
#define G_FEMALE 2
|
||||
#define G_PLURAL 3
|
||||
#define G_NEUTER 4
|
||||
#define G_NEUTER 4
|
||||
|
||||
@@ -138,10 +138,6 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
|
||||
#define MOBILITY_FLAGS_DEFAULT (MOBILITY_MOVE | MOBILITY_STAND | MOBILITY_PICKUP | MOBILITY_USE | MOBILITY_UI | MOBILITY_STORAGE | MOBILITY_PULL | MOBILITY_RESIST)
|
||||
#define MOBILITY_FLAGS_ANY_INTERACTION (MOBILITY_USE | MOBILITY_PICKUP | MOBILITY_UI | MOBILITY_STORAGE)
|
||||
|
||||
// melee_attack_chain() attackchain_flags
|
||||
/// The attack is from a parry counterattack.
|
||||
#define ATTACKCHAIN_PARRY_COUNTERATTACK (1<<0)
|
||||
|
||||
/// If the thing can reflect light (lasers/energy)
|
||||
#define RICOCHET_SHINY (1<<0)
|
||||
/// If the thing can reflect matter (bullets/bomb shrapnel)
|
||||
|
||||
@@ -52,4 +52,4 @@
|
||||
#define ORGAN_VITAL (1<<4) //Currently only the brain
|
||||
#define ORGAN_NO_SPOIL (1<<5) //Do not spoil under any circumstances
|
||||
#define ORGAN_NO_DISMEMBERMENT (1<<6) //Immune to disembowelment.
|
||||
#define ORGAN_EDIBLE (1<<5) //is a snack? :D
|
||||
#define ORGAN_EDIBLE (1<<7) //is a snack? :D
|
||||
|
||||
@@ -12,4 +12,9 @@
|
||||
#define SHOVABLE_ONTO (1<<9) //called on turf.shove_act() to consider whether an object should have a niche effect (defined in their own shove_act()) when someone is pushed onto it, or do a sanity CanPass() check.
|
||||
#define BLOCK_Z_FALL (1<<10)
|
||||
|
||||
/// Integrity defines for clothing (not flags but close enough)
|
||||
#define CLOTHING_PRISTINE 0 // We have no damage on the clothing
|
||||
#define CLOTHING_DAMAGED 1 // There's some damage on the clothing but it still has at least one functioning bodypart and can be equipped
|
||||
#define CLOTHING_SHREDDED 2 // The clothing is useless and cannot be equipped unless repaired first
|
||||
|
||||
// If you add new ones, be sure to add them to /obj/Initialize as well for complete mapping support
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/////////// ATTACKCHAIN_FLAGS ////////////
|
||||
// melee_attack_chain(), attackby(), pre_attack(), afterattack(), and tool_act(), attack() and **anything that is called by ClickOn()** return values.
|
||||
// These are all passed down through the attack chain and are binary OR'd into each other!
|
||||
/// Stop the attack chain if still in melee_attack_chain()
|
||||
#define STOP_ATTACK_PROC_CHAIN (1<<0)
|
||||
/// This attack should discard last_action instead of flushing (storing) it). You should probably know what you're doing if you use this considering this is how clickdelay is enforced.
|
||||
#define DISCARD_LAST_ACTION (1<<1)
|
||||
/// There are a number of "safety nets" intended to default-handle clickdelay. Return this flag to bypass ALL of them. Be sure
|
||||
/// you know EXACTLY what you are doing!
|
||||
#define NO_AUTO_CLICKDELAY_HANDLING (1<<2)
|
||||
/// Only used with UnarmedAttack(). Interrupts unarmed attack from progressing.
|
||||
#define INTERRUPT_UNARMED_ATTACK (1<<3)
|
||||
/// Attack should not set next action even if the atom wants it to be an action
|
||||
#define ATTACK_IGNORE_ACTION (1<<4)
|
||||
/// Attack should not at all check last_action/attack_hand_speed even if the atom wants to
|
||||
#define ATTACK_IGNORE_CLICKDELAY (1<<5)
|
||||
/// This attack is from a parry counterattack
|
||||
#define ATTACK_IS_PARRY_COUNTERATTACK (1<<6)
|
||||
|
||||
// obj/item/dropped()
|
||||
/// dropped() relocated this item, return FALSE for doUnEquip.
|
||||
#define ITEM_RELOCATED_BY_DROPPED "relocated_by_dropped"
|
||||
@@ -74,6 +74,13 @@
|
||||
#define ADMIN_PUNISHMENT_MAZING "Puzzle"
|
||||
#define ADMIN_PUNISHMENT_PIE "Cream Pie"
|
||||
#define ADMIN_PUNISHMENT_CUSTOM_PIE "Custom Cream Pie"
|
||||
#define ADMIN_PUNISHMENT_SHOES "Knot Shoes"
|
||||
#define ADMIN_PUNISHMENT_CRACK ":B:oneless"
|
||||
#define ADMIN_PUNISHMENT_BLEED ":B:loodless"
|
||||
#define ADMIN_PUNISHMENT_SCARIFY "Scarify"
|
||||
#define ADMIN_PUNISHMENT_PICKLE "Pickle-ify"
|
||||
#define ADMIN_PUNISHMENT_FRY "Fry"
|
||||
#define ADMIN_PUNISHMENT_PERFORATE ":B:erforate"
|
||||
|
||||
#define AHELP_ACTIVE 1
|
||||
#define AHELP_CLOSED 2
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// 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
|
||||
#define MAX_KEYPRESS_COMMANDLENGTH 32
|
||||
/// Maximum keys that can be bound to one button
|
||||
#define MAX_COMMANDS_PER_KEY 5
|
||||
/// Maximum keys per keybind
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// Reaction priorities, higher makes it checked first. Otherwise, it goes based on reaction temperature requirements.
|
||||
|
||||
#define CHEMICAL_REACTION_PRIORITY_DEFAULT 100
|
||||
#define CHEMICAL_REACTION_PRIORITY_SMOKE 1000
|
||||
@@ -98,6 +98,7 @@
|
||||
#define NO_APHRO (1<<9)
|
||||
#define NO_ASS_SLAP (1<<10)
|
||||
#define BIMBOFICATION (1<<11)
|
||||
#define NO_AUTO_WAG (1<<12)
|
||||
|
||||
#define TOGGLES_CITADEL 0
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
GLOBAL_VAR_INIT(clockwork_construction_value, 0) //The total value of all structures built by the clockwork cult
|
||||
GLOBAL_VAR_INIT(clockwork_vitality, 0) //How much Vitality is stored, total
|
||||
GLOBAL_VAR_INIT(clockwork_power, 0) //How many watts of power are globally available to the clockwork cult
|
||||
GLOBAL_LIST_EMPTY(active_daemons) //A list of all active tinkerer's daemons
|
||||
GLOBAL_VAR_INIT(neovgre_exists, 0) //Does neovgre exist?
|
||||
|
||||
GLOBAL_LIST_EMPTY(all_clockwork_objects) //All clockwork items, structures, and effects in existence
|
||||
@@ -19,21 +20,23 @@ GLOBAL_VAR_INIT(ark_of_the_clockwork_justiciar, FALSE) //The Ark on the Reebe z-
|
||||
|
||||
GLOBAL_VAR_INIT(clockwork_gateway_activated, FALSE) //if a gateway to the celestial derelict has ever been successfully activated
|
||||
GLOBAL_VAR_INIT(script_scripture_unlocked, FALSE) //If script scripture is available, through converting at least one crewmember
|
||||
GLOBAL_VAR_INIT(application_scripture_unlocked, FALSE) //If script scripture is available
|
||||
GLOBAL_VAR_INIT(application_scripture_unlocked, FALSE) //If application scripture is available
|
||||
GLOBAL_VAR_INIT(judgement_scripture_unlocked, FALSE) //If judgement scripture is available
|
||||
GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not used to track existing scripture
|
||||
GLOBAL_LIST_EMPTY(all_clockwork_rites) //a list containing all clockwork rites. Filled the first time any cultist interacts with a sigil of rites.
|
||||
|
||||
//Scripture tiers and requirements; peripherals should never be used
|
||||
#define SCRIPTURE_PERIPHERAL "Peripheral"
|
||||
#define SCRIPTURE_DRIVER "Driver"
|
||||
#define SCRIPTURE_SCRIPT "Script"
|
||||
#define SCRIPTURE_APPLICATION "Application"
|
||||
#define SCRIPTURE_JUDGEMENT "Judgement"
|
||||
|
||||
//Various costs related to power.
|
||||
#define MAX_CLOCKWORK_POWER 80000 //The max power in W that the cult can stockpile
|
||||
#define SCRIPT_UNLOCK_THRESHOLD 35000 //Scripts will unlock if the total power reaches this amount
|
||||
#define APPLICATION_UNLOCK_THRESHOLD 50000 //Applications will unlock if the total powre reaches this amount
|
||||
|
||||
#define ABSCOND_ABDUCTION_COST 95
|
||||
#define APPLICATION_UNLOCK_THRESHOLD 50000 //Applications will unlock if the total power reaches this amount
|
||||
#define JUDGEMENT_UNLOCK_THRESHOLD 80000 //might as well have this unlock at a power amount like the other scriptures, Judgement unlocks at this amount.
|
||||
|
||||
//clockcult power defines
|
||||
#define MIN_CLOCKCULT_POWER 25 //the minimum amount of power clockcult machines will handle gracefully
|
||||
@@ -59,11 +62,11 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
|
||||
//Ark defines
|
||||
#define GATEWAY_SUMMON_RATE 1 //the time amount the Gateway to the Celestial Derelict gets each process tick; defaults to 1 per tick
|
||||
|
||||
#define GATEWAY_REEBE_FOUND 240 //when progress is at or above this, the gateway finds reebe and begins drawing power
|
||||
#define GATEWAY_REEBE_FOUND 120 //when progress is at or above this, the gateway finds reebe and begins drawing power
|
||||
|
||||
#define GATEWAY_RATVAR_COMING 480 //when progress is at or above this, ratvar has entered and is coming through the gateway
|
||||
#define GATEWAY_RATVAR_COMING 240 //when progress is at or above this, ratvar has entered and is coming through the gateway
|
||||
|
||||
#define GATEWAY_RATVAR_ARRIVAL 600 //when progress is at or above this, game over ratvar's here everybody go home
|
||||
#define GATEWAY_RATVAR_ARRIVAL 300 //when progress is at or above this, game over ratvar's here everybody go home
|
||||
|
||||
//Objective text define
|
||||
#define CLOCKCULT_OBJECTIVE "Construct the Ark of the Clockwork Justicar and free Ratvar."
|
||||
@@ -81,7 +84,7 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
|
||||
|
||||
#define CLOCKWORK_ARMOR_COOLDOWN 1800 //The cooldown period between summoning suits of clockwork armor
|
||||
|
||||
#define RATVARIAN_SPEAR_COOLDOWN 300 //The cooldown period between summoning another Ratvarian spear
|
||||
#define RATVARIAN_WEAPON_COOLDOWN 300 //The cooldown period between summoning another Ratvarian spear
|
||||
|
||||
#define MARAUDER_SCRIPTURE_SCALING_THRESHOLD 600 //The amount of deciseconds that must pass before marauder scripture will not gain a recital penalty
|
||||
|
||||
@@ -89,4 +92,8 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
|
||||
|
||||
#define MARAUDER_SCRIPTURE_SCALING_MAX 300 //The maximum extra time applied to the marauder scripture
|
||||
|
||||
#define ARK_SCREAM_COOLDOWN 600 //This much time has to pass between instances of the Ark taking damage before it will "scream" again
|
||||
#define GUARDIAN_EMERGE_THRESHOLD 65 //guardian cannot emerge unless host is at this% or less health
|
||||
|
||||
#define ARK_SCREAM_COOLDOWN 300 //This much time has to pass between instances of the Ark taking damage before it will "scream" again
|
||||
|
||||
#define PRISM_DELAY_DURATION 1200 //how long prolonging prisms delay the shuttle for; defaults to 2 minutes
|
||||
@@ -108,7 +108,6 @@
|
||||
#define CLICK_CD_RANGE 4
|
||||
#define CLICK_CD_RAPID 2
|
||||
#define CLICK_CD_CLICK_ABILITY 6
|
||||
#define CLICK_CD_BREAKOUT 100
|
||||
#define CLICK_CD_HANDCUFFED 10
|
||||
#define CLICK_CD_RESIST 20
|
||||
#define CLICK_CD_GRABBING 10
|
||||
@@ -155,9 +154,10 @@
|
||||
#define SHOVE_KNOCKDOWN_HUMAN 30
|
||||
#define SHOVE_KNOCKDOWN_TABLE 30
|
||||
#define SHOVE_KNOCKDOWN_COLLATERAL 10
|
||||
//for the shove slowdown, see __DEFINES/movespeed_modification.dm
|
||||
#define SHOVE_SLOWDOWN_LENGTH 30
|
||||
#define SHOVE_SLOWDOWN_STRENGTH 0.85 //multiplier
|
||||
/// how long they're staggered for
|
||||
#define SHOVE_STAGGER_DURATION 35
|
||||
/// how long they're off balance for
|
||||
#define SHOVE_OFFBALANCE_DURATION 30
|
||||
//Shove disarming item list
|
||||
GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
|
||||
/obj/item/gun)))
|
||||
@@ -209,9 +209,9 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
|
||||
#define GUN_AIMING_TIME (2 SECONDS)
|
||||
|
||||
//Object/Item sharpness
|
||||
#define IS_BLUNT 0
|
||||
#define IS_SHARP 1
|
||||
#define IS_SHARP_ACCURATE 2
|
||||
#define SHARP_NONE 0
|
||||
#define SHARP_EDGED 1
|
||||
#define SHARP_POINTY 2
|
||||
|
||||
//His Grace.
|
||||
#define HIS_GRACE_SATIATED 0 //He hungers not. If bloodthirst is set to this, His Grace is asleep.
|
||||
@@ -281,7 +281,7 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
|
||||
/// changeNext_move penalty multiplier of the above.
|
||||
#define STAM_CRIT_ITEM_ATTACK_DELAY 1.75
|
||||
/// Damage penalty when fighting prone.
|
||||
#define LYING_DAMAGE_PENALTY 0.5
|
||||
#define LYING_DAMAGE_PENALTY 0.7
|
||||
/// Added delay when firing guns stam-softcritted. Summed with a hardset CLICK_CD_RANGE delay, similar to STAM_CRIT_DAMAGE_DELAY otherwise.
|
||||
#define STAM_CRIT_GUN_DELAY 2.75
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#define COMSIG_ELEMENT_DETACH "element_detach"
|
||||
|
||||
// /atom signals
|
||||
//from base of atom/proc/Initialize(): sent any time a new atom is created
|
||||
#define COMSIG_ATOM_CREATED "atom_created"
|
||||
#define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (/obj/item, /mob/living, params)
|
||||
#define COMPONENT_NO_AFTERATTACK 1 //Return this in response if you don't want afterattack to be called
|
||||
#define COMSIG_ATOM_HULK_ATTACK "hulk_attack" //from base of atom/attack_hulk(): (/mob/living/carbon/human)
|
||||
@@ -207,6 +209,8 @@
|
||||
#define COMSIG_MOB_SWAP_HANDS "mob_swap_hands" //from base of mob/swap_hand(): (obj/item)
|
||||
#define COMPONENT_BLOCK_SWAP 1
|
||||
|
||||
#define COMSIG_PROCESS_BORGCHARGER_OCCUPANT "living_charge"
|
||||
|
||||
// /client signals
|
||||
#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)
|
||||
@@ -250,7 +254,14 @@
|
||||
#define COMPONENT_INTERRUPT_LIFE_BIOLOGICAL 1 // interrupt biological processes
|
||||
#define COMPONENT_INTERRUPT_LIFE_PHYSICAL 2 // interrupt physical handling
|
||||
|
||||
// /mob/living/carbon signals
|
||||
// /mob/living/carbon physiology signals
|
||||
#define COMSIG_CARBON_GAIN_WOUND "carbon_gain_wound" //from /datum/wound/proc/apply_wound() (/mob/living/carbon/C, /datum/wound/W, /obj/item/bodypart/L)
|
||||
#define COMSIG_CARBON_LOSE_WOUND "carbon_lose_wound" //from /datum/wound/proc/remove_wound() (/mob/living/carbon/C, /datum/wound/W, /obj/item/bodypart/L)
|
||||
///from base of /obj/item/bodypart/proc/attach_limb(): (new_limb, special) allows you to fail limb attachment
|
||||
#define COMSIG_CARBON_ATTACH_LIMB "carbon_attach_limb"
|
||||
#define COMPONENT_NO_ATTACH (1<<0)
|
||||
#define COMSIG_CARBON_REMOVE_LIMB "carbon_remove_limb" //from base of /obj/item/bodypart/proc/drop_limb(special, dismembered)
|
||||
|
||||
#define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" //from base of mob/living/carbon/soundbang_act(): (list(intensity))
|
||||
#define COMSIG_CARBON_IDENTITY_TRANSFERRED_TO "carbon_id_transferred_to" //from datum/dna/transfer_identity(): (datum/dna, transfer_SE)
|
||||
#define COMSIG_CARBON_TACKLED "carbon_tackled" //sends from tackle.dm on tackle completion
|
||||
@@ -347,10 +358,10 @@
|
||||
#define COMSIG_PEN_ROTATED "pen_rotated" //called after rotation in /obj/item/pen/attack_self(): (rotation, mob/living/carbon/user)
|
||||
|
||||
// /obj/item/projectile signals (sent to the firer)
|
||||
#define COMSIG_PROJECTILE_SELF_ON_HIT "projectile_self_on_hit" // from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle)
|
||||
#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit" // from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle)
|
||||
#define COMSIG_PROJECTILE_SELF_ON_HIT "projectile_self_on_hit" ///from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle, hit_limb)
|
||||
#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit" ///from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle, hit_limb)
|
||||
#define COMSIG_PROJECTILE_BEFORE_FIRE "projectile_before_fire" // from base of /obj/item/projectile/proc/fire(): (obj/item/projectile, atom/original_target)
|
||||
#define COMSIG_PROJECTILE_FIRE "projectile_fire" ///from the base of /obj/projectile/proc/fire(): ()
|
||||
#define COMSIG_PROJECTILE_FIRE "projectile_fire" ///from the base of /obj/item/projectile/proc/fire(): ()
|
||||
#define COMSIG_PROJECTILE_RANGE_OUT "projectile_range_out" // sent to targets during the process_hit proc of projectiles
|
||||
#define COMSIG_EMBED_TRY_FORCE "item_try_embed" // sent when trying to force an embed (mainly for projectiles, only used in the embed element)
|
||||
#define COMSIG_PROJECTILE_PREHIT "com_proj_prehit" ///sent to targets during the process_hit proc of projectiles
|
||||
@@ -360,6 +371,7 @@
|
||||
// /mob/living/carbon/human signals
|
||||
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target)
|
||||
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" //from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker)
|
||||
#define COMSIG_HUMAN_EARLY_UNARMED_ATTACK "human_early_unarmed_attack"
|
||||
#define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit" //Hit by successful disarm attack (mob/living/carbon/human/attacker,zone_targeted)
|
||||
#define COMSIG_HUMAN_PREFS_COPIED_TO "human_prefs_copied_to" //from datum/preferences/copy_to(): (datum/preferences, icon_updates, roundstart_checks)
|
||||
#define COMSIG_HUMAN_HARDSET_DNA "human_hardset_dna" //from mob/living/carbon/human/hardset_dna(): (ui, list/mutation_index, newreal_name, newblood_type, datum/species, newfeatures)
|
||||
@@ -442,6 +454,9 @@
|
||||
#define COMPONENT_TWOHANDED_BLOCK_WIELD 1
|
||||
#define COMSIG_TWOHANDED_UNWIELD "twohanded_unwield" //from base of datum/component/two_handed/proc/unwield(mob/living/carbon/user): (/mob/user)
|
||||
|
||||
// /datum/component/squeak signals
|
||||
#define COMSIG_CROSS_SQUEAKED "cross_squeaked" // sent when a squeak component squeaks from crossing something, to delay anything else crossing that might squeak to prevent ear hurt.
|
||||
|
||||
// /datum/action signals
|
||||
#define COMSIG_ACTION_TRIGGER "action_trigger" //from base of datum/action/proc/Trigger(): (datum/action)
|
||||
#define COMPONENT_ACTION_BLOCK_TRIGGER 1
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/// Module is compatible with Security Cyborg models
|
||||
#define BORG_MODULE_SECURITY (1<<0)
|
||||
/// Module is compatible with Miner Cyborg models
|
||||
#define BORG_MODULE_MINER (1<<1)
|
||||
/// Module is compatible with Janitor Cyborg models
|
||||
#define BORG_MODULE_JANITOR (1<<2)
|
||||
/// Module is compatible with Medical Cyborg models
|
||||
#define BORG_MODULE_MEDICAL (1<<3)
|
||||
/// Module is compatible with Engineering Cyborg models
|
||||
#define BORG_MODULE_ENGINEERING (1<<4)
|
||||
|
||||
/// Module is compatible with Ripley Exosuit models
|
||||
#define EXOSUIT_MODULE_RIPLEY (1<<0)
|
||||
/// Module is compatible with Odyseeus Exosuit models
|
||||
#define EXOSUIT_MODULE_ODYSSEUS (1<<1)
|
||||
/// Module is compatible with Clarke Exosuit models. Rebranded to firefighter because tg nerfed it to this.
|
||||
#define EXOSUIT_MODULE_FIREFIGHTER (1<<2)
|
||||
// #define EXOSUIT_MODULE_CLARKE (1<<2)
|
||||
/// Module is compatible with Gygax Exosuit models
|
||||
#define EXOSUIT_MODULE_GYGAX (1<<3)
|
||||
/// Module is compatible with Durand Exosuit models
|
||||
#define EXOSUIT_MODULE_DURAND (1<<4)
|
||||
/// Module is compatible with H.O.N.K Exosuit models
|
||||
#define EXOSUIT_MODULE_HONK (1<<5)
|
||||
/// Module is compatible with Phazon Exosuit models
|
||||
#define EXOSUIT_MODULE_PHAZON (1<<6)
|
||||
/// Module is compatable with N models
|
||||
#define EXOSUIT_MODULE_GYGAX_MED (1<<7)
|
||||
|
||||
/// Module is compatible with "Working" Exosuit models - Ripley and Clarke
|
||||
#define EXOSUIT_MODULE_WORKING EXOSUIT_MODULE_RIPLEY | EXOSUIT_MODULE_FIREFIGHTER // | EXOSUIT_MODULE_CLARKE
|
||||
/// Module is compatible with "Combat" Exosuit models - Gygax, H.O.N.K, Durand and Phazon
|
||||
#define EXOSUIT_MODULE_COMBAT EXOSUIT_MODULE_GYGAX | EXOSUIT_MODULE_HONK | EXOSUIT_MODULE_DURAND | EXOSUIT_MODULE_PHAZON
|
||||
/// Module is compatible with "Medical" Exosuit modelsm - Odysseus
|
||||
#define EXOSUIT_MODULE_MEDICAL EXOSUIT_MODULE_ODYSSEUS | EXOSUIT_MODULE_GYGAX_MED
|
||||
@@ -7,10 +7,10 @@
|
||||
#define PULSE_CHANNEL "pulse channel"
|
||||
|
||||
// Methods of obtaining a circuit.
|
||||
#define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box and able to be printed in the IC printer.
|
||||
#define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box and is able to be printed in the IC printer.
|
||||
#define IC_SPAWN_RESEARCH 2 // If the circuit design will be available in the IC printer after upgrading it.
|
||||
|
||||
// Categories that help differentiate circuits that can do different tipes of actions
|
||||
// Categories that help differentiate circuits that can do different types of actions
|
||||
#define IC_ACTION_MOVEMENT (1<<0) // If the circuit can move the assembly
|
||||
#define IC_ACTION_COMBAT (1<<1) // If the circuit can cause harm
|
||||
#define IC_ACTION_LONG_RANGE (1<<2) // If the circuit communicate with something outside of the assembly
|
||||
|
||||
@@ -65,9 +65,8 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
|
||||
#define isslimeperson(A) (is_species(A, /datum/species/jelly/slime))
|
||||
#define isluminescent(A) (is_species(A, /datum/species/jelly/luminescent))
|
||||
#define iszombie(A) (is_species(A, /datum/species/zombie))
|
||||
#define ismoth(A) (is_species(A, /datum/species/insect))
|
||||
#define ishumanbasic(A) (is_species(A, /datum/species/human))
|
||||
#define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid) )
|
||||
#define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid))
|
||||
#define isdwarf(A) (is_species(A, /datum/species/dwarf))
|
||||
#define isdullahan(A) (is_species(A, /datum/species/dullahan))
|
||||
#define isangel(A) (is_species(A, /datum/species/angel))
|
||||
@@ -75,13 +74,12 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
|
||||
#define ismush(A) (is_species(A, /datum/species/mush))
|
||||
#define isshadow(A) (is_species(A, /datum/species/shadow))
|
||||
#define isskeleton(A) (is_species(A, /datum/species/skeleton))
|
||||
#define isethereal(A) (is_species(A, /datum/species/ethereal))
|
||||
|
||||
// Citadel specific species
|
||||
#define isipcperson(A) (is_species(A, /datum/species/ipc))
|
||||
#define issynthliz(A) (is_species(A, /datum/species/synthliz))
|
||||
#define ismammal(A) (is_species(A, /datum/species/mammal))
|
||||
#define isavian(A) (is_species(A, /datum/species/avian))
|
||||
#define isaquatic(A) (is_species(A, /datum/species/aquatic))
|
||||
#define isinsect(A) (is_species(A, /datum/species/insect))
|
||||
#define isxenoperson(A) (is_species(A, /datum/species/xeno))
|
||||
#define isstartjelly(A) (is_species(A, /datum/species/jelly/roundstartslime))
|
||||
@@ -202,21 +200,13 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
|
||||
|
||||
#define isclothing(A) (istype(A, /obj/item/clothing))
|
||||
|
||||
GLOBAL_LIST_INIT(pointed_types, typecacheof(list(
|
||||
/obj/item/pen,
|
||||
/obj/item/screwdriver,
|
||||
/obj/item/reagent_containers/syringe,
|
||||
/obj/item/kitchen/fork)))
|
||||
|
||||
#define is_pointed(W) (is_type_in_typecache(W, GLOB.pointed_types))
|
||||
|
||||
#define isbodypart(A) (istype(A, /obj/item/bodypart))
|
||||
|
||||
#define isprojectile(A) (istype(A, /obj/item/projectile))
|
||||
|
||||
#define isgun(A) (istype(A, /obj/item/gun))
|
||||
|
||||
#define isfood(A) (istype(A, /obj/item/reagent_containers/food))
|
||||
#define isfood(A) (istype(A, /obj/item/reagent_containers/food/snacks))
|
||||
|
||||
//Assemblies
|
||||
#define isassembly(O) (istype(O, /obj/item/assembly))
|
||||
|
||||
@@ -131,6 +131,8 @@
|
||||
#define LIGHTING_LAYER 15
|
||||
#define LIGHTING_RENDER_TARGET "LIGHT_PLANE"
|
||||
|
||||
#define RAD_TEXT_LAYER 15.1
|
||||
|
||||
#define ABOVE_LIGHTING_PLANE 16
|
||||
#define ABOVE_LIGHTING_LAYER 16
|
||||
#define ABOVE_LIGHTING_RENDER_TARGET "ABOVE_LIGHTING_PLANE"
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
//defines for loadout categories
|
||||
//no category defines
|
||||
#define LOADOUT_CATEGORY_NONE "ERROR"
|
||||
#define LOADOUT_SUBCATEGORY_NONE "Miscellaneous"
|
||||
#define LOADOUT_SUBCATEGORIES_NONE list("Miscellaneous")
|
||||
|
||||
//backpack
|
||||
#define LOADOUT_CATEGORY_BACKPACK "In backpack"
|
||||
#define LOADOUT_SUBCATEGORY_BACKPACK_GENERAL "General" //basically anything that there's not enough of to have its own subcategory
|
||||
#define LOADOUT_SUBCATEGORY_BACKPACK_TOYS "Toys"
|
||||
//neck
|
||||
#define LOADOUT_CATEGORY_NECK "Neck"
|
||||
#define LOADOUT_SUBCATEGORY_NECK_GENERAL "General"
|
||||
#define LOADOUT_SUBCATEGORY_NECK_TIE "Ties"
|
||||
#define LOADOUT_SUBCATEGORY_NECK_SCARVES "Scarves"
|
||||
|
||||
//mask
|
||||
#define LOADOUT_CATEGORY_MASK "Mask"
|
||||
|
||||
//hands
|
||||
#define LOADOUT_CATEGORY_HANDS "Hands"
|
||||
|
||||
//uniform
|
||||
#define LOADOUT_CATEGORY_UNIFORM "Uniform" //there's so many types of uniform it's best to have lots of categories
|
||||
#define LOADOUT_SUBCATEGORY_UNIFORM_GENERAL "General"
|
||||
#define LOADOUT_SUBCATEGORY_UNIFORM_JOBS "Jobs"
|
||||
#define LOADOUT_SUBCATEGORY_UNIFORM_SUITS "Suits"
|
||||
#define LOADOUT_SUBCATEGORY_UNIFORM_SKIRTS "Skirts"
|
||||
#define LOADOUT_SUBCATEGORY_UNIFORM_DRESSES "Dresses"
|
||||
#define LOADOUT_SUBCATEGORY_UNIFORM_SWEATERS "Sweaters"
|
||||
#define LOADOUT_SUBCATEGORY_UNIFORM_PANTS "Pants"
|
||||
#define LOADOUT_SUBCATEGORY_UNIFORM_SHORTS "Shorts"
|
||||
|
||||
//suit
|
||||
#define LOADOUT_CATEGORY_SUIT "Suit"
|
||||
#define LOADOUT_SUBCATEGORY_SUIT_GENERAL "General"
|
||||
#define LOADOUT_SUBCATEGORY_SUIT_COATS "Coats"
|
||||
#define LOADOUT_SUBCATEGORY_SUIT_JACKETS "Jackets"
|
||||
#define LOADOUT_SUBCATEGORY_SUIT_JOBS "Jobs"
|
||||
|
||||
//head
|
||||
#define LOADOUT_CATEGORY_HEAD "Head"
|
||||
#define LOADOUT_SUBCATEGORY_HEAD_GENERAL "General"
|
||||
#define LOADOUT_SUBCATEGORY_HEAD_JOBS "Jobs"
|
||||
|
||||
//shoes
|
||||
#define LOADOUT_CATEGORY_SHOES "Shoes"
|
||||
|
||||
//gloves
|
||||
#define LOADOUT_CATEGORY_GLOVES "Gloves"
|
||||
|
||||
//glasses
|
||||
#define LOADOUT_CATEGORY_GLASSES "Glasses"
|
||||
|
||||
//donator items
|
||||
#define LOADOUT_CATEGORY_DONATOR "Donator"
|
||||
@@ -38,6 +38,7 @@
|
||||
#define LOG_ADMIN_PRIVATE (1 << 14)
|
||||
#define LOG_ASAY (1 << 15)
|
||||
#define LOG_VIRUS (1 << 16)
|
||||
#define LOG_SHUTTLE (1 << 18)
|
||||
|
||||
//Individual logging panel pages
|
||||
#define INDIVIDUAL_ATTACK_LOG (LOG_ATTACK)
|
||||
|
||||
+15
-4
@@ -341,10 +341,11 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
|
||||
#define COLOUR_PRIORITY_AMOUNT 4 //how many priority levels there are.
|
||||
|
||||
//Endgame Results
|
||||
#define NUKE_MISS_STATION 1
|
||||
#define NUKE_SYNDICATE_BASE 2
|
||||
#define STATION_DESTROYED_NUKE 3
|
||||
#define STATION_EVACUATED 4
|
||||
#define NUKE_NEAR_MISS 1
|
||||
#define NUKE_MISS_STATION 2
|
||||
#define NUKE_SYNDICATE_BASE 3
|
||||
#define STATION_DESTROYED_NUKE 4
|
||||
#define STATION_EVACUATED 5
|
||||
#define BLOB_WIN 8
|
||||
#define BLOB_NUKE 9
|
||||
#define BLOB_DESTROYED 10
|
||||
@@ -434,6 +435,9 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
|
||||
#define ION_FILE "ion_laws.json"
|
||||
#define REDPILL_FILE "redpill.json"
|
||||
#define PIRATE_NAMES_FILE "pirates.json"
|
||||
#define FLESH_SCAR_FILE "wounds/flesh_scar_desc.json"
|
||||
#define BONE_SCAR_FILE "wounds/bone_scar_desc.json"
|
||||
#define SCAR_LOC_FILE "wounds/scar_loc.json"
|
||||
|
||||
|
||||
//Fullscreen overlay resolution in tiles.
|
||||
@@ -534,3 +538,10 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
|
||||
#define LOOT_RESTRICTION_CKEY 2
|
||||
#define LOOT_RESTRICTION_MIND_PILE 3 //limited to the current pile.
|
||||
#define LOOT_RESTRICTION_CKEY_PILE 4 //Idem
|
||||
|
||||
//stages of shoe tying-ness
|
||||
#define SHOES_UNTIED 0
|
||||
#define SHOES_TIED 1
|
||||
#define SHOES_KNOTTED 2
|
||||
|
||||
#define WANTED_FILE "wanted_message.json"
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
// obj/item/dropped
|
||||
/// dropped() relocated this item, return FALSE for doUnEquip.
|
||||
#define ITEM_RELOCATED_BY_DROPPED "relocated_by_dropped"
|
||||
+19
-3
@@ -12,6 +12,8 @@
|
||||
#define MOVE_INTENT_RUN "run"
|
||||
|
||||
//Blood levels
|
||||
#define BLOOD_VOLUME_MAX_LETHAL 2150
|
||||
#define BLOOD_VOLUME_EXCESS 2100
|
||||
#define BLOOD_VOLUME_MAXIMUM 2000
|
||||
#define BLOOD_VOLUME_SLIME_SPLIT 1120
|
||||
#define BLOOD_VOLUME_NORMAL 560
|
||||
@@ -57,6 +59,7 @@
|
||||
#define BODYPART_NOT_DISABLED 0
|
||||
#define BODYPART_DISABLED_DAMAGE 1
|
||||
#define BODYPART_DISABLED_PARALYSIS 2
|
||||
#define BODYPART_DISABLED_WOUND 3
|
||||
|
||||
#define DEFAULT_BODYPART_ICON 'icons/mob/human_parts.dmi'
|
||||
#define DEFAULT_BODYPART_ICON_ORGANIC 'icons/mob/human_parts_greyscale.dmi'
|
||||
@@ -103,12 +106,14 @@
|
||||
#define TRAUMA_RESILIENCE_BASIC 1 //Curable with chems
|
||||
#define TRAUMA_RESILIENCE_SURGERY 2 //Curable with brain surgery
|
||||
#define TRAUMA_RESILIENCE_LOBOTOMY 3 //Curable with lobotomy
|
||||
#define TRAUMA_RESILIENCE_MAGIC 4 //Curable only with magic
|
||||
#define TRAUMA_RESILIENCE_ABSOLUTE 5 //This is here to stay
|
||||
#define TRAUMA_RESILIENCE_WOUND 4 //Curable by healing the head wound
|
||||
#define TRAUMA_RESILIENCE_MAGIC 5 //Curable only with magic
|
||||
#define TRAUMA_RESILIENCE_ABSOLUTE 6 //This is here to stay
|
||||
|
||||
//Limit of traumas for each resilience tier
|
||||
#define TRAUMA_LIMIT_BASIC 3
|
||||
#define TRAUMA_LIMIT_SURGERY 2
|
||||
#define TRAUMA_LIMIT_WOUND 2
|
||||
#define TRAUMA_LIMIT_LOBOTOMY 3
|
||||
#define TRAUMA_LIMIT_MAGIC 3
|
||||
#define TRAUMA_LIMIT_ABSOLUTE INFINITY
|
||||
@@ -171,6 +176,15 @@
|
||||
#define DISGUST_LEVEL_VERYGROSS 50
|
||||
#define DISGUST_LEVEL_GROSS 25
|
||||
|
||||
//Charge levels for Ethereals
|
||||
#define ETHEREAL_CHARGE_NONE 0
|
||||
#define ETHEREAL_CHARGE_LOWPOWER 20
|
||||
#define ETHEREAL_CHARGE_NORMAL 50
|
||||
#define ETHEREAL_CHARGE_ALMOSTFULL 75
|
||||
#define ETHEREAL_CHARGE_FULL 100
|
||||
#define ETHEREAL_CHARGE_OVERLOAD 125
|
||||
#define ETHEREAL_CHARGE_DANGEROUS 150
|
||||
|
||||
//Slime evolution threshold. Controls how fast slimes can split/grow
|
||||
#define SLIME_EVOLUTION_THRESHOLD 10
|
||||
|
||||
@@ -279,6 +293,7 @@
|
||||
#define DOOR_CRUSH_DAMAGE 15 //the amount of damage that airlocks deal when they crush you
|
||||
|
||||
#define HUNGER_FACTOR 0.1 //factor at which mob nutrition decreases
|
||||
#define ETHEREAL_CHARGE_FACTOR 0.08 //factor at which ethereal's charge decreases
|
||||
#define REAGENTS_METABOLISM 0.4 //How many units of reagent are consumed per tick, by default.
|
||||
#define REAGENTS_EFFECT_MULTIPLIER (REAGENTS_METABOLISM / 0.4) // By defining the effect multiplier this way, it'll exactly adjust all effects according to how they originally were with the 0.4 metabolism
|
||||
|
||||
@@ -305,6 +320,7 @@
|
||||
#define GRAB_PIXEL_SHIFT_NECK 16
|
||||
|
||||
#define SLEEP_CHECK_DEATH(X) sleep(X); if(QDELETED(src) || stat == DEAD) return;
|
||||
#define INTERACTING_WITH(X, Y) (Y in X.do_afters)
|
||||
|
||||
/// Field of vision defines.
|
||||
#define FOV_90_DEGREES 90
|
||||
@@ -315,4 +331,4 @@
|
||||
#define EYE_CONTACT_RANGE 5
|
||||
|
||||
/// If you examine the same atom twice in this timeframe, we call examine_more() instead of examine()
|
||||
#define EXAMINE_MORE_TIME 1 SECONDS
|
||||
#define EXAMINE_MORE_TIME 1 SECONDS
|
||||
|
||||
@@ -63,7 +63,6 @@
|
||||
#define MOVESPEED_ID_TASED_STATUS "TASED"
|
||||
#define MOVESPEED_ID_ELECTROSTAFF "ELECTROSTAFF"
|
||||
|
||||
#define MOVESPEED_ID_SHOVE "SHOVE"
|
||||
#define MOVESPEED_ID_FAT "FAT"
|
||||
#define MOVESPEED_ID_COLD "COLD"
|
||||
#define MOVESPEED_ID_HUNGRY "HUNGRY"
|
||||
|
||||
@@ -8,6 +8,5 @@
|
||||
GLOBAL_LIST_INIT(blacklisted_pool_reagents, list(
|
||||
/datum/reagent/toxin/plasma, /datum/reagent/oxygen, /datum/reagent/nitrous_oxide, /datum/reagent/nitrogen, //gases
|
||||
/datum/reagent/fermi, //blanket fermichem ban sorry. this also covers mkultra, genital enlargers, etc etc.
|
||||
/datum/reagent/drug/aphrodisiac, /datum/reagent/drug/anaphrodisiac, /datum/reagent/drug/aphrodisiacplus, /datum/reagent/drug/anaphrodisiacplus, //literally asking for prefbreaks
|
||||
/datum/reagent/consumable/femcum, /datum/reagent/consumable/semen //NO.
|
||||
))
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#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_dmi_create_png(path, width, height, data) call(RUST_G, "dmi_create_png")(path, 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)
|
||||
@@ -14,14 +14,12 @@
|
||||
#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_METHOD_POST "post"
|
||||
#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)
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
|
||||
#define STATUS_EFFECT_REGENERATIVE_CORE /datum/status_effect/regenerative_core //removes damage slowdown while giving a slow regenerating effect
|
||||
|
||||
#define STATUS_EFFECT_DETERMINED /datum/status_effect/determined //currently in a combat high from being seriously wounded
|
||||
|
||||
/////////////
|
||||
// DEBUFFS //
|
||||
/////////////
|
||||
@@ -107,6 +109,11 @@
|
||||
|
||||
#define STATUS_EFFECT_ELECTROSTAFF /datum/status_effect/electrostaff //slows down victim
|
||||
|
||||
#define STATUS_EFFECT_LIMP /datum/status_effect/limp //For when you have a busted leg (or two!) and want additional slowdown when walking on that leg
|
||||
|
||||
/// shoves inflict this to indicate the next shove while this is in effect should disarm guns
|
||||
#define STATUS_EFFECT_OFF_BALANCE /datum/status_effect/off_balance
|
||||
|
||||
/////////////
|
||||
// NEUTRAL //
|
||||
/////////////
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
/// 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
|
||||
#define MINIMUM_PIXELS_PER_ITEM 16
|
||||
/// 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
|
||||
|
||||
@@ -107,6 +107,7 @@
|
||||
#define FIRE_PRIORITY_INSTRUMENTS 30
|
||||
#define FIRE_PRIORITY_FIELDS 30
|
||||
#define FIRE_PRIOTITY_SMOOTHING 35
|
||||
#define FIRE_PRIORITY_HUDS 40
|
||||
#define FIRE_PRIORITY_NETWORKS 40
|
||||
#define FIRE_PRIORITY_OBJ 40
|
||||
#define FIRE_PRIORITY_ACID 40
|
||||
@@ -152,14 +153,17 @@
|
||||
var/list/po = A.priority_overlays;\
|
||||
if(LAZYLEN(rm)){\
|
||||
A.overlays -= rm;\
|
||||
rm.Cut();\
|
||||
A.remove_overlays = null;\
|
||||
}\
|
||||
if(LAZYLEN(ad)){\
|
||||
A.overlays |= ad;\
|
||||
ad.Cut();\
|
||||
A.add_overlays = null;\
|
||||
}\
|
||||
if(LAZYLEN(po)){\
|
||||
A.overlays |= po;\
|
||||
}\
|
||||
else{\
|
||||
A.priority_overlays = null;\
|
||||
}\
|
||||
A.flags_1 &= ~OVERLAY_QUEUED_1;\
|
||||
}
|
||||
|
||||
+28
-4
@@ -1,4 +1,28 @@
|
||||
#define UI_INTERACTIVE 2 // Green/Interactive
|
||||
#define UI_UPDATE 1 // Orange/Updates Only
|
||||
#define UI_DISABLED 0 // Red/Disabled
|
||||
#define UI_CLOSE -1 // Closed
|
||||
/// Green eye; fully interactive
|
||||
#define UI_INTERACTIVE 2
|
||||
/// Orange eye; updates but is not interactive
|
||||
#define UI_UPDATE 1
|
||||
/// Red eye; disabled, does not update
|
||||
#define UI_DISABLED 0
|
||||
/// UI Should close
|
||||
#define UI_CLOSE -1
|
||||
|
||||
/// Maximum number of windows that can be suspended/reused
|
||||
#define TGUI_WINDOW_SOFT_LIMIT 5
|
||||
/// Maximum number of open windows
|
||||
#define TGUI_WINDOW_HARD_LIMIT 9
|
||||
|
||||
/// Maximum ping timeout allowed to detect zombie windows
|
||||
#define TGUI_PING_TIMEOUT 4 SECONDS
|
||||
|
||||
/// Window does not exist
|
||||
#define TGUI_WINDOW_CLOSED 0
|
||||
/// Window was just opened, but is still not ready to be sent data
|
||||
#define TGUI_WINDOW_LOADING 1
|
||||
/// Window is free and ready to receive data
|
||||
#define TGUI_WINDOW_READY 2
|
||||
|
||||
/// Get a window id based on the provided pool index
|
||||
#define TGUI_WINDOW_ID(index) "tgui-window-[index]"
|
||||
/// Get a pool index of the provided window id
|
||||
#define TGUI_WINDOW_INDEX(window_id) text2num(copytext(window_id, 13))
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
//Glasswork Tools
|
||||
#define TOOL_BLOW "blowing_rod"
|
||||
#define TOOL_GLASS_CUT "glasskit"
|
||||
#define TOOL_BONESET "bonesetter"
|
||||
|
||||
// If delay between the start and the end of tool operation is less than MIN_TOOL_SOUND_DELAY,
|
||||
// tool sound is only played when op is started. If not, it's played twice.
|
||||
|
||||
@@ -178,6 +178,7 @@
|
||||
#define TRAIT_FREERUNNING "freerunning"
|
||||
#define TRAIT_SKITTISH "skittish"
|
||||
#define TRAIT_POOR_AIM "poor_aim"
|
||||
#define TRAIT_INSANE_AIM "insane_aim" //they don't miss. they never miss. it was all part of their immaculate plan.
|
||||
#define TRAIT_PROSOPAGNOSIA "prosopagnosia"
|
||||
#define TRAIT_DRUNK_HEALING "drunk_healing"
|
||||
#define TRAIT_TAGGER "tagger"
|
||||
@@ -202,7 +203,7 @@
|
||||
#define TRAIT_NO_ALCOHOL "alcohol_intolerance"
|
||||
#define TRAIT_MUTATION_STASIS "mutation_stasis" //Prevents processed genetics mutations from processing.
|
||||
#define TRAIT_FAST_PUMP "fast_pump"
|
||||
#define TRAIT_NICE_SHOT "nice_shot" //hnnnnnnnggggg..... you're pretty good....
|
||||
#define TRAIT_NICE_SHOT "nice_shot" //hnnnnnnnggggg..... you're pretty good...
|
||||
|
||||
// mobility flag traits
|
||||
// IN THE FUTURE, IT WOULD BE NICE TO DO SOMETHING SIMILAR TO https://github.com/tgstation/tgstation/pull/48923/files (ofcourse not nearly the same because I have my.. thoughts on it)
|
||||
@@ -228,7 +229,7 @@
|
||||
#define TRAIT_SPRINT_LOCKED "sprint_locked"
|
||||
|
||||
//non-mob traits
|
||||
#define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it
|
||||
#define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it
|
||||
#define VEHICLE_TRAIT "vehicle" // inherited from riding vehicles
|
||||
#define INNATE_TRAIT "innate"
|
||||
|
||||
|
||||
@@ -76,6 +76,13 @@
|
||||
#define VV_HK_ADDCOMPONENT "addcomponent"
|
||||
#define VV_HK_MODIFY_TRAITS "modtraits"
|
||||
|
||||
// /datum/gas_mixture
|
||||
#define VV_HK_SET_MOLES "set_moles"
|
||||
#define VV_HK_EMPTY "empty"
|
||||
#define VV_HK_SET_TEMPERATURE "set_temp"
|
||||
#define VV_HK_PARSE_GASSTRING "parse_gasstring"
|
||||
#define VV_HK_SET_VOLUME "set_volume"
|
||||
|
||||
// /atom
|
||||
#define VV_HK_MODIFY_TRANSFORM "atom_transform"
|
||||
#define VV_HK_ADD_REAGENT "addreagent"
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
|
||||
#define WOUND_DAMAGE_EXPONENT 1.225
|
||||
|
||||
/// an attack must do this much damage after armor in order to roll for being a wound (incremental pressure damage need not apply)
|
||||
#define WOUND_MINIMUM_DAMAGE 5
|
||||
/// an attack must do this much damage after armor in order to be eliigible to dismember a suitably mushed bodypart
|
||||
#define DISMEMBER_MINIMUM_DAMAGE 10
|
||||
/// any damage dealt over this is ignored for damage rolls unless the target has the frail quirk (35^1.4=145)
|
||||
#define WOUND_MAX_CONSIDERED_DAMAGE 35
|
||||
|
||||
|
||||
#define WOUND_SEVERITY_TRIVIAL 0 // for jokey/meme wounds like stubbed toe, no standard messages/sounds or second winds
|
||||
#define WOUND_SEVERITY_MODERATE 1
|
||||
#define WOUND_SEVERITY_SEVERE 2
|
||||
#define WOUND_SEVERITY_CRITICAL 3
|
||||
#define WOUND_SEVERITY_LOSS 4 // theoretical total limb loss, like dismemberment for cuts
|
||||
|
||||
/// any brute weapon/attack that doesn't have sharpness. rolls for blunt bone wounds
|
||||
#define WOUND_BLUNT 1
|
||||
/// any brute weapon/attack with sharpness = SHARP_EDGED. rolls for slash wounds
|
||||
#define WOUND_SLASH 2
|
||||
/// any brute weapon/attack with sharpness = SHARP_POINTY. rolls for piercing wounds
|
||||
#define WOUND_PIERCE 3
|
||||
/// any concentrated burn attack (lasers really). rolls for burning wounds
|
||||
#define WOUND_BURN 4
|
||||
|
||||
// How much determination reagent to add each time someone gains a new wound in [/datum/wound/proc/second_wind()]
|
||||
#define WOUND_DETERMINATION_MODERATE 1
|
||||
#define WOUND_DETERMINATION_SEVERE 2.5
|
||||
#define WOUND_DETERMINATION_CRITICAL 5
|
||||
#define WOUND_DETERMINATION_LOSS 7.5
|
||||
|
||||
/// the max amount of determination you can have
|
||||
#define WOUND_DETERMINATION_MAX 10
|
||||
|
||||
/// set wound_bonus on an item or attack to this to disable checking wounding for the attack
|
||||
#define CANT_WOUND -100
|
||||
|
||||
// list in order of highest severity to lowest
|
||||
GLOBAL_LIST_INIT(global_wound_types, list(WOUND_BLUNT = list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate),
|
||||
WOUND_SLASH = list(/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate),
|
||||
WOUND_PIERCE = list(/datum/wound/pierce/critical, /datum/wound/pierce/severe, /datum/wound/pierce/moderate),
|
||||
WOUND_BURN = list(/datum/wound/burn/critical, /datum/wound/burn/severe, /datum/wound/burn/moderate)
|
||||
))
|
||||
|
||||
GLOBAL_LIST_INIT(global_all_wound_types, list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate,
|
||||
/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate,
|
||||
/datum/wound/pierce/critical, /datum/wound/pierce/severe, /datum/wound/pierce/moderate,
|
||||
/datum/wound/burn/critical, /datum/wound/burn/severe, /datum/wound/burn/moderate))
|
||||
|
||||
// Thresholds for infection for burn wounds, once infestation hits each threshold, things get steadily worse
|
||||
/// below this has no ill effects from infection
|
||||
#define WOUND_INFECTION_MODERATE 4
|
||||
/// then below here, you ooze some pus and suffer minor tox damage, but nothing serious
|
||||
#define WOUND_INFECTION_SEVERE 8
|
||||
/// then below here, your limb occasionally locks up from damage and infection and briefly becomes disabled. Things are getting really bad
|
||||
#define WOUND_INFECTION_CRITICAL 12
|
||||
/// below here, your skin is almost entirely falling off and your limb locks up more frequently. You are within a stone's throw of septic paralysis and losing the limb
|
||||
#define WOUND_INFECTION_SEPTIC 20
|
||||
// above WOUND_INFECTION_SEPTIC, your limb is completely putrid and you start rolling to lose the entire limb by way of paralyzation. After 3 failed rolls (~4-5% each probably), the limb is paralyzed
|
||||
|
||||
|
||||
/// how quickly sanitization removes infestation and decays per tick
|
||||
#define WOUND_BURN_SANITIZATION_RATE 0.15
|
||||
/// how much blood you can lose per tick per slash max. 8 is a LOT of blood for one cut so don't worry about hitting it easily
|
||||
#define WOUND_SLASH_MAX_BLOODFLOW 8
|
||||
/// dead people don't bleed, but they can clot! this is the minimum amount of clotting per tick on dead people, so even critical cuts will slowly clot in dead people
|
||||
#define WOUND_SLASH_DEAD_CLOT_MIN 0.05
|
||||
/// if we suffer a bone wound to the head that creates brain traumas, the timer for the trauma cycle is +/- by this percent (0-100)
|
||||
#define WOUND_BONE_HEAD_TIME_VARIANCE 20
|
||||
|
||||
// The following are for persistent scar save formats
|
||||
/// The version number of the scar we're saving
|
||||
#define SCAR_SAVE_VERS 1
|
||||
/// The body_zone we're applying to on granting
|
||||
#define SCAR_SAVE_ZONE 2
|
||||
/// The description we're loading
|
||||
#define SCAR_SAVE_DESC 3
|
||||
/// The precise location we're loading
|
||||
#define SCAR_SAVE_PRECISE_LOCATION 4
|
||||
/// The severity the scar had
|
||||
#define SCAR_SAVE_SEVERITY 5
|
||||
///how many fields there are above (NOT INCLUDING THIS OBVIOUSLY)
|
||||
#define SCAR_SAVE_LENGTH 5
|
||||
|
||||
// increment this number when you update the persistent scarring format in a way that invalidates previous saved scars (new fields, reordering, etc)
|
||||
/// saved scars with a version lower than this will be discarded
|
||||
#define SCAR_CURRENT_VERSION 1
|
||||
|
||||
|
||||
// With the wounds pt. 2 update, general dismemberment now requires 2 things for a limb to be dismemberable (bone only creatures just need the second):
|
||||
// 1. Skin is mangled: A critical slash or pierce wound on that limb
|
||||
// 2. Bone is mangled: At least a severe bone wound on that limb
|
||||
// see [/obj/item/bodypart/proc/get_mangled_state] for more information
|
||||
#define BODYPART_MANGLED_NONE 0
|
||||
#define BODYPART_MANGLED_BONE 1
|
||||
#define BODYPART_MANGLED_FLESH 2
|
||||
#define BODYPART_MANGLED_BOTH 3
|
||||
|
||||
// What kind of biology we have, and what wounds we can suffer, mostly relies on the HAS_FLESH and HAS_BONE species traits on human species
|
||||
/// golems and androids, cannot suffer any wounds
|
||||
#define BIO_INORGANIC 0
|
||||
/// skeletons and plasmemes, can only suffer bone wounds, only needs mangled bone to be able to dismember
|
||||
#define BIO_JUST_BONE 1
|
||||
/// nothing right now, maybe slimepeople in the future, can only suffer slashing, piercing, and burn wounds
|
||||
#define BIO_JUST_FLESH 2
|
||||
/// standard humanoids, can suffer all wounds, needs mangled bone and flesh to dismember
|
||||
#define BIO_FLESH_BONE 3
|
||||
|
||||
/// If this wound requires having the HAS_FLESH flag for humanoids
|
||||
#define FLESH_WOUND (1<<0)
|
||||
/// If this wound requires having the HAS_BONE flag for humanaoids
|
||||
#define BONE_WOUND (1<<1)
|
||||
/// If having this wound counts as mangled flesh for dismemberment
|
||||
#define MANGLES_FLESH (1<<2)
|
||||
/// If having this wound counts as mangled bone for dismemberment
|
||||
#define MANGLES_BONE (1<<3)
|
||||
/// If this wound marks the limb as being allowed to have gauze applied
|
||||
#define ACCEPTS_GAUZE (1<<4)
|
||||
@@ -81,6 +81,10 @@
|
||||
if (CONFIG_GET(flag/log_attack))
|
||||
WRITE_LOG(GLOB.world_attack_log, "ATTACK: [text]")
|
||||
|
||||
/proc/log_wounded(text)
|
||||
if (CONFIG_GET(flag/log_attack))
|
||||
WRITE_LOG(GLOB.world_attack_log, "WOUND: [text]")
|
||||
|
||||
/proc/log_manifest(ckey, datum/mind/mind,mob/body, latejoin = FALSE)
|
||||
if (CONFIG_GET(flag/log_manifest))
|
||||
WRITE_LOG(GLOB.world_manifest_log, "[ckey] \\ [body.real_name] \\ [mind.assigned_role] \\ [mind.special_role ? mind.special_role : "NONE"] \\ [latejoin ? "LATEJOIN":"ROUNDSTART"]")
|
||||
@@ -118,6 +122,9 @@
|
||||
//reusing the PDA option because I really don't think news comments are worth a config option
|
||||
WRITE_LOG(GLOB.world_pda_log, "COMMENT: [text]")
|
||||
|
||||
/proc/log_paper(text)
|
||||
WRITE_LOG(GLOB.world_paper_log, "PAPER: [text]")
|
||||
|
||||
/proc/log_telecomms(text)
|
||||
if (CONFIG_GET(flag/log_telecomms))
|
||||
WRITE_LOG(GLOB.world_telecomms_log, "TCOMMS: [text]")
|
||||
@@ -131,6 +138,10 @@
|
||||
if (CONFIG_GET(flag/log_vote))
|
||||
WRITE_LOG(GLOB.world_game_log, "VOTE: [text]")
|
||||
|
||||
/proc/log_shuttle(text)
|
||||
if (CONFIG_GET(flag/log_shuttle))
|
||||
WRITE_LOG(GLOB.world_shuttle_log, "SHUTTLE: [text]")
|
||||
|
||||
/proc/log_craft(text)
|
||||
if (CONFIG_GET(flag/log_craft))
|
||||
WRITE_LOG(GLOB.world_crafting_log, "CRAFT: [text]")
|
||||
@@ -190,9 +201,18 @@
|
||||
WRITE_LOG(log, "Starting up round ID [GLOB.round_id].\n-------------------------")
|
||||
|
||||
/* ui logging */
|
||||
|
||||
/proc/log_tgui(text)
|
||||
WRITE_LOG(GLOB.tgui_log, text)
|
||||
/proc/log_tgui(user_or_client, text)
|
||||
var/entry = ""
|
||||
if(!user_or_client)
|
||||
entry += "no user"
|
||||
else if(istype(user_or_client, /mob))
|
||||
var/mob/user = user_or_client
|
||||
entry += "[user.ckey] (as [user])"
|
||||
else if(istype(user_or_client, /client))
|
||||
var/client/client = user_or_client
|
||||
entry += "[client.ckey]"
|
||||
entry += ":\n[text]"
|
||||
WRITE_LOG(GLOB.tgui_log, entry)
|
||||
|
||||
/* Close open log handles. This should be called as late as possible, and no logging should hapen after. */
|
||||
/proc/shutdown_logging()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#define pick_list(FILE, KEY) (pick(strings(FILE, KEY)))
|
||||
#define pick_list_weighted(FILE, KEY) (pickweight(strings(FILE, KEY)))
|
||||
#define pick_list_replacements(FILE, KEY) (strings_replacement(FILE, KEY))
|
||||
#define json_load(FILE) (json_decode(file2text(FILE)))
|
||||
|
||||
|
||||
+17
-6
@@ -85,9 +85,6 @@ GLOBAL_VAR_INIT(cmp_field, "name")
|
||||
/proc/cmp_advdisease_resistance_asc(datum/disease/advance/A, datum/disease/advance/B)
|
||||
return A.totalResistance() - B.totalResistance()
|
||||
|
||||
/proc/cmp_job_display_asc(datum/job/A, datum/job/B)
|
||||
return A.display_order - B.display_order
|
||||
|
||||
/proc/cmp_uplink_items_dsc(datum/uplink_item/A, datum/uplink_item/B)
|
||||
return sorttext(initial(B.name), initial(A.name))
|
||||
|
||||
@@ -97,9 +94,6 @@ GLOBAL_VAR_INIT(cmp_field, "name")
|
||||
/proc/cmp_numbered_displays_name_dsc(datum/numbered_display/A, datum/numbered_display/B)
|
||||
return sorttext(B.sample_object.name, A.sample_object.name)
|
||||
|
||||
/proc/cmp_reagents_asc(datum/reagent/a, datum/reagent/b)
|
||||
return sorttext(initial(b.name),initial(a.name))
|
||||
|
||||
/proc/cmp_quirk_asc(datum/quirk/A, datum/quirk/B)
|
||||
var/a_sign = num2sign(initial(A.value) * -1)
|
||||
var/b_sign = num2sign(initial(B.value) * -1)
|
||||
@@ -125,3 +119,20 @@ GLOBAL_VAR_INIT(cmp_field, "name")
|
||||
if(A.ui_category == B.ui_category)
|
||||
return sorttext(A.name, B.name)
|
||||
return sorttext(A.ui_category, B.ui_category)
|
||||
|
||||
/proc/cmp_chemical_reactions_default(datum/chemical_reaction/A, datum/chemical_reaction/B)
|
||||
if(A.priority != B.priority)
|
||||
return B.priority - A.priority
|
||||
else if(A.is_cold_recipe)
|
||||
return A.required_temp - B.required_temp //return coldest
|
||||
else
|
||||
return B.required_temp - A.required_temp //return hottest
|
||||
|
||||
/proc/cmp_job_display_asc(datum/job/A, datum/job/B)
|
||||
return A.display_order - B.display_order
|
||||
|
||||
/proc/cmp_reagents_asc(datum/reagent/a, datum/reagent/b)
|
||||
return sorttext(initial(b.name),initial(a.name))
|
||||
|
||||
/proc/cmp_typepaths_asc(A, B)
|
||||
return sorttext("[B]","[A]")
|
||||
@@ -5,8 +5,9 @@
|
||||
#define GET_INITIALIZED_MUTATION(A) GLOB.all_mutations[A]
|
||||
#define GET_GENE_STRING(A, B) (B.mutation_index[A])
|
||||
#define GET_SEQUENCE(A) (GLOB.full_sequences[A])
|
||||
#define GET_MUTATION_TYPE_FROM_ALIAS(A) (GLOB.alias_mutations[A])
|
||||
|
||||
#define GET_MUTATION_STABILIZER(A) ((A.stabilizer_coeff < 0) ? 1 : A.stabilizer_coeff)
|
||||
#define GET_MUTATION_SYNCHRONIZER(A) ((A.synchronizer_coeff < 0) ? 1 : A.synchronizer_coeff)
|
||||
#define GET_MUTATION_POWER(A) ((A.power_coeff < 0) ? 1 : A.power_coeff)
|
||||
#define GET_MUTATION_ENERGY(A) ((A.energy_coeff < 0) ? 1 : A.energy_coeff)
|
||||
#define GET_MUTATION_ENERGY(A) ((A.energy_coeff < 0) ? 1 : A.energy_coeff)
|
||||
|
||||
@@ -166,6 +166,9 @@
|
||||
|
||||
var/target_loc = target.loc
|
||||
|
||||
LAZYADD(user.do_afters, target)
|
||||
LAZYADD(target.targeted_by, user)
|
||||
|
||||
var/holding = user.get_active_held_item()
|
||||
var/datum/progressbar/progbar
|
||||
if (progress)
|
||||
@@ -183,6 +186,13 @@
|
||||
break
|
||||
if(uninterruptible)
|
||||
continue
|
||||
if(!(target in user.do_afters))
|
||||
. = FALSE
|
||||
break
|
||||
|
||||
if(!(target in user.do_afters))
|
||||
. = FALSE
|
||||
break
|
||||
|
||||
if(drifting && !user.inertia_dir)
|
||||
drifting = 0
|
||||
@@ -191,13 +201,16 @@
|
||||
if((!drifting && user.loc != user_loc) || target.loc != target_loc || (!ignorehelditem && user.get_active_held_item() != holding) || user.incapacitated() || user.lying || (extra_checks && !extra_checks.Invoke()))
|
||||
. = 0
|
||||
break
|
||||
if (progress)
|
||||
if(progress)
|
||||
qdel(progbar)
|
||||
|
||||
if(!QDELETED(target))
|
||||
LAZYREMOVE(user.do_afters, target)
|
||||
LAZYREMOVE(target.targeted_by, user)
|
||||
|
||||
//some additional checks as a callback for for do_afters that want to break on losing health or on the mob taking action
|
||||
/mob/proc/break_do_after_checks(list/checked_health, check_clicks)
|
||||
if(check_clicks && next_move > world.time)
|
||||
if(check_clicks && !CheckActionCooldown())
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -216,6 +229,10 @@
|
||||
if(target && !isturf(target))
|
||||
Tloc = target.loc
|
||||
|
||||
if(target)
|
||||
LAZYADD(user.do_afters, target)
|
||||
LAZYADD(target.targeted_by, user)
|
||||
|
||||
var/atom/Uloc = user.loc
|
||||
|
||||
var/drifting = 0
|
||||
@@ -260,6 +277,10 @@
|
||||
. = 0
|
||||
break
|
||||
|
||||
if(target && !(target in user.do_afters))
|
||||
. = FALSE
|
||||
break
|
||||
|
||||
if(needhand)
|
||||
//This might seem like an odd check, but you can still need a hand even when it's empty
|
||||
//i.e the hand is used to pull some item/tool out of the construction
|
||||
@@ -270,8 +291,14 @@
|
||||
if(user.get_active_held_item() != holding)
|
||||
. = 0
|
||||
break
|
||||
if (progress)
|
||||
if(progress)
|
||||
qdel(progbar)
|
||||
if(!QDELETED(target))
|
||||
LAZYREMOVE(user.do_afters, target)
|
||||
|
||||
if(!QDELETED(target))
|
||||
LAZYREMOVE(user.do_afters, target)
|
||||
LAZYREMOVE(target.targeted_by, user)
|
||||
|
||||
/mob/proc/do_after_coefficent() // This gets added to the delay on a do_after, default 1
|
||||
. = 1
|
||||
@@ -291,6 +318,8 @@
|
||||
var/list/originalloc = list()
|
||||
for(var/atom/target in targets)
|
||||
originalloc[target] = target.loc
|
||||
LAZYADD(user.do_afters, target)
|
||||
LAZYADD(target.targeted_by, user)
|
||||
|
||||
var/holding = user.get_active_held_item()
|
||||
var/datum/progressbar/progbar
|
||||
@@ -321,3 +350,8 @@
|
||||
break mainloop
|
||||
if(progbar)
|
||||
qdel(progbar)
|
||||
for(var/thing in targets)
|
||||
var/atom/target = thing
|
||||
if(!QDELETED(target))
|
||||
LAZYREMOVE(user.do_afters, target)
|
||||
LAZYREMOVE(target.targeted_by, user)
|
||||
|
||||
@@ -53,6 +53,27 @@
|
||||
for(var/I in adjacent_turfs)
|
||||
. |= get_area(I)
|
||||
|
||||
/**
|
||||
* Get a bounding box of a list of atoms.
|
||||
*
|
||||
* Arguments:
|
||||
* - atoms - List of atoms. Can accept output of view() and range() procs.
|
||||
*
|
||||
* Returns: list(x1, y1, x2, y2)
|
||||
*/
|
||||
/proc/get_bbox_of_atoms(list/atoms)
|
||||
var/list/list_x = list()
|
||||
var/list/list_y = list()
|
||||
for(var/_a in atoms)
|
||||
var/atom/a = _a
|
||||
list_x += a.x
|
||||
list_y += a.y
|
||||
return list(
|
||||
min(list_x),
|
||||
min(list_y),
|
||||
max(list_x),
|
||||
max(list_y))
|
||||
|
||||
// Like view but bypasses luminosity check
|
||||
|
||||
/proc/get_hear(range, atom/source)
|
||||
|
||||
@@ -90,7 +90,6 @@
|
||||
init_subtypes(/datum/crafting_recipe, GLOB.crafting_recipes)
|
||||
|
||||
INVOKE_ASYNC(GLOBAL_PROC, /proc/init_ref_coin_values) //so the current procedure doesn't sleep because of UNTIL()
|
||||
INVOKE_ASYNC(GLOBAL_PROC, /proc/setupGenetics)
|
||||
|
||||
//creates every subtype of prototype (excluding prototype) and adds it to list L.
|
||||
//if no list/L is provided, one is created.
|
||||
@@ -117,24 +116,3 @@
|
||||
GLOB.coin_values[path] = C.value
|
||||
qdel(C)
|
||||
|
||||
/proc/setupGenetics()
|
||||
var/list/mutations = subtypesof(/datum/mutation/human)
|
||||
shuffle_inplace(mutations)
|
||||
for(var/A in subtypesof(/datum/generecipe))
|
||||
var/datum/generecipe/GR = A
|
||||
GLOB.mutation_recipes[initial(GR.required)] = initial(GR.result)
|
||||
for(var/i in 1 to LAZYLEN(mutations))
|
||||
var/path = mutations[i] //byond gets pissy when we do it in one line
|
||||
var/datum/mutation/human/B = new path ()
|
||||
B.alias = "Mutation #[i]"
|
||||
GLOB.all_mutations[B.type] = B
|
||||
GLOB.full_sequences[B.type] = generate_gene_sequence(B.blocks)
|
||||
if(B.locked)
|
||||
continue
|
||||
if(B.quality == POSITIVE)
|
||||
GLOB.good_mutations |= B
|
||||
else if(B.quality == NEGATIVE)
|
||||
GLOB.bad_mutations |= B
|
||||
else if(B.quality == MINOR_NEGATIVE)
|
||||
GLOB.not_good_mutations |= B
|
||||
CHECK_TICK
|
||||
+10
-3
@@ -145,9 +145,9 @@
|
||||
continue
|
||||
if(!S.ckeys_allowed)
|
||||
snowflake_ipc_antenna_list[S.name] = mspath
|
||||
var/color1 = random_short_color()
|
||||
var/color2 = random_short_color()
|
||||
var/color3 = random_short_color()
|
||||
var/color1 = random_color()
|
||||
var/color2 = random_color()
|
||||
var/color3 = random_color()
|
||||
|
||||
var/body_model = MALE
|
||||
switch(intended_gender)
|
||||
@@ -264,6 +264,13 @@
|
||||
if(!findname(.))
|
||||
break
|
||||
|
||||
/proc/random_unique_ethereal_name(attempts_to_find_unique_name=10)
|
||||
for(var/i in 1 to attempts_to_find_unique_name)
|
||||
. = capitalize(ethereal_name())
|
||||
|
||||
if(!findname(.))
|
||||
break
|
||||
|
||||
/proc/random_unique_moth_name(attempts_to_find_unique_name=10)
|
||||
for(var/i in 1 to attempts_to_find_unique_name)
|
||||
. = capitalize(pick(GLOB.moth_first)) + " " + capitalize(pick(GLOB.moth_last))
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
else
|
||||
return "[pick(GLOB.lizard_names_female)]-[pick(GLOB.lizard_names_female)]"
|
||||
|
||||
/proc/ethereal_name()
|
||||
var/tempname = "[pick(GLOB.ethereal_names)] [random_capital_letter()]"
|
||||
if(prob(65))
|
||||
tempname += random_capital_letter()
|
||||
return tempname
|
||||
|
||||
/proc/plasmaman_name()
|
||||
return "[pick(GLOB.plasmaman_names)] \Roman[rand(1,99)]"
|
||||
|
||||
|
||||
@@ -51,40 +51,111 @@
|
||||
return default
|
||||
return default
|
||||
|
||||
/proc/sanitize_hexcolor(color, desired_format=3, include_crunch=0, default)
|
||||
#define RGB_FORMAT_INVALID 0
|
||||
#define RGB_FORMAT_SHORT 1
|
||||
#define RGB_FORMAT_LONG 2
|
||||
|
||||
/**
|
||||
* Sanitizes a hexadecimal color. Always outputs lowercase.
|
||||
*
|
||||
* @params
|
||||
* * color - input color, 3 or 6 characters without the #.
|
||||
* * desired_format - 3 or 6 characters without the potential #. can only put in 3 or 6 here.
|
||||
* * include_crunch - do we put a # at the start
|
||||
* * default - default color. must be 3 or 6 characters with or without #.
|
||||
* * default_replacement - what we replace broken letters with.
|
||||
*/
|
||||
/proc/sanitize_hexcolor(color, desired_format = 3, include_crunch = 0, default = rgb(218, 72, 255), default_replacement = "f")
|
||||
if(!istext(default) || (length(default) < 3))
|
||||
CRASH("Default should be a text string of RGB format, with or without the crunch, 3 or 6 characters. Default was instead [default]")
|
||||
if(!istext(default_replacement) || (length(default_replacement) != 1))
|
||||
CRASH("Invalid default_replacement: [default_replacement]")
|
||||
default_replacement = lowertext(default_replacement)
|
||||
switch(text2ascii(default_replacement))
|
||||
if(48 to 57)
|
||||
if(97 to 102)
|
||||
if(65 to 70)
|
||||
else // yeah yeah i know 3 empty if's..
|
||||
CRASH("Invalid default_replacement: [default_replacement]")
|
||||
var/crunch = include_crunch ? "#" : ""
|
||||
if(!istext(color))
|
||||
color = ""
|
||||
color = default
|
||||
|
||||
var/start = 1 + (text2ascii(color, 1) == 35)
|
||||
var/len = length(color)
|
||||
var/char = ""
|
||||
// RRGGBB -> RGB but awful
|
||||
var/convert_to_shorthand = desired_format == 3 && length_char(color) > 3
|
||||
// get rid of crunch
|
||||
if(len && color[1] == "#")
|
||||
if(len >= 2)
|
||||
color = copytext(color, 2)
|
||||
else
|
||||
color = ""
|
||||
len = length(color)
|
||||
|
||||
. = ""
|
||||
var/i = start
|
||||
while(i <= len)
|
||||
switch(desired_format)
|
||||
if(3)
|
||||
desired_format = RGB_FORMAT_SHORT
|
||||
if(6)
|
||||
desired_format = RGB_FORMAT_LONG
|
||||
else
|
||||
CRASH("Invalid desired_format: [desired_format]. Must be 3 or 6.")
|
||||
var/current_format = RGB_FORMAT_INVALID
|
||||
switch(length(color))
|
||||
if(3)
|
||||
current_format = RGB_FORMAT_SHORT
|
||||
if(6)
|
||||
current_format = RGB_FORMAT_LONG
|
||||
else
|
||||
current_format = RGB_FORMAT_INVALID
|
||||
|
||||
if(current_format == RGB_FORMAT_INVALID) // nah
|
||||
color = default // process default
|
||||
if(color[1] == "#") // we checked default was at least 3 chars long earlier
|
||||
color = copytext(color, 2)
|
||||
len = length(color)
|
||||
switch(len)
|
||||
if(3)
|
||||
current_format = RGB_FORMAT_SHORT
|
||||
if(6)
|
||||
current_format = RGB_FORMAT_LONG
|
||||
else
|
||||
CRASH("Default was not 3 or 6 RGB hexadecimal characters: [default]")
|
||||
|
||||
var/sanitized = ""
|
||||
var/char = ""
|
||||
// first, sanitize hex
|
||||
for(var/i in 1 to len)
|
||||
char = color[i]
|
||||
switch(text2ascii(char))
|
||||
if(48 to 57) //numbers 0 to 9
|
||||
. += char
|
||||
if(97 to 102) //letters a to f
|
||||
. += char
|
||||
if(65 to 70) //letters A to F
|
||||
. += lowertext(char)
|
||||
if(48 to 57) // 0 to 9
|
||||
sanitized += char
|
||||
if(97 to 102) // a to f
|
||||
sanitized += char
|
||||
if(65 to 70) // A to F (capitalized!)
|
||||
sanitized += lowertext(char)
|
||||
else
|
||||
break
|
||||
i += length(char)
|
||||
if(convert_to_shorthand && i <= len) //skip next one
|
||||
i += length(color[i])
|
||||
sanitized += default_replacement
|
||||
// do we need to convert?
|
||||
if(desired_format == current_format)
|
||||
return crunch + sanitized // no
|
||||
// yes
|
||||
if((desired_format == RGB_FORMAT_SHORT) && (current_format == RGB_FORMAT_LONG)) // downconvert
|
||||
var/temp = ""
|
||||
// we could do some math but we're lazy and in practice floor()ing this.
|
||||
for(var/i in 1 to 6 step 2)
|
||||
temp += sanitized[i]
|
||||
sanitized = temp
|
||||
else if((desired_format == RGB_FORMAT_LONG) && (current_format == RGB_FORMAT_SHORT)) // upconvert
|
||||
var/temp = ""
|
||||
for(var/i in 1 to 3)
|
||||
temp += sanitized[i]
|
||||
temp += sanitized[i]
|
||||
sanitized = temp
|
||||
else
|
||||
CRASH("Invalid desired_format and current_format pair: [desired_format], [current_format]. Could not determine which way to convert.")
|
||||
return crunch + sanitized
|
||||
|
||||
if(length_char(.) != desired_format)
|
||||
if(default)
|
||||
return default
|
||||
return crunch + repeat_string(desired_format, "0")
|
||||
|
||||
return crunch + .
|
||||
#undef RGB_FORMAT_INVALID
|
||||
#undef RGB_FORMAT_SHORT
|
||||
#undef RGB_FORMAT_LONG
|
||||
|
||||
/proc/sanitize_ooccolor(color)
|
||||
if(length(color) != length_char(color))
|
||||
|
||||
+21
-1
@@ -113,6 +113,22 @@
|
||||
else
|
||||
return trim(html_encode(name), max_length)
|
||||
|
||||
/**
|
||||
* stripped_multiline_input but reflects to the user instead if it's too big and returns null.
|
||||
*/
|
||||
/proc/stripped_multiline_input_or_reflect(mob/user, message = "", title = "", default = "", max_length=MAX_MESSAGE_LEN, no_trim=FALSE)
|
||||
var/name = input(user, message, title, default) as message|null
|
||||
if(isnull(name)) // Return null if canceled.
|
||||
return null
|
||||
if(length(name) > max_length)
|
||||
to_chat(user, name)
|
||||
to_chat(user, "<span class='danger'>^^^----- The preceeding message has been DISCARDED for being over the maximum length of [max_length]. It has NOT been sent! -----^^^</span>")
|
||||
return null
|
||||
if(no_trim)
|
||||
return copytext(html_encode(name), 1, max_length)
|
||||
else
|
||||
return trim(html_encode(name), max_length)
|
||||
|
||||
#define NO_CHARS_DETECTED 0
|
||||
#define SPACES_DETECTED 1
|
||||
#define SYMBOLS_DETECTED 2
|
||||
@@ -760,6 +776,10 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
else
|
||||
return "[number]\th"
|
||||
|
||||
|
||||
/proc/random_capital_letter()
|
||||
return uppertext(pick(GLOB.alphabet))
|
||||
|
||||
/proc/unintelligize(message)
|
||||
var/regex/word_boundaries = regex(@"\b[\S]+\b", "g")
|
||||
var/prefix = message[1]
|
||||
@@ -811,4 +831,4 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
corrupted_text += pick(corruption_options)
|
||||
if(prob(15))
|
||||
corrupted_text += pick(corruption_options)
|
||||
return corrupted_text
|
||||
return corrupted_text
|
||||
|
||||
@@ -339,10 +339,24 @@
|
||||
/proc/isLeap(y)
|
||||
return ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
|
||||
|
||||
|
||||
/// For finding out what body parts a body zone covers, the inverse of the below basically
|
||||
/proc/zone2body_parts_covered(def_zone)
|
||||
switch(def_zone)
|
||||
if(BODY_ZONE_CHEST)
|
||||
return list(CHEST, GROIN)
|
||||
if(BODY_ZONE_HEAD)
|
||||
return list(HEAD)
|
||||
if(BODY_ZONE_L_ARM)
|
||||
return list(ARM_LEFT, HAND_LEFT)
|
||||
if(BODY_ZONE_R_ARM)
|
||||
return list(ARM_RIGHT, HAND_RIGHT)
|
||||
if(BODY_ZONE_L_LEG)
|
||||
return list(LEG_LEFT, FOOT_LEFT)
|
||||
if(BODY_ZONE_R_LEG)
|
||||
return list(LEG_RIGHT, FOOT_RIGHT)
|
||||
|
||||
//Turns a Body_parts_covered bitfield into a list of organ/limb names.
|
||||
//(I challenge you to find a use for this)
|
||||
//(I challenge you to find a use for this) -I found a use for it!!
|
||||
/proc/body_parts_covered2organ_names(bpc)
|
||||
var/list/covered_parts = list()
|
||||
|
||||
|
||||
@@ -1437,7 +1437,6 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
|
||||
/obj/item/reagent_containers/food/snacks/grown,
|
||||
/obj/item/reagent_containers/food/snacks/grown/mushroom,
|
||||
/obj/item/reagent_containers/food/snacks/grown/nettle, // base type
|
||||
/obj/item/reagent_containers/food/snacks/deepfryholder,
|
||||
/obj/item/reagent_containers/food/snacks/grown/shell,
|
||||
/obj/item/reagent_containers/food/snacks/clothing,
|
||||
/obj/item/reagent_containers/food/snacks/store/bread
|
||||
@@ -1509,6 +1508,8 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
|
||||
set waitfor = FALSE
|
||||
return call(source, proctype)(arglist(arguments))
|
||||
|
||||
#define TURF_FROM_COORDS_LIST(List) (locate(List[1], List[2], List[3]))
|
||||
|
||||
/proc/num2sign(numeric)
|
||||
if(numeric > 0)
|
||||
return 1
|
||||
|
||||
@@ -27,5 +27,6 @@ GLOBAL_LIST_EMPTY(full_sequences)
|
||||
GLOBAL_LIST_EMPTY(bad_mutations)
|
||||
GLOBAL_LIST_EMPTY(good_mutations)
|
||||
GLOBAL_LIST_EMPTY(not_good_mutations)
|
||||
GLOBAL_LIST_EMPTY(alias_mutations) //alias = type
|
||||
|
||||
GLOBAL_LIST_EMPTY(mutation_recipes)
|
||||
GLOBAL_LIST_EMPTY(mutation_recipes)
|
||||
|
||||
@@ -116,15 +116,16 @@ GLOBAL_LIST_INIT(ai_core_display_screens, list(
|
||||
|
||||
GLOBAL_LIST_INIT(security_depts_prefs, list(SEC_DEPT_RANDOM, SEC_DEPT_NONE, SEC_DEPT_ENGINEERING, SEC_DEPT_MEDICAL, SEC_DEPT_SCIENCE, SEC_DEPT_SUPPLY))
|
||||
|
||||
//Backpacks
|
||||
#define GBACKPACK "Grey Backpack"
|
||||
#define GSATCHEL "Grey Satchel"
|
||||
#define GDUFFELBAG "Grey Duffel Bag"
|
||||
#define LSATCHEL "Leather Satchel"
|
||||
//Backpacks
|
||||
#define DBACKPACK "Department Backpack"
|
||||
#define DSATCHEL "Department Satchel"
|
||||
#define DDUFFELBAG "Department Duffel Bag"
|
||||
GLOBAL_LIST_INIT(backbaglist, list(DBACKPACK, DSATCHEL, DDUFFELBAG, GBACKPACK, GSATCHEL, GDUFFELBAG, LSATCHEL))
|
||||
GLOBAL_LIST_INIT(backbaglist, list(DBACKPACK, DSATCHEL, DDUFFELBAG, //everything after this point is a non-department backpack
|
||||
"Grey Backpack" = /obj/item/storage/backpack,
|
||||
"Grey Satchel" = /obj/item/storage/backpack/satchel,
|
||||
"Grey Duffel Bag" = /obj/item/storage/backpack/duffelbag,
|
||||
"Leather Satchel" = /obj/item/storage/backpack/satchel/leather,
|
||||
"Snail Shell" = /obj/item/storage/backpack/snail))
|
||||
|
||||
//Suit/Skirt
|
||||
#define PREF_SUIT "Jumpsuit"
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
GLOBAL_LIST_INIT(loadout_categories, list(
|
||||
LOADOUT_CATEGORY_BACKPACK = list(LOADOUT_SUBCATEGORY_BACKPACK_GENERAL, LOADOUT_SUBCATEGORY_BACKPACK_TOYS),
|
||||
LOADOUT_CATEGORY_NECK = list(LOADOUT_SUBCATEGORY_NECK_GENERAL, LOADOUT_SUBCATEGORY_NECK_TIE, LOADOUT_SUBCATEGORY_NECK_SCARVES),
|
||||
LOADOUT_CATEGORY_MASK = LOADOUT_SUBCATEGORIES_NONE,
|
||||
LOADOUT_CATEGORY_HANDS = LOADOUT_SUBCATEGORIES_NONE,
|
||||
LOADOUT_CATEGORY_UNIFORM = list(LOADOUT_SUBCATEGORY_UNIFORM_GENERAL, LOADOUT_SUBCATEGORY_UNIFORM_JOBS, LOADOUT_SUBCATEGORY_UNIFORM_SUITS, LOADOUT_SUBCATEGORY_UNIFORM_SKIRTS, LOADOUT_SUBCATEGORY_UNIFORM_DRESSES, LOADOUT_SUBCATEGORY_UNIFORM_SWEATERS, LOADOUT_SUBCATEGORY_UNIFORM_PANTS, LOADOUT_SUBCATEGORY_UNIFORM_SHORTS),
|
||||
LOADOUT_CATEGORY_SUIT = list(LOADOUT_SUBCATEGORY_SUIT_GENERAL, LOADOUT_SUBCATEGORY_SUIT_COATS, LOADOUT_SUBCATEGORY_SUIT_JACKETS, LOADOUT_SUBCATEGORY_SUIT_JOBS),
|
||||
LOADOUT_CATEGORY_HEAD = list(LOADOUT_SUBCATEGORY_HEAD_GENERAL, LOADOUT_SUBCATEGORY_HEAD_JOBS),
|
||||
LOADOUT_CATEGORY_SHOES = LOADOUT_SUBCATEGORIES_NONE,
|
||||
LOADOUT_CATEGORY_GLOVES = LOADOUT_SUBCATEGORIES_NONE,
|
||||
LOADOUT_CATEGORY_GLASSES = LOADOUT_SUBCATEGORIES_NONE,
|
||||
LOADOUT_CATEGORY_DONATOR = LOADOUT_SUBCATEGORIES_NONE
|
||||
))
|
||||
@@ -38,8 +38,7 @@ GLOBAL_LIST_EMPTY(servant_spawns) //Servants of Ratvar spawn here
|
||||
GLOBAL_LIST_EMPTY(city_of_cogs_spawns) //Anyone entering the City of Cogs spawns here
|
||||
GLOBAL_LIST_EMPTY(ruin_landmarks)
|
||||
|
||||
//away missions
|
||||
GLOBAL_LIST_EMPTY(awaydestinations) //a list of landmarks that the warpgate can take you to
|
||||
//away missions
|
||||
GLOBAL_LIST_EMPTY(vr_spawnpoints)
|
||||
|
||||
//used by jump-to-area etc. Updated by area/updateName()
|
||||
|
||||
@@ -23,6 +23,7 @@ GLOBAL_LIST_EMPTY(joined_player_list) //all clients that have joined the game a
|
||||
GLOBAL_LIST_EMPTY(silicon_mobs) //all silicon mobs
|
||||
GLOBAL_LIST_EMPTY(mob_living_list) //all instances of /mob/living and subtypes
|
||||
GLOBAL_LIST_EMPTY(carbon_list) //all instances of /mob/living/carbon and subtypes, notably does not contain brains or simple animals
|
||||
GLOBAL_LIST_EMPTY(human_list) //all instances of /mob/living/carbon/human and subtypes
|
||||
GLOBAL_LIST_EMPTY(ai_list)
|
||||
GLOBAL_LIST_EMPTY(pai_list)
|
||||
GLOBAL_LIST_EMPTY(available_ai_shells)
|
||||
|
||||
@@ -17,6 +17,7 @@ GLOBAL_LIST_INIT(golem_names, world.file2list("strings/names/golem.txt"))
|
||||
GLOBAL_LIST_INIT(moth_first, world.file2list("strings/names/moth_first.txt"))
|
||||
GLOBAL_LIST_INIT(moth_last, world.file2list("strings/names/moth_last.txt"))
|
||||
GLOBAL_LIST_INIT(plasmaman_names, world.file2list("strings/names/plasmaman.txt"))
|
||||
GLOBAL_LIST_INIT(ethereal_names, world.file2list("strings/names/ethereal.txt"))
|
||||
GLOBAL_LIST_INIT(posibrain_names, world.file2list("strings/names/posibrain.txt"))
|
||||
GLOBAL_LIST_INIT(nightmare_names, world.file2list("strings/names/nightmare.txt"))
|
||||
GLOBAL_LIST_INIT(megacarp_first_names, world.file2list("strings/names/megacarp1.txt"))
|
||||
|
||||
@@ -32,6 +32,8 @@ GLOBAL_VAR(world_asset_log)
|
||||
GLOBAL_PROTECT(world_asset_log)
|
||||
GLOBAL_VAR(world_map_error_log)
|
||||
GLOBAL_PROTECT(world_map_error_log)
|
||||
GLOBAL_VAR(world_paper_log)
|
||||
GLOBAL_PROTECT(world_paper_log)
|
||||
GLOBAL_VAR(subsystem_log)
|
||||
GLOBAL_PROTECT(subsystem_log)
|
||||
GLOBAL_VAR(reagent_log)
|
||||
@@ -49,10 +51,10 @@ GLOBAL_LIST_EMPTY(lastsignalers) //keeps last 100 signals here in format: "[src]
|
||||
GLOBAL_PROTECT(lastsignalers)
|
||||
GLOBAL_LIST_EMPTY(lawchanges) //Stores who uploaded laws to which silicon-based lifeform, and what the law was
|
||||
GLOBAL_PROTECT(lawchanges)
|
||||
|
||||
GLOBAL_VAR(tgui_log)
|
||||
GLOBAL_PROTECT(tgui_log)
|
||||
|
||||
GLOBAL_VAR(world_shuttle_log)
|
||||
GLOBAL_PROTECT(world_shuttle_log)
|
||||
GLOBAL_LIST_EMPTY(combatlog)
|
||||
GLOBAL_PROTECT(combatlog)
|
||||
GLOBAL_LIST_EMPTY(IClog)
|
||||
|
||||
+6
-9
@@ -19,10 +19,6 @@
|
||||
A.move_camera_by_click()
|
||||
|
||||
/mob/living/silicon/ai/ClickOn(var/atom/A, params)
|
||||
if(world.time <= next_click)
|
||||
return
|
||||
next_click = world.time + 1
|
||||
|
||||
if(!can_interact_with(A))
|
||||
return
|
||||
|
||||
@@ -74,16 +70,16 @@
|
||||
CtrlClickOn(A)
|
||||
return
|
||||
|
||||
if(world.time <= next_move)
|
||||
if(!CheckActionCooldown(immediate = TRUE))
|
||||
return
|
||||
|
||||
if(aicamera.in_camera_mode)
|
||||
aicamera.camera_mode_off()
|
||||
aicamera.captureimage(pixel_turf, usr)
|
||||
INVOKE_ASYNC(aicamera, /obj/item/camera.proc/captureimage, pixel_turf, usr)
|
||||
return
|
||||
if(waypoint_mode)
|
||||
waypoint_mode = 0
|
||||
set_waypoint(A)
|
||||
waypoint_mode = FALSE
|
||||
INVOKE_ASYNC(src, .proc/set_waypoint, A)
|
||||
return
|
||||
|
||||
A.attack_ai(src)
|
||||
@@ -94,8 +90,9 @@
|
||||
The below is only really for safety, or you can alter the way
|
||||
it functions and re-insert it above.
|
||||
*/
|
||||
/mob/living/silicon/ai/UnarmedAttack(atom/A)
|
||||
/mob/living/silicon/ai/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
A.attack_ai(src)
|
||||
|
||||
/mob/living/silicon/ai/RangedAttack(atom/A)
|
||||
A.attack_ai(src)
|
||||
|
||||
|
||||
+56
-92
@@ -1,38 +1,3 @@
|
||||
/*
|
||||
Click code cleanup
|
||||
~Sayu
|
||||
*/
|
||||
|
||||
// 1 decisecond click delay (above and beyond mob/next_move)
|
||||
//This is mainly modified by click code, to modify click delays elsewhere, use next_move and changeNext_move()
|
||||
/mob/var/next_click = 0
|
||||
|
||||
// THESE DO NOT EFFECT THE BASE 1 DECISECOND DELAY OF NEXT_CLICK
|
||||
/mob/var/next_move_adjust = 0 //Amount to adjust action/click delays by, + or -
|
||||
/mob/var/next_move_modifier = 1 //Value to multiply action/click delays by
|
||||
|
||||
|
||||
//Delays the mob's next click/action by num deciseconds
|
||||
// eg: 10-3 = 7 deciseconds of delay
|
||||
// eg: 10*0.5 = 5 deciseconds of delay
|
||||
// DOES NOT EFFECT THE BASE 1 DECISECOND DELAY OF NEXT_CLICK
|
||||
|
||||
/mob/proc/timeToNextMove()
|
||||
return max(0, next_move - world.time)
|
||||
|
||||
/mob/proc/changeNext_move(num)
|
||||
next_move = world.time + ((num+next_move_adjust)*next_move_modifier)
|
||||
|
||||
/mob/living/changeNext_move(num)
|
||||
last_click_move = next_move
|
||||
var/mod = next_move_modifier
|
||||
var/adj = next_move_adjust
|
||||
for(var/i in status_effects)
|
||||
var/datum/status_effect/S = i
|
||||
mod *= S.nextmove_modifier()
|
||||
adj += S.nextmove_adjust()
|
||||
next_move = world.time + ((num + adj)*mod)
|
||||
|
||||
/*
|
||||
Before anything else, defer these calls to a per-mobtype handler. This allows us to
|
||||
remove istype() spaghetti code, but requires the addition of other handler procs to simplify it.
|
||||
@@ -45,7 +10,7 @@
|
||||
/atom/Click(location,control,params)
|
||||
if(flags_1 & INITIALIZED_1)
|
||||
SEND_SIGNAL(src, COMSIG_CLICK, location, control, params, usr)
|
||||
usr.ClickOn(src, params)
|
||||
usr.CommonClickOn(src, params)
|
||||
|
||||
/atom/DblClick(location,control,params)
|
||||
if(flags_1 & INITIALIZED_1)
|
||||
@@ -55,6 +20,21 @@
|
||||
if(flags_1 & INITIALIZED_1)
|
||||
usr.MouseWheelOn(src, delta_x, delta_y, params)
|
||||
|
||||
/**
|
||||
* Common mob click code
|
||||
*/
|
||||
/mob/proc/CommonClickOn(atom/A, params)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
if(mob_transforming)
|
||||
return
|
||||
if(SEND_SIGNAL(src, COMSIG_MOB_CLICKON, A, params) & COMSIG_MOB_CANCEL_CLICKON)
|
||||
return
|
||||
. = ClickOn(A, params)
|
||||
if(!(. & DISCARD_LAST_ACTION))
|
||||
FlushCurrentAction()
|
||||
else
|
||||
DiscardCurrentAction()
|
||||
|
||||
/*
|
||||
Standard mob ClickOn()
|
||||
Handles exceptions: Buildmode, middle click, modified clicks, mech actions
|
||||
@@ -68,50 +48,34 @@
|
||||
* item/afterattack(atom,user,adjacent,params) - used both ranged and adjacent
|
||||
* mob/RangedAttack(atom,params) - used only ranged, only used for tk and laser eyes but could be changed
|
||||
*/
|
||||
/mob/proc/ClickOn( atom/A, params )
|
||||
if(world.time <= next_click)
|
||||
return
|
||||
next_click = world.time + world.tick_lag
|
||||
|
||||
/mob/proc/ClickOn(atom/A, params)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
if(check_click_intercept(params,A))
|
||||
return
|
||||
|
||||
if(mob_transforming)
|
||||
return
|
||||
|
||||
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)
|
||||
return
|
||||
return ShiftMiddleClickOn(A)
|
||||
if(modifiers["shift"] && modifiers["ctrl"])
|
||||
CtrlShiftClickOn(A)
|
||||
return
|
||||
return CtrlShiftClickOn(A)
|
||||
if(modifiers["middle"])
|
||||
MiddleClickOn(A)
|
||||
return
|
||||
return MiddleClickOn(A)
|
||||
if(modifiers["shift"] && (client && client.show_popup_menus || modifiers["right"])) //CIT CHANGE - makes shift-click examine use right click instead of left click in combat mode
|
||||
ShiftClickOn(A)
|
||||
return
|
||||
return ShiftClickOn(A)
|
||||
if(modifiers["alt"]) // alt and alt-gr (rightalt)
|
||||
AltClickOn(A)
|
||||
return
|
||||
return AltClickOn(A)
|
||||
if(modifiers["ctrl"])
|
||||
CtrlClickOn(A)
|
||||
return
|
||||
return CtrlClickOn(A)
|
||||
|
||||
if(modifiers["right"]) //CIT CHANGE - allows right clicking to perform actions
|
||||
RightClickOn(A,params) //CIT CHANGE - ditto
|
||||
return //CIT CHANGE - ditto
|
||||
return RightClickOn(A, params) //CIT CHANGE - ditto
|
||||
|
||||
if(incapacitated(ignore_restraints = 1))
|
||||
return
|
||||
|
||||
face_atom(A)
|
||||
|
||||
if(next_move > world.time) // in the year 2000...
|
||||
if(!CheckActionCooldown(immediate = TRUE))
|
||||
return
|
||||
|
||||
if(!modifiers["catcher"] && A.IsObscured())
|
||||
@@ -119,12 +83,12 @@
|
||||
|
||||
if(ismecha(loc))
|
||||
var/obj/mecha/M = loc
|
||||
return M.click_action(A,src,params)
|
||||
M.click_action(A,src,params)
|
||||
return TRUE
|
||||
|
||||
if(restrained())
|
||||
changeNext_move(CLICK_CD_HANDCUFFED) //Doing shit in cuffs shall be vey slow
|
||||
RestrainedClickOn(A)
|
||||
return
|
||||
DelayNextAction(CLICK_CD_HANDCUFFED)
|
||||
return RestrainedClickOn(A)
|
||||
|
||||
if(in_throw_mode)
|
||||
throw_item(A)
|
||||
@@ -141,12 +105,12 @@
|
||||
//User itself, current loc, and user inventory
|
||||
if(A in DirectAccess())
|
||||
if(W)
|
||||
W.melee_attack_chain(src, A, params)
|
||||
return W.melee_attack_chain(src, A, params)
|
||||
else
|
||||
if(ismob(A))
|
||||
changeNext_move(CLICK_CD_MELEE)
|
||||
UnarmedAttack(A)
|
||||
return
|
||||
. = UnarmedAttack(A, TRUE, a_intent)
|
||||
if(!(. & NO_AUTO_CLICKDELAY_HANDLING) && ismob(A))
|
||||
DelayNextAction(CLICK_CD_MELEE)
|
||||
return
|
||||
|
||||
//Can't reach anything else in lockers or other weirdness
|
||||
if(!loc.AllowClick())
|
||||
@@ -155,16 +119,17 @@
|
||||
//Standard reach turf to turf or reaching inside storage
|
||||
if(CanReach(A,W))
|
||||
if(W)
|
||||
W.melee_attack_chain(src, A, params)
|
||||
return W.melee_attack_chain(src, A, params)
|
||||
else
|
||||
if(ismob(A))
|
||||
changeNext_move(CLICK_CD_MELEE)
|
||||
UnarmedAttack(A, 1)
|
||||
. = UnarmedAttack(A, TRUE, a_intent)
|
||||
if(!(. & NO_AUTO_CLICKDELAY_HANDLING) && ismob(A))
|
||||
DelayNextAction(CLICK_CD_MELEE)
|
||||
return
|
||||
else
|
||||
if(W)
|
||||
W.ranged_attack_chain(src, A, params)
|
||||
return W.ranged_attack_chain(src, A, params)
|
||||
else
|
||||
RangedAttack(A,params)
|
||||
return RangedAttack(A,params)
|
||||
|
||||
//Is the atom obscured by a PREVENT_CLICK_UNDER_1 object above it
|
||||
/atom/proc/IsObscured()
|
||||
@@ -269,10 +234,7 @@
|
||||
proximity_flag is not currently passed to attack_hand, and is instead used
|
||||
in human click code to allow glove touches only at melee range.
|
||||
*/
|
||||
/mob/proc/UnarmedAttack(atom/A, proximity_flag)
|
||||
if(ismob(A))
|
||||
changeNext_move(CLICK_CD_MELEE)
|
||||
return
|
||||
/mob/proc/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
|
||||
/*
|
||||
Ranged unarmed attack:
|
||||
@@ -305,7 +267,6 @@
|
||||
var/datum/antagonist/changeling/C = mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(C && C.chosen_sting)
|
||||
C.chosen_sting.try_to_sting(src,A)
|
||||
next_click = world.time + 5
|
||||
return
|
||||
swap_hand()
|
||||
|
||||
@@ -338,24 +299,24 @@
|
||||
*/
|
||||
|
||||
/mob/proc/CtrlClickOn(atom/A)
|
||||
A.CtrlClick(src)
|
||||
return
|
||||
return A.CtrlClick(src)
|
||||
|
||||
/atom/proc/CtrlClick(mob/user)
|
||||
SEND_SIGNAL(src, COMSIG_CLICK_CTRL, user)
|
||||
var/mob/living/ML = user
|
||||
if(istype(ML))
|
||||
ML.pulled(src)
|
||||
INVOKE_ASYNC(ML, /mob/living.verb/pulled, src)
|
||||
|
||||
/mob/living/carbon/human/CtrlClick(mob/user)
|
||||
if(ishuman(user) && Adjacent(user) && !user.incapacitated())
|
||||
if(world.time < user.next_move)
|
||||
if(!user.CheckActionCooldown())
|
||||
return FALSE
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.dna.species.grab(H, src, H.mind.martial_art)
|
||||
H.changeNext_move(CLICK_CD_MELEE)
|
||||
H.DelayNextAction(CLICK_CD_MELEE)
|
||||
return TRUE
|
||||
else
|
||||
..()
|
||||
return ..()
|
||||
/*
|
||||
Alt click
|
||||
Unused except for AI
|
||||
@@ -378,8 +339,8 @@
|
||||
var/datum/antagonist/changeling/C = mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(C && C.chosen_sting)
|
||||
C.chosen_sting.try_to_sting(src,A)
|
||||
next_click = world.time + 5
|
||||
return
|
||||
DelayNextAction(CLICK_CD_RANGE)
|
||||
return TRUE
|
||||
..()
|
||||
|
||||
/atom/proc/AltClick(mob/user)
|
||||
@@ -414,9 +375,11 @@
|
||||
return
|
||||
|
||||
/mob/living/LaserEyes(atom/A, params)
|
||||
changeNext_move(CLICK_CD_RANGE)
|
||||
if(!CheckActionCooldown(CLICK_CD_RANGE))
|
||||
return
|
||||
DelayNextAction()
|
||||
|
||||
var/obj/item/projectile/beam/LE = new /obj/item/projectile/beam( loc )
|
||||
var/obj/item/projectile/beam/LE = new /obj/item/projectile/beam(loc)
|
||||
LE.icon = 'icons/effects/genetics.dmi'
|
||||
LE.icon_state = "eyelasers"
|
||||
playsound(usr.loc, 'sound/weapons/taser2.ogg', 75, 1)
|
||||
@@ -425,6 +388,7 @@
|
||||
LE.def_zone = get_organ_target()
|
||||
LE.preparePixelProjectile(A, src, params)
|
||||
LE.fire()
|
||||
return TRUE
|
||||
|
||||
// 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, ismousemovement = FALSE)
|
||||
|
||||
+19
-30
@@ -7,10 +7,6 @@
|
||||
*/
|
||||
|
||||
/mob/living/silicon/robot/ClickOn(var/atom/A, var/params)
|
||||
if(world.time <= next_click)
|
||||
return
|
||||
next_click = world.time + 1
|
||||
|
||||
if(check_click_intercept(params,A))
|
||||
return
|
||||
|
||||
@@ -19,25 +15,19 @@
|
||||
|
||||
var/list/modifiers = params2list(params)
|
||||
if(modifiers["shift"] && modifiers["ctrl"])
|
||||
CtrlShiftClickOn(A)
|
||||
return
|
||||
return CtrlShiftClickOn(A)
|
||||
if(modifiers["shift"] && modifiers["middle"])
|
||||
ShiftMiddleClickOn(A)
|
||||
return
|
||||
return ShiftMiddleClickOn(A)
|
||||
if(modifiers["middle"])
|
||||
MiddleClickOn(A)
|
||||
return
|
||||
return MiddleClickOn(A)
|
||||
if(modifiers["shift"])
|
||||
ShiftClickOn(A)
|
||||
return
|
||||
return ShiftClickOn(A)
|
||||
if(modifiers["alt"]) // alt and alt-gr (rightalt)
|
||||
AltClickOn(A)
|
||||
return
|
||||
return AltClickOn(A)
|
||||
if(modifiers["ctrl"])
|
||||
CtrlClickOn(A)
|
||||
return
|
||||
return CtrlClickOn(A)
|
||||
|
||||
if(next_move >= world.time)
|
||||
if(!CheckActionCooldown(immediate = TRUE))
|
||||
return
|
||||
|
||||
face_atom(A) // change direction to face what you clicked on
|
||||
@@ -50,7 +40,7 @@
|
||||
*/
|
||||
if(aicamera.in_camera_mode) //Cyborg picture taking
|
||||
aicamera.camera_mode_off()
|
||||
aicamera.captureimage(A, usr)
|
||||
INVOKE_ASYNC(aicamera, /obj/item/camera.proc/captureimage, A, usr)
|
||||
return
|
||||
|
||||
var/obj/item/W = get_active_held_item()
|
||||
@@ -58,13 +48,8 @@
|
||||
if(!W && A.Adjacent(src) && (isobj(A) || ismob(A)))
|
||||
var/atom/movable/C = A
|
||||
if(C.can_buckle && C.has_buckled_mobs())
|
||||
if(C.buckled_mobs.len > 1)
|
||||
var/unbuckled = input(src, "Who do you wish to unbuckle?","Unbuckle Who?") as null|mob in C.buckled_mobs
|
||||
if(C.user_unbuckle_mob(unbuckled,src))
|
||||
return
|
||||
else
|
||||
if(C.user_unbuckle_mob(C.buckled_mobs[1],src))
|
||||
return
|
||||
INVOKE_ASYNC(C, /atom/movable.proc/precise_user_unbuckle_mob, src)
|
||||
return
|
||||
|
||||
if(!W && (get_dist(src,A) <= interaction_range))
|
||||
A.attack_robot(src)
|
||||
@@ -81,7 +66,9 @@
|
||||
|
||||
// cyborgs are prohibited from using storage items so we can I think safely remove (A.loc in contents)
|
||||
if(A == loc || (A in loc) || (A in contents))
|
||||
W.melee_attack_chain(src, A, params)
|
||||
. = W.melee_attack_chain(src, A, params)
|
||||
if(!(. & NO_AUTO_CLICKDELAY_HANDLING) && ismob(A))
|
||||
DelayNextAction(CLICK_CD_MELEE)
|
||||
return
|
||||
|
||||
if(!isturf(loc))
|
||||
@@ -90,11 +77,12 @@
|
||||
// cyborgs are prohibited from using storage items so we can I think safely remove (A.loc && isturf(A.loc.loc))
|
||||
if(isturf(A) || isturf(A.loc))
|
||||
if(A.Adjacent(src)) // see adjacent.dm
|
||||
W.melee_attack_chain(src, A, params)
|
||||
. = W.melee_attack_chain(src, A, params)
|
||||
if(!(. & NO_AUTO_CLICKDELAY_HANDLING) && ismob(A))
|
||||
DelayNextAction(CLICK_CD_MELEE)
|
||||
return
|
||||
else
|
||||
W.afterattack(A, src, 0, params)
|
||||
return
|
||||
return W.afterattack(A, src, 0, params)
|
||||
|
||||
//Middle click cycles through selected modules.
|
||||
/mob/living/silicon/robot/MiddleClickOn(atom/A)
|
||||
@@ -175,8 +163,9 @@
|
||||
clicks, you can do so here, but you will have to
|
||||
change attack_robot() above to the proper function
|
||||
*/
|
||||
/mob/living/silicon/robot/UnarmedAttack(atom/A)
|
||||
/mob/living/silicon/robot/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
A.attack_robot(src)
|
||||
|
||||
/mob/living/silicon/robot/RangedAttack(atom/A)
|
||||
A.attack_robot(src)
|
||||
|
||||
|
||||
@@ -168,6 +168,8 @@
|
||||
//UI position overrides for 1:1 screen layout. (default is 7:5)
|
||||
#define ui_stamina "EAST-1:28,CENTER:17" // replacing internals button
|
||||
#define ui_overridden_resist "EAST-3:24,SOUTH+1:7"
|
||||
#define ui_clickdelay "CENTER,SOUTH+1:-31"
|
||||
#define ui_resistdelay "EAST-3:24,SOUTH+1:4"
|
||||
#define ui_combat_toggle "EAST-4:22,SOUTH:5"
|
||||
|
||||
#define ui_boxcraft "EAST-4:22,SOUTH+1:6"
|
||||
|
||||
@@ -56,9 +56,6 @@
|
||||
if(id && usr.client) //try to (un)remember position
|
||||
usr.client.prefs.action_buttons_screen_locs["[name]_[id]"] = locked ? moved : null
|
||||
return TRUE
|
||||
if(usr.next_click > world.time)
|
||||
return
|
||||
usr.next_click = world.time + 1
|
||||
linked_action.Trigger()
|
||||
return TRUE
|
||||
|
||||
|
||||
+34
-11
@@ -22,7 +22,7 @@
|
||||
if(alerts[category])
|
||||
thealert = alerts[category]
|
||||
if(thealert.override_alerts)
|
||||
return 0
|
||||
return thealert
|
||||
if(new_master && new_master != thealert.master)
|
||||
WARNING("[src] threw alert [category] with new_master [new_master] while already having that alert with master [thealert.master]")
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
clear_alert(category)
|
||||
return .()
|
||||
else //no need to update
|
||||
return 0
|
||||
return thealert
|
||||
else
|
||||
thealert = new type()
|
||||
thealert.override_alerts = override
|
||||
@@ -272,7 +272,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
var/mob/living/L = usr
|
||||
if(!istype(L) || !L.can_resist())
|
||||
return
|
||||
L.changeNext_move(CLICK_CD_RESIST)
|
||||
L.MarkResistTime()
|
||||
if(CHECK_MOBILITY(L, MOBILITY_MOVE))
|
||||
return L.resist_fire() //I just want to start a flame in your hearrrrrrtttttt.
|
||||
|
||||
@@ -447,8 +447,6 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
var/time_name
|
||||
if(G.seconds_until_activation)
|
||||
time_name = "until the Ark activates"
|
||||
else if(G.grace_period)
|
||||
time_name = "of grace period remaining"
|
||||
else if(G.progress_in_seconds)
|
||||
time_name = "until the Ark finishes summoning"
|
||||
if(time_info)
|
||||
@@ -495,6 +493,16 @@ Recharging stations are available in robotics, the dormitory bathrooms, and the
|
||||
desc = "Unit's power cell is running low. Recharging stations are available in robotics, the dormitory bathrooms, and the AI satellite."
|
||||
icon_state = "lowcell"
|
||||
|
||||
/obj/screen/alert/etherealcharge
|
||||
name = "Low Blood Charge"
|
||||
desc = "Your blood's electric charge is running low, find a source of charge for your blood. Use a recharging station found in robotics or the dormitory bathrooms, or eat some Ethereal-friendly food."
|
||||
icon_state = "etherealcharge"
|
||||
|
||||
/obj/screen/alert/ethereal_overcharge
|
||||
name = "Blood Overcharge"
|
||||
desc = "Your blood's electric charge is becoming dangerously high, find an outlet for your energy. Use Grab Intent on an APC to channel your energy into it."
|
||||
icon_state = "ethereal_overcharge"
|
||||
|
||||
//Need to cover all use cases - emag, illegal upgrade module, malf AI hack, traitor cyborg
|
||||
/obj/screen/alert/hacked
|
||||
name = "Hacked"
|
||||
@@ -600,17 +608,32 @@ so as to remain in compliance with the most up-to-date laws."
|
||||
var/mob/living/L = usr
|
||||
if(!istype(L) || !L.can_resist())
|
||||
return
|
||||
L.changeNext_move(CLICK_CD_RESIST)
|
||||
if(CHECK_MOBILITY(L, MOBILITY_MOVE) && (L.last_special <= world.time))
|
||||
return L.resist_restraints()
|
||||
L.MarkResistTime()
|
||||
return L.resist_restraints()
|
||||
|
||||
/obj/screen/alert/restrained/buckled/Click()
|
||||
var/mob/living/L = usr
|
||||
if(!istype(L) || !L.can_resist())
|
||||
return
|
||||
L.changeNext_move(CLICK_CD_RESIST)
|
||||
if(L.last_special <= world.time)
|
||||
return L.resist_buckle()
|
||||
L.MarkResistTime()
|
||||
return L.resist_buckle()
|
||||
|
||||
/obj/screen/alert/shoes/untied
|
||||
name = "Untied Shoes"
|
||||
desc = "Your shoes are untied! Click the alert or your shoes to tie them."
|
||||
icon_state = "shoealert"
|
||||
|
||||
/obj/screen/alert/shoes/knotted
|
||||
name = "Knotted Shoes"
|
||||
desc = "Someone tied your shoelaces together! Click the alert or your shoes to undo the knot."
|
||||
icon_state = "shoealert"
|
||||
|
||||
/obj/screen/alert/shoes/Click()
|
||||
var/mob/living/carbon/C = usr
|
||||
if(!istype(C) || !C.can_resist() || C != mob_viewer || !C.shoes)
|
||||
return
|
||||
C.MarkResistTime()
|
||||
C.shoes.handle_tying(C)
|
||||
|
||||
// PRIVATE = only edit, use, or override these if you're editing the system as a whole
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/datum/hud/marauder
|
||||
var/obj/screen/hosthealth
|
||||
var/obj/screen/blockchance
|
||||
var/obj/screen/counterchance
|
||||
|
||||
/datum/hud/marauder/New(mob/living/simple_animal/hostile/clockwork/marauder/guardian/owner)
|
||||
..()
|
||||
var/obj/screen/using
|
||||
|
||||
healths = new /obj/screen/healths/clock()
|
||||
infodisplay += healths
|
||||
|
||||
hosthealth = new /obj/screen/healths/clock()
|
||||
hosthealth.screen_loc = ui_internal
|
||||
infodisplay += hosthealth
|
||||
|
||||
using = new /obj/screen/marauder/emerge()
|
||||
using.screen_loc = ui_zonesel
|
||||
static_inventory += using
|
||||
|
||||
/datum/hud/marauder/Destroy()
|
||||
blockchance = null
|
||||
counterchance = null
|
||||
hosthealth = null
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/create_mob_hud()
|
||||
if(client && !hud_used)
|
||||
hud_used = new /datum/hud/marauder(src, ui_style2icon(client.prefs.UI_style))
|
||||
|
||||
/obj/screen/marauder
|
||||
icon = 'icons/mob/clockwork_mobs.dmi'
|
||||
|
||||
/obj/screen/marauder/emerge
|
||||
icon_state = "clockguard_emerge"
|
||||
name = "Emerge/Return"
|
||||
desc = "Emerge or Return."
|
||||
|
||||
/obj/screen/marauder/emerge/Click()
|
||||
if(istype(usr, /mob/living/simple_animal/hostile/clockwork/marauder/guardian))
|
||||
var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/G = usr
|
||||
if(G.is_in_host())
|
||||
G.try_emerge()
|
||||
else
|
||||
G.return_to_host()
|
||||
@@ -140,6 +140,17 @@
|
||||
sprint_buffer.hud = src
|
||||
static_inventory += sprint_buffer
|
||||
|
||||
// clickdelay
|
||||
clickdelay = new
|
||||
clickdelay.hud = src
|
||||
clickdelay.screen_loc = ui_clickdelay
|
||||
static_inventory += clickdelay
|
||||
|
||||
// resistdelay
|
||||
resistdelay = new
|
||||
resistdelay.hud = src
|
||||
resistdelay.screen_loc = ui_resistdelay
|
||||
static_inventory += resistdelay
|
||||
|
||||
using = new /obj/screen/drop()
|
||||
using.icon = ui_style
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
/client
|
||||
/**
|
||||
* Assoc list with all the active maps - when a screen obj is added to
|
||||
* a map, it's put in here as well.
|
||||
*
|
||||
* Format: list(<mapname> = list(/obj/screen))
|
||||
*/
|
||||
var/list/screen_maps = list()
|
||||
|
||||
/**
|
||||
* A screen object, which acts as a container for turfs and other things
|
||||
* you want to show on the map, which you usually attach to "vis_contents".
|
||||
*/
|
||||
/obj/screen
|
||||
/**
|
||||
* Map name assigned to this object.
|
||||
* Automatically set by /client/proc/add_obj_to_map.
|
||||
*/
|
||||
var/assigned_map
|
||||
/**
|
||||
* Mark this object as garbage-collectible after you clean the map
|
||||
* it was registered on.
|
||||
*
|
||||
* This could probably be changed to be a proc, for conditional removal.
|
||||
* But for now, this works.
|
||||
*/
|
||||
var/del_on_map_removal = TRUE
|
||||
|
||||
/**
|
||||
* A generic background object.
|
||||
* It is also implicitly used to allocate a rectangle on the map, which will
|
||||
* be used for auto-scaling the map.
|
||||
*/
|
||||
/obj/screen/background
|
||||
name = "background"
|
||||
icon = 'icons/mob/map_backgrounds.dmi'
|
||||
icon_state = "clear"
|
||||
layer = GAME_PLANE
|
||||
plane = GAME_PLANE
|
||||
|
||||
/**
|
||||
* Sets screen_loc of this screen object, in form of point coordinates,
|
||||
* with optional pixel offset (px, py).
|
||||
*
|
||||
* If applicable, "assigned_map" has to be assigned before this proc call.
|
||||
*/
|
||||
/obj/screen/proc/set_position(x, y, px = 0, py = 0)
|
||||
if(assigned_map)
|
||||
screen_loc = "[assigned_map]:[x]:[px],[y]:[py]"
|
||||
else
|
||||
screen_loc = "[x]:[px],[y]:[py]"
|
||||
|
||||
/**
|
||||
* Sets screen_loc to fill a rectangular area of the map.
|
||||
*
|
||||
* If applicable, "assigned_map" has to be assigned before this proc call.
|
||||
*/
|
||||
/obj/screen/proc/fill_rect(x1, y1, x2, y2)
|
||||
if(assigned_map)
|
||||
screen_loc = "[assigned_map]:[x1],[y1] to [x2],[y2]"
|
||||
else
|
||||
screen_loc = "[x1],[y1] to [x2],[y2]"
|
||||
|
||||
/**
|
||||
* Registers screen obj with the client, which makes it visible on the
|
||||
* assigned map, and becomes a part of the assigned map's lifecycle.
|
||||
*/
|
||||
/client/proc/register_map_obj(obj/screen/screen_obj)
|
||||
if(!screen_obj.assigned_map)
|
||||
CRASH("Can't register [screen_obj] without 'assigned_map' property.")
|
||||
if(!screen_maps[screen_obj.assigned_map])
|
||||
screen_maps[screen_obj.assigned_map] = list()
|
||||
// NOTE: Possibly an expensive operation
|
||||
var/list/screen_map = screen_maps[screen_obj.assigned_map]
|
||||
if(!screen_map.Find(screen_obj))
|
||||
screen_map += screen_obj
|
||||
if(!screen.Find(screen_obj))
|
||||
screen += screen_obj
|
||||
|
||||
/**
|
||||
* Clears the map of registered screen objects.
|
||||
*
|
||||
* Not really needed most of the time, as the client's screen list gets reset
|
||||
* on relog. any of the buttons are going to get caught by garbage collection
|
||||
* anyway. they're effectively qdel'd.
|
||||
*/
|
||||
/client/proc/clear_map(map_name)
|
||||
if(!map_name || !(map_name in screen_maps))
|
||||
return FALSE
|
||||
for(var/obj/screen/screen_obj in screen_maps[map_name])
|
||||
screen_maps[map_name] -= screen_obj
|
||||
if(screen_obj.del_on_map_removal)
|
||||
qdel(screen_obj)
|
||||
screen_maps -= map_name
|
||||
|
||||
/**
|
||||
* Clears all the maps of registered screen objects.
|
||||
*/
|
||||
/client/proc/clear_all_maps()
|
||||
for(var/map_name in screen_maps)
|
||||
clear_map(map_name)
|
||||
|
||||
/**
|
||||
* Creates a popup window with a basic map element in it, without any
|
||||
* further initialization.
|
||||
*
|
||||
* Ratio is how many pixels by how many pixels (keep it simple).
|
||||
*
|
||||
* Returns a map name.
|
||||
*/
|
||||
/client/proc/create_popup(name, ratiox = 100, ratioy = 100)
|
||||
winclone(src, "popupwindow", name)
|
||||
var/list/winparams = list()
|
||||
winparams["size"] = "[ratiox]x[ratioy]"
|
||||
winparams["on-close"] = "handle-popup-close [name]"
|
||||
winset(src, "[name]", list2params(winparams))
|
||||
winshow(src, "[name]", 1)
|
||||
|
||||
var/list/params = list()
|
||||
params["parent"] = "[name]"
|
||||
params["type"] = "map"
|
||||
params["size"] = "[ratiox]x[ratioy]"
|
||||
params["anchor1"] = "0,0"
|
||||
params["anchor2"] = "[ratiox],[ratioy]"
|
||||
winset(src, "[name]_map", list2params(params))
|
||||
|
||||
return "[name]_map"
|
||||
|
||||
/**
|
||||
* Create the popup, and get it ready for generic use by giving
|
||||
* it a background.
|
||||
*
|
||||
* Width and height are multiplied by 64 by default.
|
||||
*/
|
||||
/client/proc/setup_popup(popup_name, width = 9, height = 9, \
|
||||
tilesize = 2, bg_icon)
|
||||
if(!popup_name)
|
||||
return
|
||||
clear_map("[popup_name]_map")
|
||||
var/x_value = world.icon_size * tilesize * width
|
||||
var/y_value = world.icon_size * tilesize * height
|
||||
var/map_name = create_popup(popup_name, x_value, y_value)
|
||||
|
||||
var/obj/screen/background/background = new
|
||||
background.assigned_map = map_name
|
||||
background.fill_rect(1, 1, width, height)
|
||||
if(bg_icon)
|
||||
background.icon_state = bg_icon
|
||||
register_map_obj(background)
|
||||
|
||||
return map_name
|
||||
|
||||
/**
|
||||
* Closes a popup.
|
||||
*/
|
||||
/client/proc/close_popup(popup)
|
||||
winshow(src, popup, 0)
|
||||
handle_popup_close(popup)
|
||||
|
||||
/**
|
||||
* When the popup closes in any way (player or proc call) it calls this.
|
||||
*/
|
||||
/client/verb/handle_popup_close(window_id as text)
|
||||
set hidden = TRUE
|
||||
clear_map("[window_id]_map")
|
||||
@@ -128,7 +128,7 @@
|
||||
deltimer(C.parallax_animate_timer)
|
||||
var/datum/callback/CB = CALLBACK(src, .proc/update_parallax_motionblur, C, animatedir, new_parallax_movedir, newtransform)
|
||||
if(skip_windups)
|
||||
CB.Invoke()
|
||||
CB.InvokeAsync()
|
||||
else
|
||||
C.parallax_animate_timer = addtimer(CB, min(shortesttimer, PARALLAX_LOOP_TIME), TIMER_CLIENT_TIME|TIMER_STOPPABLE)
|
||||
|
||||
@@ -219,6 +219,7 @@
|
||||
L.screen_loc = "CENTER-7:[round(L.offset_x,1)],CENTER-7:[round(L.offset_y,1)]"
|
||||
|
||||
/atom/movable/proc/update_parallax_contents()
|
||||
set waitfor = FALSE
|
||||
if(length(client_mobs_in_contents))
|
||||
for(var/thing in client_mobs_in_contents)
|
||||
var/mob/M = thing
|
||||
|
||||
@@ -47,17 +47,7 @@
|
||||
name = "swap hand"
|
||||
|
||||
/obj/screen/swap_hand/Click()
|
||||
// At this point in client Click() code we have passed the 1/10 sec check and little else
|
||||
// We don't even know if it's a middle click
|
||||
if(world.time <= usr.next_move)
|
||||
return 1
|
||||
|
||||
if(usr.incapacitated())
|
||||
return 1
|
||||
|
||||
if(ismob(usr))
|
||||
var/mob/M = usr
|
||||
M.swap_hand()
|
||||
usr.swap_hand()
|
||||
return 1
|
||||
|
||||
/obj/screen/craft
|
||||
@@ -101,15 +91,9 @@
|
||||
plane = HUD_PLANE
|
||||
|
||||
/obj/screen/inventory/Click(location, control, params)
|
||||
// At this point in client Click() code we have passed the 1/10 sec check and little else
|
||||
// We don't even know if it's a middle click
|
||||
if(world.time <= usr.next_move)
|
||||
return TRUE
|
||||
|
||||
if(usr.incapacitated())
|
||||
return TRUE
|
||||
if(ismecha(usr.loc)) // stops inventory actions in a mech
|
||||
return TRUE
|
||||
if(hud?.mymob && (hud.mymob != usr))
|
||||
return
|
||||
// just redirect clicks
|
||||
|
||||
if(hud?.mymob && slot_id)
|
||||
var/obj/item/inv_item = hud.mymob.get_item_by_slot(slot_id)
|
||||
@@ -190,17 +174,10 @@
|
||||
|
||||
|
||||
/obj/screen/inventory/hand/Click(location, control, params)
|
||||
// At this point in client Click() code we have passed the 1/10 sec check and little else
|
||||
// We don't even know if it's a middle click
|
||||
var/mob/user = hud?.mymob
|
||||
if(usr != user)
|
||||
return TRUE
|
||||
if(world.time <= user.next_move)
|
||||
return TRUE
|
||||
if(user.incapacitated())
|
||||
return TRUE
|
||||
if (ismecha(user.loc)) // stops inventory actions in a mech
|
||||
return TRUE
|
||||
if(hud?.mymob && (hud.mymob != usr))
|
||||
return
|
||||
var/mob/user = hud.mymob
|
||||
// just redirect clicks
|
||||
|
||||
if(user.active_hand_index == held_index)
|
||||
var/obj/item/I = user.get_active_held_item()
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/obj/screen/action_bar
|
||||
|
||||
/obj/screen/action_bar/Destroy()
|
||||
STOP_PROCESSING(SShuds, src)
|
||||
return ..()
|
||||
|
||||
/obj/screen/action_bar/proc/mark_dirty()
|
||||
var/mob/living/L = hud?.mymob
|
||||
if(L?.client && update_to_mob(L))
|
||||
START_PROCESSING(SShuds, src)
|
||||
|
||||
/obj/screen/action_bar/process()
|
||||
var/mob/living/L = hud?.mymob
|
||||
if(!L?.client || !update_to_mob(L))
|
||||
return PROCESS_KILL
|
||||
|
||||
/obj/screen/action_bar/proc/update_to_mob(mob/living/L)
|
||||
return FALSE
|
||||
|
||||
/datum/hud/var/obj/screen/action_bar/clickdelay/clickdelay
|
||||
|
||||
/obj/screen/action_bar/clickdelay
|
||||
name = "click delay"
|
||||
icon = 'icons/effects/progessbar.dmi'
|
||||
icon_state = "prog_bar_100"
|
||||
layer = 20 // under hand buttons
|
||||
|
||||
/obj/screen/action_bar/clickdelay/Initialize()
|
||||
. = ..()
|
||||
var/matrix/M = new
|
||||
M.Scale(2, 1)
|
||||
transform = M
|
||||
|
||||
/obj/screen/action_bar/clickdelay/update_to_mob(mob/living/L)
|
||||
var/estimated = L.EstimatedNextActionTime()
|
||||
var/diff = estimated - L.last_action
|
||||
var/left = estimated - world.time
|
||||
if(left < 0 || diff < 0)
|
||||
icon_state = "prog_bar_100"
|
||||
return FALSE
|
||||
icon_state = "prog_bar_[round(clamp(((diff - left)/diff) * 100, 0, 100), 5)]"
|
||||
return TRUE
|
||||
|
||||
/datum/hud/var/obj/screen/action_bar/resistdelay/resistdelay
|
||||
|
||||
/obj/screen/action_bar/resistdelay
|
||||
name = "resist delay"
|
||||
icon = 'icons/effects/progessbar.dmi'
|
||||
icon_state = "prog_bar_100"
|
||||
|
||||
/obj/screen/action_bar/resistdelay/update_to_mob(mob/living/L)
|
||||
var/diff = L.next_resist - L.last_resist
|
||||
var/left = L.next_resist - world.time
|
||||
if(left < 0 || diff < 0)
|
||||
icon_state = "prog_bar_100"
|
||||
return FALSE
|
||||
icon_state = "prog_bar_[round(clamp(((diff - left)/diff) * 100, 0, 100), 5)]"
|
||||
return TRUE
|
||||
@@ -0,0 +1,58 @@
|
||||
/obj/screen/mov_intent
|
||||
icon = 'modular_citadel/icons/ui/screen_midnight.dmi'
|
||||
|
||||
/obj/screen/sprintbutton
|
||||
name = "toggle sprint"
|
||||
icon = 'modular_citadel/icons/ui/screen_midnight.dmi'
|
||||
icon_state = "act_sprint"
|
||||
layer = ABOVE_HUD_LAYER - 0.1
|
||||
var/mutable_appearance/flashy
|
||||
|
||||
/obj/screen/sprintbutton/Click()
|
||||
if(ishuman(usr))
|
||||
var/mob/living/carbon/human/H = usr
|
||||
H.default_toggle_sprint()
|
||||
|
||||
/obj/screen/sprintbutton/update_icon_state()
|
||||
var/mob/living/user = hud?.mymob
|
||||
if(!istype(user))
|
||||
return
|
||||
if(user.combat_flags & COMBAT_FLAG_SPRINT_ACTIVE)
|
||||
icon_state = "act_sprint_on"
|
||||
else if(HAS_TRAIT(user, TRAIT_SPRINT_LOCKED))
|
||||
icon_state = "act_sprint_locked"
|
||||
else
|
||||
icon_state = "act_sprint"
|
||||
|
||||
/obj/screen/sprintbutton/update_overlays()
|
||||
. = ..()
|
||||
var/mob/living/carbon/user = hud?.mymob
|
||||
if(!istype(user) || !user.client)
|
||||
return
|
||||
|
||||
if((user.combat_flags & COMBAT_FLAG_SPRINT_ACTIVE) && user.client.prefs.hud_toggle_flash)
|
||||
if(!flashy)
|
||||
flashy = mutable_appearance('icons/mob/screen_gen.dmi', "togglehalf_flash")
|
||||
if(flashy.color != user.client.prefs.hud_toggle_color)
|
||||
flashy.color = user.client.prefs.hud_toggle_color
|
||||
. += flashy
|
||||
|
||||
//Sprint buffer onscreen code.
|
||||
/datum/hud/var/obj/screen/sprint_buffer/sprint_buffer
|
||||
|
||||
/obj/screen/sprint_buffer
|
||||
name = "sprint buffer"
|
||||
icon = 'icons/effects/progessbar.dmi'
|
||||
icon_state = "prog_bar_100"
|
||||
|
||||
/obj/screen/sprint_buffer/Click()
|
||||
if(isliving(usr))
|
||||
var/mob/living/L = usr
|
||||
to_chat(L, "<span class='boldnotice'>Your sprint buffer's maximum capacity is [L.sprint_buffer_max]. It is currently at [L.sprint_buffer], regenerating at [L.sprint_buffer_regen_ds * 10] per second. \
|
||||
Sprinting while this is empty will incur a [L.sprint_stamina_cost] stamina cost per tile.</span>")
|
||||
|
||||
/obj/screen/sprint_buffer/proc/update_to_mob(mob/living/L)
|
||||
var/amount = 0
|
||||
if(L.sprint_buffer_max > 0)
|
||||
amount = round(clamp((L.sprint_buffer / L.sprint_buffer_max) * 100, 0, 100), 5)
|
||||
icon_state = "prog_bar_[amount]"
|
||||
@@ -0,0 +1,61 @@
|
||||
/datum/hud/var/obj/screen/staminas/staminas
|
||||
/datum/hud/var/obj/screen/staminabuffer/staminabuffer
|
||||
|
||||
/obj/screen/staminas
|
||||
icon = 'modular_citadel/icons/ui/screen_gen.dmi'
|
||||
name = "stamina"
|
||||
icon_state = "stamina0"
|
||||
screen_loc = ui_stamina
|
||||
mouse_opacity = 1
|
||||
|
||||
/obj/screen/staminas/Click(location,control,params)
|
||||
if(isliving(usr))
|
||||
var/mob/living/L = usr
|
||||
to_chat(L, "<span class='notice'>You have <b>[L.getStaminaLoss()]</b> stamina loss.<br>Your stamina buffer can take <b>[L.stambuffer]</b> stamina loss, and recharges at no cost.<br>Your stamina buffer is <b>[(L.stambuffer*(100/L.stambuffer))-(L.bufferedstam*(100/L.stambuffer))]%</b> full.</span>")
|
||||
|
||||
/obj/screen/staminas/update_icon_state()
|
||||
var/mob/living/carbon/user = hud?.mymob
|
||||
if(!user)
|
||||
return
|
||||
if(user.stat == DEAD || (user.combat_flags & COMBAT_FLAG_HARD_STAMCRIT) || (user.hal_screwyhud in 1 to 2))
|
||||
icon_state = "staminacrit"
|
||||
else if(user.hal_screwyhud == 5)
|
||||
icon_state = "stamina0"
|
||||
else
|
||||
icon_state = "stamina[clamp(FLOOR(user.getStaminaLoss() /20, 1), 0, 6)]"
|
||||
|
||||
//stam buffer
|
||||
/obj/screen/staminabuffer
|
||||
icon = 'modular_citadel/icons/ui/screen_gen.dmi'
|
||||
name = "stamina buffer"
|
||||
icon_state = "stambuffer0"
|
||||
screen_loc = ui_stamina
|
||||
layer = ABOVE_HUD_LAYER + 0.1
|
||||
mouse_opacity = 0
|
||||
|
||||
/obj/screen/staminabuffer/update_icon_state()
|
||||
var/mob/living/carbon/user = hud?.mymob
|
||||
if(!user)
|
||||
return
|
||||
if(user.stat == DEAD || (user.combat_flags & COMBAT_FLAG_HARD_STAMCRIT) || (user.hal_screwyhud in 1 to 2))
|
||||
icon_state = "stambuffer7"
|
||||
else if(user.hal_screwyhud == 5)
|
||||
icon_state = "stambuffer0"
|
||||
else
|
||||
switch(user.bufferedstam / user.stambuffer)
|
||||
if(0.95 to INFINITY)
|
||||
icon_state = "stambuffer7"
|
||||
if(0.9 to 0.95)
|
||||
icon_state = "stambuffer6"
|
||||
if(0.8 to 0.9)
|
||||
icon_state = "stambuffer5"
|
||||
if(0.6 to 0.8)
|
||||
icon_state = "stambuffer4"
|
||||
if(0.4 to 0.6)
|
||||
icon_state = "stambuffer3"
|
||||
if(0.2 to 0.4)
|
||||
icon_state = "stambuffer2"
|
||||
if(0.05 to 0.2)
|
||||
icon_state = "stambuffer1"
|
||||
else
|
||||
icon_state = "stambuffer0"
|
||||
@@ -9,12 +9,9 @@
|
||||
/obj/screen/storage/Click(location, control, params)
|
||||
if(!insertion_click)
|
||||
return ..()
|
||||
if(world.time <= usr.next_move)
|
||||
return TRUE
|
||||
if(usr.incapacitated())
|
||||
return TRUE
|
||||
if (ismecha(usr.loc)) // stops inventory actions in a mech
|
||||
return TRUE
|
||||
if(hud?.mymob && (hud.mymob != usr))
|
||||
return
|
||||
// just redirect clicks
|
||||
if(master)
|
||||
var/obj/item/I = usr.get_active_held_item()
|
||||
if(I)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/obj/screen/voretoggle
|
||||
name = "toggle vore mode"
|
||||
icon = 'modular_citadel/icons/ui/screen_midnight.dmi'
|
||||
icon_state = "nom_off"
|
||||
|
||||
/obj/screen/voretoggle/Click()
|
||||
if(usr != hud.mymob)
|
||||
return
|
||||
var/mob/living/carbon/C = usr
|
||||
if(SEND_SIGNAL(usr, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE))
|
||||
to_chat(usr, "<span class='warning'>Disable combat mode first.</span>")
|
||||
return
|
||||
C.toggle_vore_mode()
|
||||
|
||||
/obj/screen/voretoggle/update_icon_state()
|
||||
var/mob/living/carbon/user = hud?.mymob
|
||||
if(!istype(user))
|
||||
return
|
||||
if(user.voremode)
|
||||
icon_state = "nom"
|
||||
else
|
||||
icon_state = "nom_off"
|
||||
@@ -7,21 +7,22 @@
|
||||
*and lastly
|
||||
*afterattack. The return value does not matter.
|
||||
*/
|
||||
/obj/item/proc/melee_attack_chain(mob/user, atom/target, params, flags, damage_multiplier = 1)
|
||||
/obj/item/proc/melee_attack_chain(mob/user, atom/target, params, attackchain_flags, damage_multiplier = 1)
|
||||
if(isliving(user))
|
||||
var/mob/living/L = user
|
||||
if(!CHECK_MOBILITY(L, MOBILITY_USE) && !(flags & ATTACKCHAIN_PARRY_COUNTERATTACK))
|
||||
if(!CHECK_MOBILITY(L, MOBILITY_USE) && !(attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK))
|
||||
to_chat(L, "<span class='warning'>You are unable to swing [src] right now!</span>")
|
||||
return
|
||||
if(tool_behaviour && target.tool_act(user, src, tool_behaviour))
|
||||
. = attackchain_flags
|
||||
if(tool_behaviour && ((. = target.tool_act(user, src, tool_behaviour)) & STOP_ATTACK_PROC_CHAIN))
|
||||
return
|
||||
if(pre_attack(target, user, params))
|
||||
if((. |= pre_attack(target, user, params, ., damage_multiplier)) & STOP_ATTACK_PROC_CHAIN)
|
||||
return
|
||||
if(target.attackby(src, user, params, flags, damage_multiplier))
|
||||
if((. |= target.attackby(src, user, params, ., damage_multiplier)) & STOP_ATTACK_PROC_CHAIN)
|
||||
return
|
||||
if(QDELETED(src) || QDELETED(target))
|
||||
return
|
||||
afterattack(target, user, TRUE, params)
|
||||
. |= afterattack(target, user, TRUE, params)
|
||||
|
||||
/// Like melee_attack_chain but for ranged.
|
||||
/obj/item/proc/ranged_attack_chain(mob/user, atom/target, params)
|
||||
@@ -30,7 +31,7 @@
|
||||
if(!CHECK_MOBILITY(L, MOBILITY_USE))
|
||||
to_chat(L, "<span class='warning'>You are unable to raise [src] right now!</span>")
|
||||
return
|
||||
afterattack(target, user, FALSE, params)
|
||||
return afterattack(target, user, FALSE, params)
|
||||
|
||||
// Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown.
|
||||
/obj/item/proc/attack_self(mob/user)
|
||||
@@ -38,28 +39,43 @@
|
||||
return
|
||||
interact(user)
|
||||
|
||||
/obj/item/proc/pre_attack(atom/A, mob/living/user, params) //do stuff before attackby!
|
||||
/obj/item/proc/pre_attack(atom/A, mob/living/user, params, attackchain_flags, damage_multiplier) //do stuff before attackby!
|
||||
if(SEND_SIGNAL(src, COMSIG_ITEM_PRE_ATTACK, A, user, params) & COMPONENT_NO_ATTACK)
|
||||
return TRUE
|
||||
return FALSE //return TRUE to avoid calling attackby after this proc does stuff
|
||||
return STOP_ATTACK_PROC_CHAIN
|
||||
if(!(attackchain_flags & ATTACK_IGNORE_CLICKDELAY) && !CheckAttackCooldown(user, A))
|
||||
return STOP_ATTACK_PROC_CHAIN
|
||||
|
||||
// No comment
|
||||
/atom/proc/attackby(obj/item/W, mob/user, params)
|
||||
if(SEND_SIGNAL(src, COMSIG_PARENT_ATTACKBY, W, user, params) & COMPONENT_NO_AFTERATTACK)
|
||||
return TRUE
|
||||
return FALSE
|
||||
return STOP_ATTACK_PROC_CHAIN
|
||||
|
||||
/obj/attackby(obj/item/I, mob/living/user, params)
|
||||
return ..() || ((obj_flags & CAN_BE_HIT) && I.attack_obj(src, user))
|
||||
. = ..()
|
||||
if(. & STOP_ATTACK_PROC_CHAIN)
|
||||
return
|
||||
if(obj_flags & CAN_BE_HIT)
|
||||
. |= I.attack_obj(src, user)
|
||||
|
||||
/mob/living/attackby(obj/item/I, mob/living/user, params, attackchain_flags, damage_multiplier)
|
||||
if(..())
|
||||
return TRUE
|
||||
I.attack_delay_done = FALSE //Should be set TRUE in pre_attacked_by()
|
||||
. = I.attack(src, user, attackchain_flags, damage_multiplier)
|
||||
if(!I.attack_delay_done) //Otherwise, pre_attacked_by() should handle it.
|
||||
user.changeNext_move(I.click_delay)
|
||||
. = ..()
|
||||
if(. & STOP_ATTACK_PROC_CHAIN)
|
||||
return
|
||||
. |= I.attack(src, user, attackchain_flags, damage_multiplier)
|
||||
if(!(. & NO_AUTO_CLICKDELAY_HANDLING)) // SAFETY NET - unless the proc tells us we should not handle this, give them the basic melee cooldown!
|
||||
I.ApplyAttackCooldown(user, src, attackchain_flags)
|
||||
|
||||
/**
|
||||
* Called when someone uses us to attack a mob in melee combat.
|
||||
*
|
||||
* This proc respects CheckAttackCooldown() default clickdelay handling.
|
||||
*
|
||||
* @params
|
||||
* * mob/living/M - target
|
||||
* * mob/living/user - attacker
|
||||
* * attackchain_Flags - see [code/__DEFINES/_flags/return_values.dm]
|
||||
* * damage_multiplier - what to multiply the damage by
|
||||
*/
|
||||
/obj/item/proc/attack(mob/living/M, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user) & COMPONENT_ITEM_NO_ATTACK)
|
||||
return
|
||||
@@ -88,6 +104,17 @@
|
||||
if(weight)
|
||||
user.adjustStaminaLossBuffered(weight)
|
||||
|
||||
// CIT SCREENSHAKE
|
||||
if(force >= 15)
|
||||
shake_camera(user, ((force - 10) * 0.01 + 1), ((force - 10) * 0.01))
|
||||
if(M.client)
|
||||
switch (M.client.prefs.damagescreenshake)
|
||||
if (1)
|
||||
shake_camera(M, ((force - 10) * 0.015 + 1), ((force - 10) * 0.015))
|
||||
if (2)
|
||||
if(!CHECK_MOBILITY(M, MOBILITY_MOVE))
|
||||
shake_camera(M, ((force - 10) * 0.015 + 1), ((force - 10) * 0.015))
|
||||
|
||||
//the equivalent of the standard version of attack() but for object targets.
|
||||
/obj/item/proc/attack_obj(obj/O, mob/living/user)
|
||||
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_OBJ, O, user) & COMPONENT_NO_ATTACK_OBJ)
|
||||
@@ -95,8 +122,7 @@
|
||||
if(item_flags & NOBLUDGEON)
|
||||
return
|
||||
user.do_attack_animation(O)
|
||||
if(!O.attacked_by(src, user))
|
||||
user.changeNext_move(click_delay)
|
||||
O.attacked_by(src, user)
|
||||
var/weight = getweight(user, STAM_COST_ATTACK_OBJ_MULT)
|
||||
if(weight)
|
||||
user.adjustStaminaLossBuffered(weight)//CIT CHANGE - makes attacking things cause stamina loss
|
||||
@@ -109,12 +135,9 @@
|
||||
var/bad_trait
|
||||
|
||||
var/stamloss = user.getStaminaLoss()
|
||||
var/next_move_mult = 1
|
||||
if(stamloss > STAMINA_NEAR_SOFTCRIT) //The more tired you are, the less damage you do.
|
||||
var/penalty = (stamloss - STAMINA_NEAR_SOFTCRIT)/(STAMINA_NEAR_CRIT - STAMINA_NEAR_SOFTCRIT)*STAM_CRIT_ITEM_ATTACK_PENALTY
|
||||
totitemdamage *= 1 - penalty
|
||||
next_move_mult += penalty*STAM_CRIT_ITEM_ATTACK_DELAY
|
||||
user.changeNext_move(I.click_delay*next_move_mult)
|
||||
|
||||
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
bad_trait = SKILL_COMBAT_MODE //blacklist combat skills.
|
||||
@@ -126,18 +149,18 @@
|
||||
if(!(SKILL_TRAIN_ATTACK_OBJ in I.used_skills[skill]))
|
||||
continue
|
||||
user.mind.auto_gain_experience(skill, I.skill_gain)
|
||||
|
||||
if(!(attackchain_flags & NO_AUTO_CLICKDELAY_HANDLING))
|
||||
I.ApplyAttackCooldown(user, src, attackchain_flags)
|
||||
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.
|
||||
log_combat(user, src, "attacked", I)
|
||||
take_damage(totitemdamage, I.damtype, "melee", 1)
|
||||
return TRUE
|
||||
|
||||
/mob/living/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
var/list/block_return = list()
|
||||
var/totitemdamage = pre_attacked_by(I, user) * damage_multiplier
|
||||
if((user != src) && mob_run_block(I, totitemdamage, "the [I.name]", ((attackchain_flags & ATTACKCHAIN_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE) | ATTACK_TYPE_MELEE, I.armour_penetration, user, null, block_return) & BLOCK_SUCCESS)
|
||||
if((user != src) && mob_run_block(I, totitemdamage, "the [I.name]", ((attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)? ATTACK_IS_PARRY_COUNTERATTACK : NONE) | ATTACK_TYPE_MELEE, I.armour_penetration, user, null, block_return) & BLOCK_SUCCESS)
|
||||
return FALSE
|
||||
totitemdamage = block_calculate_resultant_damage(totitemdamage, block_return)
|
||||
send_item_attack_message(I, user, null, totitemdamage)
|
||||
@@ -155,8 +178,7 @@
|
||||
|
||||
/mob/living/simple_animal/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
if(I.force < force_threshold || I.damtype == STAMINA)
|
||||
playsound(loc, 'sound/weapons/tap.ogg', I.get_clamped_volume(), 1, -1)
|
||||
user.changeNext_move(I.click_delay) //pre_attacked_by not called
|
||||
playsound(src, 'sound/weapons/tap.ogg', I.get_clamped_volume(), 1, -1)
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -167,25 +189,21 @@
|
||||
|
||||
var/stamloss = user.getStaminaLoss()
|
||||
var/stam_mobility_mult = 1
|
||||
var/next_move_mult = 1
|
||||
if(stamloss > STAMINA_NEAR_SOFTCRIT) //The more tired you are, the less damage you do.
|
||||
var/penalty = (stamloss - STAMINA_NEAR_SOFTCRIT)/(STAMINA_NEAR_CRIT - STAMINA_NEAR_SOFTCRIT)*STAM_CRIT_ITEM_ATTACK_PENALTY
|
||||
stam_mobility_mult -= penalty
|
||||
next_move_mult += penalty*STAM_CRIT_ITEM_ATTACK_DELAY
|
||||
if(stam_mobility_mult > LYING_DAMAGE_PENALTY && !CHECK_MOBILITY(user, MOBILITY_STAND)) //damage penalty for fighting prone, doesn't stack with the above.
|
||||
stam_mobility_mult = LYING_DAMAGE_PENALTY
|
||||
. *= stam_mobility_mult
|
||||
user.changeNext_move(I.click_delay*next_move_mult)
|
||||
I.attack_delay_done = TRUE
|
||||
|
||||
var/bad_trait
|
||||
if(!(I.item_flags & NO_COMBAT_MODE_FORCE_MODIFIER))
|
||||
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
bad_trait = SKILL_COMBAT_MODE //blacklist combat skills.
|
||||
if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE))
|
||||
. *= 0.5
|
||||
. *= 0.8
|
||||
else if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
. *= 1.5
|
||||
. *= 1.2
|
||||
|
||||
if(!user.mind || !I.used_skills)
|
||||
return
|
||||
@@ -197,8 +215,18 @@
|
||||
var/datum/skill/S = GLOB.skill_datums[skill]
|
||||
user.mind.auto_gain_experience(skill, I.skill_gain*S.item_skill_gain_multi)
|
||||
|
||||
// Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person.
|
||||
// Click parameters is the params string from byond Click() code, see that documentation.
|
||||
/**
|
||||
* Called after attacking something if the melee attack chain isn't interrupted before.
|
||||
* Also called when clicking on something with an item without being in melee range
|
||||
*
|
||||
* WARNING: This does not automatically check clickdelay if not in a melee attack! Be sure to account for this!
|
||||
*
|
||||
* @params
|
||||
* * target - The thing we clicked
|
||||
* * user - mob of person clicking
|
||||
* * proximity_flag - are we in melee range/doing it in a melee attack
|
||||
* * click_parameters - mouse control parameters, check BYOND ref.
|
||||
*/
|
||||
/obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
SEND_SIGNAL(src, COMSIG_ITEM_AFTERATTACK, target, user, proximity_flag, click_parameters)
|
||||
SEND_SIGNAL(user, COMSIG_MOB_ITEM_AFTERATTACK, target, user, proximity_flag, click_parameters)
|
||||
@@ -210,25 +238,24 @@
|
||||
else
|
||||
return clamp(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100
|
||||
|
||||
/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area, current_force)
|
||||
/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area, obj/item/bodypart/hit_bodypart)
|
||||
var/message_verb = "attacked"
|
||||
if(I.attack_verb && I.attack_verb.len)
|
||||
if(length(I.attack_verb))
|
||||
message_verb = "[pick(I.attack_verb)]"
|
||||
if(current_force < I.force * FEEBLE_ATTACK_MSG_THRESHOLD)
|
||||
message_verb = "[pick("feebly", "limply", "saplessly")] [message_verb]"
|
||||
else if(!I.force)
|
||||
return
|
||||
var/message_hit_area = ""
|
||||
if(hit_area)
|
||||
message_hit_area = " in the [hit_area]"
|
||||
var/attack_message = "[src] has been [message_verb][message_hit_area] with [I]."
|
||||
var/attack_message = "[src] is [message_verb][message_hit_area] with [I]!"
|
||||
var/attack_message_local = "You're [message_verb][message_hit_area] with [I]!"
|
||||
if(user in viewers(src, null))
|
||||
attack_message = "[user] has [message_verb] [src][message_hit_area] with [I]!"
|
||||
attack_message = "[user] [message_verb] [src][message_hit_area] with [I]!"
|
||||
attack_message_local = "[user] [message_verb] you[message_hit_area] with [I]!"
|
||||
if(user == src)
|
||||
attack_message_local = "You [message_verb] yourself[message_hit_area] with [I]"
|
||||
visible_message("<span class='danger'>[attack_message]</span>",\
|
||||
"<span class='userdanger'>[attack_message]</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
if(hit_area == BODY_ZONE_HEAD)
|
||||
if(prob(2))
|
||||
playsound(src, 'sound/weapons/dink.ogg', 30, 1)
|
||||
"<span class='userdanger'>[attack_message_local]</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
return 1
|
||||
|
||||
/// How much stamina this takes to swing this is not for realism purposes hecc off.
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
CtrlClickOn(A)
|
||||
return
|
||||
|
||||
if(world.time <= next_move)
|
||||
if(!CheckActionCooldown())
|
||||
return
|
||||
// You are responsible for checking config.ghost_interaction when you override this function
|
||||
// Not all of them require checking, see below
|
||||
@@ -63,18 +63,9 @@
|
||||
// And here are some good things for free:
|
||||
// Now you can click through portals, wormholes, gateways, and teleporters while observing. -Sayu
|
||||
|
||||
/obj/machinery/gateway/centerstation/attack_ghost(mob/user)
|
||||
if(awaygate)
|
||||
user.forceMove(awaygate.loc)
|
||||
else
|
||||
to_chat(user, "[src] has no destination.")
|
||||
return ..()
|
||||
|
||||
/obj/machinery/gateway/centeraway/attack_ghost(mob/user)
|
||||
if(stationgate)
|
||||
user.forceMove(stationgate.loc)
|
||||
else
|
||||
to_chat(user, "[src] has no destination.")
|
||||
/obj/effect/gateway_portal_bumper/attack_ghost(mob/user)
|
||||
if(gateway)
|
||||
gateway.Transfer(user)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/teleport/hub/attack_ghost(mob/user)
|
||||
|
||||
+67
-51
@@ -4,39 +4,57 @@
|
||||
|
||||
Otherwise pretty standard.
|
||||
*/
|
||||
/mob/living/carbon/human/UnarmedAttack(atom/A, proximity)
|
||||
|
||||
/mob/living/carbon/human/UnarmedAttack(atom/A, proximity, intent = a_intent, attackchain_flags = NONE)
|
||||
|
||||
if(!has_active_hand()) //can't attack without a hand.
|
||||
to_chat(src, "<span class='notice'>You look at your arm and sigh.</span>")
|
||||
return
|
||||
|
||||
var/obj/item/bodypart/check_arm = get_active_hand()
|
||||
if(check_arm && check_arm.is_disabled() == BODYPART_DISABLED_WOUND)
|
||||
to_chat(src, "<span class='warning'>The damage in your [check_arm.name] is preventing you from using it! Get it fixed, or at least splinted!</span>")
|
||||
return
|
||||
|
||||
. = attackchain_flags
|
||||
// Special glove functions:
|
||||
// If the gloves do anything, have them return 1 to stop
|
||||
// normal attack_hand() here.
|
||||
var/obj/item/clothing/gloves/G = gloves // not typecast specifically enough in defines
|
||||
if(proximity && istype(G) && G.Touch(A,1))
|
||||
return
|
||||
|
||||
var/override = 0
|
||||
if(proximity && istype(G))
|
||||
. |= G.Touch(A, TRUE)
|
||||
if(. & INTERRUPT_UNARMED_ATTACK)
|
||||
return
|
||||
|
||||
for(var/datum/mutation/human/HM in dna.mutations)
|
||||
override += HM.on_attack_hand(A, proximity)
|
||||
. |= HM.on_attack_hand(A, proximity, intent, .)
|
||||
|
||||
if(override)
|
||||
if(. & INTERRUPT_UNARMED_ATTACK)
|
||||
return
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, A)
|
||||
A.attack_hand(src)
|
||||
return . | A.attack_hand(src, intent, .)
|
||||
|
||||
//Return TRUE to cancel other attack hand effects that respect it.
|
||||
/atom/proc/attack_hand(mob/user)
|
||||
. = FALSE
|
||||
/atom/proc/attack_hand(mob/user, act_intent = user.a_intent, attackchain_flags)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
if(!(interaction_flags_atom & INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND))
|
||||
add_fingerprint(user)
|
||||
if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_HAND, user) & COMPONENT_NO_ATTACK_HAND)
|
||||
. = TRUE
|
||||
return
|
||||
. = attackchain_flags
|
||||
if(attack_hand_speed && !(. & ATTACK_IGNORE_CLICKDELAY))
|
||||
if(!user.CheckActionCooldown(attack_hand_speed))
|
||||
return
|
||||
if(interaction_flags_atom & INTERACT_ATOM_ATTACK_HAND)
|
||||
. = _try_interact(user)
|
||||
INVOKE_ASYNC(src, .proc/on_attack_hand, user, act_intent, .)
|
||||
if(!(. & ATTACK_IGNORE_ACTION))
|
||||
if(attack_hand_unwieldlyness)
|
||||
user.DelayNextAction(attack_hand_unwieldlyness, considered_action = attack_hand_is_action)
|
||||
else if(attack_hand_is_action)
|
||||
user.DelayNextAction()
|
||||
|
||||
/atom/proc/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
|
||||
//Return a non FALSE value to cancel whatever called this from propagating, if it respects it.
|
||||
/atom/proc/_try_interact(mob/user)
|
||||
@@ -44,7 +62,6 @@
|
||||
return interact(user)
|
||||
if(can_interact(user))
|
||||
return interact(user)
|
||||
return FALSE
|
||||
|
||||
/atom/proc/can_interact(mob/user)
|
||||
if(!user.can_interact_with(src))
|
||||
@@ -74,8 +91,7 @@
|
||||
else
|
||||
add_fingerprint(user)
|
||||
if(interaction_flags_atom & INTERACT_ATOM_UI_INTERACT)
|
||||
return ui_interact(user)
|
||||
return FALSE
|
||||
ui_interact(user)
|
||||
|
||||
/*
|
||||
/mob/living/carbon/human/RestrainedClickOn(var/atom/A) ---carbons will handle this
|
||||
@@ -89,13 +105,19 @@
|
||||
. = ..()
|
||||
if(gloves)
|
||||
var/obj/item/clothing/gloves/G = gloves
|
||||
if(istype(G) && G.Touch(A,0)) // for magic gloves
|
||||
. |= G.Touch(A, FALSE)
|
||||
if(. & INTERRUPT_UNARMED_ATTACK)
|
||||
return
|
||||
if(istype(glasses))
|
||||
. |= glasses.ranged_attack(src, A, mouseparams)
|
||||
if(. & INTERRUPT_UNARMED_ATTACK)
|
||||
return
|
||||
if (istype(glasses) && glasses.ranged_attack(src,A,mouseparams))
|
||||
return
|
||||
|
||||
for(var/datum/mutation/human/HM in dna.mutations)
|
||||
HM.on_ranged_attack(A, mouseparams)
|
||||
. |= HM.on_ranged_attack(A, mouseparams)
|
||||
|
||||
if(. & INTERRUPT_UNARMED_ATTACK)
|
||||
return
|
||||
|
||||
if(isturf(A) && get_dist(src,A) <= 1)
|
||||
src.Move_Pulled(A)
|
||||
@@ -104,8 +126,8 @@
|
||||
/*
|
||||
Animals & All Unspecified
|
||||
*/
|
||||
/mob/living/UnarmedAttack(atom/A)
|
||||
A.attack_animal(src)
|
||||
/mob/living/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
A.attack_animal(src, intent, flags)
|
||||
|
||||
/atom/proc/attack_animal(mob/user)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_ANIMAL, user)
|
||||
@@ -116,8 +138,10 @@
|
||||
/*
|
||||
Monkeys
|
||||
*/
|
||||
/mob/living/carbon/monkey/UnarmedAttack(atom/A)
|
||||
A.attack_paw(src)
|
||||
/mob/living/carbon/monkey/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
if(!CheckActionCooldown(CLICK_CD_MELEE))
|
||||
return
|
||||
return !isnull(A.attack_paw(src, intent, flags))
|
||||
|
||||
/atom/proc/attack_paw(mob/user)
|
||||
if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_PAW, user) & COMPONENT_NO_ATTACK_HAND)
|
||||
@@ -138,6 +162,8 @@
|
||||
return
|
||||
if(is_muzzled())
|
||||
return
|
||||
if(!CheckActionCooldown(CLICK_CD_MELEE))
|
||||
return
|
||||
var/mob/living/carbon/ML = A
|
||||
if(istype(ML))
|
||||
var/dam_zone = pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
|
||||
@@ -157,13 +183,14 @@
|
||||
ML.ForceContractDisease(D)
|
||||
else
|
||||
ML.visible_message("<span class='danger'>[src] has attempted to bite [ML]!</span>")
|
||||
DelayNextAction()
|
||||
|
||||
/*
|
||||
Aliens
|
||||
Defaults to same as monkey in most places
|
||||
*/
|
||||
/mob/living/carbon/alien/UnarmedAttack(atom/A)
|
||||
A.attack_alien(src)
|
||||
/mob/living/carbon/alien/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
A.attack_alien(src, intent, flags)
|
||||
|
||||
/atom/proc/attack_alien(mob/living/carbon/alien/user)
|
||||
attack_paw(user)
|
||||
@@ -173,29 +200,29 @@
|
||||
return
|
||||
|
||||
// Babby aliens
|
||||
/mob/living/carbon/alien/larva/UnarmedAttack(atom/A)
|
||||
A.attack_larva(src)
|
||||
/mob/living/carbon/alien/larva/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
A.attack_larva(src, intent, flags)
|
||||
|
||||
/atom/proc/attack_larva(mob/user)
|
||||
return
|
||||
|
||||
|
||||
/*
|
||||
Slimes
|
||||
Nothing happening here
|
||||
*/
|
||||
/mob/living/simple_animal/slime/UnarmedAttack(atom/A)
|
||||
A.attack_slime(src)
|
||||
/mob/living/simple_animal/slime/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
A.attack_slime(src, intent, flags)
|
||||
|
||||
/atom/proc/attack_slime(mob/user)
|
||||
return
|
||||
/mob/living/simple_animal/slime/RestrainedClickOn(atom/A)
|
||||
return
|
||||
|
||||
|
||||
/*
|
||||
Drones
|
||||
*/
|
||||
/mob/living/simple_animal/drone/UnarmedAttack(atom/A)
|
||||
A.attack_drone(src)
|
||||
/mob/living/simple_animal/drone/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
A.attack_drone(src, intent, flags)
|
||||
|
||||
/atom/proc/attack_drone(mob/living/simple_animal/drone/user)
|
||||
attack_hand(user) //defaults to attack_hand. Override it when you don't want drones to do same stuff as humans.
|
||||
@@ -203,55 +230,44 @@
|
||||
/mob/living/simple_animal/slime/RestrainedClickOn(atom/A)
|
||||
return
|
||||
|
||||
|
||||
/*
|
||||
True Devil
|
||||
*/
|
||||
|
||||
/mob/living/carbon/true_devil/UnarmedAttack(atom/A, proximity)
|
||||
/mob/living/carbon/true_devil/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
A.attack_hand(src)
|
||||
|
||||
/*
|
||||
Brain
|
||||
*/
|
||||
|
||||
/mob/living/brain/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default
|
||||
/mob/living/brain/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
return
|
||||
|
||||
|
||||
/*
|
||||
pAI
|
||||
*/
|
||||
|
||||
/mob/living/silicon/pai/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default
|
||||
/mob/living/silicon/pai/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
return
|
||||
|
||||
|
||||
/*
|
||||
Simple animals
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/UnarmedAttack(atom/A, proximity)
|
||||
/mob/living/simple_animal/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
if(!dextrous)
|
||||
return ..()
|
||||
if(!ismob(A))
|
||||
A.attack_hand(src)
|
||||
A.attack_hand(src, intent, flags)
|
||||
update_inv_hands()
|
||||
|
||||
|
||||
/*
|
||||
Hostile animals
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/hostile/UnarmedAttack(atom/A)
|
||||
/mob/living/simple_animal/hostile/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
target = A
|
||||
if(dextrous && !ismob(A))
|
||||
..()
|
||||
return ..()
|
||||
else
|
||||
AttackingTarget()
|
||||
|
||||
|
||||
|
||||
/*
|
||||
New Players:
|
||||
Have no reason to click on anything at all.
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/mob/proc/RightClickOn(atom/A, params) //mostly a copy-paste from ClickOn()
|
||||
var/list/modifiers = params2list(params)
|
||||
if(incapacitated(ignore_restraints = 1))
|
||||
return
|
||||
|
||||
face_atom(A)
|
||||
|
||||
if(!CheckActionCooldown())
|
||||
return
|
||||
|
||||
if(!modifiers["catcher"] && A.IsObscured())
|
||||
return
|
||||
|
||||
if(ismecha(loc))
|
||||
var/obj/mecha/M = loc
|
||||
return M.click_action(A,src,params)
|
||||
|
||||
if(restrained())
|
||||
DelayNextAction(CLICK_CD_HANDCUFFED)
|
||||
return RestrainedClickOn(A)
|
||||
|
||||
if(in_throw_mode)
|
||||
throw_item(A)//todo: make it plausible to lightly toss items via right-click
|
||||
return
|
||||
|
||||
var/obj/item/W = get_active_held_item()
|
||||
|
||||
if(W == A)
|
||||
if(!W.rightclick_attack_self(src))
|
||||
W.attack_self(src)
|
||||
update_inv_hands()
|
||||
return
|
||||
|
||||
//These are always reachable.
|
||||
//User itself, current loc, and user inventory
|
||||
if(A in DirectAccess())
|
||||
if(W)
|
||||
return W.rightclick_melee_attack_chain(src, A, params)
|
||||
else
|
||||
if(!AltUnarmedAttack(A, TRUE))
|
||||
. = UnarmedAttack(A, TRUE, a_intent)
|
||||
if(!(. & NO_AUTO_CLICKDELAY_HANDLING) && ismob(A))
|
||||
DelayNextAction(CLICK_CD_MELEE)
|
||||
return
|
||||
return
|
||||
|
||||
//Can't reach anything else in lockers or other weirdness
|
||||
if(!loc.AllowClick())
|
||||
return
|
||||
|
||||
//Standard reach turf to turf or reaching inside storage
|
||||
if(CanReach(A,W))
|
||||
if(W)
|
||||
return W.rightclick_melee_attack_chain(src, A, params)
|
||||
else
|
||||
if(!AltUnarmedAttack(A, TRUE))
|
||||
. = UnarmedAttack(A, TRUE, a_intent)
|
||||
if(!(. & NO_AUTO_CLICKDELAY_HANDLING) && ismob(A))
|
||||
DelayNextAction(CLICK_CD_MELEE)
|
||||
return
|
||||
return
|
||||
else
|
||||
if(W)
|
||||
if(!W.altafterattack(A, src, FALSE, params))
|
||||
return W.afterattack(A, src, FALSE, params)
|
||||
else
|
||||
if(!AltRangedAttack(A, params))
|
||||
return RangedAttack(A, params)
|
||||
|
||||
/mob/proc/AltUnarmedAttack(atom/A, proximity_flag)
|
||||
if(ismob(A))
|
||||
DelayNextAction(CLICK_CD_MELEE)
|
||||
return FALSE
|
||||
|
||||
/mob/proc/AltRangedAttack(atom/A, params)
|
||||
return FALSE
|
||||
@@ -0,0 +1,19 @@
|
||||
/obj/item/proc/rightclick_melee_attack_chain(mob/user, atom/target, params)
|
||||
if(!alt_pre_attack(target, user, params)) //Hey, does this item have special behavior that should override all normal right-click functionality?
|
||||
if(!target.altattackby(src, user, params)) //Does the target do anything special when we right-click on it?
|
||||
. = melee_attack_chain(user, target, params) //Ugh. Lame! I'm filing a legal complaint about the discrimination against the right mouse button!
|
||||
else
|
||||
. = altafterattack(target, user, TRUE, params)
|
||||
|
||||
/obj/item/proc/alt_pre_attack(atom/A, mob/living/user, params)
|
||||
return FALSE //return something other than false if you wanna override attacking completely
|
||||
|
||||
/atom/proc/altattackby(obj/item/W, mob/user, params)
|
||||
return FALSE //return something other than false if you wanna add special right-click behavior to objects.
|
||||
|
||||
/obj/item/proc/rightclick_attack_self(mob/user)
|
||||
return FALSE
|
||||
|
||||
/obj/item/proc/altafterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
SEND_SIGNAL(src, COMSIG_ITEM_ALT_AFTERATTACK, target, user, proximity_flag, click_parameters)
|
||||
return FALSE
|
||||
@@ -0,0 +1,50 @@
|
||||
/mob/living/carbon/human/AltUnarmedAttack(atom/A, proximity)
|
||||
if(!has_active_hand())
|
||||
to_chat(src, "<span class='notice'>You look at the state of the universe and sigh.</span>") //lets face it, people rarely ever see this message in its intended condition.
|
||||
return TRUE
|
||||
|
||||
return A.alt_attack_hand(src)
|
||||
|
||||
/mob/living/carbon/human/AltRangedAttack(atom/A, params)
|
||||
if(isturf(A) || incapacitated()) // pretty annoying to wave your fist at floors and walls. And useless.
|
||||
return
|
||||
if(!CheckActionCooldown(CLICK_CD_RANGE))
|
||||
return
|
||||
DelayNextAction()
|
||||
var/list/target_viewers = fov_viewers(11, A) //doesn't check for blindness.
|
||||
if(!(src in target_viewers)) //click catcher issuing calls for out of view objects.
|
||||
return TRUE
|
||||
if(!has_active_hand())
|
||||
to_chat(src, "<span class='notice'>You ponder your life choices and sigh.</span>")
|
||||
return TRUE
|
||||
var/list/src_viewers = viewers(DEFAULT_MESSAGE_RANGE, src) - src // src has a different message.
|
||||
var/the_action = "waves to [A]"
|
||||
var/what_action = "waves to something you can't see"
|
||||
var/self_action = "wave to [A]"
|
||||
|
||||
switch(a_intent)
|
||||
if(INTENT_DISARM)
|
||||
the_action = "shoos away [A]"
|
||||
what_action = "shoo away something out of your vision"
|
||||
self_action = "shoo away [A]"
|
||||
if(INTENT_GRAB)
|
||||
the_action = "beckons [A] to come"
|
||||
what_action = "beckons something out of your vision to come"
|
||||
self_action = "beckon [A] to come"
|
||||
if(INTENT_HARM)
|
||||
var/pronoun = "[p_their()]"
|
||||
the_action = "shakes [pronoun] fist at [A]"
|
||||
what_action = "shakes [pronoun] fist at something out of your vision"
|
||||
self_action = "shake your fist at [A]"
|
||||
|
||||
if(!eye_blind)
|
||||
to_chat(src, "You [self_action].")
|
||||
for(var/B in src_viewers)
|
||||
var/mob/M = B
|
||||
if(!M.eye_blind)
|
||||
var/message = (M in target_viewers) ? the_action : what_action
|
||||
to_chat(M, "[src] [message].")
|
||||
return TRUE
|
||||
|
||||
/atom/proc/alt_attack_hand(mob/user)
|
||||
return FALSE
|
||||
@@ -123,7 +123,8 @@
|
||||
. = ..()
|
||||
if(!target || !user)
|
||||
return
|
||||
|
||||
if(!user.CheckActionCooldown(CLICK_CD_MELEE))
|
||||
return
|
||||
if(!focus)
|
||||
focus_object(target)
|
||||
return
|
||||
@@ -145,7 +146,7 @@
|
||||
else
|
||||
apply_focus_overlay()
|
||||
focus.throw_at(target, 10, 1,user)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
user.DelayNextAction(considered_action = TRUE, flush = TRUE)
|
||||
update_icon()
|
||||
|
||||
/proc/tkMaxRangeCheck(mob/user, atom/target)
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
var/auto_trim = TRUE
|
||||
|
||||
/datum/config_entry/string/vv_edit_var(var_name, var_value)
|
||||
return var_name != "auto_trim" && ..()
|
||||
return var_name != NAMEOF(src, auto_trim) && ..()
|
||||
|
||||
/datum/config_entry/string/ValidateAndSet(str_val, during_load)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
@@ -110,7 +110,7 @@
|
||||
return FALSE
|
||||
|
||||
/datum/config_entry/number/vv_edit_var(var_name, var_value)
|
||||
var/static/list/banned_edits = list("max_val", "min_val", "integer")
|
||||
var/static/list/banned_edits = list(NAMEOF(src, max_val), NAMEOF(src, min_val), NAMEOF(src, integer))
|
||||
return !(var_name in banned_edits) && ..()
|
||||
|
||||
/datum/config_entry/flag
|
||||
@@ -216,7 +216,7 @@
|
||||
return FALSE
|
||||
|
||||
/datum/config_entry/keyed_list/vv_edit_var(var_name, var_value)
|
||||
return var_name != "splitter" && ..()
|
||||
return var_name != NAMEOF(src, splitter) && ..()
|
||||
|
||||
/datum/config_entry/keyed_list/proc/preprocess_key(key)
|
||||
return key
|
||||
|
||||
@@ -56,6 +56,8 @@
|
||||
/datum/config_entry/flag/log_adminchat // log admin chat messages
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
/datum/config_entry/flag/log_shuttle // log shuttle related actions, ie shuttle computers, shuttle manipulator, emergency console
|
||||
|
||||
/datum/config_entry/flag/log_pda // log pda messages
|
||||
|
||||
/datum/config_entry/flag/log_telecomms // log telecomms messages
|
||||
@@ -468,3 +470,5 @@
|
||||
|
||||
/datum/config_entry/flag/minimaps_enabled
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/string/centcom_ban_db // URL for the CentCom Galactic Ban DB API
|
||||
|
||||
@@ -210,10 +210,10 @@
|
||||
|
||||
/datum/controller/subsystem/vv_edit_var(var_name, var_value)
|
||||
switch (var_name)
|
||||
if ("can_fire")
|
||||
if (NAMEOF(src, can_fire))
|
||||
//this is so the subsystem doesn't rapid fire to make up missed ticks causing more lag
|
||||
if (var_value)
|
||||
next_fire = world.time + wait
|
||||
if ("queued_priority") //editing this breaks things.
|
||||
return 0
|
||||
if (NAMEOF(src, queued_priority)) //editing this breaks things.
|
||||
return FALSE
|
||||
. = ..()
|
||||
|
||||
@@ -16,6 +16,7 @@ SUBSYSTEM_DEF(atoms)
|
||||
|
||||
/datum/controller/subsystem/atoms/Initialize(timeofday)
|
||||
GLOB.fire_overlay.appearance_flags = RESET_COLOR
|
||||
setupGenetics()
|
||||
initialized = INITIALIZATION_INNEW_MAPLOAD
|
||||
InitializeAtoms()
|
||||
return ..()
|
||||
@@ -106,6 +107,29 @@ SUBSYSTEM_DEF(atoms)
|
||||
old_initialized = SSatoms.old_initialized
|
||||
BadInitializeCalls = SSatoms.BadInitializeCalls
|
||||
|
||||
/datum/controller/subsystem/atoms/proc/setupGenetics()
|
||||
var/list/mutations = subtypesof(/datum/mutation/human)
|
||||
shuffle_inplace(mutations)
|
||||
for(var/A in subtypesof(/datum/generecipe))
|
||||
var/datum/generecipe/GR = A
|
||||
GLOB.mutation_recipes[initial(GR.required)] = initial(GR.result)
|
||||
for(var/i in 1 to LAZYLEN(mutations))
|
||||
var/path = mutations[i] //byond gets pissy when we do it in one line
|
||||
var/datum/mutation/human/B = new path ()
|
||||
B.alias = "Mutation [i]"
|
||||
GLOB.all_mutations[B.type] = B
|
||||
GLOB.full_sequences[B.type] = generate_gene_sequence(B.blocks)
|
||||
GLOB.alias_mutations[B.alias] = B.type
|
||||
if(B.locked)
|
||||
continue
|
||||
if(B.quality == POSITIVE)
|
||||
GLOB.good_mutations |= B
|
||||
else if(B.quality == NEGATIVE)
|
||||
GLOB.bad_mutations |= B
|
||||
else if(B.quality == MINOR_NEGATIVE)
|
||||
GLOB.not_good_mutations |= B
|
||||
CHECK_TICK
|
||||
|
||||
/datum/controller/subsystem/atoms/proc/InitLog()
|
||||
. = ""
|
||||
for(var/path in BadInitializeCalls)
|
||||
|
||||
@@ -60,9 +60,9 @@ SUBSYSTEM_DEF(blackbox)
|
||||
|
||||
/datum/controller/subsystem/blackbox/vv_edit_var(var_name, var_value)
|
||||
switch(var_name)
|
||||
if("feedback")
|
||||
if(NAMEOF(src, feedback))
|
||||
return FALSE
|
||||
if("sealed")
|
||||
if(NAMEOF(src, sealed))
|
||||
if(var_value)
|
||||
return Seal()
|
||||
return FALSE
|
||||
|
||||
@@ -31,19 +31,13 @@ SUBSYSTEM_DEF(chat)
|
||||
|
||||
//Some macros remain in the string even after parsing and fuck up the eventual output
|
||||
var/original_message = message
|
||||
message = replacetext(message, "\improper", "")
|
||||
message = replacetext(message, "\proper", "")
|
||||
if(handle_whitespace)
|
||||
message = replacetext(message, "\n", "<br>")
|
||||
message = replacetext(message, "\t", "[FOURSPACES][FOURSPACES]")
|
||||
if (trailing_newline)
|
||||
message += "<br>"
|
||||
|
||||
//url_encode it TWICE, this way any UTF-8 characters are able to be decoded by the Javascript.
|
||||
//Do the double-encoding here to save nanoseconds
|
||||
var/twiceEncoded = url_encode(url_encode(message))
|
||||
var/twiceEncoded
|
||||
|
||||
if(islist(target))
|
||||
var/sanitized_message = FALSE
|
||||
for(var/I in target)
|
||||
var/client/C = CLIENT_FROM_VAR(I) //Grab us a client if possible
|
||||
|
||||
@@ -55,6 +49,17 @@ SUBSYSTEM_DEF(chat)
|
||||
|
||||
if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file.
|
||||
continue
|
||||
|
||||
if(!sanitized_message)
|
||||
message = replacetext(message, "\improper", "")
|
||||
message = replacetext(message, "\proper", "")
|
||||
if(handle_whitespace)
|
||||
message = replacetext(message, "\n", "<br>")
|
||||
message = replacetext(message, "\t", "[FOURSPACES][FOURSPACES]")
|
||||
if (trailing_newline)
|
||||
message += "<br>"
|
||||
twiceEncoded = url_encode(url_encode(message))
|
||||
sanitized_message = TRUE
|
||||
|
||||
if(!C.chatOutput.loaded) //Client still loading, put their messages in a queue
|
||||
C.chatOutput.messageQueue += message
|
||||
@@ -74,6 +79,15 @@ SUBSYSTEM_DEF(chat)
|
||||
if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file.
|
||||
return
|
||||
|
||||
message = replacetext(message, "\improper", "")
|
||||
message = replacetext(message, "\proper", "")
|
||||
if(handle_whitespace)
|
||||
message = replacetext(message, "\n", "<br>")
|
||||
message = replacetext(message, "\t", "[FOURSPACES][FOURSPACES]")
|
||||
if (trailing_newline)
|
||||
message += "<br>"
|
||||
twiceEncoded = url_encode(url_encode(message))
|
||||
|
||||
if(!C.chatOutput.loaded) //Client still loading, put their messages in a queue
|
||||
C.chatOutput.messageQueue += message
|
||||
return
|
||||
|
||||
@@ -674,7 +674,7 @@ SUBSYSTEM_DEF(job)
|
||||
return
|
||||
for(var/i in the_mob.client.prefs.chosen_gear)
|
||||
var/datum/gear/G = i
|
||||
G = GLOB.loadout_items[slot_to_string(initial(G.category))][initial(G.name)]
|
||||
G = GLOB.loadout_items[initial(G.category)][initial(G.subcategory)][initial(G.name)]
|
||||
if(!G)
|
||||
continue
|
||||
var/permitted = TRUE
|
||||
@@ -682,14 +682,14 @@ SUBSYSTEM_DEF(job)
|
||||
permitted = FALSE
|
||||
if(G.donoritem && !G.donator_ckey_check(the_mob.client.ckey))
|
||||
permitted = FALSE
|
||||
if(!equipbackpackstuff && G.category == SLOT_IN_BACKPACK)//snowflake check since plopping stuff in the backpack doesnt work for pre-job equip loadout stuffs
|
||||
if(!equipbackpackstuff && G.slot == SLOT_IN_BACKPACK)//snowflake check since plopping stuff in the backpack doesnt work for pre-job equip loadout stuffs
|
||||
permitted = FALSE
|
||||
if(equipbackpackstuff && G.category != SLOT_IN_BACKPACK)//ditto
|
||||
if(equipbackpackstuff && G.slot != SLOT_IN_BACKPACK)//ditto
|
||||
permitted = FALSE
|
||||
if(!permitted)
|
||||
continue
|
||||
var/obj/item/I = new G.path
|
||||
if(!M.equip_to_slot_if_possible(I, G.category, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) // If the job's dresscode compliant, try to put it in its slot, first
|
||||
if(!M.equip_to_slot_if_possible(I, G.slot, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) // If the job's dresscode compliant, try to put it in its slot, first
|
||||
if(iscarbon(M))
|
||||
var/mob/living/carbon/C = M
|
||||
var/obj/item/storage/backpack/B = C.back
|
||||
|
||||
@@ -334,6 +334,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
for (var/map in mapvotes)
|
||||
if (!map)
|
||||
mapvotes.Remove(map)
|
||||
continue
|
||||
if (!(map in global.config.maplist))
|
||||
mapvotes.Remove(map)
|
||||
continue
|
||||
@@ -468,11 +469,10 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
else
|
||||
return
|
||||
|
||||
possible_options += "Custom"
|
||||
var/lvl_name
|
||||
var/datum/space_level/level
|
||||
var/away_name
|
||||
var/datum/space_level/away_level
|
||||
|
||||
var/answer = input("What kind ? ","Away/VR") as null|anything in possible_options
|
||||
var/answer = input("What kind ? ","Away/VR") as null|anything in list(possible_options + "Custom")
|
||||
switch(answer)
|
||||
if(null)
|
||||
return
|
||||
@@ -480,34 +480,22 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
var/mapfile = input("Pick file:", "File") as null|file
|
||||
if(!mapfile)
|
||||
return
|
||||
lvl_name = "[mapfile] custom"
|
||||
to_chat(usr,"<span class='notice'>Loading [lvl_name]...</span>")
|
||||
away_name = "[mapfile] custom"
|
||||
to_chat(usr,"<span class='notice'>Loading [away_name]...</span>")
|
||||
var/datum/map_template/template = new(mapfile, choice, ztraits)
|
||||
level = template.load_new_z(ztraits)
|
||||
away_level = template.load_new_z(ztraits)
|
||||
else
|
||||
lvl_name = answer
|
||||
to_chat(usr,"<span class='notice'>Loading [lvl_name]...</span>")
|
||||
var/datum/map_template/template = new(lvl_name, choice)
|
||||
level = template.load_new_z(ztraits)
|
||||
away_name = answer
|
||||
to_chat(usr,"<span class='notice'>Loading [away_name]...</span>")
|
||||
var/datum/map_template/template = new(away_name, choice)
|
||||
away_level = template.load_new_z(ztraits)
|
||||
|
||||
message_admins("Admin [key_name_admin(usr)] has loaded [lvl_name] [choice].")
|
||||
log_admin("Admin [key_name(usr)] has loaded [lvl_name] [choice].")
|
||||
if(!level)
|
||||
message_admins("Loading [lvl_name] failed!")
|
||||
message_admins("Admin [key_name_admin(usr)] has loaded [away_name] away mission.")
|
||||
log_admin("Admin [key_name(usr)] has loaded [away_name] away mission.")
|
||||
if(!away_level)
|
||||
message_admins("Loading [away_name] failed!")
|
||||
return
|
||||
|
||||
|
||||
if(choice == AWAY_MISSION_NAME && GLOB.the_gateway)
|
||||
//Link any found away gate with station gate
|
||||
var/obj/machinery/gateway/centeraway/new_gate
|
||||
for(var/obj/machinery/gateway/centeraway/G in GLOB.machines)
|
||||
if(G.z == level.z_value) //I'll have to refactor gateway shitcode before multi-away support.
|
||||
new_gate = G
|
||||
break
|
||||
//Link station gate with away gate and remove wait time.
|
||||
GLOB.the_gateway.awaygate = new_gate
|
||||
GLOB.the_gateway.wait = world.time
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/RequestBlockReservation(width, height, z, type = /datum/turf_reservation, turf_type_override, border_type_override)
|
||||
UNTIL((!z || reservation_ready["[z]"]) && !clearing_reserved_turfs)
|
||||
var/datum/turf_reservation/reserve = new type
|
||||
|
||||
@@ -268,6 +268,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
SaveRandomizedRecipes()
|
||||
SavePanicBunker()
|
||||
SavePaintings()
|
||||
SaveScars()
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadPanicBunker()
|
||||
var/bunker_path = file("data/bunker_passthrough.json")
|
||||
@@ -547,3 +548,24 @@ SUBSYSTEM_DEF(persistence)
|
||||
var/json_file = file("data/paintings.json")
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(paintings))
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/SaveScars()
|
||||
for(var/i in GLOB.joined_player_list)
|
||||
var/mob/living/carbon/human/ending_human = get_mob_by_ckey(i)
|
||||
if(!istype(ending_human) || !ending_human.mind || !ending_human.client || !ending_human.client.prefs || !ending_human.client.prefs.persistent_scars)
|
||||
continue
|
||||
|
||||
var/mob/living/carbon/human/original_human = ending_human.mind.original_character
|
||||
if(!original_human || original_human.stat == DEAD || !original_human.all_scars || !(original_human == ending_human))
|
||||
if(ending_human.client) // i was told if i don't check this every step of the way byond might decide a client ceases to exist mid proc so here we go
|
||||
ending_human.client.prefs.scars_list["[ending_human.client.prefs.scars_index]"] = ""
|
||||
else
|
||||
for(var/k in ending_human.all_wounds)
|
||||
var/datum/wound/iter_wound = k
|
||||
iter_wound.remove_wound() // so we can get the scars for open wounds
|
||||
if(!ending_human.client)
|
||||
return
|
||||
ending_human.client.prefs.scars_list["[ending_human.client.prefs.scars_index]"] = ending_human.format_scars()
|
||||
if(!ending_human.client)
|
||||
return
|
||||
ending_human.client.prefs.save_character()
|
||||
|
||||
@@ -50,20 +50,17 @@ PROCESSING_SUBSYSTEM_DEF(circuit)
|
||||
/obj/item/electronic_assembly/simple,
|
||||
/obj/item/electronic_assembly/hook,
|
||||
/obj/item/electronic_assembly/pda,
|
||||
/obj/item/electronic_assembly/dildo,
|
||||
/obj/item/electronic_assembly/small/default,
|
||||
/obj/item/electronic_assembly/small/cylinder,
|
||||
/obj/item/electronic_assembly/small/scanner,
|
||||
/obj/item/electronic_assembly/small/hook,
|
||||
/obj/item/electronic_assembly/small/box,
|
||||
/obj/item/electronic_assembly/small/dildo,
|
||||
/obj/item/electronic_assembly/medium/default,
|
||||
/obj/item/electronic_assembly/medium/box,
|
||||
/obj/item/electronic_assembly/medium/clam,
|
||||
/obj/item/electronic_assembly/medium/medical,
|
||||
/obj/item/electronic_assembly/medium/gun,
|
||||
/obj/item/electronic_assembly/medium/radio,
|
||||
/obj/item/electronic_assembly/medium/dildo,
|
||||
/obj/item/electronic_assembly/large/default,
|
||||
/obj/item/electronic_assembly/large/scope,
|
||||
/obj/item/electronic_assembly/large/terminal,
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// Smooth HUD updates, but low priority
|
||||
PROCESSING_SUBSYSTEM_DEF(huds)
|
||||
name = "HUD updates"
|
||||
wait = 0.5
|
||||
priority = FIRE_PRIORITY_HUDS
|
||||
stat_tag = "HUDS"
|
||||
@@ -7,10 +7,9 @@ SUBSYSTEM_DEF(shuttle)
|
||||
flags = SS_KEEP_TIMING|SS_NO_TICK_CHECK
|
||||
runlevels = RUNLEVEL_SETUP | RUNLEVEL_GAME
|
||||
|
||||
var/obj/machinery/shuttle_manipulator/manipulator
|
||||
|
||||
var/list/mobile = list()
|
||||
var/list/stationary = list()
|
||||
var/list/beacons = list()
|
||||
var/list/transit = list()
|
||||
|
||||
var/list/transit_requesters = list()
|
||||
@@ -57,6 +56,15 @@ SUBSYSTEM_DEF(shuttle)
|
||||
|
||||
var/realtimeofstart = 0
|
||||
|
||||
var/datum/map_template/shuttle/selected
|
||||
|
||||
var/obj/docking_port/mobile/existing_shuttle
|
||||
|
||||
var/obj/docking_port/mobile/preview_shuttle
|
||||
var/datum/map_template/shuttle/preview_template
|
||||
|
||||
var/datum/turf_reservation/preview_reservation
|
||||
|
||||
/datum/controller/subsystem/shuttle/Initialize(timeofday)
|
||||
ordernum = rand(1, 9000)
|
||||
|
||||
@@ -76,13 +84,10 @@ SUBSYSTEM_DEF(shuttle)
|
||||
WARNING("No /obj/docking_port/mobile/emergency/backup placed on the map!")
|
||||
if(!supply)
|
||||
WARNING("No /obj/docking_port/mobile/supply placed on the map!")
|
||||
realtimeofstart = world.realtime
|
||||
realtimeofstart = world.realtime
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/initial_load()
|
||||
if(!istype(manipulator))
|
||||
CRASH("No shuttle manipulator found.")
|
||||
|
||||
for(var/s in stationary)
|
||||
var/obj/docking_port/stationary/S = s
|
||||
S.load_roundstart()
|
||||
@@ -143,11 +148,13 @@ SUBSYSTEM_DEF(shuttle)
|
||||
++alive
|
||||
|
||||
var/total = GLOB.joined_player_list.len
|
||||
if(total <= 0)
|
||||
return //no players no autoevac
|
||||
|
||||
if(alive / total <= threshold)
|
||||
var/msg = "Automatically dispatching shuttle due to crew death."
|
||||
var/msg = "Automatically dispatching emergency shuttle due to crew death."
|
||||
message_admins(msg)
|
||||
log_game("[msg] Alive: [alive], Roundstart: [total], Threshold: [threshold]")
|
||||
log_shuttle("[msg] Alive: [alive], Roundstart: [total], Threshold: [threshold]")
|
||||
emergencyNoRecall = TRUE
|
||||
priority_announce("Catastrophic casualties detected: crisis shuttle protocols activated - jamming recall signals across all frequencies.")
|
||||
if(emergency.timeLeft(1) > emergencyCallTime * 0.4)
|
||||
@@ -172,6 +179,34 @@ SUBSYSTEM_DEF(shuttle)
|
||||
return S
|
||||
WARNING("couldn't find dock with id: [id]")
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/canEvac(mob/user)
|
||||
var/srd = CONFIG_GET(number/shuttle_refuel_delay)
|
||||
if(world.time - SSticker.round_start_time < srd)
|
||||
to_chat(user, "<span class='alert'>The emergency shuttle is refueling. Please wait [DisplayTimeText(srd - (world.time - SSticker.round_start_time))] before trying again.</span>")
|
||||
return FALSE
|
||||
|
||||
switch(emergency.mode)
|
||||
if(SHUTTLE_RECALL)
|
||||
to_chat(user, "<span class='alert'>The emergency shuttle may not be called while returning to CentCom.</span>")
|
||||
return FALSE
|
||||
if(SHUTTLE_CALL)
|
||||
to_chat(user, "<span class='alert'>The emergency shuttle is already on its way.</span>")
|
||||
return FALSE
|
||||
if(SHUTTLE_DOCKED)
|
||||
to_chat(user, "<span class='alert'>The emergency shuttle is already here.</span>")
|
||||
return FALSE
|
||||
if(SHUTTLE_IGNITING)
|
||||
to_chat(user, "<span class='alert'>The emergency shuttle is firing its engines to leave.</span>")
|
||||
return FALSE
|
||||
if(SHUTTLE_ESCAPE)
|
||||
to_chat(user, "<span class='alert'>The emergency shuttle is moving away to a safe distance.</span>")
|
||||
return FALSE
|
||||
if(SHUTTLE_STRANDED)
|
||||
to_chat(user, "<span class='alert'>The emergency shuttle has been disabled by CentCom.</span>")
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/requestEvac(mob/user, call_reason)
|
||||
if(!emergency)
|
||||
WARNING("requestEvac(): There is no emergency shuttle, but the \
|
||||
@@ -185,35 +220,14 @@ SUBSYSTEM_DEF(shuttle)
|
||||
manually, and then calling register() on the mobile docking port. \
|
||||
Good luck.")
|
||||
emergency = backup_shuttle
|
||||
var/srd = CONFIG_GET(number/shuttle_refuel_delay)
|
||||
if(world.time - SSticker.round_start_time < srd)
|
||||
to_chat(user, "The emergency shuttle is refueling. Please wait [DisplayTimeText(srd - (world.time - SSticker.round_start_time))] before trying again.")
|
||||
return
|
||||
|
||||
switch(emergency.mode)
|
||||
if(SHUTTLE_RECALL)
|
||||
to_chat(user, "The emergency shuttle may not be called while returning to CentCom.")
|
||||
return
|
||||
if(SHUTTLE_CALL)
|
||||
to_chat(user, "The emergency shuttle is already on its way.")
|
||||
return
|
||||
if(SHUTTLE_DOCKED)
|
||||
to_chat(user, "The emergency shuttle is already here.")
|
||||
return
|
||||
if(SHUTTLE_IGNITING)
|
||||
to_chat(user, "The emergency shuttle is firing its engines to leave.")
|
||||
return
|
||||
if(SHUTTLE_ESCAPE)
|
||||
to_chat(user, "The emergency shuttle is moving away to a safe distance.")
|
||||
return
|
||||
if(SHUTTLE_STRANDED)
|
||||
to_chat(user, "The emergency shuttle has been disabled by CentCom.")
|
||||
return
|
||||
if(!canEvac(user))
|
||||
return
|
||||
|
||||
call_reason = trim(html_encode(call_reason))
|
||||
|
||||
if(length(call_reason) < CALL_SHUTTLE_REASON_LENGTH && GLOB.security_level > SEC_LEVEL_GREEN)
|
||||
to_chat(user, "You must provide a reason.")
|
||||
to_chat(user, "<span class='alert'>You must provide a reason.</span>")
|
||||
return
|
||||
|
||||
var/area/signal_origin = get_area(user)
|
||||
@@ -235,11 +249,11 @@ SUBSYSTEM_DEF(shuttle)
|
||||
|
||||
var/area/A = get_area(user)
|
||||
|
||||
log_game("[key_name(user)] has called the shuttle.")
|
||||
deadchat_broadcast("<span class='deadsay'><span class='name'>[user.real_name]</span> has called the shuttle at <span class='name'>[A.name]</span>.</span>", user)
|
||||
log_shuttle("[key_name(user)] has called the emergency shuttle.")
|
||||
deadchat_broadcast(" has called the shuttle at <span class='name'>[A.name]</span>.", "<span class='name'>[user.real_name]</span>", user)
|
||||
if(call_reason)
|
||||
SSblackbox.record_feedback("text", "shuttle_reason", 1, "[call_reason]")
|
||||
log_game("Shuttle call reason: [call_reason]")
|
||||
log_shuttle("Shuttle call reason: [call_reason]")
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] has called the shuttle. (<A HREF='?_src_=holder;[HrefToken()];trigger_centcom_recall=1'>TRIGGER CENTCOM RECALL</A>)")
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/centcom_recall(old_timer, admiral_message)
|
||||
@@ -272,9 +286,9 @@ SUBSYSTEM_DEF(shuttle)
|
||||
/datum/controller/subsystem/shuttle/proc/cancelEvac(mob/user)
|
||||
if(canRecall())
|
||||
emergency.cancel(get_area(user))
|
||||
log_game("[key_name(user)] has recalled the shuttle.")
|
||||
log_shuttle("[key_name(user)] has recalled the shuttle.")
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] has recalled the shuttle.")
|
||||
deadchat_broadcast("<span class='deadsay'><span class='name'>[user.real_name]</span> has recalled the shuttle from <span class='name'>[get_area_name(user, TRUE)]</span>.</span>", user)
|
||||
deadchat_broadcast(" has recalled the shuttle from <span class='name'>[get_area_name(user, TRUE)]</span>.", "<span class='name'>[user.real_name]</span>", user)
|
||||
return 1
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/canRecall()
|
||||
@@ -294,7 +308,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
else
|
||||
if(emergency.timeLeft(1) < emergencyCallTime * 0.25)
|
||||
return
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/autoEvac()
|
||||
if (!SSticker.IsRoundInProgress())
|
||||
@@ -322,7 +336,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
if(callShuttle)
|
||||
if(EMERGENCY_IDLE_OR_RECALLED)
|
||||
emergency.request(null, set_coefficient = 2.5)
|
||||
log_game("There is no means of calling the shuttle anymore. Shuttle automatically called.")
|
||||
log_shuttle("There is no means of calling the emergency shuttle anymore. Shuttle automatically called.")
|
||||
message_admins("All the communications consoles were destroyed and all AIs are inactive. Shuttle called.")
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/registerHostileEnvironment(datum/bad)
|
||||
@@ -559,6 +573,14 @@ SUBSYSTEM_DEF(shuttle)
|
||||
shuttle_purchased = SSshuttle.shuttle_purchased
|
||||
lockdown = SSshuttle.lockdown
|
||||
|
||||
selected = SSshuttle.selected
|
||||
|
||||
existing_shuttle = SSshuttle.existing_shuttle
|
||||
|
||||
preview_shuttle = SSshuttle.preview_shuttle
|
||||
preview_template = SSshuttle.preview_template
|
||||
|
||||
preview_reservation = SSshuttle.preview_reservation
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/is_in_shuttle_bounds(atom/A)
|
||||
var/area/current = get_area(A)
|
||||
@@ -641,3 +663,254 @@ SUBSYSTEM_DEF(shuttle)
|
||||
message_admins("Round end vote passed. Shuttle has been auto-called.")
|
||||
emergencyNoRecall = TRUE
|
||||
endvote_passed = TRUE
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/action_load(datum/map_template/shuttle/loading_template, obj/docking_port/stationary/destination_port)
|
||||
// Check for an existing preview
|
||||
if(preview_shuttle && (loading_template != preview_template))
|
||||
preview_shuttle.jumpToNullSpace()
|
||||
preview_shuttle = null
|
||||
preview_template = null
|
||||
QDEL_NULL(preview_reservation)
|
||||
|
||||
if(!preview_shuttle)
|
||||
if(load_template(loading_template))
|
||||
preview_shuttle.linkup(loading_template, destination_port)
|
||||
preview_template = loading_template
|
||||
|
||||
// get the existing shuttle information, if any
|
||||
var/timer = 0
|
||||
var/mode = SHUTTLE_IDLE
|
||||
var/obj/docking_port/stationary/D
|
||||
|
||||
if(istype(destination_port))
|
||||
D = destination_port
|
||||
else if(existing_shuttle)
|
||||
timer = existing_shuttle.timer
|
||||
mode = existing_shuttle.mode
|
||||
D = existing_shuttle.get_docked()
|
||||
|
||||
if(!D)
|
||||
D = generate_transit_dock(preview_shuttle)
|
||||
|
||||
if(!D)
|
||||
CRASH("No dock found for preview shuttle ([preview_template.name]), aborting.")
|
||||
|
||||
var/result = preview_shuttle.canDock(D)
|
||||
// truthy value means that it cannot dock for some reason
|
||||
// but we can ignore the someone else docked error because we'll
|
||||
// be moving into their place shortly
|
||||
if((result != SHUTTLE_CAN_DOCK) && (result != SHUTTLE_SOMEONE_ELSE_DOCKED))
|
||||
WARNING("Template shuttle [preview_shuttle] cannot dock at [D] ([result]).")
|
||||
return
|
||||
|
||||
if(existing_shuttle)
|
||||
existing_shuttle.jumpToNullSpace()
|
||||
|
||||
var/list/force_memory = preview_shuttle.movement_force
|
||||
preview_shuttle.movement_force = list("KNOCKDOWN" = 0, "THROW" = 0)
|
||||
preview_shuttle.initiate_docking(D)
|
||||
preview_shuttle.movement_force = force_memory
|
||||
|
||||
. = preview_shuttle
|
||||
|
||||
// Shuttle state involves a mode and a timer based on world.time, so
|
||||
// plugging the existing shuttles old values in works fine.
|
||||
preview_shuttle.timer = timer
|
||||
preview_shuttle.mode = mode
|
||||
|
||||
preview_shuttle.register()
|
||||
|
||||
// TODO indicate to the user that success happened, rather than just
|
||||
// blanking the modification tab
|
||||
preview_shuttle = null
|
||||
preview_template = null
|
||||
existing_shuttle = null
|
||||
selected = null
|
||||
QDEL_NULL(preview_reservation)
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/load_template(datum/map_template/shuttle/S)
|
||||
. = FALSE
|
||||
// load shuttle template, centred at shuttle import landmark,
|
||||
preview_reservation = SSmapping.RequestBlockReservation(S.width, S.height, SSmapping.transit.z_value, /datum/turf_reservation/transit)
|
||||
if(!preview_reservation)
|
||||
CRASH("failed to reserve an area for shuttle template loading")
|
||||
var/turf/BL = TURF_FROM_COORDS_LIST(preview_reservation.bottom_left_coords)
|
||||
S.load(BL, centered = FALSE, register = FALSE)
|
||||
|
||||
var/affected = S.get_affected_turfs(BL, centered=FALSE)
|
||||
|
||||
var/found = 0
|
||||
// Search the turfs for docking ports
|
||||
// - We need to find the mobile docking port because that is the heart of
|
||||
// the shuttle.
|
||||
// - We need to check that no additional ports have slipped in from the
|
||||
// template, because that causes unintended behaviour.
|
||||
for(var/T in affected)
|
||||
for(var/obj/docking_port/P in T)
|
||||
if(istype(P, /obj/docking_port/mobile))
|
||||
found++
|
||||
if(found > 1)
|
||||
qdel(P, force=TRUE)
|
||||
log_world("Map warning: Shuttle Template [S.mappath] has multiple mobile docking ports.")
|
||||
else
|
||||
preview_shuttle = P
|
||||
if(istype(P, /obj/docking_port/stationary))
|
||||
log_world("Map warning: Shuttle Template [S.mappath] has a stationary docking port.")
|
||||
if(!found)
|
||||
var/msg = "load_template(): Shuttle Template [S.mappath] has no mobile docking port. Aborting import."
|
||||
for(var/T in affected)
|
||||
var/turf/T0 = T
|
||||
T0.empty()
|
||||
|
||||
message_admins(msg)
|
||||
WARNING(msg)
|
||||
return
|
||||
//Everything fine
|
||||
S.post_load(preview_shuttle)
|
||||
return TRUE
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/unload_preview()
|
||||
if(preview_shuttle)
|
||||
preview_shuttle.jumpToNullSpace()
|
||||
preview_shuttle = null
|
||||
|
||||
|
||||
/datum/controller/subsystem/shuttle/ui_state(mob/user)
|
||||
return GLOB.admin_state
|
||||
|
||||
/datum/controller/subsystem/shuttle/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "ShuttleManipulator")
|
||||
ui.open()
|
||||
|
||||
/datum/controller/subsystem/shuttle/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["tabs"] = list("Status", "Templates", "Modification")
|
||||
|
||||
// Templates panel
|
||||
data["templates"] = list()
|
||||
var/list/templates = data["templates"]
|
||||
data["templates_tabs"] = list()
|
||||
data["selected"] = list()
|
||||
|
||||
for(var/shuttle_id in SSmapping.shuttle_templates)
|
||||
var/datum/map_template/shuttle/S = SSmapping.shuttle_templates[shuttle_id]
|
||||
|
||||
if(!templates[S.port_id])
|
||||
data["templates_tabs"] += S.port_id
|
||||
templates[S.port_id] = list(
|
||||
"port_id" = S.port_id,
|
||||
"templates" = list())
|
||||
|
||||
var/list/L = list()
|
||||
L["name"] = S.name
|
||||
L["shuttle_id"] = S.shuttle_id
|
||||
L["port_id"] = S.port_id
|
||||
L["description"] = S.description
|
||||
L["admin_notes"] = S.admin_notes
|
||||
|
||||
if(selected == S)
|
||||
data["selected"] = L
|
||||
|
||||
templates[S.port_id]["templates"] += list(L)
|
||||
|
||||
data["templates_tabs"] = sortList(data["templates_tabs"])
|
||||
|
||||
data["existing_shuttle"] = null
|
||||
|
||||
// Status panel
|
||||
data["shuttles"] = list()
|
||||
for(var/i in mobile)
|
||||
var/obj/docking_port/mobile/M = i
|
||||
var/timeleft = M.timeLeft(1)
|
||||
var/list/L = list()
|
||||
L["name"] = M.name
|
||||
L["id"] = M.id
|
||||
L["timer"] = M.timer
|
||||
L["timeleft"] = M.getTimerStr()
|
||||
if (timeleft > 1 HOURS)
|
||||
L["timeleft"] = "Infinity"
|
||||
L["can_fast_travel"] = M.timer && timeleft >= 50
|
||||
L["can_fly"] = TRUE
|
||||
if(istype(M, /obj/docking_port/mobile/emergency))
|
||||
L["can_fly"] = FALSE
|
||||
else if(!M.destination)
|
||||
L["can_fast_travel"] = FALSE
|
||||
if (M.mode != SHUTTLE_IDLE)
|
||||
L["mode"] = capitalize(M.mode)
|
||||
L["status"] = M.getDbgStatusText()
|
||||
if(M == existing_shuttle)
|
||||
data["existing_shuttle"] = L
|
||||
|
||||
data["shuttles"] += list(L)
|
||||
|
||||
return data
|
||||
|
||||
/datum/controller/subsystem/shuttle/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/mob/user = usr
|
||||
|
||||
// Preload some common parameters
|
||||
var/shuttle_id = params["shuttle_id"]
|
||||
var/datum/map_template/shuttle/S = SSmapping.shuttle_templates[shuttle_id]
|
||||
|
||||
switch(action)
|
||||
if("select_template")
|
||||
if(S)
|
||||
existing_shuttle = getShuttle(S.port_id)
|
||||
selected = S
|
||||
. = TRUE
|
||||
if("jump_to")
|
||||
if(params["type"] == "mobile")
|
||||
for(var/i in mobile)
|
||||
var/obj/docking_port/mobile/M = i
|
||||
if(M.id == params["id"])
|
||||
user.forceMove(get_turf(M))
|
||||
. = TRUE
|
||||
break
|
||||
|
||||
if("fly")
|
||||
for(var/i in mobile)
|
||||
var/obj/docking_port/mobile/M = i
|
||||
if(M.id == params["id"])
|
||||
. = TRUE
|
||||
M.admin_fly_shuttle(user)
|
||||
break
|
||||
|
||||
if("fast_travel")
|
||||
for(var/i in mobile)
|
||||
var/obj/docking_port/mobile/M = i
|
||||
if(M.id == params["id"] && M.timer && M.timeLeft(1) >= 50)
|
||||
M.setTimer(50)
|
||||
. = TRUE
|
||||
message_admins("[key_name_admin(usr)] fast travelled [M]")
|
||||
log_admin("[key_name(usr)] fast travelled [M]")
|
||||
SSblackbox.record_feedback("text", "shuttle_manipulator", 1, "[M.name]")
|
||||
break
|
||||
|
||||
if("preview")
|
||||
if(S)
|
||||
. = TRUE
|
||||
unload_preview()
|
||||
load_template(S)
|
||||
if(preview_shuttle)
|
||||
preview_template = S
|
||||
user.forceMove(get_turf(preview_shuttle))
|
||||
if("load")
|
||||
if(existing_shuttle == backup_shuttle)
|
||||
// TODO make the load button disabled
|
||||
WARNING("The shuttle that the selected shuttle will replace \
|
||||
is the backup shuttle. Backup shuttle is required to be \
|
||||
intact for round sanity.")
|
||||
else if(S)
|
||||
. = TRUE
|
||||
// If successful, returns the mobile docking port
|
||||
var/obj/docking_port/mobile/mdp = action_load(S)
|
||||
if(mdp)
|
||||
user.forceMove(get_turf(mdp))
|
||||
message_admins("[key_name_admin(usr)] loaded [mdp] with the shuttle manipulator.")
|
||||
log_admin("[key_name(usr)] loaded [mdp] with the shuttle manipulator.</span>")
|
||||
SSblackbox.record_feedback("text", "shuttle_manipulator", 1, "[mdp.name]")
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
/**
|
||||
* tgui subsystem
|
||||
*
|
||||
* Contains all tgui state and subsystem code.
|
||||
*
|
||||
* Copyright (c) 2020 Aleksej Komarov
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
SUBSYSTEM_DEF(tgui)
|
||||
name = "tgui"
|
||||
wait = 9
|
||||
@@ -5,33 +14,338 @@ SUBSYSTEM_DEF(tgui)
|
||||
priority = FIRE_PRIORITY_TGUI
|
||||
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
|
||||
|
||||
var/list/currentrun = list()
|
||||
var/list/open_uis = list() // A list of open UIs, grouped by src_object and ui_key.
|
||||
var/list/processing_uis = list() // A list of processing UIs, ungrouped.
|
||||
var/basehtml // The HTML base used for all UIs.
|
||||
/// A list of UIs scheduled to process
|
||||
var/list/current_run = list()
|
||||
/// A list of open UIs
|
||||
var/list/open_uis = list()
|
||||
/// A list of open UIs, grouped by src_object.
|
||||
var/list/open_uis_by_src = list()
|
||||
/// The HTML base used for all UIs.
|
||||
var/basehtml
|
||||
|
||||
/datum/controller/subsystem/tgui/PreInit()
|
||||
basehtml = file2text('tgui-next/packages/tgui/public/tgui-main.html')
|
||||
basehtml = file2text('tgui/packages/tgui/public/tgui.html')
|
||||
|
||||
/datum/controller/subsystem/tgui/Shutdown()
|
||||
close_all_uis()
|
||||
|
||||
/datum/controller/subsystem/tgui/stat_entry()
|
||||
..("P:[processing_uis.len]")
|
||||
..("P:[open_uis.len]")
|
||||
|
||||
/datum/controller/subsystem/tgui/fire(resumed = 0)
|
||||
if (!resumed)
|
||||
src.currentrun = processing_uis.Copy()
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
|
||||
while(currentrun.len)
|
||||
var/datum/tgui/ui = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
if(!resumed)
|
||||
src.current_run = open_uis.Copy()
|
||||
// Cache for sanic speed (lists are references anyways)
|
||||
var/list/current_run = src.current_run
|
||||
while(current_run.len)
|
||||
var/datum/tgui/ui = current_run[current_run.len]
|
||||
current_run.len--
|
||||
// TODO: Move user/src_object check to process()
|
||||
if(ui && ui.user && ui.src_object)
|
||||
ui.process()
|
||||
else
|
||||
processing_uis.Remove(ui)
|
||||
if (MC_TICK_CHECK)
|
||||
open_uis.Remove(ui)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Requests a usable tgui window from the pool.
|
||||
* Returns null if pool was exhausted.
|
||||
*
|
||||
* required user mob
|
||||
* return datum/tgui
|
||||
*/
|
||||
/datum/controller/subsystem/tgui/proc/request_pooled_window(mob/user)
|
||||
if(!user.client)
|
||||
return null
|
||||
var/list/windows = user.client.tgui_windows
|
||||
var/window_id
|
||||
var/datum/tgui_window/window
|
||||
var/window_found = FALSE
|
||||
// Find a usable window
|
||||
for(var/i in 1 to TGUI_WINDOW_HARD_LIMIT)
|
||||
window_id = TGUI_WINDOW_ID(i)
|
||||
window = windows[window_id]
|
||||
// As we are looping, create missing window datums
|
||||
if(!window)
|
||||
window = new(user.client, window_id, pooled = TRUE)
|
||||
// Skip windows with acquired locks
|
||||
if(window.locked)
|
||||
continue
|
||||
if(window.status == TGUI_WINDOW_READY)
|
||||
return window
|
||||
if(window.status == TGUI_WINDOW_CLOSED)
|
||||
window.status = TGUI_WINDOW_LOADING
|
||||
window_found = TRUE
|
||||
break
|
||||
if(!window_found)
|
||||
log_tgui(user, "Error: Pool exhausted")
|
||||
return null
|
||||
return window
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Force closes all tgui windows.
|
||||
*
|
||||
* required user mob
|
||||
*/
|
||||
/datum/controller/subsystem/tgui/proc/force_close_all_windows(mob/user)
|
||||
log_tgui(user, "force_close_all_windows")
|
||||
if(user.client)
|
||||
user.client.tgui_windows = list()
|
||||
for(var/i in 1 to TGUI_WINDOW_HARD_LIMIT)
|
||||
var/window_id = TGUI_WINDOW_ID(i)
|
||||
user << browse(null, "window=[window_id]")
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Force closes the tgui window by window_id.
|
||||
*
|
||||
* required user mob
|
||||
* required window_id string
|
||||
*/
|
||||
/datum/controller/subsystem/tgui/proc/force_close_window(mob/user, window_id)
|
||||
log_tgui(user, "force_close_window")
|
||||
// Close all tgui datums based on window_id.
|
||||
for(var/datum/tgui/ui in user.tgui_open_uis)
|
||||
if(ui.window && ui.window.id == window_id)
|
||||
ui.close(can_be_suspended = FALSE)
|
||||
// Unset machine just to be sure.
|
||||
user.unset_machine()
|
||||
// Close window directly just to be sure.
|
||||
user << browse(null, "window=[window_id]")
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Try to find an instance of a UI, and push an update to it.
|
||||
*
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
* required src_object datum The object/datum which owns the UI.
|
||||
* optional ui datum/tgui The UI to be updated, if it exists.
|
||||
* optional force_open bool If the UI should be re-opened instead of updated.
|
||||
*
|
||||
* return datum/tgui The found UI.
|
||||
*/
|
||||
/datum/controller/subsystem/tgui/proc/try_update_ui(
|
||||
mob/user,
|
||||
datum/src_object,
|
||||
datum/tgui/ui)
|
||||
// Look up a UI if it wasn't passed
|
||||
if(isnull(ui))
|
||||
ui = get_open_ui(user, src_object)
|
||||
// Couldn't find a UI.
|
||||
if(isnull(ui))
|
||||
return null
|
||||
ui.process_status()
|
||||
// UI ended up with the closed status
|
||||
// or is actively trying to close itself.
|
||||
// FIXME: Doesn't actually fix the paper bug.
|
||||
if(ui.status <= UI_CLOSE)
|
||||
ui.close()
|
||||
return null
|
||||
ui.send_update()
|
||||
return ui
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Get a open UI given a user and src_object.
|
||||
*
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
* required src_object datum The object/datum which owns the UI.
|
||||
*
|
||||
* return datum/tgui The found UI.
|
||||
*/
|
||||
/datum/controller/subsystem/tgui/proc/get_open_ui(mob/user, datum/src_object)
|
||||
var/key = "[REF(src_object)]"
|
||||
// No UIs opened for this src_object
|
||||
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
|
||||
return null
|
||||
for(var/datum/tgui/ui in open_uis_by_src[key])
|
||||
// Make sure we have the right user
|
||||
if(ui.user == user)
|
||||
return ui
|
||||
return null
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Update all UIs attached to src_object.
|
||||
*
|
||||
* required src_object datum The object/datum which owns the UIs.
|
||||
*
|
||||
* return int The number of UIs updated.
|
||||
*/
|
||||
/datum/controller/subsystem/tgui/proc/update_uis(datum/src_object)
|
||||
var/count = 0
|
||||
var/key = "[REF(src_object)]"
|
||||
// No UIs opened for this src_object
|
||||
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
|
||||
return count
|
||||
for(var/datum/tgui/ui in open_uis_by_src[key])
|
||||
// Check if UI is valid.
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user))
|
||||
ui.process(force = 1)
|
||||
count++
|
||||
return count
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Close all UIs attached to src_object.
|
||||
*
|
||||
* required src_object datum The object/datum which owns the UIs.
|
||||
*
|
||||
* return int The number of UIs closed.
|
||||
*/
|
||||
/datum/controller/subsystem/tgui/proc/close_uis(datum/src_object)
|
||||
var/count = 0
|
||||
var/key = "[REF(src_object)]"
|
||||
// No UIs opened for this src_object
|
||||
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
|
||||
return count
|
||||
for(var/datum/tgui/ui in open_uis_by_src[key])
|
||||
// Check if UI is valid.
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user))
|
||||
ui.close()
|
||||
count++
|
||||
return count
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Close all UIs regardless of their attachment to src_object.
|
||||
*
|
||||
* return int The number of UIs closed.
|
||||
*/
|
||||
/datum/controller/subsystem/tgui/proc/close_all_uis()
|
||||
var/count = 0
|
||||
for(var/key in open_uis_by_src)
|
||||
for(var/datum/tgui/ui in open_uis_by_src[key])
|
||||
// Check if UI is valid.
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user))
|
||||
ui.close()
|
||||
count++
|
||||
return count
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Update all UIs belonging to a user.
|
||||
*
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
* optional src_object datum If provided, only update UIs belonging this src_object.
|
||||
*
|
||||
* return int The number of UIs updated.
|
||||
*/
|
||||
/datum/controller/subsystem/tgui/proc/update_user_uis(mob/user, datum/src_object)
|
||||
var/count = 0
|
||||
if(length(user?.tgui_open_uis) == 0)
|
||||
return count
|
||||
for(var/datum/tgui/ui in user.tgui_open_uis)
|
||||
if(isnull(src_object) || ui.src_object == src_object)
|
||||
ui.process(force = 1)
|
||||
count++
|
||||
return count
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Close all UIs belonging to a user.
|
||||
*
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
* optional src_object datum If provided, only close UIs belonging this src_object.
|
||||
*
|
||||
* return int The number of UIs closed.
|
||||
*/
|
||||
/datum/controller/subsystem/tgui/proc/close_user_uis(mob/user, datum/src_object)
|
||||
var/count = 0
|
||||
if(length(user?.tgui_open_uis) == 0)
|
||||
return count
|
||||
for(var/datum/tgui/ui in user.tgui_open_uis)
|
||||
if(isnull(src_object) || ui.src_object == src_object)
|
||||
ui.close()
|
||||
count++
|
||||
return count
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Add a UI to the list of open UIs.
|
||||
*
|
||||
* required ui datum/tgui The UI to be added.
|
||||
*/
|
||||
/datum/controller/subsystem/tgui/proc/on_open(datum/tgui/ui)
|
||||
var/key = "[REF(ui.src_object)]"
|
||||
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
|
||||
open_uis_by_src[key] = list()
|
||||
ui.user.tgui_open_uis |= ui
|
||||
var/list/uis = open_uis_by_src[key]
|
||||
uis |= ui
|
||||
open_uis |= ui
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Remove a UI from the list of open UIs.
|
||||
*
|
||||
* required ui datum/tgui The UI to be removed.
|
||||
*
|
||||
* return bool If the UI was removed or not.
|
||||
*/
|
||||
/datum/controller/subsystem/tgui/proc/on_close(datum/tgui/ui)
|
||||
var/key = "[REF(ui.src_object)]"
|
||||
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
|
||||
return FALSE
|
||||
// Remove it from the list of processing UIs.
|
||||
open_uis.Remove(ui)
|
||||
// If the user exists, remove it from them too.
|
||||
if(ui.user)
|
||||
ui.user.tgui_open_uis.Remove(ui)
|
||||
var/list/uis = open_uis_by_src[key]
|
||||
uis.Remove(ui)
|
||||
if(length(uis) == 0)
|
||||
open_uis_by_src.Remove(key)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Handle client logout, by closing all their UIs.
|
||||
*
|
||||
* required user mob The mob which logged out.
|
||||
*
|
||||
* return int The number of UIs closed.
|
||||
*/
|
||||
/datum/controller/subsystem/tgui/proc/on_logout(mob/user)
|
||||
close_user_uis(user)
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Handle clients switching mobs, by transferring their UIs.
|
||||
*
|
||||
* required user source The client's original mob.
|
||||
* required user target The client's new mob.
|
||||
*
|
||||
* return bool If the UIs were transferred.
|
||||
*/
|
||||
/datum/controller/subsystem/tgui/proc/on_transfer(mob/source, mob/target)
|
||||
// The old mob had no open UIs.
|
||||
if(length(source?.tgui_open_uis) == 0)
|
||||
return FALSE
|
||||
if(isnull(target.tgui_open_uis) || !istype(target.tgui_open_uis, /list))
|
||||
target.tgui_open_uis = list()
|
||||
// Transfer all the UIs.
|
||||
for(var/datum/tgui/ui in source.tgui_open_uis)
|
||||
// Inform the UIs of their new owner.
|
||||
ui.user = target
|
||||
target.tgui_open_uis.Add(ui)
|
||||
// Clear the old list.
|
||||
source.tgui_open_uis.Cut()
|
||||
return TRUE
|
||||
|
||||
@@ -711,7 +711,8 @@ SUBSYSTEM_DEF(ticker)
|
||||
'sound/roundend/yeehaw.ogg',
|
||||
'sound/roundend/disappointed.ogg',
|
||||
'sound/roundend/gondolabridge.ogg',
|
||||
'sound/roundend/haveabeautifultime.ogg'\
|
||||
'sound/roundend/haveabeautifultime.ogg',
|
||||
'sound/roundend/CitadelStationHasSeenBetterDays.ogg'\
|
||||
)
|
||||
|
||||
SEND_SOUND(world, sound(round_end_sound))
|
||||
|
||||
@@ -47,7 +47,7 @@ SUBSYSTEM_DEF(title)
|
||||
. = ..()
|
||||
if(.)
|
||||
switch(var_name)
|
||||
if("icon")
|
||||
if(NAMEOF(src, icon))
|
||||
if(splash_turf)
|
||||
splash_turf.icon = icon
|
||||
|
||||
@@ -66,4 +66,4 @@ SUBSYSTEM_DEF(title)
|
||||
icon = SStitle.icon
|
||||
splash_turf = SStitle.splash_turf
|
||||
file_path = SStitle.file_path
|
||||
previous_icon = SStitle.previous_icon
|
||||
previous_icon = SStitle.previous_icon
|
||||
|
||||
@@ -15,6 +15,8 @@ SUBSYSTEM_DEF(vote)
|
||||
var/vote_system = PLURALITY_VOTING
|
||||
var/question = null
|
||||
var/list/choices = list()
|
||||
/// List of choice = object for statclick objects for statpanel voting
|
||||
var/list/choice_statclicks = list()
|
||||
var/list/scores = list()
|
||||
var/list/choice_descs = list() // optional descriptions
|
||||
var/list/voted = list()
|
||||
@@ -47,7 +49,33 @@ SUBSYSTEM_DEF(vote)
|
||||
client_popup.open(0)
|
||||
next_pop = world.time+VOTE_COOLDOWN
|
||||
|
||||
|
||||
/**
|
||||
* Renders a statpanel. Directly uses statpanel/stat calls since this is called from base of mob/Stat().
|
||||
*/
|
||||
/datum/controller/subsystem/vote/proc/render_statpanel(mob/M)
|
||||
if(!mode) // check if vote is running
|
||||
return
|
||||
if(!statpanel("Status")) // don't bother if they're not focused on this panel
|
||||
return
|
||||
var/static/list/supported = list(PLURALITY_VOTING, APPROVAL_VOTING)
|
||||
stat("Vote active!", "There is currently a vote running. Question: [question]")
|
||||
if(!(vote_system in supported))
|
||||
stat("<STATPANEL VOTING DISABLED>", "The current vote system is not supported by statpanel rendering. Please vote manually by opening the vote popup using the action button or chat link.")
|
||||
return
|
||||
stat("Time Left:", "[round(end_time - world.time)] seconds")
|
||||
stat(null, null)
|
||||
stat("Choices:", null)
|
||||
stat(null, null)
|
||||
for(var/i in 1 to choice_statclicks.len)
|
||||
var/choice = choice_statclicks[i]
|
||||
var/ivotedforthis = FALSE
|
||||
switch(vote_system)
|
||||
if(APPROVAL_VOTING)
|
||||
ivotedforthis = voted[usr.ckey] && (i in voted[usr.ckey])
|
||||
if(PLURALITY_VOTING)
|
||||
ivotedforthis = voted[usr.ckey] == i
|
||||
stat(ivotedforthis? "\[X\]" : "\[ \]", choice_statclicks[choice])
|
||||
stat(null, null)
|
||||
|
||||
/datum/controller/subsystem/vote/proc/reset()
|
||||
initiator = null
|
||||
@@ -59,9 +87,26 @@ SUBSYSTEM_DEF(vote)
|
||||
voted.Cut()
|
||||
voting.Cut()
|
||||
scores.Cut()
|
||||
cleanup_statclicks()
|
||||
display_votes = initial(display_votes) //CIT CHANGE - obfuscated votes
|
||||
remove_action_buttons()
|
||||
|
||||
/datum/controller/subsystem/vote/proc/cleanup_statclicks()
|
||||
for(var/choice in choice_statclicks)
|
||||
qdel(choice_statclicks[choice])
|
||||
choice_statclicks = list()
|
||||
|
||||
/obj/effect/statclick/vote
|
||||
name = "ERROR"
|
||||
var/choice
|
||||
|
||||
/obj/effect/statclick/vote/Click()
|
||||
SSvote.submit_vote(choice)
|
||||
|
||||
/obj/effect/statclick/vote/New(loc, choice, name)
|
||||
src.choice = choice
|
||||
src.name = name
|
||||
|
||||
/datum/controller/subsystem/vote/proc/get_result()
|
||||
//get the highest number of votes
|
||||
var/greatest_votes = 0
|
||||
@@ -536,6 +581,12 @@ SUBSYSTEM_DEF(vote)
|
||||
vp = CONFIG_GET(number/vote_period)
|
||||
to_chat(world, "\n<font color='purple'><b>[text]</b>\nType <b>vote</b> or click <a href='?src=[REF(src)]'>here</a> to place your votes.\nYou have [DisplayTimeText(vp)] to vote.</font>")
|
||||
end_time = started_time+vp
|
||||
// generate statclick list
|
||||
cleanup_statclicks()
|
||||
for(var/i in 1 to choices.len)
|
||||
var/choice = choices[i]
|
||||
choice_statclicks[choice] = new /obj/effect/statclick/vote(null, i, choice)
|
||||
//
|
||||
for(var/c in GLOB.clients)
|
||||
SEND_SOUND(c, sound('sound/misc/server-ready.ogg'))
|
||||
var/client/C = c
|
||||
|
||||
+17
-10
@@ -431,25 +431,31 @@
|
||||
if(!owner)
|
||||
owner = M
|
||||
|
||||
/datum/ai_laws/proc/get_law_list(include_zeroth = 0, show_numbers = 1)
|
||||
/**
|
||||
* Generates a list of all laws on this datum, including rendered HTML tags if required
|
||||
*
|
||||
* Arguments:
|
||||
* * include_zeroth - Operator that controls if law 0 or law 666 is returned in the set
|
||||
* * show_numbers - Operator that controls if law numbers are prepended to the returned laws
|
||||
* * render_html - Operator controlling if HTML tags are rendered on the returned laws
|
||||
*/
|
||||
/datum/ai_laws/proc/get_law_list(include_zeroth = FALSE, show_numbers = TRUE, render_html = TRUE)
|
||||
var/list/data = list()
|
||||
|
||||
if (include_zeroth && devillaws && devillaws.len)
|
||||
for(var/i in devillaws)
|
||||
data += "[show_numbers ? "666:" : ""] <font color='#cc5500'>[i]</font>"
|
||||
if (include_zeroth && devillaws)
|
||||
for(var/law in devillaws)
|
||||
data += "[show_numbers ? "666:" : ""] [render_html ? "<font color='#cc5500'>[law]</font>" : law]"
|
||||
|
||||
if (include_zeroth && zeroth)
|
||||
data += "[show_numbers ? "0:" : ""] <font color='#ff0000'><b>[zeroth]</b></font>"
|
||||
data += "[show_numbers ? "0:" : ""] [render_html ? "<font color='#ff0000'><b>[zeroth]</b></font>" : zeroth]"
|
||||
|
||||
for(var/law in hacked)
|
||||
if (length(law) > 0)
|
||||
var/num = ionnum()
|
||||
data += "[show_numbers ? "[num]:" : ""] <font color='#660000'>[law]</font>"
|
||||
data += "[show_numbers ? "[ionnum()]:" : ""] [render_html ? "<font color='#660000'>[law]</font>" : law]"
|
||||
|
||||
for(var/law in ion)
|
||||
if (length(law) > 0)
|
||||
var/num = ionnum()
|
||||
data += "[show_numbers ? "[num]:" : ""] <font color='#547DFE'>[law]</font>"
|
||||
data += "[show_numbers ? "[ionnum()]:" : ""] [render_html ? "<font color='#547DFE'>[law]</font>" : law]"
|
||||
|
||||
var/number = 1
|
||||
for(var/law in inherent)
|
||||
@@ -459,6 +465,7 @@
|
||||
|
||||
for(var/law in supplied)
|
||||
if (length(law) > 0)
|
||||
data += "[show_numbers ? "[number]:" : ""] <font color='#990099'>[law]</font>"
|
||||
data += "[show_numbers ? "[number]:" : ""] [render_html ? "<font color='#990099'>[law]</font>" : law]"
|
||||
number++
|
||||
return data
|
||||
|
||||
|
||||
+15
-12
@@ -1,9 +1,9 @@
|
||||
#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]"
|
||||
#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]-[wound]"
|
||||
|
||||
/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
|
||||
/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0)
|
||||
. = locate(ARMORID)
|
||||
if (!.)
|
||||
. = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
|
||||
. = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic, wound)
|
||||
|
||||
/datum/armor
|
||||
datum_flags = DF_USE_TAG
|
||||
@@ -17,8 +17,9 @@
|
||||
var/fire
|
||||
var/acid
|
||||
var/magic
|
||||
var/wound
|
||||
|
||||
/datum/armor/New(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
|
||||
/datum/armor/New(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0)
|
||||
src.melee = melee
|
||||
src.bullet = bullet
|
||||
src.laser = laser
|
||||
@@ -29,15 +30,16 @@
|
||||
src.fire = fire
|
||||
src.acid = acid
|
||||
src.magic = magic
|
||||
src.wound = wound
|
||||
tag = ARMORID
|
||||
|
||||
/datum/armor/proc/modifyRating(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
|
||||
return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic)
|
||||
/datum/armor/proc/modifyRating(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0)
|
||||
return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic, src.wound+wound)
|
||||
|
||||
/datum/armor/proc/modifyAllRatings(modifier = 0)
|
||||
return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier)
|
||||
return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier, wound+modifier)
|
||||
|
||||
/datum/armor/proc/setRating(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
|
||||
/datum/armor/proc/setRating(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic, wound)
|
||||
return getArmor((isnull(melee) ? src.melee : melee),\
|
||||
(isnull(bullet) ? src.bullet : bullet),\
|
||||
(isnull(laser) ? src.laser : laser),\
|
||||
@@ -47,19 +49,20 @@
|
||||
(isnull(rad) ? src.rad : rad),\
|
||||
(isnull(fire) ? src.fire : fire),\
|
||||
(isnull(acid) ? src.acid : acid),\
|
||||
(isnull(magic) ? src.magic : magic))
|
||||
(isnull(magic) ? src.magic : magic),\
|
||||
(isnull(wound) ? src.wound : wound))
|
||||
|
||||
/datum/armor/proc/getRating(rating)
|
||||
return vars[rating]
|
||||
|
||||
/datum/armor/proc/getList()
|
||||
return list("melee" = melee, "bullet" = bullet, "laser" = laser, "energy" = energy, "bomb" = bomb, "bio" = bio, "rad" = rad, "fire" = fire, "acid" = acid, "magic" = magic)
|
||||
return list("melee" = melee, "bullet" = bullet, "laser" = laser, "energy" = energy, "bomb" = bomb, "bio" = bio, "rad" = rad, "fire" = fire, "acid" = acid, "magic" = magic, "wound" = wound)
|
||||
|
||||
/datum/armor/proc/attachArmor(datum/armor/AA)
|
||||
return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic)
|
||||
return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic, wound+AA.wound)
|
||||
|
||||
/datum/armor/proc/detachArmor(datum/armor/AA)
|
||||
return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic)
|
||||
return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic, wound-AA.wound)
|
||||
|
||||
/datum/armor/vv_edit_var(var_name, var_value)
|
||||
if (var_name == NAMEOF(src, tag))
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
//similar to dog_fashion, but for beepsky, who has far more refined fashion tastes
|
||||
/datum/beepsky_fashion
|
||||
var/name //not setting the name and desc makes them go to the default
|
||||
var/desc
|
||||
|
||||
var/icon_file = 'icons/mob/secbot_accessories.dmi' //we sell secbots and secbot accessories
|
||||
var/obj_icon_state
|
||||
var/obj_alpha
|
||||
var/obj_color
|
||||
|
||||
var/list/stun_sounds //sound that replaces the stun attack when set
|
||||
var/ignore_sound = FALSE //whether to ignore sounds entirely or not
|
||||
|
||||
//emotes (don't set them if you want the default value)
|
||||
var/death_emote //what is said when beepsky dies
|
||||
var/capture_one //what is said when cuffing someone
|
||||
var/capture_two //what is said when cuffing someone, directly to the person being cuffed
|
||||
var/infraction //the level of threat detected
|
||||
var/taunt // beepsky pointing at a criminal
|
||||
var/attack_one //text when attacking criminal
|
||||
var/attack_two //text when attacking criminal, but directly to the criminal
|
||||
var/patrol_emote //engaging patrol text
|
||||
var/patrol_fail_emote //failing to engage patrol text
|
||||
var/list/arrest_texts //first is for not-cuffing, second is for cuffing
|
||||
var/arrest_emote //text stating that you're cuffing some criminal C with a threat of level X in location Y
|
||||
|
||||
//for reference, the following words are replaced when processed before speech:
|
||||
//LOCATION = the location passed, if any (this is only used by arrest_emote)
|
||||
//CRIMINAL = the name of the criminal (this is used by everything but patrol_emote and infraction)
|
||||
//BOT = the name of the bot (this can be used on any of the emotes)
|
||||
//THREAT_LEVEL = the level of the threat detected (can be used on arrest_emote and infraction)
|
||||
|
||||
/datum/beepsky_fashion/proc/get_overlay(var/dir)
|
||||
if(icon_file && obj_icon_state)
|
||||
var/image/beepsky_overlay = image(icon_file, obj_icon_state, dir = dir)
|
||||
beepsky_overlay.alpha = obj_alpha
|
||||
beepsky_overlay.color = obj_color
|
||||
return beepsky_overlay
|
||||
|
||||
/datum/beepsky_fashion/proc/stun_attack(mob/living/carbon/C) //fired when beepsky does a stun attack with the fashion worn, for sounds/overlays/etc
|
||||
return
|
||||
|
||||
//actual fashions from here on out
|
||||
/datum/beepsky_fashion/wizard
|
||||
obj_icon_state = "wizard"
|
||||
name = "Archmage Beepsky"
|
||||
desc = "A secbot stolen from the wizard federation."
|
||||
death_emote = "BOT casts EI NATH on themselves!"
|
||||
capture_one = "BOT is casting cable ties on CRIMINAL!"
|
||||
capture_two = "BOT is casting cable ties on you!"
|
||||
infraction = "Magical disturbance of magnitude THREAT_LEVEL detected!"
|
||||
taunt = "BOT points his staff towards CRIMINAL!"
|
||||
attack_one = "BOT casts magic missile on CRIMINAL!"
|
||||
attack_two = "BOT casts magic missile on you!"
|
||||
patrol_emote = "Beginning search for magical disturbances."
|
||||
patrol_fail_emote = "Failure to find magical disturbances. Recallibrating."
|
||||
arrest_emote = "ARREST_TYPE level THREAT_LEVEL magical practitioner CRIMINAL in LOCATION."
|
||||
stun_sounds = list('sound/magic/lightningbolt.ogg',
|
||||
'sound/magic/fireball.ogg',
|
||||
'sound/weapons/zapbang.ogg',
|
||||
'sound/magic/knock.ogg',
|
||||
'sound/magic/fleshtostone.ogg',
|
||||
'sound/effects/magic.ogg',
|
||||
'sound/magic/disintegrate.ogg')
|
||||
|
||||
/datum/beepsky_fashion/cowboy
|
||||
obj_icon_state = "cowboy"
|
||||
name = "Sheriff Beepsky"
|
||||
desc = "The sheriff of this here station."
|
||||
capture_one = "BOT is tying CRIMINAL up!"
|
||||
capture_two = "BOT is tying you up!"
|
||||
infraction = "Outlaws with a bounty of THREAT_LEVEL000 space dollars detected!"
|
||||
taunt = "BOT aims his revolver towards CRIMINAL!"
|
||||
attack_one = "BOT unloads his revolver onto CRIMINAL!"
|
||||
attack_two = "BOT unloads his revolver onto you!"
|
||||
patrol_emote = "Engaging bounty hunting protocols."
|
||||
patrol_fail_emote = "Unable to find any bounties due to error. Rebooting."
|
||||
arrest_emote = "ARREST_TYPE outlaw CRIMINAL with a bounty of THREAT_LEVEL000 in LOCATION."
|
||||
stun_sounds = list('sound/weapons/Gunshot.ogg',
|
||||
'sound/weapons/Gunshot2.ogg',
|
||||
'sound/weapons/Gunshot3.ogg',
|
||||
'sound/weapons/Gunshot4.ogg')
|
||||
|
||||
/datum/beepsky_fashion/chef
|
||||
obj_icon_state = "chef"
|
||||
name = "Chef Beepsky"
|
||||
desc = "Cooking up the finest foods the station has ever seen."
|
||||
death_emote = "Mamma-mia!"
|
||||
infraction = "Grade THREAT_LEVEL prosciutto detected!"
|
||||
taunt = "BOT glares at CRIMINAL."
|
||||
attack_one = "BOT CQCs CRIMINAL!"
|
||||
attack_two = "BOT CQCs you!"
|
||||
patrol_emote = "Beginning search for the bad prosciutto."
|
||||
patrol_fail_emote = "All prosciutto is stale. Rebooting."
|
||||
arrest_texts = list("Frying", "Grilling") //any good secoff knows the difference
|
||||
arrest_emote = "ARREST_TYPE grade THREAT_LEVEL prosciutto CRIMINAL in LOCATION."
|
||||
stun_sounds = list('sound/weapons/cqchit1.ogg',
|
||||
'sound/weapons/cqchit2.ogg')
|
||||
|
||||
/datum/beepsky_fashion/cat
|
||||
obj_icon_state = "cat"
|
||||
name = "OwOfficer Bweepskwee"
|
||||
desc = "A beepsky unit with cat ears. Catgirl science has gone too far."
|
||||
death_emote = "Nya!"
|
||||
capture_one = "BOT is tying CRIMINAL up!!"
|
||||
capture_two = "BOT is tying you up!"
|
||||
infraction = "Wevel THREAT_LEVEL infwactwion awert!!!"
|
||||
taunt = "BOT points at CRIMINAL and nyas!"
|
||||
attack_one = "BOT shoves CRIMINAL onto a table!"
|
||||
attack_two = "BOT shoves you onto a table!"
|
||||
patrol_emote = "Enwgagwing patwol mwodies.."
|
||||
patrol_fail_emote = "Unawbwle two stwawt patwollies. Nya."
|
||||
arrest_texts = list("Dwetwaining", "Awwesting")
|
||||
arrest_emote = "ARREST_TYPE wevel THREAT_LEVEL scwumbwag CRIMINAL in LOCATION. Nya."
|
||||
ignore_sound = TRUE //we instead make the stunned person fire the nya emote
|
||||
|
||||
/datum/beepsky_fashion/cat/stun_attack(var/mob/living/carbon/C) //makes a fake table under you on hit, makes cat people nya when hit
|
||||
if(iscatperson(C))
|
||||
C.emote("nya")
|
||||
var/turf/target_turf = get_turf(C)
|
||||
if(target_turf) //slams you on a fake table
|
||||
playsound(src, 'sound/weapons/sonic_jackhammer.ogg', 50, 1)
|
||||
var/obj/effect/overlay_holder = new(target_turf)
|
||||
overlay_holder.name = "Catboy Table"
|
||||
overlay_holder.desc = "Where bad catboys go."
|
||||
var/image/table_overlay = image('icons/obj/smooth_structures/table.dmi', "table")
|
||||
overlay_holder.add_overlay(table_overlay)
|
||||
QDEL_IN(overlay_holder, 10)
|
||||
|
||||
/datum/beepsky_fashion/cake //nothing else. it's just beepsky. with a cake on his head.
|
||||
obj_icon_state = "cake"
|
||||
name = "Cakesky"
|
||||
desc = "It's a secbot, wearing a cake on his head!"
|
||||
|
||||
/datum/beepsky_fashion/captain
|
||||
obj_icon_state = "captain"
|
||||
name = "Captainsky"
|
||||
desc = "The real captain of this station."
|
||||
capture_one = "BOT is lecturing CRIMINAL on why he is the captain!"
|
||||
capture_two = "BOT is lecturing you on why he is the captain!"
|
||||
infraction = "Level THREAT_LEVEL greytider detected."
|
||||
attack_one = "BOT beats CRIMINAL with the chain of command!"
|
||||
attack_two = "BOT beats you with the chain of command!"
|
||||
patrol_emote = "Uselessness protocols engaged."
|
||||
patrol_fail_emote = "Unit has been found as useless. Rebooting."
|
||||
arrest_texts = list("Demoting", "Firing")
|
||||
arrest_emote = "ARREST_TYPE level THREAT_LEVEL lesser crewmember CRIMINAL in LOCATION."
|
||||
stun_sounds = list('sound/weapons/chainhit.ogg')
|
||||
|
||||
/datum/beepsky_fashion/king
|
||||
obj_icon_state = "king"
|
||||
name = "King Beepsky"
|
||||
desc = "He who has ascended to bare the right of king, sits atop the throne."
|
||||
capture_one = "BOT is calling the guards onto CRIMINAL!"
|
||||
capture_two = "BOT is calling the guards onto you!"
|
||||
infraction = "Treason of level THREAT_LEVEL detected!"
|
||||
attack_one = "BOT strikes CRIMINAL with his kingly authority!"
|
||||
attack_two = "BOT strikes you with his kingly authority!"
|
||||
patrol_emote = "Searching for peasants to beat up."
|
||||
patrol_fail_emote = "Peasants are using dark magic. Recallibrating."
|
||||
arrest_texts = list("Knighting", "Executing")
|
||||
arrest_emote = "ARREST_TYPE level THREAT_LEVEL peasant CRIMINAL in LOCATION."
|
||||
stun_sounds = list('sound/weapons/punch1.ogg',
|
||||
'sound/weapons/punch2.ogg',
|
||||
'sound/weapons/punch3.ogg',
|
||||
'sound/weapons/punch4.ogg')
|
||||
|
||||
/datum/beepsky_fashion/pirate
|
||||
obj_icon_state = "pirate"
|
||||
name = "Beepsbeard the Pirate"
|
||||
desc = "Sailor of the seven seas, all sea-faring bots fear the one known as Beepsbeard."
|
||||
capture_one = "BOT is making CRIMINAL walk the plank!"
|
||||
capture_two = "BOT is making you walk the plank!"
|
||||
infraction = "Enemy vessel spotted with threat level THREAT_LEVEL!"
|
||||
attack_one = "BOT strikes CRIMINAL with his cutlass!"
|
||||
attack_two = "BOT strikes you with his cutlass!"
|
||||
patrol_emote = "Searching for enemy vessels to board."
|
||||
patrol_fail_emote = "No way to engage enemy vessels. Rebooting."
|
||||
arrest_texts = list("Boarding", "Sinking")
|
||||
arrest_emote = "ARREST_TYPE level THREAT_LEVEL vessel CRIMINAL in LOCATION."
|
||||
stun_sounds = list('sound/weapons/bladeslice.ogg')
|
||||
|
||||
/datum/beepsky_fashion/engineer
|
||||
obj_icon_state = "engineer"
|
||||
name = "Chief Engineer Beepsky"
|
||||
desc = "He fixes criminals with a wrench to the face."
|
||||
capture_one = "BOT is tying CRIMINAL up!"
|
||||
capture_two = "BOT is tying you up!"
|
||||
infraction = "Structural integrity issue spotted with threat level THREAT_LEVEL"
|
||||
attack_one = "BOT strikes CRIMINAL with his wrench!"
|
||||
attack_two = "BOT strikes you with his wrench!"
|
||||
arrest_texts = list("Fixing", "Repairing")
|
||||
arrest_emote = "ARREST_TYPE level THREAT_LEVEL structural issue in LOCATION"
|
||||
stun_sounds = list('sound/weapons/genhit.ogg')
|
||||
|
||||
/datum/beepsky_fashion/tophat
|
||||
obj_icon_state = "tophat"
|
||||
name = "Fancy Beepsky"
|
||||
desc = "It's a secbot, wearing a top hat! How fancy."
|
||||
|
||||
/datum/beepsky_fashion/fedora
|
||||
obj_icon_state = "fedora"
|
||||
name = "Fedorasky"
|
||||
desc = "It's a secbot, wearing a fedora!"
|
||||
|
||||
/datum/beepsky_fashion/sombrero
|
||||
obj_icon_state = "sombrero"
|
||||
name = "Sombrerosky"
|
||||
desc = "A secbot wearing a sombrero. Truly, a hombre to all."
|
||||
|
||||
/datum/beepsky_fashion/santa
|
||||
obj_icon_state = "santa"
|
||||
name = "Saint Beepsky"
|
||||
desc = "Have you been a level 7 infraction this holiday season?"
|
||||
capture_one = "BOT is tying CRIMINAL up with fairy lights!"
|
||||
capture_two = "BOT is tying you up with fairy lights!"
|
||||
infraction = "Level THREAT_LEVEL threat to holiday cheer spotted!"
|
||||
attack_one = "BOT crushes CRIMINAL with their holiday spirit!"
|
||||
attack_two = "BOT crushes you with their holiday spirit!"
|
||||
arrest_emote = "ARREST_TYPE level THREAT_LEVEL threat to holiday cheer in LOCATION"
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
if(get_dist(owner, stalker) <= 1)
|
||||
playsound(owner, 'sound/magic/demon_attack1.ogg', 50)
|
||||
owner.visible_message("<span class='warning'>[owner] is torn apart by invisible claws!</span>", "<span class='userdanger'>Ghostly claws tear your body apart!</span>")
|
||||
owner.take_bodypart_damage(rand(20, 45))
|
||||
owner.take_bodypart_damage(rand(20, 45), wound_bonus=CANT_WOUND)
|
||||
else if(prob(50))
|
||||
stalker.forceMove(get_step_towards(stalker, owner))
|
||||
if(get_dist(owner, stalker) <= 8)
|
||||
|
||||
@@ -103,8 +103,7 @@
|
||||
. = ..()
|
||||
QDEL_IN(src, 300)
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/effect/hallucination/simple/bluespace_stream/attack_hand(mob/user)
|
||||
/obj/effect/hallucination/simple/bluespace_stream/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(user != seer || !linked_to)
|
||||
return
|
||||
var/slip_in_message = pick("slides sideways in an odd way, and disappears", "jumps into an unseen dimension",\
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
var/speed = 80 //time in deciseconds taken to butcher something
|
||||
var/effectiveness = 100 //percentage effectiveness; numbers above 100 yield extra drops
|
||||
var/bonus_modifier = 0 //percentage increase to bonus item chance
|
||||
var/butcher_sound = 'sound/weapons/slice.ogg' //sound played when butchering
|
||||
var/butcher_sound = 'sound/effects/butcher.ogg' //sound played when butchering
|
||||
var/butchering_enabled = TRUE
|
||||
var/can_be_blunt = FALSE
|
||||
|
||||
@@ -64,8 +64,11 @@
|
||||
H.visible_message("<span class='danger'>[user] slits [H]'s throat!</span>", \
|
||||
"<span class='userdanger'>[user] slits your throat...</span>")
|
||||
log_combat(user, H, "finishes slicing the throat of")
|
||||
H.apply_damage(source.force, BRUTE, BODY_ZONE_HEAD)
|
||||
H.bleed_rate = clamp(H.bleed_rate + 20, 0, 30)
|
||||
H.apply_damage(source.force, BRUTE, BODY_ZONE_HEAD, wound_bonus=CANT_WOUND) // easy tiger, we'll get to that in a sec
|
||||
var/obj/item/bodypart/slit_throat = H.get_bodypart(BODY_ZONE_HEAD)
|
||||
if(slit_throat)
|
||||
var/datum/wound/slash/critical/screaming_through_a_slit_throat = new
|
||||
screaming_through_a_slit_throat.apply_wound(slit_throat)
|
||||
H.apply_status_effect(/datum/status_effect/neck_slice)
|
||||
|
||||
/datum/component/butchering/proc/Butcher(mob/living/butcher, mob/living/meat)
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
var/damage = rand(min_damage, max_damage)
|
||||
if(HAS_TRAIT(H, TRAIT_LIGHT_STEP))
|
||||
damage *= 0.75
|
||||
H.apply_damage(damage, BRUTE, picked_def_zone)
|
||||
H.apply_damage(damage, BRUTE, picked_def_zone, wound_bonus = CANT_WOUND)
|
||||
|
||||
if(cooldown < world.time - 10) //cooldown to avoid message spam.
|
||||
if(!H.incapacitated(ignore_restraints = TRUE))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user