Merge branch 'master' into patch-17
This commit is contained in:
+65
-31
@@ -2,32 +2,57 @@
|
||||
|
||||
#define CHECK_DNA_AND_SPECIES(C) if((!(C.dna)) || (!(C.dna.species))) return
|
||||
|
||||
//Defines copying names of mutations in all cases, make sure to change this if you change mutation's name
|
||||
#define HULK "Hulk"
|
||||
#define XRAY "X Ray Vision"
|
||||
#define COLDRES "Cold Resistance"
|
||||
#define TK "Telekinesis"
|
||||
#define NERVOUS "Nervousness"
|
||||
#define EPILEPSY "Epilepsy"
|
||||
#define MUTATE "Unstable DNA"
|
||||
#define COUGH "Cough"
|
||||
#define DWARFISM "Dwarfism"
|
||||
#define CLOWNMUT "Clumsiness"
|
||||
#define TOURETTES "Tourettes Syndrome"
|
||||
#define DEAFMUT "Deafness"
|
||||
#define BLINDMUT "Blindness"
|
||||
#define RACEMUT "Monkified"
|
||||
#define BADSIGHT "Near Sightness"
|
||||
#define LASEREYES "Laser Eyes"
|
||||
#define CHAMELEON "Chameleon"
|
||||
#define WACKY "Wacky"
|
||||
#define MUT_MUTE "Mute"
|
||||
#define SMILE "Smile"
|
||||
#define STONER "Stoner"
|
||||
#define UNINTELLIGIBLE "Unintelligible"
|
||||
#define SWEDISH "Swedish"
|
||||
#define CHAV "Chav"
|
||||
#define ELVIS "Elvis"
|
||||
//Defines copying names of mutations in all cases, make sure to change this if you change mutation's type
|
||||
#define HULK /datum/mutation/human/hulk
|
||||
#define XRAY /datum/mutation/human/thermal/x_ray
|
||||
#define SPACEMUT /datum/mutation/human/space_adaptation
|
||||
#define TK /datum/mutation/human/telekinesis
|
||||
#define NERVOUS /datum/mutation/human/nervousness
|
||||
#define EPILEPSY /datum/mutation/human/epilepsy
|
||||
#define MUTATE /datum/mutation/human/bad_dna
|
||||
#define COUGH /datum/mutation/human/cough
|
||||
#define DWARFISM /datum/mutation/human/dwarfism
|
||||
#define GIGANTISM /datum/mutation/human/gigantism
|
||||
#define CLOWNMUT /datum/mutation/human/clumsy
|
||||
#define TOURETTES /datum/mutation/human/tourettes
|
||||
#define DEAFMUT /datum/mutation/human/deaf
|
||||
#define BLINDMUT /datum/mutation/human/blind
|
||||
#define RACEMUT /datum/mutation/human/race
|
||||
#define BADSIGHT /datum/mutation/human/nearsight
|
||||
#define LASEREYES /datum/mutation/human/laser_eyes
|
||||
#define CHAMELEON /datum/mutation/human/chameleon
|
||||
#define WACKY /datum/mutation/human/wacky
|
||||
#define MUT_MUTE /datum/mutation/human/mute
|
||||
#define SMILE /datum/mutation/human/smile
|
||||
#define STONER /datum/mutation/human/stoner
|
||||
#define UNINTELLIGIBLE /datum/mutation/human/unintelligible
|
||||
#define SWEDISH /datum/mutation/human/swedish
|
||||
#define CHAV /datum/mutation/human/chav
|
||||
#define ELVIS /datum/mutation/human/elvis
|
||||
#define RADIOACTIVE /datum/mutation/human/radioactive
|
||||
#define GLOWY /datum/mutation/human/glow
|
||||
#define ANTIGLOWY /datum/mutation/human/glow/anti
|
||||
#define TELEPATHY /datum/mutation/human/telepathy
|
||||
#define FIREBREATH /datum/mutation/human/firebreath
|
||||
#define VOID /datum/mutation/human/void
|
||||
#define TONGUESPIKE /datum/mutation/human/tongue_spike
|
||||
#define TONGUESPIKECHEM /datum/mutation/human/tongue_spike/chem
|
||||
#define STRONG /datum/mutation/human/strong
|
||||
#define STIMMED /datum/mutation/human/stimmed
|
||||
#define FIRESWEAT /datum/mutation/human/fire
|
||||
#define THERMAL /datum/mutation/human/thermal
|
||||
#define ANTENNA /datum/mutation/human/antenna
|
||||
#define PARANOIA /datum/mutation/human/paranoia
|
||||
#define MINDREAD /datum/mutation/human/mindreader
|
||||
#define INSULATED /datum/mutation/human/insulated
|
||||
#define SHOCKTOUCH /datum/mutation/human/shock
|
||||
#define OLFACTION /datum/mutation/human/olfaction
|
||||
#define ACIDFLESH /datum/mutation/human/acidflesh
|
||||
#define BADBLINK /datum/mutation/human/badblink
|
||||
#define SPASTIC /datum/mutation/human/spastic
|
||||
#define GELADIKINESIS /datum/mutation/human/geladikinesis
|
||||
#define CRYOKINESIS /datum/mutation/human/cryokinesis
|
||||
#define SPIDER_WEB /datum/mutation/human/webbing
|
||||
|
||||
#define UI_CHANGED "ui changed"
|
||||
#define UE_CHANGED "ue changed"
|
||||
@@ -39,10 +64,12 @@
|
||||
//Types of usual mutations
|
||||
#define POSITIVE 1
|
||||
#define NEGATIVE 2
|
||||
#define MINOR_NEGATIVE 3
|
||||
#define MINOR_NEGATIVE 4
|
||||
|
||||
//Mutations that cant be taken from genetics and are not in SE
|
||||
#define NON_SCANNABLE -1
|
||||
//Mutation classes. Normal being on them, extra being additional mutations with instability and other being stuff you dont want people to fuck with like wizard mutate
|
||||
#define MUT_NORMAL 1
|
||||
#define MUT_EXTRA 2
|
||||
#define MUT_OTHER 3
|
||||
|
||||
//DNA - Because fuck you and your magic numbers being all over the codebase.
|
||||
#define DNA_BLOCK_SIZE 3
|
||||
@@ -63,7 +90,8 @@
|
||||
#define DNA_MUTANTMARKING_BLOCK 13
|
||||
#define DNA_TAUR_BLOCK 14
|
||||
|
||||
#define DNA_STRUC_ENZYMES_BLOCKS 18
|
||||
#define DNA_SEQUENCE_LENGTH 4
|
||||
#define DNA_MUTATION_BLOCKS 8
|
||||
#define DNA_UNIQUE_ENZYMES_LEN 32
|
||||
|
||||
//Transformation proc stuff
|
||||
@@ -141,7 +169,13 @@
|
||||
#define STANDARD_ORGAN_HEALING (1/(15 MINUTES / (2 SECONDS)))
|
||||
#define STANDARD_ORGAN_DECAY (1/(15 MINUTES / (2 SECONDS))) //designed to fail organs when left to decay for ~15 minutes. 2 SECOND is SSmobs tickrate.
|
||||
|
||||
|
||||
//used for the can_chromosome var on mutations
|
||||
#define CHROMOSOME_NEVER 0
|
||||
#define CHROMOSOME_NONE 1
|
||||
#define CHROMOSOME_USED 2
|
||||
|
||||
#define G_MALE 1
|
||||
#define G_FEMALE 2
|
||||
#define G_PLURAL 3
|
||||
#define G_NEUTER 4
|
||||
#define G_NEUTER 4
|
||||
@@ -34,6 +34,21 @@
|
||||
#define HIJACK_HIJACKER 1 //Needs to be present for shuttle to be hijacked
|
||||
#define HIJACK_PREVENT 2 //Prevents hijacking same way as non-antags
|
||||
|
||||
//Syndicate Contracts
|
||||
#define CONTRACT_STATUS_INACTIVE 1
|
||||
#define CONTRACT_STATUS_ACTIVE 2
|
||||
#define CONTRACT_STATUS_BOUNTY_CONSOLE_ACTIVE 3
|
||||
#define CONTRACT_STATUS_EXTRACTING 4
|
||||
#define CONTRACT_STATUS_COMPLETE 5
|
||||
#define CONTRACT_STATUS_ABORTED 6
|
||||
|
||||
#define CONTRACT_PAYOUT_LARGE 1
|
||||
#define CONTRACT_PAYOUT_MEDIUM 2
|
||||
#define CONTRACT_PAYOUT_SMALL 3
|
||||
|
||||
#define CONTRACT_UPLINK_PAGE_CONTRACTS "CONTRACTS"
|
||||
#define CONTRACT_UPLINK_PAGE_HUB "HUB"
|
||||
|
||||
//Overthrow time to update heads obj
|
||||
#define OBJECTIVE_UPDATING_TIME 300
|
||||
|
||||
@@ -57,3 +72,8 @@
|
||||
#define CAT_STRUCTURE "Structures"
|
||||
|
||||
#define MARTIALART_HUNTER "hunter-fu"
|
||||
|
||||
//Blob
|
||||
/// blob gets a free reroll every X time
|
||||
#define BLOB_REROLL_TIME 2400
|
||||
#define BLOB_REFLECTOR_COST 15
|
||||
@@ -39,9 +39,9 @@
|
||||
#define COCK_SIZE_MIN 1
|
||||
#define COCK_SIZE_MAX 20
|
||||
|
||||
#define COCK_GIRTH_RATIO_MAX 1.25
|
||||
#define COCK_GIRTH_RATIO_DEF 0.75
|
||||
#define COCK_GIRTH_RATIO_MIN 0.5
|
||||
#define COCK_DIAMETER_RATIO_MAX 0.42
|
||||
#define COCK_DIAMETER_RATIO_DEF 0.25
|
||||
#define COCK_DIAMETER_RATIO_MIN 0.15
|
||||
|
||||
#define KNOT_GIRTH_RATIO_MAX 3
|
||||
#define KNOT_GIRTH_RATIO_DEF 2.1
|
||||
|
||||
@@ -47,6 +47,10 @@
|
||||
#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted" //before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation
|
||||
#define COMSIG_PARENT_QDELETING "parent_qdeleting" //just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called
|
||||
|
||||
/// Trait signals
|
||||
#define COMPONENT_ADD_TRAIT (1<<0)
|
||||
#define COMPONENT_REMOVE_TRAIT (1<<1)
|
||||
|
||||
// /atom signals
|
||||
#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
|
||||
@@ -202,14 +206,25 @@
|
||||
#define COMSIG_LIVING_RESIST "living_resist" //from base of mob/living/resist() (/mob/living)
|
||||
#define COMSIG_LIVING_IGNITED "living_ignite" //from base of mob/living/IgniteMob() (/mob/living)
|
||||
#define COMSIG_LIVING_EXTINGUISHED "living_extinguished" //from base of mob/living/ExtinguishMob() (/mob/living)
|
||||
#define COMSIG_LIVING_ELECTROCUTE_ACT "living_electrocute_act" //from base of mob/living/electrocute_act(): (shock_damage)
|
||||
#define COMSIG_LIVING_ELECTROCUTE_ACT "living_electrocute_act" //from base of mob/living/electrocute_act(): (shock_damage, source, siemens_coeff, flags)
|
||||
#define COMSIG_LIVING_MINOR_SHOCK "living_minor_shock" //sent by stuff like stunbatons and tasers: ()
|
||||
#define COMSIG_LIVING_REVIVE "living_revive" //from base of mob/living/revive() (full_heal, admin_revive)
|
||||
#define COMSIG_MOB_CLIENT_LOGIN "comsig_mob_client_login" //sent when a mob/login() finishes: (client)
|
||||
#define COMSIG_LIVING_GUN_PROCESS_FIRE "living_gun_process_fire" //from base of /obj/item/gun/proc/process_fire(): (atom/target, params, zone_override)
|
||||
|
||||
//ALL OF THESE DO NOT TAKE INTO ACCOUNT WHETHER AMOUNT IS 0 OR LOWER AND ARE SENT REGARDLESS!
|
||||
#define COMSIG_LIVING_STATUS_STUN "living_stun" //from base of mob/living/Stun() (amount, update, ignore)
|
||||
#define COMSIG_LIVING_STATUS_KNOCKDOWN "living_knockdown" //from base of mob/living/Knockdown() (amount, update, ignore)
|
||||
#define COMSIG_LIVING_STATUS_PARALYZE "living_paralyze" //from base of mob/living/Paralyze() (amount, update, ignore)
|
||||
#define COMSIG_LIVING_STATUS_IMMOBILIZE "living_immobilize" //from base of mob/living/Immobilize() (amount, update, ignore)
|
||||
#define COMSIG_LIVING_STATUS_UNCONSCIOUS "living_unconscious" //from base of mob/living/Unconscious() (amount, update, ignore)
|
||||
#define COMSIG_LIVING_STATUS_SLEEP "living_sleeping" //from base of mob/living/Sleeping() (amount, update, ignore)
|
||||
#define COMSIG_LIVING_STATUS_DAZE "living_daze" //from base of mob/living/Daze() (amount, update, ignore)
|
||||
#define COMPONENT_NO_STUN 1 //For all of them
|
||||
|
||||
// /mob/living/carbon signals
|
||||
#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)
|
||||
|
||||
// /mob/living/simple_animal/hostile signals
|
||||
#define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget"
|
||||
@@ -233,6 +248,7 @@
|
||||
#define COMSIG_ITEM_PRE_ATTACK "item_pre_attack" //from base of obj/item/pre_attack(): (atom/target, mob/user, params)
|
||||
#define COMPONENT_NO_ATTACK 1
|
||||
#define COMSIG_ITEM_AFTERATTACK "item_afterattack" //from base of obj/item/afterattack(): (atom/target, mob/user, params)
|
||||
#define COMSIG_ITEM_ALT_AFTERATTACK "item_alt_afterattack" //from base of obj/item/altafterattack(): (atom/target, mob/user, proximity, params)
|
||||
#define COMSIG_ITEM_EQUIPPED "item_equip" //from base of obj/item/equipped(): (/mob/equipper, slot)
|
||||
#define COMSIG_ITEM_DROPPED "item_drop" //from base of obj/item/dropped(): (mob/user)
|
||||
#define COMSIG_ITEM_PICKUP "item_pickup" //from base of obj/item/pickup(): (/mob/taker)
|
||||
@@ -274,6 +290,9 @@
|
||||
#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_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, se, newreal_name, newblood_type, datum/species, newfeatures)
|
||||
#define COMSIG_HUMAN_ON_RANDOMIZE "humman_on_randomize" //from base of proc/randomize_human()
|
||||
|
||||
// /datum/species signals
|
||||
#define COMSIG_SPECIES_GAIN "species_gain" //from datum/species/on_species_gain(): (datum/species/new_species, datum/species/old_species)
|
||||
|
||||
@@ -92,3 +92,30 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
|
||||
// radiation
|
||||
#define RAD_PROTECT_CONTENTS (1<<0)
|
||||
#define RAD_NO_CONTAMINATE (1<<1)
|
||||
|
||||
//Mob mobility var flags
|
||||
/// any flag
|
||||
#define CHECK_MOBILITY(target, flags) CHECK_BITFIELD(target.mobility_flags, flags)
|
||||
#define CHECK_ALL_MOBILITY(target, flags) CHECK_MULTIPLE_BITFIELDS(target.mobility_flags, flags)
|
||||
|
||||
/// can move
|
||||
#define MOBILITY_MOVE (1<<0)
|
||||
/// can, and is, standing up.
|
||||
#define MOBILITY_STAND (1<<1)
|
||||
/// can pickup items
|
||||
#define MOBILITY_PICKUP (1<<2)
|
||||
/// can use items and interact with world objects like opening closets/etc
|
||||
#define MOBILITY_USE (1<<3)
|
||||
/// can use interfaces like consoles
|
||||
#define MOBILITY_UI (1<<4)
|
||||
/// can use storage item
|
||||
#define MOBILITY_STORAGE (1<<5)
|
||||
/// can pull things
|
||||
#define MOBILITY_PULL (1<<6)
|
||||
/// can hold non-nodropped items voluntarily
|
||||
#define MOBILITY_HOLD (1<<7)
|
||||
/// Can resist out of buckling, grabs, cuffs, etc, in the usual order (buckle --> cuffs --> grab)
|
||||
#define MOBILITY_RESIST (1<<8)
|
||||
|
||||
#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)
|
||||
|
||||
@@ -4,11 +4,8 @@
|
||||
/// Hard materials, such as iron or metal
|
||||
#define MAT_CATEGORY_RIGID "rigid material"
|
||||
|
||||
|
||||
/// Gets the reference for the material type that was given
|
||||
#define getmaterialref(A) (SSmaterials.materials[A] || A)
|
||||
|
||||
/// Flag for atoms, this flag ensures it isn't re-colored by materials. Useful for snowflake icons such as default toolboxes.
|
||||
#define MATERIAL_COLOR (1<<0)
|
||||
#define MATERIAL_ADD_PREFIX (1<<1)
|
||||
#define MATERIAL_NO_EFFECTS (1<<2)
|
||||
#define MATERIAL_AFFECT_STATISTICS (1<<3)
|
||||
@@ -407,6 +407,7 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
|
||||
#define DUMMY_HUMAN_SLOT_ADMIN "admintools"
|
||||
#define DUMMY_HUMAN_SLOT_MANIFEST "dummy_manifest_generation"
|
||||
#define DUMMY_HUMAN_SLOT_HALLUCINATION "dummy_hallucination"
|
||||
#define DUMMY_HUMAN_SLOT_EXAMINER "dummy_examiner"
|
||||
|
||||
#define PR_ANNOUNCEMENTS_PER_ROUND 5 //The number of unique PR announcements allowed per round
|
||||
//This makes sure that a single person can only spam 3 reopens and 3 closes before being ignored
|
||||
|
||||
@@ -58,8 +58,10 @@
|
||||
#define BODYPART_DISABLED_DAMAGE 1
|
||||
#define BODYPART_DISABLED_PARALYSIS 2
|
||||
|
||||
#define DEFAULT_BODYPART_ICON 'icons/mob/human_parts.dmi'
|
||||
#define DEFAULT_BODYPART_ICON_ORGANIC 'icons/mob/human_parts_greyscale.dmi'
|
||||
#define DEFAULT_BODYPART_ICON_ROBOTIC 'icons/mob/augmentation/augments.dmi'
|
||||
#define DEFAULT_BODYPART_ICON_CITADEL 'modular_citadel/icons/mob/mutant_bodyparts.dmi'
|
||||
|
||||
#define MONKEY_BODYPART "monkey"
|
||||
#define ALIEN_BODYPART "alien"
|
||||
@@ -208,6 +210,17 @@
|
||||
|
||||
#define MAX_CHICKENS 50
|
||||
|
||||
///Flags used by the flags parameter of electrocute act.
|
||||
|
||||
///Makes it so that the shock doesn't take gloves into account.
|
||||
#define SHOCK_NOGLOVES (1 << 0)
|
||||
///Used when the shock is from a tesla bolt.
|
||||
#define SHOCK_TESLA (1 << 1)
|
||||
///Used when an illusion shocks something. Makes the shock deal stamina damage and not trigger certain secondary effects.
|
||||
#define SHOCK_ILLUSION (1 << 2)
|
||||
///The shock doesn't stun.
|
||||
#define SHOCK_NOSTUN (1 << 3)
|
||||
|
||||
|
||||
#define INCORPOREAL_MOVE_BASIC 1
|
||||
#define INCORPOREAL_MOVE_SHADOW 2 // leaves a trail of shadows
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
//ids
|
||||
|
||||
#define MOVESPEED_ID_MOB_WALK_RUN_CONFIG_SPEED "MOB_WALK_RUN"
|
||||
#define MOVESPEED_ID_MOB_GRAB_STATE "MOB_GRAB_STATE"
|
||||
#define MOVESPEED_ID_MOB_EQUIPMENT "MOB_EQUIPMENT"
|
||||
#define MOVESPEED_ID_MOB_GRAVITY "MOB_GRAVITY"
|
||||
#define MOVESPEED_ID_CONFIG_SPEEDMOD "MOB_CONFIG_MODIFIER"
|
||||
|
||||
#define MOVESPEED_ID_SLIME_REAGENTMOD "SLIME_REAGENT_MODIFIER"
|
||||
@@ -28,6 +31,7 @@
|
||||
#define MOVESPEED_ID_TARANTULA_WEB "TARANTULA_WEB"
|
||||
|
||||
#define MOVESPEED_ID_LIVING_TURF_SPEEDMOD "LIVING_TURF_SPEEDMOD"
|
||||
#define MOVESPEED_ID_LIVING_LIMBLESS "LIVING_LIMBLESS"
|
||||
|
||||
#define MOVESPEED_ID_CARBON_SOFTCRIT "CARBON_SOFTCRIT"
|
||||
#define MOVESPEED_ID_CARBON_OLDSPEED "CARBON_DEPRECATED_SPEED"
|
||||
@@ -59,15 +63,19 @@
|
||||
#define MOVESPEED_ID_HUMAN_CARRYING "HUMAN_CARRY"
|
||||
#define MOVESPEED_ID_SHRINK_RAY "SHRUNKEN_SPEED_MODIFIER"
|
||||
|
||||
#define MOVESPEED_ID_TASED_STATUS "TASED"
|
||||
|
||||
#define MOVESPEED_ID_SLAUGHTER "SLAUGHTER"
|
||||
|
||||
#define MOVESPEED_ID_CYBER_THRUSTER "CYBER_IMPLANT_THRUSTER"
|
||||
#define MOVESPEED_ID_JETPACK "JETPACK"
|
||||
|
||||
#define MOVESPEED_ID_SHOVE "SHOVE"
|
||||
|
||||
#define MOVESPEED_ID_MKULTRA "MKULTRA"
|
||||
|
||||
#define MOVESPEED_ID_ELECTROSTAFF "ELECTROSTAFF"
|
||||
#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"
|
||||
#define MOVESPEED_ID_DAMAGE_SLOWDOWN "DAMAGE"
|
||||
#define MOVESPEED_ID_DAMAGE_SLOWDOWN_FLYING "FLYING"
|
||||
@@ -23,6 +23,10 @@ Ask ninjanomnom if they're around
|
||||
|
||||
#define RAD_MOB_MUTATE 1250 // How much stored radiation to check for mutation
|
||||
|
||||
#define RAD_MONKEY_GORILLIZE 1650 // How much stored radiation to check for Harambe time.
|
||||
#define RAD_MOB_GORILLIZE_FACTOR 100
|
||||
#define RAD_MONKEY_GORILLIZE_EXPONENT 0.5
|
||||
|
||||
#define RAD_MOB_VOMIT 2000 // The amount of radiation to check for vomitting
|
||||
#define RAD_MOB_VOMIT_PROB 1 // Chance per tick of vomitting
|
||||
|
||||
|
||||
@@ -37,10 +37,17 @@
|
||||
/////////////
|
||||
// DEBUFFS //
|
||||
/////////////
|
||||
/// The affected is unable to move, or to use, hold, or pickup items.
|
||||
#define STATUS_EFFECT_STUN /datum/status_effect/incapacitating/stun
|
||||
|
||||
#define STATUS_EFFECT_STUN /datum/status_effect/incapacitating/stun //the affected is stunned
|
||||
#define STATUS_EFFECT_KNOCKDOWN /datum/status_effect/incapacitating/knockdown //the affected is unable to stand up
|
||||
|
||||
#define STATUS_EFFECT_KNOCKDOWN /datum/status_effect/incapacitating/knockdown //the affected is knocked down
|
||||
#define STATUS_EFFECT_IMMOBILIZED /datum/status_effect/incapacitating/immobilized //the affected is unable to move
|
||||
|
||||
#define STATUS_EFFECT_PARALYZED /datum/status_effect/incapacitating/paralyzed //the affected is unable to move, use items, or stand up.
|
||||
|
||||
/// The affected is unable to use or pickup items
|
||||
#define STATUS_EFFECT_DAZED /datum/status_effect/incapacitating/dazed
|
||||
|
||||
#define STATUS_EFFECT_UNCONSCIOUS /datum/status_effect/incapacitating/unconscious //the affected is unconscious
|
||||
|
||||
@@ -111,3 +118,4 @@
|
||||
|
||||
#define STATUS_EFFECT_RAINBOWPROTECTION /datum/status_effect/rainbow_protection //Invulnerable and pacifistic
|
||||
#define STATUS_EFFECT_SLIMESKIN /datum/status_effect/slimeskin //Increased armor
|
||||
#define STATUS_EFFECT_DNA_MELT /datum/status_effect/dna_melt //usually does something horrible to you when you hit 100 genetic instability
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
#define INIT_ORDER_SERVER_MAINT 93
|
||||
#define INIT_ORDER_INPUT 85
|
||||
#define INIT_ORDER_VIS 80
|
||||
#define INIT_ORDER_MATERIALS 76
|
||||
#define INIT_ORDER_RESEARCH 75
|
||||
#define INIT_ORDER_EVENTS 70
|
||||
#define INIT_ORDER_JOBS 65
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#define SIGNAL_TRAIT(trait_ref) "trait [trait_ref]"
|
||||
|
||||
// trait accessor defines
|
||||
#define ADD_TRAIT(target, trait, source) \
|
||||
do { \
|
||||
@@ -6,12 +8,14 @@
|
||||
target.status_traits = list(); \
|
||||
_L = target.status_traits; \
|
||||
_L[trait] = list(source); \
|
||||
SEND_SIGNAL(target, SIGNAL_TRAIT(trait), COMPONENT_ADD_TRAIT); \
|
||||
} else { \
|
||||
_L = target.status_traits; \
|
||||
if (_L[trait]) { \
|
||||
_L[trait] |= list(source); \
|
||||
} else { \
|
||||
_L[trait] = list(source); \
|
||||
SEND_SIGNAL(target, SIGNAL_TRAIT(trait), COMPONENT_ADD_TRAIT); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -31,7 +35,8 @@
|
||||
} \
|
||||
};\
|
||||
if (!length(_L[trait])) { \
|
||||
_L -= trait \
|
||||
_L -= trait; \
|
||||
SEND_SIGNAL(target, SIGNAL_TRAIT(trait), COMPONENT_REMOVE_TRAIT); \
|
||||
}; \
|
||||
if (!length(_L)) { \
|
||||
target.status_traits = null \
|
||||
@@ -46,7 +51,8 @@
|
||||
for (var/_T in _L) { \
|
||||
_L[_T] &= _S;\
|
||||
if (!length(_L[_T])) { \
|
||||
_L -= _T } \
|
||||
_L -= _T ; \
|
||||
SEND_SIGNAL(target, SIGNAL_TRAIT(_T), COMPONENT_REMOVE_TRAIT); } \
|
||||
};\
|
||||
if (!length(_L)) { \
|
||||
target.status_traits = null\
|
||||
@@ -77,6 +83,7 @@
|
||||
#define TRAIT_DISFIGURED "disfigured"
|
||||
#define TRAIT_XENO_HOST "xeno_host" //Tracks whether we're gonna be a baby alien's mummy.
|
||||
#define TRAIT_STUNIMMUNE "stun_immunity"
|
||||
#define TRAIT_TASED_RESISTANCE "tased_resistance" //prevents you from suffering most of the effects of being tased
|
||||
#define TRAIT_SLEEPIMMUNE "sleep_immunity"
|
||||
#define TRAIT_PUSHIMMUNE "push_immunity"
|
||||
#define TRAIT_SHOCKIMMUNE "shock_immunity"
|
||||
@@ -137,6 +144,19 @@
|
||||
#define TRAIT_NOMARROW "nomarrow" // You don't make blood, with chemicals or nanites.
|
||||
#define TRAIT_NOPULSE "nopulse" // Your heart doesn't beat.
|
||||
#define TRAIT_EXEMPT_HEALTH_EVENTS "exempt-health-events"
|
||||
|
||||
// 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)
|
||||
// BUT FOR NOW, THESE ARE HOOKED TO DO update_mobility() VIA COMSIG IN living_mobility.dm
|
||||
// SO IF YOU ADD MORE, BESURE TO UPDATE IT THERE.
|
||||
|
||||
/// Disallow movement
|
||||
#define TRAIT_MOBILITY_NOMOVE "mobility_nomove"
|
||||
/// Disallow pickup
|
||||
#define TRAIT_MOBILITY_NOPICKUP "mobility_nopickup"
|
||||
/// Disallow item use
|
||||
#define TRAIT_MOBILITY_NOUSE "mobility_nouse"
|
||||
|
||||
#define TRAIT_SWIMMING "swimming" //only applied by /datum/element/swimming, for checking
|
||||
|
||||
//non-mob traits
|
||||
@@ -175,6 +195,8 @@
|
||||
#define TRAIT_AUTO_CATCH_ITEM "auto_catch_item"
|
||||
#define TRAIT_CLOWN_MENTALITY "clown_mentality" // The future is now, clownman.
|
||||
#define TRAIT_FREESPRINT "free_sprinting"
|
||||
#define TRAIT_XRAY_VISION "xray_vision"
|
||||
#define TRAIT_THERMAL_VISION "thermal_vision"
|
||||
#define TRAIT_NO_TELEPORT "no-teleport" //you just can't
|
||||
#define TRAIT_NO_INTERNALS "no-internals"
|
||||
#define TRAIT_NO_ALCOHOL "alcohol_intolerance"
|
||||
|
||||
@@ -107,38 +107,6 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
|
||||
if(!src.holder) return
|
||||
message_admins("[key_name_admin(usr)] manually reloaded mentors")
|
||||
|
||||
//Flavor Text
|
||||
/mob/proc/set_flavor()
|
||||
set name = "Set Flavor Text"
|
||||
set desc = "Sets an extended description of your character's features."
|
||||
set category = "IC"
|
||||
|
||||
var/new_flavor = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", flavor_text, MAX_FAVOR_LEN, TRUE)
|
||||
if(!isnull(new_flavor))
|
||||
flavor_text = html_decode(new_flavor)
|
||||
to_chat(src, "Your flavor text has been updated.")
|
||||
|
||||
//Flavor Text
|
||||
/mob/proc/set_flavor_2()
|
||||
set name = "Set Temporary Flavor Text"
|
||||
set desc = "Sets a description of your character's current appearance. Use this for emotions, poses etc."
|
||||
set category = "IC"
|
||||
|
||||
var/new_flavor = stripped_multiline_input(usr, "Set the temporary flavor text in your 'examine' verb. This should be used only for things pertaining to the current round!", "Short-Term Flavor Text", flavor_text_2, MAX_FAVOR_LEN, TRUE)
|
||||
if(!isnull(new_flavor))
|
||||
flavor_text_2 = html_decode(new_flavor)
|
||||
to_chat(src, "Your temporary flavor text has been updated.")
|
||||
|
||||
/mob/proc/print_flavor_text(flavor,temp = FALSE)
|
||||
if(!flavor)
|
||||
return
|
||||
// We are decoding and then encoding to not only get correct amount of characters, but also to prevent partial escaping characters being shown.
|
||||
var/msg = html_decode(replacetext(flavor, "\n", " "))
|
||||
if(length_char(msg) <= 40)
|
||||
return "<span class='notice'>[html_encode(msg)]</span>"
|
||||
else
|
||||
return "<span class='notice'>[html_encode(copytext_char(msg, 1, 37))]... <a href='?src=[REF(src)];flavor[temp ? "2" : ""]_more=1'>More...</span></a>"
|
||||
|
||||
//LOOC toggles
|
||||
/client/verb/listen_looc()
|
||||
set name = "Show/Hide LOOC"
|
||||
|
||||
@@ -174,6 +174,15 @@
|
||||
L[T] = TRUE
|
||||
return L
|
||||
|
||||
/proc/typecacheof_assoc_list(list/pathlist, ignore_root_path = FALSE)
|
||||
. = list()
|
||||
if(!istype(pathlist))
|
||||
return
|
||||
for(var/P in pathlist)
|
||||
var/value = pathlist[P]
|
||||
for(var/T in (ignore_root_path ? subtypesof(P) : typesof(P)))
|
||||
.[T] = value
|
||||
|
||||
//Empties the list by setting the length to 0. Hopefully the elements get garbage collected
|
||||
/proc/clearlist(list/list)
|
||||
if(istype(list))
|
||||
@@ -579,4 +588,4 @@
|
||||
var/list/ret = list()
|
||||
for(var/key in input)
|
||||
ret += key
|
||||
return ret
|
||||
return ret
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
#define BP_MAX_ROOM_SIZE 300
|
||||
|
||||
GLOBAL_LIST_INIT(typecache_powerfailure_safe_areas, typecacheof(/area/engine/engineering, \
|
||||
/area/engine/supermatter, \
|
||||
/area/engine/atmospherics_engine, \
|
||||
/area/ai_monitored/turret_protected/ai))
|
||||
|
||||
//Repopulates sortedAreas list
|
||||
/proc/repopulate_sorted_areas()
|
||||
GLOB.sortedAreas = list()
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
//////////////////////////////////////////////////////////
|
||||
//A bunch of helpers to make genetics less of a headache//
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
#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_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)
|
||||
@@ -549,3 +549,36 @@
|
||||
var/pressure = environment.return_pressure()
|
||||
if(pressure <= LAVALAND_EQUIPMENT_EFFECT_PRESSURE)
|
||||
. = TRUE
|
||||
|
||||
/proc/ispipewire(item)
|
||||
var/static/list/pipe_wire = list(
|
||||
/obj/machinery/atmospherics,
|
||||
/obj/structure/disposalpipe,
|
||||
/obj/structure/cable
|
||||
)
|
||||
return (is_type_in_list(item, pipe_wire))
|
||||
|
||||
// Find a obstruction free turf that's within the range of the center. Can also condition on if it is of a certain area type.
|
||||
/proc/find_obstruction_free_location(var/range, var/atom/center, var/area/specific_area)
|
||||
var/list/turfs = RANGE_TURFS(range, center)
|
||||
var/list/possible_loc = list()
|
||||
for(var/turf/found_turf in turfs)
|
||||
var/area/turf_area = get_area(found_turf)
|
||||
if(specific_area) // We check if both the turf is a floor, and that it's actually in the area. // We also want a location that's clear of any obstructions.
|
||||
if(!istype(turf_area, specific_area))
|
||||
continue
|
||||
if(!isspaceturf(found_turf))
|
||||
if(!is_blocked_turf(found_turf))
|
||||
possible_loc.Add(found_turf)
|
||||
if(possible_loc.len < 1) // Need at least one free location.
|
||||
return FALSE
|
||||
return pick(possible_loc)
|
||||
|
||||
/proc/power_fail(duration_min, duration_max)
|
||||
for(var/P in GLOB.apcs_list)
|
||||
var/obj/machinery/power/apc/C = P
|
||||
if(C.cell && SSmapping.level_trait(C.z, ZTRAIT_STATION))
|
||||
var/area/A = C.area
|
||||
if(GLOB.typecache_powerfailure_safe_areas[A.type])
|
||||
continue
|
||||
C.energy_fail(rand(duration_min,duration_max))
|
||||
+30
-14
@@ -47,7 +47,7 @@
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear/socks, GLOB.socks_list)
|
||||
return pick(GLOB.socks_list)
|
||||
|
||||
/proc/random_features()
|
||||
/proc/random_features(intendedspecies)
|
||||
if(!GLOB.tails_list_human.len)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/human, GLOB.tails_list_human)
|
||||
if(!GLOB.tails_list_lizard.len)
|
||||
@@ -105,6 +105,8 @@
|
||||
var/datum/sprite_accessory/mam_tails/instance = GLOB.mam_tails_list[mtpath]
|
||||
if(istype(instance, /datum/sprite_accessory))
|
||||
var/datum/sprite_accessory/S = instance
|
||||
if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies))
|
||||
continue
|
||||
if(!S.ckeys_allowed)
|
||||
snowflake_mam_tails_list[S.name] = mtpath
|
||||
var/list/snowflake_markings_list = list()
|
||||
@@ -112,6 +114,8 @@
|
||||
var/datum/sprite_accessory/mam_body_markings/instance = GLOB.mam_body_markings_list[mmpath]
|
||||
if(istype(instance, /datum/sprite_accessory))
|
||||
var/datum/sprite_accessory/S = instance
|
||||
if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies))
|
||||
continue
|
||||
if(!S.ckeys_allowed)
|
||||
snowflake_markings_list[S.name] = mmpath
|
||||
var/list/snowflake_ears_list = list()
|
||||
@@ -119,6 +123,8 @@
|
||||
var/datum/sprite_accessory/mam_ears/instance = GLOB.mam_ears_list[mepath]
|
||||
if(istype(instance, /datum/sprite_accessory))
|
||||
var/datum/sprite_accessory/S = instance
|
||||
if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies))
|
||||
continue
|
||||
if(!S.ckeys_allowed)
|
||||
snowflake_ears_list[S.name] = mepath
|
||||
var/list/snowflake_mam_snouts_list = list()
|
||||
@@ -126,8 +132,19 @@
|
||||
var/datum/sprite_accessory/mam_snouts/instance = GLOB.mam_snouts_list[mspath]
|
||||
if(istype(instance, /datum/sprite_accessory))
|
||||
var/datum/sprite_accessory/S = instance
|
||||
if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies))
|
||||
continue
|
||||
if(!S.ckeys_allowed)
|
||||
snowflake_mam_snouts_list[S.name] = mspath
|
||||
var/list/snowflake_ipc_antenna_list = list()
|
||||
for(var/mspath in GLOB.ipc_antennas_list)
|
||||
var/datum/sprite_accessory/mam_snouts/instance = GLOB.ipc_antennas_list[mspath]
|
||||
if(istype(instance, /datum/sprite_accessory))
|
||||
var/datum/sprite_accessory/S = instance
|
||||
if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies))
|
||||
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()
|
||||
@@ -153,10 +170,10 @@
|
||||
"insect_fluff" = "None",
|
||||
"insect_markings" = pick(GLOB.insect_markings_list),
|
||||
"taur" = "None",
|
||||
"mam_body_markings" = pick(snowflake_markings_list),
|
||||
"mam_ears" = pick(snowflake_ears_list),
|
||||
"mam_snouts" = pick(snowflake_mam_snouts_list),
|
||||
"mam_tail" = pick(snowflake_mam_tails_list),
|
||||
"mam_body_markings" = snowflake_markings_list.len ? pick(snowflake_markings_list) : "None",
|
||||
"mam_ears" = snowflake_ears_list ? pick(snowflake_ears_list) : "None",
|
||||
"mam_snouts" = snowflake_mam_snouts_list ? pick(snowflake_mam_snouts_list) : "None",
|
||||
"mam_tail" = snowflake_mam_tails_list ? pick(snowflake_mam_tails_list) : "None",
|
||||
"mam_tail_animated" = "None",
|
||||
"xenodorsal" = "Standard",
|
||||
"xenohead" = "Standard",
|
||||
@@ -165,7 +182,7 @@
|
||||
"has_cock" = FALSE,
|
||||
"cock_shape" = pick(GLOB.cock_shapes_list),
|
||||
"cock_length" = 6,
|
||||
"cock_girth_ratio" = COCK_GIRTH_RATIO_DEF,
|
||||
"cock_diameter_ratio" = COCK_DIAMETER_RATIO_DEF,
|
||||
"cock_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"),
|
||||
"has_sheath" = FALSE,
|
||||
"sheath_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"),
|
||||
@@ -204,7 +221,7 @@
|
||||
"womb_cum_rate" = CUM_RATE,
|
||||
"womb_cum_mult" = CUM_RATE_MULT,
|
||||
"womb_efficiency" = CUM_EFFICIENCY,
|
||||
"ipc_screen" = "Sunburst",
|
||||
"ipc_screen" = snowflake_ipc_antenna_list ? pick(snowflake_ipc_antenna_list) : "None",
|
||||
"ipc_antenna" = "None",
|
||||
"flavor_text" = "",
|
||||
"meat_type" = "Mammalian"
|
||||
@@ -356,7 +373,7 @@ GLOBAL_LIST_EMPTY(species_list)
|
||||
checked_health["health"] = health
|
||||
return ..()
|
||||
|
||||
/proc/do_after(mob/user, var/delay, needhand = 1, atom/target = null, progress = 1, datum/callback/extra_checks = null)
|
||||
/proc/do_after(mob/user, var/delay, needhand = 1, atom/target = null, progress = 1, datum/callback/extra_checks = null, required_mobility_flags = (MOBILITY_USE|MOBILITY_MOVE))
|
||||
if(!user)
|
||||
return 0
|
||||
var/atom/Tloc = null
|
||||
@@ -384,6 +401,7 @@ GLOBAL_LIST_EMPTY(species_list)
|
||||
var/endtime = world.time + delay
|
||||
var/starttime = world.time
|
||||
. = 1
|
||||
var/mob/living/L = isliving(user) && user //evals to last thing eval'd
|
||||
while (world.time < endtime)
|
||||
stoplag(1)
|
||||
if (progress)
|
||||
@@ -393,15 +411,13 @@ GLOBAL_LIST_EMPTY(species_list)
|
||||
drifting = 0
|
||||
Uloc = user.loc
|
||||
|
||||
if(QDELETED(user) || user.stat || user.IsKnockdown() || user.IsStun() || (!drifting && user.loc != Uloc) || (extra_checks && !extra_checks.Invoke()))
|
||||
if(L && !CHECK_ALL_MOBILITY(L, required_mobility_flags))
|
||||
. = 0
|
||||
break
|
||||
|
||||
if(isliving(user))
|
||||
var/mob/living/L = user
|
||||
if(L.recoveringstam)
|
||||
. = 0
|
||||
break
|
||||
if(QDELETED(user) || user.stat || (!drifting && user.loc != Uloc) || (extra_checks && !extra_checks.Invoke()))
|
||||
. = 0
|
||||
break
|
||||
|
||||
if(!QDELETED(Tloc) && (QDELETED(target) || Tloc != target.loc))
|
||||
if((Uloc != Tloc || Tloc != user) && !drifting)
|
||||
|
||||
@@ -354,6 +354,7 @@
|
||||
roundend_report.set_content(content)
|
||||
roundend_report.stylesheets = list()
|
||||
roundend_report.add_stylesheet("roundend", 'html/browser/roundend.css')
|
||||
roundend_report.add_stylesheet("font-awesome", 'html/font-awesome/css/all.min.css')
|
||||
roundend_report.open(0)
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/personal_report(client/C, popcount)
|
||||
|
||||
+15
-1
@@ -49,7 +49,7 @@
|
||||
alert("Invalid name.")
|
||||
return ""
|
||||
return sanitize(t)
|
||||
|
||||
|
||||
/proc/sanitize_filename(t)
|
||||
return sanitize_simple(t, list("\n"="", "\t"="", "/"="", "\\"="", "?"="", "%"="", "*"="", ":"="", "|"="", "\""="", "<"="", ">"=""))
|
||||
|
||||
@@ -798,3 +798,17 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
out += prob(replaceprob)? pick(replacementchars) : char
|
||||
return out.Join("")
|
||||
|
||||
/proc/readable_corrupted_text(text)
|
||||
var/list/corruption_options = list("..", "£%", "~~\"", "!!", "*", "^", "$!", "-", "}", "?")
|
||||
var/corrupted_text = ""
|
||||
for(var/letter_index = 1; letter_index <= length(text); letter_index++) // Have every letter have a chance of creating corruption on either side
|
||||
var/letter = text[letter_index] // Small chance of letters being removed in place of corruption - still overall readable
|
||||
if(prob(15))
|
||||
corrupted_text += pick(corruption_options)
|
||||
if(prob(95))
|
||||
corrupted_text += letter
|
||||
else
|
||||
corrupted_text += pick(corruption_options)
|
||||
if(prob(15))
|
||||
corrupted_text += pick(corruption_options)
|
||||
return corrupted_text
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
// Contains VOREStation based vore description type2type functions
|
||||
// list2text - takes delimiter and returns text
|
||||
// text2list - takes delimiter, and creates list
|
||||
//
|
||||
*/
|
||||
|
||||
// Concatenates a list of strings into a single string. A seperator may optionally be provided.
|
||||
/proc/list2text(list/ls, sep)
|
||||
if (ls.len <= 1) // Early-out code for empty or singleton lists.
|
||||
return ls.len ? ls[1] : ""
|
||||
|
||||
var/l = ls.len // Made local for sanic speed.
|
||||
var/i = 0 // Incremented every time a list index is accessed.
|
||||
|
||||
if (sep <> null)
|
||||
// Macros expand to long argument lists like so: sep, ls[++i], sep, ls[++i], sep, ls[++i], etc...
|
||||
#define S1 sep, ls[++i]
|
||||
#define S4 S1, S1, S1, S1
|
||||
#define S16 S4, S4, S4, S4
|
||||
#define S64 S16, S16, S16, S16
|
||||
|
||||
. = "[ls[++i]]" // Make sure the initial element is converted to text.
|
||||
|
||||
// Having the small concatenations come before the large ones boosted speed by an average of at least 5%.
|
||||
if (l-1 & 0x01) // 'i' will always be 1 here.
|
||||
. = text("[][][]", ., S1) // Append 1 element if the remaining elements are not a multiple of 2.
|
||||
if (l-i & 0x02)
|
||||
. = text("[][][][][]", ., S1, S1) // Append 2 elements if the remaining elements are not a multiple of 4.
|
||||
if (l-i & 0x04)
|
||||
. = text("[][][][][][][][][]", ., S4) // And so on....
|
||||
if (l-i & 0x08)
|
||||
. = text("[][][][][][][][][][][][][][][][][]", ., S4, S4)
|
||||
if (l-i & 0x10)
|
||||
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16)
|
||||
if (l-i & 0x20)
|
||||
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16, S16)
|
||||
if (l-i & 0x40)
|
||||
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64)
|
||||
while (l > i) // Chomp through the rest of the list, 128 elements at a time.
|
||||
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
|
||||
|
||||
#undef S64
|
||||
#undef S16
|
||||
#undef S4
|
||||
#undef S1
|
||||
else
|
||||
// Macros expand to long argument lists like so: ls[++i], ls[++i], ls[++i], etc...
|
||||
#define S1 ls[++i]
|
||||
#define S4 S1, S1, S1, S1
|
||||
#define S16 S4, S4, S4, S4
|
||||
#define S64 S16, S16, S16, S16
|
||||
|
||||
. = "[ls[++i]]" // Make sure the initial element is converted to text.
|
||||
|
||||
if (l-1 & 0x01) // 'i' will always be 1 here.
|
||||
. += S1 // Append 1 element if the remaining elements are not a multiple of 2.
|
||||
if (l-i & 0x02)
|
||||
. = text("[][][]", ., S1, S1) // Append 2 elements if the remaining elements are not a multiple of 4.
|
||||
if (l-i & 0x04)
|
||||
. = text("[][][][][]", ., S4) // And so on...
|
||||
if (l-i & 0x08)
|
||||
. = text("[][][][][][][][][]", ., S4, S4)
|
||||
if (l-i & 0x10)
|
||||
. = text("[][][][][][][][][][][][][][][][][]", ., S16)
|
||||
if (l-i & 0x20)
|
||||
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16, S16)
|
||||
if (l-i & 0x40)
|
||||
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64)
|
||||
while (l > i) // Chomp through the rest of the list, 128 elements at a time.
|
||||
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
|
||||
|
||||
#undef S64
|
||||
#undef S16
|
||||
#undef S4
|
||||
#undef S1
|
||||
|
||||
// Converts a string into a list by splitting the string at each delimiter found. (discarding the seperator)
|
||||
/proc/text2list(text, delimiter="\n")
|
||||
var/delim_len = length(delimiter)
|
||||
if (delim_len < 1)
|
||||
return list(text)
|
||||
|
||||
. = list()
|
||||
var/last_found = 1
|
||||
var/found
|
||||
|
||||
do
|
||||
found = findtext(text, delimiter, last_found, 0)
|
||||
. += copytext(text, last_found, found)
|
||||
last_found = found + delim_len
|
||||
while (found)
|
||||
|
||||
// Returns true if val is from min to max, inclusive.
|
||||
/proc/IsInRange(val, min, max)
|
||||
return (val >= min) && (val <= max)
|
||||
@@ -1,39 +0,0 @@
|
||||
|
||||
|
||||
/datum/projectile_data
|
||||
var/src_x
|
||||
var/src_y
|
||||
var/time
|
||||
var/distance
|
||||
var/power_x
|
||||
var/power_y
|
||||
var/dest_x
|
||||
var/dest_y
|
||||
|
||||
/datum/projectile_data/New(var/src_x, var/src_y, var/time, var/distance, \
|
||||
var/power_x, var/power_y, var/dest_x, var/dest_y)
|
||||
src.src_x = src_x
|
||||
src.src_y = src_y
|
||||
src.time = time
|
||||
src.distance = distance
|
||||
src.power_x = power_x
|
||||
src.power_y = power_y
|
||||
src.dest_x = dest_x
|
||||
src.dest_y = dest_y
|
||||
|
||||
/proc/projectile_trajectory(src_x, src_y, rotation, angle, power)
|
||||
|
||||
// returns the destination (Vx,y) that a projectile shot at [src_x], [src_y], with an angle of [angle],
|
||||
// rotated at [rotation] and with the power of [power]
|
||||
// Thanks to VistaPOWA for this function
|
||||
|
||||
var/power_x = power * cos(angle)
|
||||
var/power_y = power * sin(angle)
|
||||
var/time = 2* power_y / 10 //10 = g
|
||||
|
||||
var/distance = time * power_x
|
||||
|
||||
var/dest_x = src_x + distance*sin(rotation);
|
||||
var/dest_y = src_y + distance*cos(rotation);
|
||||
|
||||
return new /datum/projectile_data(src_x, src_y, time, distance, power_x, power_y, dest_x, dest_y)
|
||||
@@ -214,7 +214,7 @@ GLOBAL_LIST_INIT(bitfields, list(
|
||||
"CAN_MASTURBATE_WITH" = CAN_MASTURBATE_WITH,
|
||||
"MASTURBATE_LINKED_ORGAN" = MASTURBATE_LINKED_ORGAN,
|
||||
"CAN_CLIMAX_WITH" = CAN_CLIMAX_WITH
|
||||
|
||||
|
||||
),
|
||||
"mob_biotypes" = list (
|
||||
"MOB_ORGANIC" = MOB_ORGANIC,
|
||||
@@ -227,5 +227,16 @@ GLOBAL_LIST_INIT(bitfields, list(
|
||||
"MOB_EPIC" = MOB_EPIC,
|
||||
"MOB_REPTILE" = MOB_REPTILE,
|
||||
"MOB_SPIRIT" = MOB_SPIRIT
|
||||
),
|
||||
"mobility_flags" = list(
|
||||
"MOBILITY_MOVE" = MOBILITY_MOVE,
|
||||
"MOBILITY_STAND" = MOBILITY_STAND,
|
||||
"MOBILITY_PICKUP" = MOBILITY_PICKUP,
|
||||
"MOBILITY_USE" = MOBILITY_USE,
|
||||
"MOBILITY_UI" = MOBILITY_UI,
|
||||
"MOBILITY_STORAGE" = MOBILITY_STORAGE,
|
||||
"MOBILITY_PULL" = MOBILITY_PULL,
|
||||
"MOBILITY_HOLD" = MOBILITY_HOLD,
|
||||
"MOBILITY_RESIST" = MOBILITY_RESIST
|
||||
)
|
||||
))
|
||||
|
||||
@@ -21,8 +21,11 @@ GLOBAL_LIST(op_se_blocks)
|
||||
GLOBAL_VAR(NULLED_SE)
|
||||
GLOBAL_VAR(NULLED_UI)
|
||||
|
||||
GLOBAL_LIST_EMPTY(global_mutations) // list of hidden mutation things
|
||||
GLOBAL_LIST_EMPTY(all_mutations)
|
||||
GLOBAL_LIST_EMPTY(full_sequences)
|
||||
|
||||
GLOBAL_LIST_EMPTY(bad_mutations)
|
||||
GLOBAL_LIST_EMPTY(good_mutations)
|
||||
GLOBAL_LIST_EMPTY(not_good_mutations)
|
||||
GLOBAL_LIST_EMPTY(not_good_mutations)
|
||||
|
||||
GLOBAL_LIST_EMPTY(mutation_recipes)
|
||||
@@ -29,7 +29,6 @@ GLOBAL_LIST_EMPTY(available_ai_shells)
|
||||
GLOBAL_LIST_INIT(simple_animals, list(list(),list(),list(),list())) // One for each AI_* status define
|
||||
GLOBAL_LIST_EMPTY(spidermobs) //all sentient spider mobs
|
||||
GLOBAL_LIST_EMPTY(bots_list)
|
||||
GLOBAL_LIST_EMPTY(living_cameras)
|
||||
GLOBAL_LIST_EMPTY(aiEyes)
|
||||
|
||||
GLOBAL_LIST_EMPTY(language_datum_instances)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#define POLL_IGNORE_DEMON "demon"
|
||||
#define POLL_IGNORE_WIZARD "wizard"
|
||||
#define POLL_IGNORE_CLONE "clone"
|
||||
#define POLL_IGNORE_CONTRACTOR_SUPPORT "contractor_support"
|
||||
|
||||
GLOBAL_LIST_INIT(poll_ignore_desc, list(
|
||||
POLL_IGNORE_SENTIENCE_POTION = "Sentience potion",
|
||||
@@ -37,7 +38,8 @@ GLOBAL_LIST_INIT(poll_ignore_desc, list(
|
||||
POLL_IGNORE_SPLITPERSONALITY = "Split Personality",
|
||||
POLL_IGNORE_DEMON = "Demons",
|
||||
POLL_IGNORE_WIZARD = "Wizards",
|
||||
POLL_IGNORE_CLONE = "Defective/SDGF clones"
|
||||
POLL_IGNORE_CLONE = "Defective/SDGF clones",
|
||||
POLL_IGNORE_CONTRACTOR_SUPPORT = "Contractor Support Unit"
|
||||
))
|
||||
GLOBAL_LIST_INIT(poll_ignore, init_poll_ignore())
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
if(check_click_intercept(params,A))
|
||||
return
|
||||
|
||||
if(stat || lockcharge || IsKnockdown() || IsStun() || IsUnconscious())
|
||||
if(stat || locked_down || IsParalyzed() || IsStun() || IsUnconscious())
|
||||
return
|
||||
|
||||
var/list/modifiers = params2list(params)
|
||||
@@ -66,7 +66,7 @@
|
||||
if(C.user_unbuckle_mob(C.buckled_mobs[1],src))
|
||||
return
|
||||
|
||||
if(!W && get_dist(src,A) <= interaction_range)
|
||||
if(!W && (get_dist(src,A) <= interaction_range))
|
||||
A.attack_robot(src)
|
||||
return
|
||||
|
||||
|
||||
@@ -273,7 +273,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
if(!istype(L) || !L.can_resist())
|
||||
return
|
||||
L.changeNext_move(CLICK_CD_RESIST)
|
||||
if(L.canmove)
|
||||
if(CHECK_MOBILITY(L, MOBILITY_MOVE))
|
||||
return L.resist_fire() //I just want to start a flame in your hearrrrrrtttttt.
|
||||
|
||||
|
||||
@@ -601,7 +601,7 @@ so as to remain in compliance with the most up-to-date laws."
|
||||
if(!istype(L) || !L.can_resist())
|
||||
return
|
||||
L.changeNext_move(CLICK_CD_RESIST)
|
||||
if((L.canmove) && (L.last_special <= world.time))
|
||||
if(CHECK_MOBILITY(L, MOBILITY_MOVE) && (L.last_special <= world.time))
|
||||
return L.resist_restraints()
|
||||
|
||||
/obj/screen/alert/restrained/buckled/Click()
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
if(isovermind(usr))
|
||||
var/mob/camera/blob/B = usr
|
||||
if(!B.placed)
|
||||
B.place_blob_core(B.base_point_rate, 0)
|
||||
B.place_blob_core(0)
|
||||
B.transport_core()
|
||||
|
||||
/obj/screen/blob/Blobbernaut
|
||||
@@ -91,26 +91,26 @@
|
||||
var/mob/camera/blob/B = usr
|
||||
B.create_factory()
|
||||
|
||||
/obj/screen/blob/ReadaptChemical
|
||||
/obj/screen/blob/ReadaptStrain
|
||||
icon_state = "ui_chemswap"
|
||||
name = "Readapt Chemical (40)"
|
||||
desc = "Randomly rerolls your chemical for 40 resources."
|
||||
name = "Readapt Strain (40)"
|
||||
desc = "Allows you to choose a new strain from 4 random choices for 40 resources."
|
||||
|
||||
/obj/screen/blob/ReadaptChemical/MouseEntered(location,control,params)
|
||||
/obj/screen/blob/ReadaptStrain/MouseEntered(location,control,params)
|
||||
if(hud && hud.mymob && isovermind(hud.mymob))
|
||||
var/mob/camera/blob/B = hud.mymob
|
||||
if(B.free_chem_rerolls)
|
||||
name = "Readapt Chemical (FREE)"
|
||||
desc = "Randomly rerolls your chemical for free."
|
||||
if(B.free_strain_rerolls)
|
||||
name = "Readapt Strain (FREE)"
|
||||
desc = "Randomly rerolls your strain for free."
|
||||
else
|
||||
name = initial(name)
|
||||
desc = initial(desc)
|
||||
..()
|
||||
|
||||
/obj/screen/blob/ReadaptChemical/Click()
|
||||
/obj/screen/blob/ReadaptStrain/Click()
|
||||
if(isovermind(usr))
|
||||
var/mob/camera/blob/B = usr
|
||||
B.chemical_reroll()
|
||||
B.strain_reroll()
|
||||
|
||||
/obj/screen/blob/RelocateCore
|
||||
icon_state = "ui_swap"
|
||||
@@ -175,7 +175,7 @@
|
||||
using.hud = src
|
||||
static_inventory += using
|
||||
|
||||
using = new /obj/screen/blob/ReadaptChemical()
|
||||
using = new /obj/screen/blob/ReadaptStrain()
|
||||
using.screen_loc = ui_storage1
|
||||
using.hud = src
|
||||
static_inventory += using
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
var/mob/living/carbon/tempcarb = user
|
||||
if(!tempcarb.combatmode)
|
||||
totitemdamage *= 0.5
|
||||
if(user.resting)
|
||||
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
|
||||
totitemdamage *= 0.5
|
||||
//CIT CHANGES END HERE
|
||||
if(user != src && check_shields(I, totitemdamage, "the [I.name]", MELEE_ATTACK, I.armour_penetration))
|
||||
|
||||
@@ -335,6 +335,10 @@
|
||||
config_entry_value = 16
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/station_space_budget
|
||||
config_entry_value = 10
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/flag/allow_random_events // Enables random events mid-round when set
|
||||
|
||||
/datum/config_entry/number/events_min_time_mul // Multipliers for random events minimal starting time and minimal players amounts
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
//Sleeping in here prevents future fires until returned.
|
||||
/datum/controller/subsystem/proc/fire(resumed = 0)
|
||||
flags |= SS_NO_FIRE
|
||||
throw EXCEPTION("Subsystem [src]([type]) does not fire() but did not set the SS_NO_FIRE flag. Please add the SS_NO_FIRE flag to any subsystem that doesn't fire so it doesn't get added to the processing list and waste cpu.")
|
||||
CRASH("Subsystem [src]([type]) does not fire() but did not set the SS_NO_FIRE flag. Please add the SS_NO_FIRE flag to any subsystem that doesn't fire so it doesn't get added to the processing list and waste cpu.")
|
||||
|
||||
/datum/controller/subsystem/Destroy()
|
||||
dequeue()
|
||||
|
||||
@@ -16,7 +16,7 @@ SUBSYSTEM_DEF(atoms)
|
||||
|
||||
/datum/controller/subsystem/atoms/Initialize(timeofday)
|
||||
GLOB.fire_overlay.appearance_flags = RESET_COLOR
|
||||
setupGenetics() //to set the mutations' place in structural enzymes, so monkey.initialize() knows where to put the monkey mutation.
|
||||
setupGenetics() //to set the mutations' sequence.
|
||||
initialized = INITIALIZATION_INNEW_MAPLOAD
|
||||
InitializeAtoms()
|
||||
return ..()
|
||||
@@ -108,16 +108,19 @@ SUBSYSTEM_DEF(atoms)
|
||||
BadInitializeCalls = SSatoms.BadInitializeCalls
|
||||
|
||||
/datum/controller/subsystem/atoms/proc/setupGenetics()
|
||||
var/list/avnums = new /list(DNA_STRUC_ENZYMES_BLOCKS)
|
||||
for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++)
|
||||
avnums[i] = i
|
||||
CHECK_TICK
|
||||
|
||||
for(var/A in subtypesof(/datum/mutation/human))
|
||||
var/datum/mutation/human/B = new A()
|
||||
if(B.dna_block == NON_SCANNABLE)
|
||||
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
|
||||
B.dna_block = pick_n_take(avnums)
|
||||
if(B.quality == POSITIVE)
|
||||
GLOB.good_mutations |= B
|
||||
else if(B.quality == NEGATIVE)
|
||||
|
||||
@@ -6,7 +6,7 @@ SUBSYSTEM_DEF(garbage)
|
||||
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
|
||||
init_order = INIT_ORDER_GARBAGE
|
||||
|
||||
var/list/collection_timeout = list(0, 2 MINUTES, 10 SECONDS) // deciseconds to wait before moving something up in the queue to the next level
|
||||
var/list/collection_timeout = list(15 SECONDS, 30 SECONDS) // deciseconds to wait before moving something up in the queue to the next level
|
||||
|
||||
//Stat tracking
|
||||
var/delslasttick = 0 // number of del()'s we've done this tick
|
||||
|
||||
@@ -83,15 +83,15 @@ SUBSYSTEM_DEF(jukeboxes)
|
||||
return
|
||||
for(var/list/jukeinfo in activejukeboxes)
|
||||
if(!jukeinfo.len)
|
||||
EXCEPTION("Active jukebox without any associated metadata.")
|
||||
stack_trace("Active jukebox without any associated metadata.")
|
||||
continue
|
||||
var/datum/track/juketrack = jukeinfo[1]
|
||||
if(!istype(juketrack))
|
||||
EXCEPTION("Invalid jukebox track datum.")
|
||||
stack_trace("Invalid jukebox track datum.")
|
||||
continue
|
||||
var/obj/jukebox = jukeinfo[3]
|
||||
if(!istype(jukebox))
|
||||
EXCEPTION("Nonexistant or invalid object associated with jukebox.")
|
||||
stack_trace("Nonexistant or invalid object associated with jukebox.")
|
||||
continue
|
||||
var/sound/song_played = sound(juketrack.song_path)
|
||||
var/area/currentarea = get_area(jukebox)
|
||||
|
||||
@@ -14,6 +14,7 @@ SUBSYSTEM_DEF(mapping)
|
||||
var/list/ruins_templates = list()
|
||||
var/list/space_ruins_templates = list()
|
||||
var/list/lava_ruins_templates = list()
|
||||
var/list/station_ruins_templates = list()
|
||||
var/datum/space_level/isolated_ruins_z //Created on demand during ruin loading.
|
||||
|
||||
var/list/shuttle_templates = list()
|
||||
@@ -94,6 +95,11 @@ SUBSYSTEM_DEF(mapping)
|
||||
var/list/space_ruins = levels_by_trait(ZTRAIT_SPACE_RUINS)
|
||||
if (space_ruins.len)
|
||||
seedRuins(space_ruins, CONFIG_GET(number/space_budget), /area/space, space_ruins_templates)
|
||||
|
||||
// Generate station space ruins
|
||||
var/list/station_ruins = levels_by_trait(ZTRAIT_STATION)
|
||||
if (station_ruins.len)
|
||||
seedRuins(station_ruins, CONFIG_GET(number/station_space_budget), /area/space/station_ruins, station_ruins_templates)
|
||||
SSmapping.seedStation()
|
||||
loading_ruins = FALSE
|
||||
#endif
|
||||
@@ -161,6 +167,7 @@ SUBSYSTEM_DEF(mapping)
|
||||
ruins_templates = SSmapping.ruins_templates
|
||||
space_ruins_templates = SSmapping.space_ruins_templates
|
||||
lava_ruins_templates = SSmapping.lava_ruins_templates
|
||||
station_ruins_templates = SSmapping.station_ruins_templates
|
||||
shuttle_templates = SSmapping.shuttle_templates
|
||||
shelter_templates = SSmapping.shelter_templates
|
||||
unused_turfs = SSmapping.unused_turfs
|
||||
@@ -352,6 +359,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
// Still supporting bans by filename
|
||||
var/list/banned = generateMapList("[global.config.directory]/lavaruinblacklist.txt")
|
||||
banned += generateMapList("[global.config.directory]/spaceruinblacklist.txt")
|
||||
banned += generateMapList("[global.config.directory]/stationruinblacklist.txt")
|
||||
|
||||
for(var/item in sortList(subtypesof(/datum/map_template/ruin), /proc/cmp_ruincost_priority))
|
||||
var/datum/map_template/ruin/ruin_type = item
|
||||
@@ -372,6 +380,8 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
space_ruins_templates[R.name] = R
|
||||
else if(istype(R, /datum/map_template/ruin/station))
|
||||
station_room_templates[R.name] = R
|
||||
else if(istype(R, /datum/map_template/ruin/spacenearstation))
|
||||
station_ruins_templates[R.name] = R
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/preloadShuttleTemplates()
|
||||
var/list/unbuyable = generateMapList("[global.config.directory]/unbuyableshuttles.txt")
|
||||
|
||||
@@ -5,23 +5,25 @@ These materials call on_applied() on whatever item they are applied to, common e
|
||||
|
||||
SUBSYSTEM_DEF(materials)
|
||||
name = "Materials"
|
||||
flags = SS_NO_FIRE
|
||||
init_order = INIT_ORDER_MATERIALS
|
||||
flags = SS_NO_FIRE | SS_NO_INIT
|
||||
///Dictionary of material.type || material ref
|
||||
var/list/materials = list()
|
||||
var/list/materials
|
||||
///Dictionary of category || list of material refs
|
||||
var/list/materials_by_category = list()
|
||||
var/list/materials_by_category
|
||||
///List of stackcrafting recipes for materials using rigid materials
|
||||
var/list/rigid_stack_recipes = list(new/datum/stack_recipe("chair", /obj/structure/chair/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE))
|
||||
|
||||
/datum/controller/subsystem/materials/Initialize(timeofday)
|
||||
InitializeMaterials()
|
||||
return ..()
|
||||
|
||||
///Ran on initialize, populated the materials and materials_by_category dictionaries with their appropiate vars (See these variables for more info)
|
||||
/datum/controller/subsystem/materials/proc/InitializeMaterials(timeofday)
|
||||
/datum/controller/subsystem/materials/proc/InitializeMaterials()
|
||||
materials = list()
|
||||
materials_by_category = list()
|
||||
for(var/type in subtypesof(/datum/material))
|
||||
var/datum/material/ref = new type
|
||||
materials[type] = ref
|
||||
for(var/c in ref.categories)
|
||||
materials_by_category[c] += list(ref)
|
||||
|
||||
/datum/controller/subsystem/materials/proc/GetMaterialRef(datum/material/fakemat)
|
||||
if(!materials)
|
||||
InitializeMaterials()
|
||||
return materials[fakemat] || fakemat
|
||||
@@ -26,18 +26,16 @@ SUBSYSTEM_DEF(mobs)
|
||||
var/seconds = wait * 0.1
|
||||
if (!resumed)
|
||||
src.currentrun = GLOB.mob_living_list.Copy()
|
||||
if (GLOB.living_cameras.len)
|
||||
src.currentrun += GLOB.living_cameras
|
||||
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
var/times_fired = src.times_fired
|
||||
while(currentrun.len)
|
||||
var/mob/M = currentrun[currentrun.len]
|
||||
var/mob/living/L = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
if(M)
|
||||
M.Life(seconds, times_fired)
|
||||
if(L)
|
||||
L.Life(seconds, times_fired)
|
||||
else
|
||||
GLOB.mob_living_list.Remove(M)
|
||||
GLOB.mob_living_list.Remove(L)
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
@@ -113,11 +113,8 @@ SUBSYSTEM_DEF(shuttle)
|
||||
qdel(T, force=TRUE)
|
||||
CheckAutoEvac()
|
||||
|
||||
//Cargo stuff start
|
||||
var/fire_time_diff = max(0, world.time - last_fire) //Don't want this to be below 0, seriously.
|
||||
var/point_gain = (fire_time_diff / 600) * passive_supply_points_per_minute
|
||||
points += point_gain
|
||||
//Cargo stuff end
|
||||
if(!(times_fired % CEILING(600/wait, 1)))
|
||||
points += passive_supply_points_per_minute
|
||||
|
||||
var/esETA = emergency?.getModeStr()
|
||||
emergency_shuttle_stat_text = "[esETA? "[esETA] [emergency.getTimerStr()]" : ""]"
|
||||
@@ -185,14 +182,13 @@ SUBSYSTEM_DEF(shuttle)
|
||||
WARNING("requestEvac(): There is no emergency shuttle, but the \
|
||||
shuttle was called. Using the backup shuttle instead.")
|
||||
if(!backup_shuttle)
|
||||
throw EXCEPTION("requestEvac(): There is no emergency shuttle, \
|
||||
CRASH("requestEvac(): There is no emergency shuttle, \
|
||||
or backup shuttle! The game will be unresolvable. This is \
|
||||
possibly a mapping error, more likely a bug with the shuttle \
|
||||
manipulation system, or badminry. It is possible to manually \
|
||||
resolve this problem by loading an emergency shuttle template \
|
||||
manually, and then calling register() on the mobile docking port. \
|
||||
Good luck.")
|
||||
return
|
||||
emergency = backup_shuttle
|
||||
var/srd = CONFIG_GET(number/shuttle_refuel_delay)
|
||||
if(world.time - SSticker.round_start_time < srd)
|
||||
@@ -420,7 +416,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/request_transit_dock(obj/docking_port/mobile/M)
|
||||
if(!istype(M))
|
||||
throw EXCEPTION("[M] is not a mobile docking port")
|
||||
CRASH("[M] is not a mobile docking port")
|
||||
|
||||
if(M.assigned_transit)
|
||||
return
|
||||
|
||||
@@ -370,7 +370,7 @@ SUBSYSTEM_DEF(vote)
|
||||
var/list/runnable_storytellers = config.get_runnable_storytellers()
|
||||
for(var/T in runnable_storytellers)
|
||||
var/datum/dynamic_storyteller/S = T
|
||||
runnable_storytellers[S] *= scores[initial(S.name)]
|
||||
runnable_storytellers[S] *= stored_gamemode_votes[initial(S.name)]
|
||||
var/datum/dynamic_storyteller/S = pickweightAllowZero(runnable_storytellers)
|
||||
GLOB.dynamic_storyteller_type = S
|
||||
if("map")
|
||||
@@ -499,10 +499,11 @@ SUBSYSTEM_DEF(vote)
|
||||
modes_to_add -= "traitor" // makes it so that traitor is always available
|
||||
choices.Add(modes_to_add)
|
||||
if("dynamic")
|
||||
var/list/probabilities = CONFIG_GET(keyed_list/storyteller_weight)
|
||||
for(var/T in config.storyteller_cache)
|
||||
var/datum/dynamic_storyteller/S = T
|
||||
var/list/probabilities = CONFIG_GET(keyed_list/storyteller_weight)
|
||||
if(probabilities[initial(S.config_tag)] > 0)
|
||||
var/probability = ((initial(S.config_tag) in probabilities) ? probabilities[initial(S.config_tag)] : initial(S.weight))
|
||||
if(probability > 0)
|
||||
choices.Add(initial(S.name))
|
||||
choice_descs.Add(initial(S.desc))
|
||||
if("custom")
|
||||
|
||||
+15
-9
@@ -8,6 +8,7 @@
|
||||
var/desc = null
|
||||
var/obj/target = null
|
||||
var/check_flags = 0
|
||||
var/required_mobility_flags = MOBILITY_USE
|
||||
var/processing = FALSE
|
||||
var/obj/screen/movable/action_button/button = null
|
||||
var/buttontooltipstyle = ""
|
||||
@@ -96,20 +97,23 @@
|
||||
|
||||
/datum/action/proc/IsAvailable()
|
||||
if(!owner)
|
||||
return 0
|
||||
return FALSE
|
||||
var/mob/living/L = owner
|
||||
if(istype(L) && !CHECK_ALL_MOBILITY(L, required_mobility_flags))
|
||||
return FALSE
|
||||
if(check_flags & AB_CHECK_RESTRAINED)
|
||||
if(owner.restrained())
|
||||
return 0
|
||||
return FALSE
|
||||
if(check_flags & AB_CHECK_STUN)
|
||||
if(owner.IsKnockdown() || owner.IsStun())
|
||||
return 0
|
||||
if(istype(L) && !CHECK_MOBILITY(L, MOBILITY_USE))
|
||||
return FALSE
|
||||
if(check_flags & AB_CHECK_LYING)
|
||||
if(owner.lying)
|
||||
return 0
|
||||
if(istype(L) && !CHECK_MOBILITY(L, MOBILITY_STAND))
|
||||
return FALSE
|
||||
if(check_flags & AB_CHECK_CONSCIOUS)
|
||||
if(owner.stat)
|
||||
return 0
|
||||
return 1
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/proc/UpdateButtonIcon(status_only = FALSE, force = FALSE)
|
||||
if(button)
|
||||
@@ -422,6 +426,7 @@
|
||||
|
||||
/datum/action/item_action/hands_free
|
||||
check_flags = AB_CHECK_CONSCIOUS
|
||||
required_mobility_flags = NONE
|
||||
|
||||
/datum/action/item_action/hands_free/activate
|
||||
name = "Activate"
|
||||
@@ -430,7 +435,8 @@
|
||||
name = "Shift Nerves"
|
||||
|
||||
/datum/action/item_action/explosive_implant
|
||||
check_flags = 0
|
||||
check_flags = NONE
|
||||
required_mobility_flags = NONE
|
||||
name = "Activate Explosive Implant"
|
||||
|
||||
/datum/action/item_action/toggle_research_scanner
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
fall_chance += 2
|
||||
if(prob(fall_chance) && !owner.lying && !owner.buckled)
|
||||
to_chat(owner, "<span class='warning'>Your leg gives out!</span>")
|
||||
owner.Knockdown(35)
|
||||
owner.DefaultCombatKnockdown(35)
|
||||
|
||||
else if(owner.get_active_held_item())
|
||||
var/drop_chance = 1
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
/datum/brain_trauma/special/godwoken/on_life()
|
||||
..()
|
||||
if(prob(4))
|
||||
if(prob(33) && (owner.IsStun() || owner.IsKnockdown() || owner.IsUnconscious()))
|
||||
if(prob(33) && owner.HighestImmobilityAmount())
|
||||
speak("unstun", TRUE)
|
||||
else if(prob(60) && owner.health <= owner.crit_threshold)
|
||||
speak("heal", TRUE)
|
||||
|
||||
@@ -39,12 +39,18 @@
|
||||
//title_image = ntitle_image
|
||||
|
||||
/datum/browser/proc/add_stylesheet(name, file)
|
||||
if(istype(name, /datum/asset/spritesheet))
|
||||
if (istype(name, /datum/asset/spritesheet))
|
||||
var/datum/asset/spritesheet/sheet = name
|
||||
stylesheets["spritesheet_[sheet.name].css"] = "data/spritesheets/[sheet.name]"
|
||||
else
|
||||
stylesheets["[ckey(name)].css"] = file
|
||||
register_asset("[ckey(name)].css", file)
|
||||
var/asset_name = "[name].css"
|
||||
stylesheets[asset_name] = file
|
||||
if(!SSassets.cache[asset_name])
|
||||
register_asset(asset_name, file)
|
||||
|
||||
/datum/browser/proc/add_script(name, file)
|
||||
scripts["[ckey(name)].js"] = file
|
||||
register_asset("[ckey(name)].js", file)
|
||||
|
||||
/datum/browser/proc/set_content(ncontent)
|
||||
content = ncontent
|
||||
|
||||
@@ -59,4 +59,4 @@
|
||||
"<span class='userdanger'>You slide on [A]!</span>")
|
||||
|
||||
cooldown = world.time
|
||||
H.Knockdown(60)
|
||||
H.DefaultCombatKnockdown(60)
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
AM.forceMove(T)
|
||||
if(isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
L.Knockdown(100)
|
||||
L.DefaultCombatKnockdown(100)
|
||||
L.adjustBruteLoss(30)
|
||||
falling_atoms -= AM
|
||||
|
||||
@@ -110,8 +110,7 @@
|
||||
if (isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
L.notransform = TRUE
|
||||
L.Stun(200)
|
||||
L.resting = TRUE
|
||||
L.Paralyze(200)
|
||||
|
||||
var/oldtransform = AM.transform
|
||||
var/oldcolor = AM.color
|
||||
|
||||
@@ -33,11 +33,17 @@
|
||||
/obj/item/organ/ears/cat = 1)
|
||||
category = CAT_CLOTHING
|
||||
|
||||
////////
|
||||
//Huds//
|
||||
////////
|
||||
|
||||
/datum/crafting_recipe/hudsunsec
|
||||
name = "Security HUDsunglasses"
|
||||
result = /obj/item/clothing/glasses/hud/security/sunglasses
|
||||
time = 20
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
|
||||
parts = list(/obj/item/clothing/glasses/hud/security = 1,
|
||||
/obj/item/clothing/glasses/sunglasses = 1)
|
||||
reqs = list(/obj/item/clothing/glasses/hud/security = 1,
|
||||
/obj/item/clothing/glasses/sunglasses = 1,
|
||||
/obj/item/stack/cable_coil = 5)
|
||||
@@ -56,9 +62,11 @@
|
||||
result = /obj/item/clothing/glasses/hud/health/sunglasses
|
||||
time = 20
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
|
||||
parts = list(/obj/item/clothing/glasses/hud/health = 1,
|
||||
/obj/item/clothing/glasses/sunglasses = 1)
|
||||
reqs = list(/obj/item/clothing/glasses/hud/health = 1,
|
||||
/obj/item/clothing/glasses/sunglasses = 1,
|
||||
/obj/item/stack/cable_coil = 5)
|
||||
/obj/item/clothing/glasses/sunglasses = 1,
|
||||
/obj/item/stack/cable_coil = 5)
|
||||
category = CAT_CLOTHING
|
||||
|
||||
/datum/crafting_recipe/hudsunmedremoval
|
||||
@@ -86,6 +94,27 @@
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
|
||||
reqs = list(/obj/item/clothing/glasses/sunglasses/reagent = 1)
|
||||
category = CAT_CLOTHING
|
||||
|
||||
/datum/crafting_recipe/diagnostic_sunglasses
|
||||
name = "Diagnostic HUDsunglasses"
|
||||
result = /obj/item/clothing/glasses/hud/diagnostic/sunglasses
|
||||
time = 20
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
|
||||
parts = list(/obj/item/clothing/glasses/hud/diagnostic = 1,
|
||||
/obj/item/clothing/glasses/sunglasses = 1)
|
||||
reqs = list(/obj/item/clothing/glasses/hud/diagnostic = 1,
|
||||
/obj/item/clothing/glasses/sunglasses = 1,
|
||||
/obj/item/stack/cable_coil = 5)
|
||||
category = CAT_CLOTHING
|
||||
|
||||
/datum/crafting_recipe/diagnostic_singlasses_removal
|
||||
name = "Diagnostic HUDsunglasses removal"
|
||||
result = /obj/item/clothing/glasses/sunglasses
|
||||
time = 20
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
|
||||
reqs = list(/obj/item/clothing/glasses/hud/diagnostic/sunglasses = 1)
|
||||
category = CAT_CLOTHING
|
||||
|
||||
/* //Kevinz doesn't want it as a recipe for now, leaving it in if anything ever changes to let it in
|
||||
/datum/crafting_recipe/stunglasses
|
||||
name = "Stunglasses"
|
||||
@@ -130,7 +159,6 @@
|
||||
reqs = list(/obj/item/stack/sheet/durathread = 7,
|
||||
/obj/item/stack/sheet/leather = 3)
|
||||
time = 70
|
||||
always_availible = TRUE
|
||||
category = CAT_CLOTHING
|
||||
|
||||
/datum/crafting_recipe/durathread_toolbelt
|
||||
@@ -139,7 +167,6 @@
|
||||
reqs = list(/obj/item/stack/sheet/durathread = 5,
|
||||
/obj/item/stack/sheet/leather = 2)
|
||||
time = 30
|
||||
always_availible = TRUE
|
||||
category = CAT_CLOTHING
|
||||
|
||||
/datum/crafting_recipe/durathread_bandolier
|
||||
@@ -148,7 +175,6 @@
|
||||
reqs = list(/obj/item/stack/sheet/durathread = 6,
|
||||
/obj/item/stack/sheet/leather = 2)
|
||||
time = 50
|
||||
always_availible = TRUE
|
||||
category = CAT_CLOTHING
|
||||
|
||||
/datum/crafting_recipe/durathread_helmet
|
||||
@@ -157,7 +183,6 @@
|
||||
reqs = list(/obj/item/stack/sheet/durathread = 4,
|
||||
/obj/item/stack/sheet/leather = 2)
|
||||
time = 30
|
||||
always_availible = TRUE
|
||||
category = CAT_CLOTHING
|
||||
|
||||
/datum/crafting_recipe/durathread_vest
|
||||
@@ -166,7 +191,6 @@
|
||||
reqs = list(/obj/item/stack/sheet/durathread = 6,
|
||||
/obj/item/stack/sheet/leather = 3)
|
||||
time = 50
|
||||
always_availible = TRUE
|
||||
category = CAT_CLOTHING
|
||||
|
||||
/datum/crafting_recipe/durathread_wintercoat
|
||||
@@ -183,5 +207,4 @@
|
||||
reqs = list(/obj/item/clothing/suit/hooded/wintercoat = 1,
|
||||
/obj/item/bedsheet/cosmos = 1)
|
||||
time = 60
|
||||
always_availible = TRUE
|
||||
category = CAT_CLOTHING
|
||||
|
||||
@@ -119,18 +119,6 @@
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
/datum/crafting_recipe/switchblade_ms
|
||||
name = "Switchblade"
|
||||
result = /obj/item/switchblade/crafted
|
||||
reqs = list(/obj/item/weaponcrafting/stock = 1,
|
||||
/obj/item/weaponcrafting/receiver = 1,
|
||||
/obj/item/kitchen/knife = 1,
|
||||
/obj/item/stack/cable_coil = 2)
|
||||
tools = list(TOOL_WELDER)
|
||||
time = 45
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
//////////////////
|
||||
///BOMB CRAFTING//
|
||||
//////////////////
|
||||
@@ -310,19 +298,15 @@
|
||||
subcategory = CAT_AMMO
|
||||
|
||||
/datum/crafting_recipe/ashen_arrow
|
||||
name = "Bonfire-Hardened Arrow"
|
||||
name = "Fire Hardened Arrow"
|
||||
result = /obj/item/ammo_casing/caseless/arrow/ashen
|
||||
tools = list(/obj/structure/bonfire)
|
||||
tools = list(TOOL_WELDER)
|
||||
time = 30
|
||||
always_availible = FALSE
|
||||
reqs = list(/obj/item/ammo_casing/caseless/arrow = 1)
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_AMMO
|
||||
|
||||
/datum/crafting_recipe/ashen_arrow/welder
|
||||
name = "Welder-Hardened Arrow"
|
||||
tools = list(TOOL_WELDER)
|
||||
|
||||
/datum/crafting_recipe/smartdart
|
||||
name = "Medical smartdart"
|
||||
result = /obj/item/reagent_containers/syringe/dart
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
var/mob/living/LM = parent
|
||||
var/v = volume
|
||||
var/e = e_range
|
||||
if(!T.footstep || LM.buckled || LM.lying || !LM.canmove || LM.resting || LM.buckled || LM.throwing || LM.movement_type & (VENTCRAWLING | FLYING))
|
||||
if(!T.footstep || LM.buckled || !CHECK_MOBILITY(LM, MOBILITY_STAND) || LM.buckled || LM.throwing || (LM.movement_type & (VENTCRAWLING | FLYING)))
|
||||
if (LM.lying && !LM.buckled && !(!T.footstep || LM.movement_type & (VENTCRAWLING | FLYING))) //play crawling sound if we're lying
|
||||
playsound(T, 'sound/effects/footstep/crawl1.ogg', 15 * v)
|
||||
return
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
msg += " and knocks [target] [target_buckled? "off of [target.buckled]" : "down"]"
|
||||
if(target_buckled)
|
||||
target.buckled.unbuckle_mob(target)
|
||||
target.Knockdown(knockdown_time)
|
||||
target.DefaultCombatKnockdown(knockdown_time)
|
||||
if(length(msg))
|
||||
user.visible_message("<span class='danger'>[msg]!</span>")
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/OnExamine)
|
||||
|
||||
for(var/mat in mat_list) //Make the assoc list ref | amount
|
||||
var/datum/material/M = getmaterialref(mat) || mat
|
||||
var/datum/material/M = SSmaterials.GetMaterialRef(mat)
|
||||
materials[M] = 0
|
||||
|
||||
/datum/component/material_container/proc/OnExamine(datum/source, mob/user, list/examine_list)
|
||||
@@ -130,7 +130,7 @@
|
||||
/// For inserting an amount of material
|
||||
/datum/component/material_container/proc/insert_amount_mat(amt, var/datum/material/mat)
|
||||
if(!istype(mat))
|
||||
mat = getmaterialref(mat)
|
||||
mat = SSmaterials.GetMaterialRef(mat)
|
||||
if(amt > 0 && has_space(amt))
|
||||
var/total_amount_saved = total_amount
|
||||
if(mat)
|
||||
@@ -145,7 +145,7 @@
|
||||
/// Uses an amount of a specific material, effectively removing it.
|
||||
/datum/component/material_container/proc/use_amount_mat(amt, var/datum/material/mat)
|
||||
if(!istype(mat))
|
||||
mat = getmaterialref(mat)
|
||||
mat = SSmaterials.GetMaterialRef(mat)
|
||||
var/amount = materials[mat]
|
||||
if(mat)
|
||||
if(amount >= amt)
|
||||
@@ -157,7 +157,7 @@
|
||||
/// Proc for transfering materials to another container.
|
||||
/datum/component/material_container/proc/transer_amt_to(var/datum/component/material_container/T, amt, var/datum/material/mat)
|
||||
if(!istype(mat))
|
||||
mat = getmaterialref(mat)
|
||||
mat = SSmaterials.GetMaterialRef(mat)
|
||||
if((amt==0)||(!T)||(!mat))
|
||||
return FALSE
|
||||
if(amt<0)
|
||||
@@ -190,7 +190,7 @@
|
||||
for(var/x in mats) //Loop through all required materials
|
||||
var/datum/material/req_mat = x
|
||||
if(!istype(req_mat))
|
||||
req_mat = getmaterialref(req_mat) //Get the ref if necesary
|
||||
req_mat = SSmaterials.GetMaterialRef(req_mat) //Get the ref if necesary
|
||||
if(!materials[req_mat]) //Do we have the resource?
|
||||
return FALSE //Can't afford it
|
||||
var/amount_required = mats[x] * multiplier
|
||||
@@ -251,7 +251,7 @@
|
||||
var/datum/material/req_mat = x
|
||||
if(!istype(req_mat))
|
||||
if(ispath(req_mat)) //Is this an actual material, or is it a category?
|
||||
req_mat = getmaterialref(req_mat) //Get the ref
|
||||
req_mat = SSmaterials.GetMaterialRef(req_mat) //Get the ref
|
||||
|
||||
else // Its a category. (For example MAT_CATEGORY_RIGID)
|
||||
if(!has_enough_of_category(req_mat, mats[req_mat], multiplier)) //Do we have enough of this category?
|
||||
@@ -316,5 +316,5 @@
|
||||
/// Returns the amount of a specific material in this container.
|
||||
/datum/component/material_container/proc/get_material_amount(var/datum/material/mat)
|
||||
if(!istype(mat))
|
||||
mat = getmaterialref(mat)
|
||||
mat = SSmaterials.GetMaterialRef(mat)
|
||||
return(materials[mat])
|
||||
|
||||
@@ -240,7 +240,7 @@
|
||||
/datum/component/riding/human/force_dismount(mob/living/user)
|
||||
var/atom/movable/AM = parent
|
||||
AM.unbuckle_mob(user)
|
||||
user.Knockdown(60)
|
||||
user.DefaultCombatKnockdown(60)
|
||||
user.visible_message("<span class='warning'>[AM] pushes [user] off of [AM.p_them()]!</span>")
|
||||
|
||||
/datum/component/riding/cyborg
|
||||
@@ -298,7 +298,7 @@
|
||||
M.Move(targetm)
|
||||
M.visible_message("<span class='warning'>[M] is thrown clear of [AM]!</span>")
|
||||
M.throw_at(target, 14, 5, AM)
|
||||
M.Knockdown(60)
|
||||
M.DefaultCombatKnockdown(60)
|
||||
|
||||
/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1, mob/living/riding_target_override)
|
||||
var/list/equipped
|
||||
@@ -341,7 +341,7 @@
|
||||
var/mob/living/parent
|
||||
var/selfdeleting = FALSE
|
||||
|
||||
/obj/item/riding_offhand/dropped()
|
||||
/obj/item/riding_offhand/dropped(mob/user)
|
||||
selfdeleting = TRUE
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
return //undeads are unaffected by the spook-pocalypse.
|
||||
if(istype(H.dna.species, /datum/species/zombie))
|
||||
H.adjustStaminaLoss(25)
|
||||
H.Knockdown(15) //zombies can't resist the doot
|
||||
H.DefaultCombatKnockdown(15) //zombies can't resist the doot
|
||||
C.Jitter(35)
|
||||
C.stuttering = 20
|
||||
if((!istype(H.dna.species, /datum/species/skeleton)) && (!istype(H.dna.species, /datum/species/golem)) && (!istype(H.dna.species, /datum/species/android)) && (!istype(H.dna.species, /datum/species/jelly)))
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
/datum/component/spooky/proc/spectral_change(mob/living/carbon/human/H, mob/user)
|
||||
if((H.getStaminaLoss() > 95) && (!istype(H.dna.species, /datum/species/skeleton)) && (!istype(H.dna.species, /datum/species/golem)) && (!istype(H.dna.species, /datum/species/android)) && (!istype(H.dna.species, /datum/species/jelly)))
|
||||
H.Knockdown(20)
|
||||
H.DefaultCombatKnockdown(20)
|
||||
H.set_species(/datum/species/skeleton)
|
||||
H.visible_message("<span class='warning'>[H] has given up on life as a mortal.</span>")
|
||||
var/T = get_turf(H)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
var/turf/loccheck = get_turf(A)
|
||||
if(is_reebe(loccheck.z))
|
||||
user.visible_message("<span class='warning'>An unseen force knocks [user] to the ground!</span>", "<span class='big_brass'>\"I think not!\"</span>")
|
||||
user.Knockdown(60)
|
||||
user.DefaultCombatKnockdown(60)
|
||||
return
|
||||
if(istype(loccheck.loc, /area/fabric_of_reality))
|
||||
to_chat(user, "<span class='danger'>You can't do that here!</span>")
|
||||
@@ -25,7 +25,7 @@
|
||||
for(var/mob/living/M in T)
|
||||
if(M.movement_type & FLYING)
|
||||
M.visible_message("<span class='danger'>The bluespace collapse crushes the air towards it, pulling [M] towards the ground...</span>")
|
||||
M.Knockdown(5, TRUE, TRUE) //Overrides stun absorbs.
|
||||
M.DefaultCombatKnockdown(5, TRUE, TRUE) //Overrides stun absorbs.
|
||||
T.TerraformTurf(/turf/open/chasm/magic, /turf/open/chasm/magic)
|
||||
for (var/obj/structure/ladder/unbreakable/binary/ladder in GLOB.ladders)
|
||||
ladder.ActivateAlmonds()
|
||||
|
||||
@@ -409,7 +409,7 @@
|
||||
|
||||
/datum/component/storage/proc/check_views()
|
||||
for(var/mob/M in can_see_contents())
|
||||
if(!isobserver(M) && !M.CanReach(src, view_only = TRUE))
|
||||
if(!isobserver(M) && !M.CanReach(parent, view_only = TRUE))
|
||||
close(M)
|
||||
|
||||
/datum/component/storage/proc/emp_act(datum/source, severity)
|
||||
|
||||
@@ -287,7 +287,6 @@
|
||||
G.fields["gender"] = "Other"
|
||||
L.fields["blood_type"] = H.dna.blood_type
|
||||
L.fields["b_dna"] = H.dna.unique_enzymes
|
||||
L.fields["enzymes"] = H.dna.struc_enzymes
|
||||
L.fields["identity"] = H.dna.uni_identity
|
||||
L.fields["species"] = H.dna.species.type
|
||||
L.fields["features"] = H.dna.features
|
||||
|
||||
+14
-16
@@ -26,10 +26,10 @@
|
||||
/datum/proc/vv_get_dropdown()
|
||||
. = list()
|
||||
. += "---"
|
||||
.["Call Proc"] = "?_src_=vars;[HrefToken()];proc_call=[REF(src)]"
|
||||
.["Mark Object"] = "?_src_=vars;[HrefToken()];mark_object=[REF(src)]"
|
||||
.["Delete"] = "?_src_=vars;[HrefToken()];delete=[REF(src)]"
|
||||
.["Show VV To Player"] = "?_src_=vars;[HrefToken(TRUE)];expose=[REF(src)]"
|
||||
.["Call Proc"] = "?_src_=vars;[HrefToken()];proc_call=\ref[src]"
|
||||
.["Mark Object"] = "?_src_=vars;[HrefToken()];mark_object=\ref[src]"
|
||||
.["Delete"] = "?_src_=vars;[HrefToken()];delete=\ref[src]"
|
||||
.["Show VV To Player"] = "?_src_=vars;[HrefToken(TRUE)];expose=\ref[src]"
|
||||
|
||||
|
||||
/datum/proc/on_reagent_change(changetype)
|
||||
@@ -54,7 +54,7 @@
|
||||
return
|
||||
|
||||
var/title = ""
|
||||
var/refid = REF(D)
|
||||
var/refid = "\ref[D]"
|
||||
var/icon/sprite
|
||||
var/hash
|
||||
|
||||
@@ -62,8 +62,6 @@
|
||||
if (!islist)
|
||||
type = D.type
|
||||
|
||||
|
||||
|
||||
if(istype(D, /atom))
|
||||
var/atom/AT = D
|
||||
if(AT.icon && AT.icon_state)
|
||||
@@ -410,7 +408,7 @@
|
||||
|
||||
|
||||
/client/proc/vv_update_display(datum/D, span, content)
|
||||
src << output("[span]:[content]", "variables[REF(D)].browser:replace_span")
|
||||
src << output("[span]:[content]", "variables\ref[D].browser:replace_span")
|
||||
|
||||
|
||||
#define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing )
|
||||
@@ -423,9 +421,9 @@
|
||||
name = DA[name] //name is really the index until this line
|
||||
else
|
||||
value = DA[name]
|
||||
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken()];listedit=[REF(DA)];index=[index]'>E</a>) (<a href='?_src_=vars;[HrefToken()];listchange=[REF(DA)];index=[index]'>C</a>) (<a href='?_src_=vars;[HrefToken()];listremove=[REF(DA)];index=[index]'>-</a>) "
|
||||
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken()];listedit=\ref[DA];index=[index]'>E</a>) (<a href='?_src_=vars;[HrefToken()];listchange=\ref[DA];index=[index]'>C</a>) (<a href='?_src_=vars;[HrefToken()];listremove=\ref[DA];index=[index]'>-</a>) "
|
||||
else
|
||||
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken()];datumedit=[REF(DA)];varnameedit=[name]'>E</a>) (<a href='?_src_=vars;[HrefToken()];datumchange=[REF(DA)];varnamechange=[name]'>C</a>) (<a href='?_src_=vars;[HrefToken()];datummass=[REF(DA)];varnamemass=[name]'>M</a>) "
|
||||
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken()];datumedit=\ref[DA];varnameedit=[name]'>E</a>) (<a href='?_src_=vars;[HrefToken()];datumchange=\ref[DA];varnamechange=[name]'>C</a>) (<a href='?_src_=vars;[HrefToken()];datummass=\ref[DA];varnamemass=[name]'>M</a>) "
|
||||
else
|
||||
header = "<li>"
|
||||
|
||||
@@ -440,7 +438,7 @@
|
||||
#ifdef VARSICON
|
||||
var/icon/I = new/icon(value)
|
||||
var/rnd = rand(1,10000)
|
||||
var/rname = "tmp[REF(I)][rnd].png"
|
||||
var/rname = "tmp\ref[I][rnd].png"
|
||||
usr << browse_rsc(I, rname)
|
||||
item = "[VV_HTML_ENCODE(name)] = (<span class='value'>[value]</span>) <img class=icon src=\"[rname]\">"
|
||||
#else
|
||||
@@ -453,9 +451,9 @@
|
||||
else if (istype(value, /datum))
|
||||
var/datum/D = value
|
||||
if ("[D]" != "[D.type]") //if the thing as a name var, lets use it.
|
||||
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = [D] [D.type]"
|
||||
item = "<a href='?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = [D] [D.type]"
|
||||
else
|
||||
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = [D.type]"
|
||||
item = "<a href='?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = [D.type]"
|
||||
|
||||
else if (islist(value))
|
||||
var/list/L = value
|
||||
@@ -473,9 +471,9 @@
|
||||
|
||||
items += debug_variable(key, val, level + 1, sanitize = sanitize)
|
||||
|
||||
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a><ul>[items.Join()]</ul>"
|
||||
item = "<a href='?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a><ul>[items.Join()]</ul>"
|
||||
else
|
||||
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a>"
|
||||
item = "<a href='?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a>"
|
||||
|
||||
else if (name in GLOB.bitfields)
|
||||
var/list/flags = list()
|
||||
@@ -587,7 +585,7 @@
|
||||
var/prompt = alert("Do you want to grant [C] access to view this VV window? (they will not be able to edit or change anything nor open nested vv windows unless they themselves are an admin)", "Confirm", "Yes", "No")
|
||||
if (prompt != "Yes" || !usr.client)
|
||||
return
|
||||
message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a <a href='?_src_=vars;[HrefToken(TRUE)];datumrefresh=[REF(thing)]'>VV window</a>")
|
||||
message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a <a href='?_src_=vars;[HrefToken(TRUE)];datumrefresh=\ref[thing]'>VV window</a>")
|
||||
log_admin("Admin [key_name(usr)] Showed [key_name(C)] a VV window of a [thing]")
|
||||
to_chat(C, "[usr.client.holder.fakekey ? "an Administrator" : "[usr.client.key]"] has granted you access to view a View Variables window")
|
||||
C.debug_variables(thing)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
return FALSE
|
||||
|
||||
|
||||
if(!(type in D.viable_mobtypes))
|
||||
if(!D.viable_mobtypes[type])
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
var/stage_prob = 4
|
||||
|
||||
//Other
|
||||
var/list/viable_mobtypes = list() //typepaths of viable mobs
|
||||
var/list/viable_mobtypes = list() //typecache of viable mobs
|
||||
var/mob/living/carbon/affected_mob = null
|
||||
var/list/cures = list() //list of cures if the disease has the CURABLE flag, these are reagent ids
|
||||
var/infectivity = 65
|
||||
@@ -34,6 +34,10 @@
|
||||
var/process_dead = FALSE //if this ticks while the host is dead
|
||||
var/copy_type = null //if this is null, copies will use the type of the instance being copied
|
||||
|
||||
/datum/disease/New(make_typecache = TRUE)
|
||||
if(make_typecache && length(viable_mobtypes))
|
||||
viable_mobtypes = typecacheof(viable_mobtypes)
|
||||
|
||||
/datum/disease/Destroy()
|
||||
. = ..()
|
||||
if(affected_mob)
|
||||
|
||||
@@ -80,7 +80,8 @@
|
||||
|
||||
*/
|
||||
|
||||
/datum/disease/advance/New()
|
||||
/datum/disease/advance/New(make_typecache = TRUE)
|
||||
..()
|
||||
Refresh()
|
||||
|
||||
/datum/disease/advance/Destroy()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/datum/disease/advance/cold
|
||||
copy_type = /datum/disease/advance
|
||||
|
||||
/datum/disease/advance/cold/New()
|
||||
/datum/disease/advance/cold/New(make_typecache = TRUE)
|
||||
name = "Cold"
|
||||
symptoms = list(new/datum/symptom/sneeze)
|
||||
..()
|
||||
@@ -11,7 +11,7 @@
|
||||
/datum/disease/advance/flu
|
||||
copy_type = /datum/disease/advance
|
||||
|
||||
/datum/disease/advance/flu/New()
|
||||
/datum/disease/advance/flu/New(make_typecache = TRUE)
|
||||
name = "Flu"
|
||||
symptoms = list(new/datum/symptom/cough)
|
||||
..()
|
||||
@@ -21,7 +21,7 @@
|
||||
name = "Experimental Disease"
|
||||
copy_type = /datum/disease/advance
|
||||
|
||||
/datum/disease/advance/random/New(max_symptoms, max_level = 8)
|
||||
/datum/disease/advance/random/New(make_typecache = TRUE, max_symptoms, max_level = 8)
|
||||
if(!max_symptoms)
|
||||
max_symptoms = rand(1, VIRUS_SYMPTOM_LIMIT)
|
||||
var/list/datum/symptom/possible_symptoms = list()
|
||||
@@ -37,6 +37,6 @@
|
||||
if(chosen_symptom)
|
||||
var/datum/symptom/S = new chosen_symptom
|
||||
symptoms += S
|
||||
Refresh()
|
||||
|
||||
name = "Sample #[rand(1,10000)]"
|
||||
name = "Sample #[rand(1,10000)]"
|
||||
..()
|
||||
@@ -61,12 +61,12 @@ Bonus
|
||||
symptom_delay_max = 60
|
||||
if(A.properties["resistance"] >= 8) //mutate twice
|
||||
power = 2
|
||||
possible_mutations = (GLOB.bad_mutations | GLOB.not_good_mutations) - GLOB.mutations_list[RACEMUT]
|
||||
possible_mutations = (GLOB.bad_mutations | GLOB.not_good_mutations) - GLOB.all_mutations[RACEMUT]
|
||||
var/mob/living/carbon/M = A.affected_mob
|
||||
if(M)
|
||||
if(!M.has_dna())
|
||||
return
|
||||
archived_dna = M.dna.struc_enzymes
|
||||
archived_dna = M.dna.mutation_index
|
||||
|
||||
// Give them back their old DNA when cured.
|
||||
/datum/symptom/genetic_mutation/End(datum/disease/advance/A)
|
||||
@@ -77,5 +77,5 @@ Bonus
|
||||
if(M && archived_dna)
|
||||
if(!M.has_dna())
|
||||
return
|
||||
M.dna.struc_enzymes = archived_dna
|
||||
M.dna.mutation_index = archived_dna
|
||||
M.domutcheck()
|
||||
|
||||
@@ -257,6 +257,8 @@
|
||||
/datum/symptom/heal/coma/End(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
if(active_coma)
|
||||
uncoma()
|
||||
REMOVE_TRAIT(A.affected_mob, TRAIT_NOCRITDAMAGE, DISEASE_TRAIT)
|
||||
|
||||
/datum/symptom/heal/coma/CanHeal(datum/disease/advance/A)
|
||||
@@ -277,9 +279,9 @@
|
||||
/datum/symptom/heal/coma/proc/coma(mob/living/M)
|
||||
if(deathgasp)
|
||||
M.emote("deathgasp")
|
||||
M.fakedeath("regenerative_coma")
|
||||
M.fakedeath("regenerative_coma", TRUE)
|
||||
M.update_stat()
|
||||
M.update_canmove()
|
||||
M.update_mobility()
|
||||
addtimer(CALLBACK(src, .proc/uncoma, M), 300)
|
||||
|
||||
/datum/symptom/heal/coma/proc/uncoma(mob/living/M)
|
||||
@@ -288,7 +290,7 @@
|
||||
active_coma = FALSE
|
||||
M.cure_fakedeath("regenerative_coma")
|
||||
M.update_stat()
|
||||
M.update_canmove()
|
||||
M.update_mobility()
|
||||
|
||||
/datum/symptom/heal/coma/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power)
|
||||
var/heal_amt = 4 * actual_power
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
if(prob(25))
|
||||
affected_mob.vomit(95)
|
||||
H.emote("cough")
|
||||
H.Knockdown(40)
|
||||
H.DefaultCombatKnockdown(40)
|
||||
H.losebreath += 4
|
||||
if(prob(3))
|
||||
to_chat(H, "<span class='danger'>You feel very weak and dizzy...</span>")
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
stage_prob = 2
|
||||
var/restcure = 0
|
||||
|
||||
/datum/disease/dna_retrovirus/New()
|
||||
/datum/disease/dna_retrovirus/New(make_typecache = TRUE)
|
||||
..()
|
||||
agent = "Virus class [pick("A","B","C","D","E","F")][pick("A","B","C","D","E","F")]-[rand(50,300)]"
|
||||
if(prob(40))
|
||||
|
||||
+247
-61
@@ -2,7 +2,6 @@
|
||||
/////////////////////////// DNA DATUM
|
||||
/datum/dna
|
||||
var/unique_enzymes
|
||||
var/struc_enzymes
|
||||
var/uni_identity
|
||||
var/blood_type
|
||||
var/datum/species/species = new /datum/species/human //The type of mutant race the player is if applicable (i.e. potato-man)
|
||||
@@ -11,10 +10,13 @@
|
||||
var/nameless = FALSE
|
||||
var/custom_species //siiiiigh I guess this is important
|
||||
var/list/mutations = list() //All mutations are from now on here
|
||||
var/list/temporary_mutations = list() //Timers for temporary mutations
|
||||
var/list/temporary_mutations = list() //Temporary changes to the UE
|
||||
var/list/previous = list() //For temporary name/ui/ue/blood_type modifications
|
||||
var/mob/living/holder
|
||||
var/delete_species = TRUE //Set to FALSE when a body is scanned by a cloner to fix #38875
|
||||
var/mutation_index[DNA_MUTATION_BLOCKS] //List of which mutations this carbon has and its assigned block
|
||||
var/stability = 100
|
||||
var/scrambled = FALSE //Did we take something like mutagen? In that case we cant get our genes scanned to instantly cheese all the powers.
|
||||
|
||||
/datum/dna/New(mob/living/new_holder)
|
||||
if(istype(new_holder))
|
||||
@@ -42,8 +44,8 @@
|
||||
destination.dna.unique_enzymes = unique_enzymes
|
||||
destination.dna.uni_identity = uni_identity
|
||||
destination.dna.blood_type = blood_type
|
||||
destination.dna.features = features.Copy()
|
||||
destination.set_species(species.type, icon_update=0)
|
||||
destination.dna.features = features.Copy()
|
||||
destination.dna.real_name = real_name
|
||||
destination.dna.nameless = nameless
|
||||
destination.dna.custom_species = custom_species
|
||||
@@ -51,13 +53,14 @@
|
||||
if(ishuman(destination))
|
||||
var/mob/living/carbon/human/H = destination
|
||||
H.give_genitals(TRUE)//This gives the body the genitals of this DNA. Used for any transformations based on DNA
|
||||
destination.flavor_text = destination.dna.features["flavor_text"] //Update the flavor_text to use new dna text
|
||||
if(transfer_SE)
|
||||
destination.dna.struc_enzymes = struc_enzymes
|
||||
destination.dna.mutation_index = mutation_index
|
||||
|
||||
SEND_SIGNAL(destination, COMSIG_CARBON_IDENTITY_TRANSFERRED_TO, src, transfer_SE)
|
||||
|
||||
/datum/dna/proc/copy_dna(datum/dna/new_dna)
|
||||
new_dna.unique_enzymes = unique_enzymes
|
||||
new_dna.struc_enzymes = struc_enzymes
|
||||
new_dna.mutation_index = mutation_index
|
||||
new_dna.uni_identity = uni_identity
|
||||
new_dna.blood_type = blood_type
|
||||
new_dna.features = features.Copy()
|
||||
@@ -67,26 +70,32 @@
|
||||
new_dna.custom_species = custom_species
|
||||
new_dna.mutations = mutations.Copy()
|
||||
|
||||
/datum/dna/proc/add_mutation(mutation_name)
|
||||
var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name]
|
||||
HM.on_acquiring(holder)
|
||||
//See mutation.dm for what 'class' does. 'time' is time till it removes itself in decimals. 0 for no timer
|
||||
/datum/dna/proc/add_mutation(mutation, class = MUT_OTHER, time)
|
||||
var/mutation_type = mutation
|
||||
if(istype(mutation, /datum/mutation/human))
|
||||
var/datum/mutation/human/HM = mutation
|
||||
mutation_type = HM.type
|
||||
if(get_mutation(mutation_type))
|
||||
return
|
||||
return force_give(new mutation_type (class, time, copymut = mutation))
|
||||
|
||||
/datum/dna/proc/remove_mutation(mutation_name)
|
||||
var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name]
|
||||
HM.on_losing(holder)
|
||||
/datum/dna/proc/remove_mutation(mutation_type)
|
||||
return force_lose(get_mutation(mutation_type))
|
||||
|
||||
/datum/dna/proc/check_mutation(mutation_name)
|
||||
var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name]
|
||||
return mutations.Find(HM)
|
||||
/datum/dna/proc/check_mutation(mutation_type)
|
||||
return get_mutation(mutation_type)
|
||||
|
||||
/datum/dna/proc/remove_all_mutations()
|
||||
remove_mutation_group(mutations)
|
||||
/datum/dna/proc/remove_all_mutations(list/classes = list(MUT_NORMAL, MUT_EXTRA, MUT_OTHER), mutadone = FALSE)
|
||||
remove_mutation_group(mutations, classes, mutadone)
|
||||
scrambled = FALSE
|
||||
|
||||
/datum/dna/proc/remove_mutation_group(list/group)
|
||||
/datum/dna/proc/remove_mutation_group(list/group, list/classes = list(MUT_NORMAL, MUT_EXTRA, MUT_OTHER), mutadone = FALSE)
|
||||
if(!group)
|
||||
return
|
||||
for(var/datum/mutation/human/HM in group)
|
||||
HM.force_lose(holder)
|
||||
if((HM.class in classes) && !(HM.mutadone_proof && mutadone))
|
||||
force_lose(HM)
|
||||
|
||||
/datum/dna/proc/generate_uni_identity()
|
||||
. = ""
|
||||
@@ -136,19 +145,49 @@
|
||||
. += random_string(DNA_BLOCK_SIZE,GLOB.hex_characters)
|
||||
return .
|
||||
|
||||
/datum/dna/proc/generate_struc_enzymes()
|
||||
var/list/sorting = new /list(DNA_STRUC_ENZYMES_BLOCKS)
|
||||
var/result = ""
|
||||
for(var/datum/mutation/human/A in GLOB.good_mutations + GLOB.bad_mutations + GLOB.not_good_mutations)
|
||||
if(A.name == RACEMUT && ismonkey(holder))
|
||||
sorting[A.dna_block] = num2hex(A.lowest_value + rand(0, 256 * 6), DNA_BLOCK_SIZE)
|
||||
mutations |= A
|
||||
else
|
||||
sorting[A.dna_block] = random_string(DNA_BLOCK_SIZE, list("0","1","2","3","4","5","6"))
|
||||
/datum/dna/proc/generate_dna_blocks()
|
||||
var/bonus
|
||||
if(species && species.inert_mutation)
|
||||
bonus = GET_INITIALIZED_MUTATION(species.inert_mutation)
|
||||
var/list/mutations_temp = GLOB.good_mutations + GLOB.bad_mutations + GLOB.not_good_mutations + bonus
|
||||
if(!LAZYLEN(mutations_temp))
|
||||
return
|
||||
mutation_index.Cut()
|
||||
shuffle_inplace(mutations_temp)
|
||||
if(ismonkey(holder))
|
||||
mutations |= new RACEMUT(MUT_NORMAL)
|
||||
mutation_index[RACEMUT] = GET_SEQUENCE(RACEMUT)
|
||||
else
|
||||
mutation_index[RACEMUT] = create_sequence(RACEMUT, FALSE)
|
||||
for(var/i in 2 to DNA_MUTATION_BLOCKS)
|
||||
var/datum/mutation/human/M = mutations_temp[i]
|
||||
mutation_index[M.type] = create_sequence(M.type, FALSE,M.difficulty)
|
||||
shuffle_inplace(mutation_index)
|
||||
|
||||
for(var/B in sorting)
|
||||
result += B
|
||||
return result
|
||||
//Used to generate original gene sequences for every mutation
|
||||
/proc/generate_gene_sequence(length=4)
|
||||
var/static/list/active_sequences = list("AT","TA","GC","CG")
|
||||
var/sequence
|
||||
for(var/i in 1 to length*DNA_SEQUENCE_LENGTH)
|
||||
sequence += pick(active_sequences)
|
||||
return sequence
|
||||
|
||||
//Used to create a chipped gene sequence
|
||||
/proc/create_sequence(mutation, active, difficulty)
|
||||
if(!difficulty)
|
||||
var/datum/mutation/human/A = GET_INITIALIZED_MUTATION(mutation) //leaves the possibility to change difficulty mid-round
|
||||
if(!A)
|
||||
return
|
||||
difficulty = A.difficulty
|
||||
difficulty += rand(-2,4)
|
||||
var/sequence = GET_SEQUENCE(mutation)
|
||||
if(active)
|
||||
return sequence
|
||||
while(difficulty)
|
||||
var/randnum = rand(1, length(sequence))
|
||||
sequence = copytext(sequence, 1, randnum) + "X" + copytext(sequence, randnum+1, length(sequence)+1)
|
||||
difficulty--
|
||||
return sequence
|
||||
|
||||
/datum/dna/proc/generate_unique_enzymes()
|
||||
. = ""
|
||||
@@ -201,12 +240,57 @@
|
||||
if(DNA_TAUR_BLOCK)
|
||||
construct_block(GLOB.taur_list.Find(features["taur"]), GLOB.taur_list.len)
|
||||
|
||||
//Please use add_mutation or activate_mutation instead
|
||||
/datum/dna/proc/force_give(datum/mutation/human/HM)
|
||||
if(holder && HM)
|
||||
if(HM.class == MUT_NORMAL)
|
||||
set_se(1, HM)
|
||||
. = HM.on_acquiring(holder)
|
||||
if(.)
|
||||
qdel(HM)
|
||||
update_instability()
|
||||
|
||||
//Use remove_mutation instead
|
||||
/datum/dna/proc/force_lose(datum/mutation/human/HM)
|
||||
if(holder && (HM in mutations))
|
||||
set_se(0, HM)
|
||||
. = HM.on_losing(holder)
|
||||
update_instability(FALSE)
|
||||
return
|
||||
|
||||
/datum/dna/proc/is_same_as(datum/dna/D)
|
||||
if(uni_identity == D.uni_identity && struc_enzymes == D.struc_enzymes && real_name == D.real_name && nameless == D.nameless && custom_species == D.custom_species)
|
||||
if(uni_identity == D.uni_identity && mutation_index == D.mutation_index && real_name == D.real_name && nameless == D.nameless && custom_species == D.custom_species)
|
||||
if(species.type == D.species.type && features == D.features && blood_type == D.blood_type)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/dna/proc/update_instability(alert=TRUE)
|
||||
stability = 100
|
||||
for(var/datum/mutation/human/M in mutations)
|
||||
if(M.class == MUT_EXTRA)
|
||||
stability -= M.instability * GET_MUTATION_STABILIZER(M)
|
||||
if(holder)
|
||||
var/message
|
||||
if(alert)
|
||||
switch(stability)
|
||||
if(70 to 90)
|
||||
message = "<span class='warning'>You shiver.</span>"
|
||||
if(60 to 69)
|
||||
message = "<span class='warning'>You feel cold.</span>"
|
||||
if(40 to 59)
|
||||
message = "<span class='warning'>You feel sick.</span>"
|
||||
if(20 to 39)
|
||||
message = "<span class='warning'>It feels like your skin is moving.</span>"
|
||||
if(1 to 19)
|
||||
message = "<span class='warning'>You can feel your cells burning.</span>"
|
||||
if(-INFINITY to 0)
|
||||
message = "<span class='boldwarning'>You can feel your DNA exploding, we need to do something fast!</span>"
|
||||
if(stability <= 0)
|
||||
holder.apply_status_effect(STATUS_EFFECT_DNA_MELT)
|
||||
if(message)
|
||||
to_chat(holder, message)
|
||||
|
||||
|
||||
//used to update dna UI, UE, and dna.real_name.
|
||||
/datum/dna/proc/update_dna_identity()
|
||||
uni_identity = generate_uni_identity()
|
||||
@@ -217,8 +301,8 @@
|
||||
blood_type = newblood_type
|
||||
unique_enzymes = generate_unique_enzymes()
|
||||
uni_identity = generate_uni_identity()
|
||||
struc_enzymes = generate_struc_enzymes()
|
||||
features = random_features()
|
||||
generate_dna_blocks()
|
||||
features = random_features(species?.id)
|
||||
|
||||
|
||||
/datum/dna/stored //subtype used by brain mob's stored_dna
|
||||
@@ -232,10 +316,10 @@
|
||||
/datum/dna/stored/check_mutation(mutation_name)
|
||||
return
|
||||
|
||||
/datum/dna/stored/remove_all_mutations()
|
||||
/datum/dna/stored/remove_all_mutations(list/classes = list(MUT_NORMAL, MUT_EXTRA, MUT_OTHER), mutadone = FALSE)
|
||||
return
|
||||
|
||||
/datum/dna/stored/remove_mutation_group(list/group)
|
||||
/datum/dna/stored/remove_mutation_group(list/group, list/classes = list(MUT_NORMAL, MUT_EXTRA, MUT_OTHER), mutadone = FALSE)
|
||||
return
|
||||
|
||||
/////////////////////////// DNA MOB-PROCS //////////////////////
|
||||
@@ -270,6 +354,7 @@
|
||||
if(icon_update)
|
||||
update_body()
|
||||
update_hair()
|
||||
update_body_parts()
|
||||
update_mutations_overlay()// no lizard with human hulk overlay please.
|
||||
|
||||
|
||||
@@ -280,11 +365,10 @@
|
||||
return dna
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/hardset_dna(ui, se, newreal_name, newblood_type, datum/species/mrace, newfeatures)
|
||||
/mob/living/carbon/human/proc/hardset_dna(ui, list/mutation_index, newreal_name, newblood_type, datum/species/mrace, newfeatures)
|
||||
|
||||
if(newfeatures)
|
||||
dna.features = newfeatures
|
||||
flavor_text = dna.features["flavor_text"] //Update the flavor_text to use new dna text
|
||||
|
||||
if(mrace)
|
||||
var/datum/species/newrace = new mrace.type
|
||||
@@ -302,10 +386,12 @@
|
||||
dna.uni_identity = ui
|
||||
updateappearance(icon_update=0)
|
||||
|
||||
if(se)
|
||||
dna.struc_enzymes = se
|
||||
if(LAZYLEN(mutation_index))
|
||||
dna.mutation_index = mutation_index.Copy()
|
||||
domutcheck()
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_HUMAN_HARDSET_DNA, ui, se, newreal_name, newblood_type, mrace, newfeatures)
|
||||
|
||||
if(mrace || newfeatures || ui)
|
||||
update_body()
|
||||
update_hair()
|
||||
@@ -355,19 +441,63 @@
|
||||
/mob/proc/domutcheck()
|
||||
return
|
||||
|
||||
/mob/living/carbon/domutcheck(force_powers=0) //Set force_powers to 1 to bypass the power chance
|
||||
/mob/living/carbon/domutcheck()
|
||||
if(!has_dna())
|
||||
return
|
||||
|
||||
for(var/datum/mutation/human/A in GLOB.good_mutations | GLOB.bad_mutations | GLOB.not_good_mutations)
|
||||
if(ismob(A.check_block(src, force_powers)))
|
||||
for(var/mutation in dna.mutation_index)
|
||||
if(ismob(dna.check_block(mutation)))
|
||||
return //we got monkeyized/humanized, this mob will be deleted, no need to continue.
|
||||
|
||||
update_mutations_overlay()
|
||||
|
||||
/datum/dna/proc/check_block(mutation)
|
||||
var/datum/mutation/human/HM = get_mutation(mutation)
|
||||
if(check_block_string(mutation))
|
||||
if(!HM)
|
||||
. = add_mutation(mutation, MUT_NORMAL)
|
||||
return
|
||||
return force_lose(HM)
|
||||
|
||||
//Return the active mutation of a type if there is one
|
||||
/datum/dna/proc/get_mutation(A)
|
||||
for(var/datum/mutation/human/HM in mutations)
|
||||
if(HM.type == A)
|
||||
return HM
|
||||
|
||||
/datum/dna/proc/check_block_string(mutation)
|
||||
if((LAZYLEN(mutation_index) > DNA_MUTATION_BLOCKS) || !(mutation in mutation_index))
|
||||
return 0
|
||||
return is_gene_active(mutation)
|
||||
|
||||
/datum/dna/proc/is_gene_active(mutation)
|
||||
return (mutation_index[mutation] == GET_SEQUENCE(mutation))
|
||||
|
||||
/datum/dna/proc/set_se(on=TRUE, datum/mutation/human/HM)
|
||||
if(!HM || !(HM.type in mutation_index) || (LAZYLEN(mutation_index) < DNA_MUTATION_BLOCKS))
|
||||
return
|
||||
. = TRUE
|
||||
if(on)
|
||||
mutation_index[HM.type] = GET_SEQUENCE(HM.type)
|
||||
else if(GET_SEQUENCE(HM.type) == mutation_index[HM.type])
|
||||
mutation_index[HM.type] = create_sequence(HM.type, FALSE, HM.difficulty)
|
||||
|
||||
/datum/dna/proc/activate_mutation(mutation) //note that this returns a boolean and not a new mob
|
||||
if(!mutation)
|
||||
return FALSE
|
||||
var/mutation_type = mutation
|
||||
if(istype(mutation, /datum/mutation/human))
|
||||
var/datum/mutation/human/M = mutation
|
||||
mutation_type = M.type
|
||||
if(!mutation_in_sequence(mutation_type)) //cant activate what we dont have, use add_mutation
|
||||
return FALSE
|
||||
add_mutation(mutation, MUT_NORMAL)
|
||||
return TRUE
|
||||
|
||||
|
||||
|
||||
/////////////////////////// DNA HELPER-PROCS //////////////////////////////
|
||||
|
||||
/proc/getleftblocks(input,blocknumber,blocksize)
|
||||
if(blocknumber > 1)
|
||||
return copytext_char(input,1,((blocksize*blocknumber)-(blocksize-1)))
|
||||
@@ -384,29 +514,47 @@
|
||||
return 0
|
||||
return getleftblocks(istring, blocknumber, blocksize) + replacement + getrightblocks(istring, blocknumber, blocksize)
|
||||
|
||||
/datum/dna/proc/mutation_in_sequence(mutation)
|
||||
if(!mutation)
|
||||
return
|
||||
if(istype(mutation, /datum/mutation/human))
|
||||
var/datum/mutation/human/HM = mutation
|
||||
if(HM.type in mutation_index)
|
||||
return TRUE
|
||||
else if(mutation in mutation_index)
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/proc/randmut(list/candidates, difficulty = 2)
|
||||
if(!has_dna())
|
||||
return
|
||||
var/datum/mutation/human/num = pick(candidates)
|
||||
. = num.force_give(src)
|
||||
var/mutation = pick(candidates)
|
||||
. = dna.add_mutation(mutation)
|
||||
|
||||
/mob/living/carbon/proc/randmutb()
|
||||
/mob/living/carbon/proc/easy_randmut(quality = POSITIVE + NEGATIVE + MINOR_NEGATIVE, scrambled = TRUE, sequence = TRUE, exclude_monkey = TRUE)
|
||||
if(!has_dna())
|
||||
return
|
||||
var/datum/mutation/human/HM = pick((GLOB.bad_mutations | GLOB.not_good_mutations) - GLOB.mutations_list[RACEMUT])
|
||||
. = HM.force_give(src)
|
||||
var/list/mutations = list()
|
||||
if(quality & POSITIVE)
|
||||
mutations += GLOB.good_mutations
|
||||
if(quality & NEGATIVE)
|
||||
mutations += GLOB.bad_mutations
|
||||
if(quality & MINOR_NEGATIVE)
|
||||
mutations += GLOB.not_good_mutations
|
||||
var/list/possible = list()
|
||||
for(var/datum/mutation/human/A in mutations)
|
||||
if((!sequence || dna.mutation_in_sequence(A.type)) && !dna.get_mutation(A.type))
|
||||
possible += A.type
|
||||
if(exclude_monkey)
|
||||
possible.Remove(RACEMUT)
|
||||
if(LAZYLEN(possible))
|
||||
var/mutation = pick(possible)
|
||||
. = dna.activate_mutation(mutation)
|
||||
if(scrambled)
|
||||
var/datum/mutation/human/HM = dna.get_mutation(mutation)
|
||||
if(HM)
|
||||
HM.scrambled = TRUE
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/proc/randmutg()
|
||||
if(!has_dna())
|
||||
return
|
||||
var/datum/mutation/human/HM = pick(GLOB.good_mutations)
|
||||
. = HM.force_give(src)
|
||||
|
||||
/mob/living/carbon/proc/randmutvg()
|
||||
if(!has_dna())
|
||||
return
|
||||
var/datum/mutation/human/HM = pick((GLOB.good_mutations) - GLOB.mutations_list[HULK] - GLOB.mutations_list[DWARFISM])
|
||||
. = HM.force_give(src)
|
||||
|
||||
/mob/living/carbon/proc/randmuti()
|
||||
if(!has_dna())
|
||||
@@ -429,9 +577,9 @@
|
||||
if(!M.has_dna())
|
||||
return 0
|
||||
if(se)
|
||||
for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++)
|
||||
for(var/i=1, i<=DNA_MUTATION_BLOCKS, i++)
|
||||
if(prob(probability))
|
||||
M.dna.struc_enzymes = setblock(M.dna.struc_enzymes, i, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters))
|
||||
M.dna.generate_dna_blocks()
|
||||
M.domutcheck()
|
||||
if(ui)
|
||||
for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++)
|
||||
@@ -458,3 +606,41 @@
|
||||
return value
|
||||
|
||||
/////////////////////////// DNA HELPER-PROCS
|
||||
|
||||
/mob/living/carbon/human/proc/something_horrible()
|
||||
if(!has_dna()) //shouldn't ever happen anyway so it's just in really weird cases
|
||||
return
|
||||
if(dna.stability > 0)
|
||||
return
|
||||
var/instability = -dna.stability
|
||||
dna.remove_all_mutations()
|
||||
dna.stability = 100
|
||||
if(prob(max(70-instability,0)))
|
||||
switch(rand(0,3)) //not complete and utter death
|
||||
if(0)
|
||||
monkeyize()
|
||||
if(1)
|
||||
gain_trauma(/datum/brain_trauma/severe/paralysis)
|
||||
if(2)
|
||||
corgize()
|
||||
if(3)
|
||||
to_chat(src, "<span class='notice'>Oh, we actually feel quite alright!</span>")
|
||||
else
|
||||
switch(rand(0,3))
|
||||
if(0)
|
||||
gib()
|
||||
if(1)
|
||||
dust()
|
||||
|
||||
if(2)
|
||||
death()
|
||||
petrify(INFINITY)
|
||||
if(3)
|
||||
if(prob(90))
|
||||
var/obj/item/bodypart/BP = get_bodypart(pick(BODY_ZONE_CHEST,BODY_ZONE_HEAD))
|
||||
if(BP)
|
||||
BP.dismember()
|
||||
else
|
||||
gib()
|
||||
else
|
||||
set_species(/datum/species/dullahan)
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
|
||||
|
||||
/datum/element/flavor_text
|
||||
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
|
||||
id_arg_index = 3
|
||||
var/flavor_name = "Flavor Text"
|
||||
var/list/texts_by_atom = list()
|
||||
var/addendum = "This can also be used for OOC notes and preferences!"
|
||||
var/always_show = FALSE
|
||||
var/max_len = MAX_FAVOR_LEN
|
||||
var/can_edit = TRUE
|
||||
|
||||
/datum/element/flavor_text/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FAVOR_LEN, _always_show = FALSE, _edit = TRUE)
|
||||
. = ..()
|
||||
|
||||
if(. == ELEMENT_INCOMPATIBLE || !isatom(target)) //no reason why this shouldn't work on atoms too.
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
|
||||
if(_max_len)
|
||||
max_len = _max_len
|
||||
texts_by_atom[target] = copytext(text, 1, max_len)
|
||||
if(_name)
|
||||
flavor_name = _name
|
||||
if(!isnull(addendum))
|
||||
addendum = _addendum
|
||||
always_show = _always_show
|
||||
can_edit = _edit
|
||||
|
||||
RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/show_flavor)
|
||||
|
||||
if(can_edit && ismob(target)) //but only mobs receive the proc/verb for the time being
|
||||
var/mob/M = target
|
||||
LAZYOR(GLOB.mobs_with_editable_flavor_text[M], src)
|
||||
M.verbs |= /mob/proc/manage_flavor_tests
|
||||
|
||||
/datum/element/flavor_text/Detach(atom/A)
|
||||
. = ..()
|
||||
UnregisterSignal(A, COMSIG_PARENT_EXAMINE)
|
||||
texts_by_atom -= A
|
||||
if(can_edit && ismob(A))
|
||||
var/mob/M = A
|
||||
LAZYREMOVE(GLOB.mobs_with_editable_flavor_text[M], src)
|
||||
if(!GLOB.mobs_with_editable_flavor_text[M])
|
||||
GLOB.mobs_with_editable_flavor_text -= M
|
||||
M.verbs -= /mob/proc/manage_flavor_tests
|
||||
|
||||
/datum/element/flavor_text/proc/show_flavor(atom/target, mob/user, list/examine_list)
|
||||
if(!always_show && isliving(target))
|
||||
var/mob/living/L = target
|
||||
var/unknown = L.get_visible_name() == "Unknown"
|
||||
if(!unknown && iscarbon(target))
|
||||
var/mob/living/carbon/C = L
|
||||
unknown = (C.wear_mask && (C.wear_mask.flags_inv & HIDEFACE)) || (C.head && (C.head.flags_inv & HIDEFACE))
|
||||
if(unknown)
|
||||
if(!("...?" in examine_list)) //can't think of anything better in case of multiple flavor texts.
|
||||
examine_list += "...?"
|
||||
return
|
||||
var/text = texts_by_atom[target]
|
||||
if(!text)
|
||||
return
|
||||
var/msg = replacetext(text, "\n", " ")
|
||||
if(length_char(msg) <= 40)
|
||||
examine_list += "<span class='notice'>[html_encode(msg)]</span>"
|
||||
else
|
||||
examine_list += "<span class='notice'>[html_encode(copytext_char(msg, 1, 37))]... <a href='?src=[REF(src)];show_flavor=[REF(target)]'>More...</span></a>"
|
||||
|
||||
/datum/element/flavor_text/Topic(href, href_list)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(href_list["show_flavor"])
|
||||
var/atom/target = locate(href_list["show_flavor"])
|
||||
var/text = texts_by_atom[target]
|
||||
if(text)
|
||||
usr << browse("<HTML><HEAD><TITLE>[target.name]</TITLE></HEAD><BODY><TT>[replacetext(texts_by_atom[target], "\n", "<BR>")]</TT></BODY></HTML>", "window=[target.name];size=500x200")
|
||||
onclose(usr, "[target.name]")
|
||||
return TRUE
|
||||
|
||||
/mob/proc/manage_flavor_tests()
|
||||
set name = "Manage Flavor Texts"
|
||||
set desc = "Used to manage your various flavor texts."
|
||||
set category = "IC"
|
||||
|
||||
var/list/L = GLOB.mobs_with_editable_flavor_text[src]
|
||||
|
||||
if(length(L) == 1)
|
||||
var/datum/element/flavor_text/F = L[1]
|
||||
F.set_flavor(src)
|
||||
return
|
||||
|
||||
var/list/choices = list()
|
||||
|
||||
for(var/i in L)
|
||||
var/datum/element/flavor_text/F = i
|
||||
choices[F.flavor_name] = F
|
||||
|
||||
var/chosen = input(src, "Which flavor text would you like to modify?") as null|anything in choices
|
||||
if(!chosen)
|
||||
return
|
||||
var/datum/element/flavor_text/F = choices[chosen]
|
||||
F.set_flavor(src)
|
||||
|
||||
/datum/element/flavor_text/proc/set_flavor(mob/user)
|
||||
if(!(user in texts_by_atom))
|
||||
return FALSE
|
||||
|
||||
var/lower_name = lowertext(flavor_name)
|
||||
var/new_text = stripped_multiline_input(user, "Set the [lower_name] displayed on 'examine'. [addendum]", flavor_name, texts_by_atom[usr], max_len, TRUE)
|
||||
if(!isnull(new_text) && (user in texts_by_atom))
|
||||
texts_by_atom[user] = html_decode(new_text)
|
||||
to_chat(src, "Your [lower_name] has been updated.")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
//subtypes with additional hooks for DNA and preferences.
|
||||
/datum/element/flavor_text/carbon
|
||||
|
||||
/datum/element/flavor_text/carbon/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FAVOR_LEN, _always_show = FALSE, _edit = TRUE)
|
||||
if(!iscarbon(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
. = ..()
|
||||
if(. == ELEMENT_INCOMPATIBLE)
|
||||
return
|
||||
RegisterSignal(target, COMSIG_CARBON_IDENTITY_TRANSFERRED_TO, .proc/update_dna_flavor_text)
|
||||
if(ishuman(target))
|
||||
RegisterSignal(target, COMSIG_HUMAN_PREFS_COPIED_TO, .proc/update_prefs_flavor_text)
|
||||
RegisterSignal(target, COMSIG_HUMAN_HARDSET_DNA, .proc/update_dna_flavor_text)
|
||||
RegisterSignal(target, COMSIG_HUMAN_ON_RANDOMIZE, .proc/unset_flavor)
|
||||
|
||||
/datum/element/flavor_text/carbon/Detach(mob/living/carbon/C)
|
||||
. = ..()
|
||||
UnregisterSignal(C, list(COMSIG_CARBON_IDENTITY_TRANSFERRED_TO, COMSIG_HUMAN_PREFS_COPIED_TO, COMSIG_HUMAN_HARDSET_DNA, COMSIG_HUMAN_ON_RANDOMIZE))
|
||||
|
||||
/datum/element/flavor_text/carbon/proc/update_dna_flavor_text(mob/living/carbon/C)
|
||||
texts_by_atom[C] = C.dna.features["flavor_text"]
|
||||
|
||||
/datum/element/flavor_text/carbon/proc/update_prefs_flavor_text(mob/living/carbon/human/H, datum/preferences/P, icon_updates = TRUE, roundstart_checks = TRUE)
|
||||
texts_by_atom[H] = P.features["flavor_text"]
|
||||
|
||||
/datum/element/flavor_text/carbon/set_flavor(mob/living/carbon/user)
|
||||
. = ..()
|
||||
if(. && user.dna)
|
||||
user.dna.features["flavor_text"] = texts_by_atom[user]
|
||||
|
||||
/datum/element/flavor_text/carbon/proc/unset_flavor(mob/living/carbon/user)
|
||||
texts_by_atom[user] = ""
|
||||
@@ -138,7 +138,7 @@
|
||||
destination = get_turf(loc)
|
||||
AM.forceMove(destination)
|
||||
|
||||
/obj/item/clothing/head/mob_holder/dropped()
|
||||
/obj/item/clothing/head/mob_holder/dropped(mob/user)
|
||||
. = ..()
|
||||
if(held_mob && isturf(loc))//don't release on soft-drops
|
||||
release()
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/datum/element/sword_point
|
||||
element_flags = ELEMENT_DETACH
|
||||
|
||||
/datum/element/sword_point/Attach(datum/target)
|
||||
. = ..()
|
||||
if(. == ELEMENT_INCOMPATIBLE)
|
||||
return
|
||||
if(!istype(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
RegisterSignal(target, COMSIG_ITEM_ALT_AFTERATTACK, .proc/point)
|
||||
|
||||
/datum/element/sword_point/Detach(datum/source)
|
||||
. = ..()
|
||||
UnregisterSignal(source, COMSIG_ITEM_ALT_AFTERATTACK)
|
||||
|
||||
/datum/element/sword_point/proc/point(datum/source, atom/target, mob/user, proximity_flag, params)
|
||||
if(!proximity_flag && ismob(target))
|
||||
user.visible_message("<span class='notice'>[user] points the tip of [src] at [target].</span>", "<span class='notice'>You point the tip of [src] at [target].</span>")
|
||||
@@ -118,7 +118,8 @@
|
||||
if(DEAD)
|
||||
to_chat(user, "<span class='notice'>You cannot [key] while dead.</span>")
|
||||
return FALSE
|
||||
if(restraint_check && (user.IsStun() || user.IsKnockdown()))
|
||||
var/mob/living/L = user
|
||||
if(restraint_check && (istype(L) && !CHECK_MOBILITY(L, MOBILITY_USE)))
|
||||
if(!intentional)
|
||||
return FALSE
|
||||
to_chat(user, "<span class='notice'>You cannot [key] while stunned.</span>")
|
||||
|
||||
+10
-10
@@ -42,19 +42,19 @@
|
||||
/datum/martial_art/cqc/proc/Slam(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(!can_use(A))
|
||||
return FALSE
|
||||
if(!D.stat || !D.IsKnockdown())
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
D.visible_message("<span class='warning'>[A] slams [D] into the ground!</span>", \
|
||||
"<span class='userdanger'>[A] slams you into the ground!</span>")
|
||||
playsound(get_turf(A), 'sound/weapons/slam.ogg', 50, 1, -1)
|
||||
D.apply_damage(10, BRUTE)
|
||||
D.Knockdown(120)
|
||||
D.DefaultCombatKnockdown(120)
|
||||
log_combat(A, D, "slammed (CQC)")
|
||||
return TRUE
|
||||
|
||||
/datum/martial_art/cqc/proc/Kick(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(!can_use(A))
|
||||
return FALSE
|
||||
if(!D.stat || !D.IsKnockdown())
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
D.visible_message("<span class='warning'>[A] kicks [D] back!</span>", \
|
||||
"<span class='userdanger'>[A] kicks you back!</span>")
|
||||
playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
|
||||
@@ -62,7 +62,7 @@
|
||||
D.throw_at(throw_target, 1, 14, A)
|
||||
D.apply_damage(10, BRUTE)
|
||||
log_combat(A, D, "kicked (CQC)")
|
||||
if(D.IsKnockdown() && !D.stat)
|
||||
if(!CHECK_MOBILITY(D, MOBILITY_STAND) && CHECK_MOBILITY(D, MOBILITY_USE))
|
||||
log_combat(A, D, "knocked out (Head kick)(CQC)")
|
||||
D.visible_message("<span class='warning'>[A] kicks [D]'s head, knocking [D.p_them()] out!</span>", \
|
||||
"<span class='userdanger'>[A] kicks your head, knocking you out!</span>")
|
||||
@@ -119,7 +119,7 @@
|
||||
D.grabbedby(A, 1)
|
||||
if(old_grab_state == GRAB_PASSIVE)
|
||||
D.drop_all_held_items()
|
||||
A.grab_state = GRAB_AGGRESSIVE //Instant agressive grab if on grab intent
|
||||
A.setGrabState(GRAB_AGGRESSIVE) //Instant agressive grab if on grab intent
|
||||
log_combat(A, D, "grabbed", addition="aggressively")
|
||||
D.visible_message("<span class='warning'>[A] violently grabs [D]!</span>", \
|
||||
"<span class='userdanger'>[A] violently grabs you!</span>")
|
||||
@@ -136,7 +136,7 @@
|
||||
A.do_attack_animation(D)
|
||||
var/picked_hit_type = pick("CQC'd", "Big Bossed")
|
||||
var/bonus_damage = 13
|
||||
if(D.IsKnockdown() || D.resting || D.lying)
|
||||
if(!CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
bonus_damage += 5
|
||||
picked_hit_type = "stomps on"
|
||||
D.apply_damage(bonus_damage, BRUTE)
|
||||
@@ -147,12 +147,12 @@
|
||||
D.visible_message("<span class='danger'>[A] [picked_hit_type] [D]!</span>", \
|
||||
"<span class='userdanger'>[A] [picked_hit_type] you!</span>")
|
||||
log_combat(A, D, "[picked_hit_type] (CQC)")
|
||||
if(A.resting && !D.stat && !D.IsKnockdown())
|
||||
if(!CHECK_MOBILITY(A, MOBILITY_STAND) && !D.stat && CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
D.visible_message("<span class='warning'>[A] leg sweeps [D]!", \
|
||||
"<span class='userdanger'>[A] leg sweeps you!</span>")
|
||||
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1)
|
||||
D.apply_damage(10, BRUTE)
|
||||
D.Knockdown(60)
|
||||
D.DefaultCombatKnockdown(60)
|
||||
log_combat(A, D, "sweeped (CQC)")
|
||||
return TRUE
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
if(check_streak(A,D))
|
||||
return TRUE
|
||||
if(prob(65))
|
||||
if(!D.stat || !D.IsKnockdown() || !restraining)
|
||||
if(CHECK_MOBILITY(D, MOBILITY_MOVE) || !restraining)
|
||||
I = D.get_active_held_item()
|
||||
D.visible_message("<span class='warning'>[A] strikes [D]'s jaw with their hand!</span>", \
|
||||
"<span class='userdanger'>[A] strikes your jaw, disorienting you!</span>")
|
||||
@@ -185,7 +185,7 @@
|
||||
D.SetSleeping(400)
|
||||
restraining = FALSE
|
||||
if(A.grab_state < GRAB_NECK)
|
||||
A.grab_state = GRAB_NECK
|
||||
A.setGrabState(GRAB_NECK)
|
||||
else
|
||||
restraining = FALSE
|
||||
return FALSE
|
||||
|
||||
@@ -96,13 +96,13 @@
|
||||
return 0
|
||||
|
||||
/datum/martial_art/krav_maga/proc/leg_sweep(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(D.lying || D.IsKnockdown())
|
||||
if(!CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
return 0
|
||||
D.visible_message("<span class='warning'>[A] leg sweeps [D]!</span>", \
|
||||
"<span class='userdanger'>[A] leg sweeps you!</span>")
|
||||
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1)
|
||||
D.apply_damage(5, BRUTE)
|
||||
D.Knockdown(40, override_hardstun = 0.01, override_stamdmg = 25)
|
||||
D.DefaultCombatKnockdown(40, override_hardstun = 0.01, override_stamdmg = 25)
|
||||
log_combat(A, D, "leg sweeped")
|
||||
return 1
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
log_combat(A, D, "punched")
|
||||
var/picked_hit_type = pick("punches", "kicks")
|
||||
var/bonus_damage = 10
|
||||
if(D.IsKnockdown() || D.resting || D.lying)
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
bonus_damage += 5
|
||||
picked_hit_type = "stomps on"
|
||||
D.apply_damage(bonus_damage, BRUTE)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
playsound(D, 'sound/effects/meteorimpact.ogg', 25, 1, -1)
|
||||
var/throwtarget = get_edge_target_turf(A, get_dir(A, get_step_away(D, A)))
|
||||
D.throw_at(throwtarget, 4, 2, A)//So stuff gets tossed around at the same time.
|
||||
D.Knockdown(20)
|
||||
D.DefaultCombatKnockdown(20)
|
||||
if(atk_verb)
|
||||
log_combat(A, D, "[atk_verb] (Mushroom Punch)")
|
||||
return TRUE
|
||||
|
||||
@@ -34,10 +34,10 @@
|
||||
log_combat(A, D, "grabbed", addition="aggressively")
|
||||
D.visible_message("<span class='warning'>[A] violently grabs [D]!</span>", \
|
||||
"<span class='userdanger'>[A] violently grabs you!</span>")
|
||||
A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab
|
||||
A.setGrabState(GRAB_AGGRESSIVE) //Instant aggressive grab
|
||||
else
|
||||
log_combat(A, D, "grabbed", addition="passively")
|
||||
A.grab_state = GRAB_PASSIVE
|
||||
A.setGrabState(GRAB_PASSIVE)
|
||||
if(4)
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
|
||||
atk_verb = "headbutts"
|
||||
@@ -49,7 +49,7 @@
|
||||
if(!istype(D.head,/obj/item/clothing/head/helmet/) && !istype(D.head,/obj/item/clothing/head/hardhat))
|
||||
D.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5)
|
||||
A.Stun(rand(10,45))
|
||||
D.Knockdown(rand(5,30))//CIT CHANGE - makes stuns from martial arts always use Knockdown instead of Stun for the sake of consistency
|
||||
D.DefaultCombatKnockdown(rand(5,30))//CIT CHANGE - makes stuns from martial arts always use Knockdown instead of Stun for the sake of consistency
|
||||
if(5,6)
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
|
||||
atk_verb = pick("punches", "kicks", "hits", "slams into")
|
||||
@@ -59,7 +59,7 @@
|
||||
playsound(get_turf(D), 'sound/effects/meteorimpact.ogg', 25, 1, -1)
|
||||
var/throwtarget = get_edge_target_turf(A, get_dir(A, get_step_away(D, A)))
|
||||
D.throw_at(throwtarget, 4, 2, A)//So stuff gets tossed around at the same time.
|
||||
D.Knockdown(60)
|
||||
D.DefaultCombatKnockdown(60)
|
||||
if(7,8)
|
||||
basic_hit(A,D)
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#define SIDE_KICK_COMBO "DH"
|
||||
#define REPULSE_PUNCH_COMBO "HDHD"
|
||||
#define SHOULDER_FLIP_COMBO "GHDGHH"
|
||||
#define FOOT_SMASH_COMBO "HH"
|
||||
#define SIDE_KICK_COMBO "skick"
|
||||
#define DEFT_SWITCH_COMBO "deft"
|
||||
|
||||
/datum/martial_art/the_rising_bass
|
||||
name = "The Rising Bass"
|
||||
@@ -8,7 +10,7 @@
|
||||
dodge_chance = 100
|
||||
allow_temp_override = FALSE
|
||||
help_verb = /mob/living/carbon/human/proc/rising_bass_help
|
||||
var/datum/action/risingbassmove/repulsepunch = new/datum/action/risingbassmove/repulsepunch()
|
||||
var/datum/action/risingbassmove/sidekick = new/datum/action/risingbassmove/sidekick()
|
||||
var/datum/action/risingbassmove/deftswitch = new/datum/action/risingbassmove/deftswitch()
|
||||
var/repulsecool = 0
|
||||
|
||||
@@ -21,7 +23,7 @@
|
||||
streak = ""
|
||||
shoulderFlip(A,D)
|
||||
return 1
|
||||
if(findtext(streak,"rplse"))
|
||||
if(findtext(streak,REPULSE_PUNCH_COMBO))
|
||||
streak = ""
|
||||
repulsePunch(A,D)
|
||||
return 1
|
||||
@@ -29,7 +31,7 @@
|
||||
streak = ""
|
||||
footSmash(A,D)
|
||||
return 1
|
||||
if(findtext(streak,"deft"))
|
||||
if(findtext(streak,DEFT_SWITCH_COMBO))
|
||||
streak = ""
|
||||
deftSwitch(A,D)
|
||||
return 1
|
||||
@@ -58,42 +60,46 @@
|
||||
to_chat(H,"<span class='danger'>You get ready to use the [name] maneuver!</span>")
|
||||
H.mind.martial_art.streak = "[movestreak]"
|
||||
|
||||
/datum/action/risingbassmove/repulsepunch
|
||||
name = "Repulse Punch"
|
||||
button_icon_state = "repulsepunch"
|
||||
movestreak = "rplse"
|
||||
/datum/action/risingbassmove/sidekick
|
||||
name = "Side Kick"
|
||||
button_icon_state = "sidekick"
|
||||
movestreak = "skick"
|
||||
|
||||
/datum/action/risingbassmove/deftswitch
|
||||
name = "Deft Switch"
|
||||
button_icon_state = "deftswitch"
|
||||
movestreak = "deft"
|
||||
|
||||
/datum/martial_art/the_rising_bass/proc/checkfordensity(turf/T,mob/M)
|
||||
if (T.density)
|
||||
return FALSE
|
||||
for(var/obj/O in T)
|
||||
if(!O.CanPass(M,T))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/martial_art/the_rising_bass/proc/sideKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(!D.IsKnockdown() || D.lying == 0)
|
||||
var/turf/H = get_step(D, A.dir & (NORTH | SOUTH) ? pick(EAST, WEST) : pick(NORTH, SOUTH))
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
var/dir = A.dir & (NORTH | SOUTH) ? pick(EAST, WEST) : pick(NORTH, SOUTH)
|
||||
var/oppdir = dir == NORTH ? SOUTH : dir == SOUTH ? NORTH : dir == EAST ? WEST : EAST
|
||||
var/turf/H = get_step(D, dir)
|
||||
var/turf/K = get_step(D, oppdir)
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
|
||||
D.visible_message("<span class='warning'>[A] kicks [D] in the side, sliding them over!</span>", \
|
||||
"<span class='userdanger'>[A] kicks you in the side, forcing you to step away!</span>")
|
||||
playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
D.apply_damage(5, BRUTE, BODY_ZONE_CHEST)
|
||||
D.Knockdown(60)
|
||||
var/L = H
|
||||
for(var/obj/i in H.contents)
|
||||
if(!istype(i,/mob) && i.density == 1)
|
||||
L = D.loc
|
||||
D.DefaultCombatKnockdown(60)
|
||||
var/L = !checkfordensity(H,D) ? (!checkfordensity(K,D) ? D.loc : K) : H
|
||||
D.forceMove(L)
|
||||
log_combat(A, D, "side kicked (Rising Bass)")
|
||||
return 1
|
||||
return TRUE
|
||||
return basic_hit(A,D)
|
||||
|
||||
/datum/martial_art/the_rising_bass/proc/shoulderFlip(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(!D.IsKnockdown() || !D.lying)
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
var/turf/H = get_step(A, get_dir(D,A))
|
||||
var/L = H
|
||||
for(var/obj/i in H.contents)
|
||||
if(!istype(i,/mob) && i.density == 1)//(i.anchored == 1 && i.density == 1) || istype(i,/obj/structure) || istype(i,/turf/closed)
|
||||
L = A.loc
|
||||
var/L = checkfordensity(H,D) ? H : A.loc
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
|
||||
D.visible_message("<span class='warning'>[A] flips [D] over their shoulder, slamming them into the ground!</span>", \
|
||||
"<span class='userdanger'>[A] flips you over their shoulder, slamming you into the ground!</span>")
|
||||
@@ -102,14 +108,14 @@
|
||||
D.apply_damage(10, BRUTE, BODY_ZONE_CHEST)
|
||||
D.apply_damage(30, BRUTE, BODY_ZONE_HEAD)
|
||||
D.Sleeping(60)
|
||||
D.Knockdown(300)
|
||||
D.DefaultCombatKnockdown(300)
|
||||
D.forceMove(L)
|
||||
log_combat(A, D, "shoulder flipped (Rising Bass)")
|
||||
return 1
|
||||
return TRUE
|
||||
return basic_hit(A,D)
|
||||
|
||||
/datum/martial_art/the_rising_bass/proc/repulsePunch(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(!D.IsKnockdown() || !D.lying || repulsecool > world.time)
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND) && repulsecool < world.time)
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
|
||||
D.visible_message("<span class='warning'>[A] smashes [D] in the chest, throwing them away!</span>", \
|
||||
"<span class='userdanger'>[A] smashes you in the chest, repelling you away!</span>")
|
||||
@@ -117,14 +123,14 @@
|
||||
var/atom/F = get_edge_target_turf(D, get_dir(A, get_step_away(D, A)))
|
||||
D.throw_at(F, 10, 1)
|
||||
D.apply_damage(10, BRUTE, BODY_ZONE_CHEST)
|
||||
D.Knockdown(90)
|
||||
D.DefaultCombatKnockdown(90)
|
||||
log_combat(A, D, "repulse punched (Rising Bass)")
|
||||
repulsecool = world.time + 3 SECONDS
|
||||
return 1
|
||||
return TRUE
|
||||
return basic_hit(A,D)
|
||||
|
||||
/datum/martial_art/the_rising_bass/proc/footSmash(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(!D.IsKnockdown() || !D.lying)
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
|
||||
D.visible_message("<span class='warning'>[A] smashes their foot down on [D]'s foot!</span>", \
|
||||
"<span class='userdanger'>[A] smashes your foot!</span>")
|
||||
@@ -132,11 +138,11 @@
|
||||
D.apply_damage(5, BRUTE, pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
|
||||
D.dropItemToGround(D.get_active_held_item())
|
||||
log_combat(A, D, "foot smashed (Rising Bass)")
|
||||
return 1
|
||||
return TRUE
|
||||
return basic_hit(A,D)
|
||||
|
||||
/datum/martial_art/the_rising_bass/proc/deftSwitch(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(!D.IsKnockdown() || !D.lying)
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
if (D.get_active_held_item())
|
||||
var/obj/item/G = D.get_active_held_item()
|
||||
if (G && !(G.item_flags & (ABSTRACT|DROPDEL)) && D.temporarilyRemoveItemFromInventory(G))
|
||||
@@ -144,10 +150,10 @@
|
||||
D.visible_message("<span class='warning'>[A] slaps [D]'s hands, taking [G] from them!</span>", \
|
||||
"<span class='userdanger'>[A] slaps you, taking [G] from you!</span>")
|
||||
log_combat(A, D, "deft switched (Rising Bass)")
|
||||
return 1
|
||||
return TRUE
|
||||
else
|
||||
to_chat(A, "<i>[G] can't be taken out of [D]'s hands!</i>")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/datum/martial_art/the_rising_bass/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
add_to_streak("D",D)
|
||||
@@ -168,7 +174,7 @@
|
||||
return ..()
|
||||
|
||||
/datum/martial_art/the_rising_bass/add_to_streak(element,mob/living/carbon/human/D)
|
||||
if (streak == "deft" || streak == "rplse")
|
||||
if (streak == DEFT_SWITCH_COMBO || streak == SIDE_KICK_COMBO)
|
||||
return
|
||||
. = ..()
|
||||
|
||||
@@ -179,24 +185,24 @@
|
||||
|
||||
to_chat(usr, "<b><i>You retreat inward and recall the teachings of the Rising Bass...</i></b>")
|
||||
|
||||
to_chat(usr, "<span class='notice'>Side Kick</span>: Disarm Harm. Forces opponent to step to the side.")
|
||||
to_chat(usr, "<span class='notice'>Side Kick</span>: Forces opponent to step to the side.")
|
||||
to_chat(usr, "<span class='notice'>Shoulder Flip</span>: Grab Harm Disarm Grab Harm Harm. Flips opponent over your shoulder and stuns.")
|
||||
to_chat(usr, "<span class='notice'>Repulse Punch</span>: Grab Harm Grab Harm. Slams the opponent far away from you.")
|
||||
to_chat(usr, "<span class='notice'>Repulse Punch</span>: Harm Disarm Harm Disarm. Slams the opponent far away from you.")
|
||||
to_chat(usr, "<span class='notice'>Foot Smash</span>: Harm Harm. Stuns opponent, minor damage.")
|
||||
to_chat(usr, "<span class='notice'>Deft Switch</span>: Grab Disarm Disarm. Switches the opponent's held item for your own. Most useful with nothing in your hand.")
|
||||
to_chat(usr, "<span class='notice'>Deft Switch</span>: Switches the opponent's held item for your own. Most useful with nothing in your hand.")
|
||||
|
||||
/datum/martial_art/the_rising_bass/teach(mob/living/carbon/human/H, make_temporary = FALSE)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
deftswitch.Grant(H)
|
||||
repulsepunch.Grant(H)
|
||||
sidekick.Grant(H)
|
||||
ADD_TRAIT(H, TRAIT_NOGUNS, RISING_BASS_TRAIT)
|
||||
ADD_TRAIT(H, TRAIT_AUTO_CATCH_ITEM, RISING_BASS_TRAIT)
|
||||
|
||||
/datum/martial_art/the_rising_bass/on_remove(mob/living/carbon/human/H)
|
||||
. = ..()
|
||||
deftswitch.Remove(H)
|
||||
repulsepunch.Remove(H)
|
||||
sidekick.Remove(H)
|
||||
REMOVE_TRAIT(H, TRAIT_NOGUNS, RISING_BASS_TRAIT)
|
||||
REMOVE_TRAIT(H, TRAIT_AUTO_CATCH_ITEM, RISING_BASS_TRAIT)
|
||||
REMOVE_TRAIT(H, TRAIT_AUTO_CATCH_ITEM, RISING_BASS_TRAIT)
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
return FALSE
|
||||
|
||||
/datum/martial_art/the_sleeping_carp/proc/wristWrench(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(!D.stat && !D.IsStun() && !D.IsKnockdown())
|
||||
if(CHECK_MOBILITY(D, MOBILITY_USE))
|
||||
log_combat(A, D, "wrist wrenched (Sleeping Carp)")
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
|
||||
D.visible_message("<span class='warning'>[A] grabs [D]'s wrist and wrenches it sideways!</span>", \
|
||||
@@ -46,19 +46,19 @@
|
||||
D.emote("scream")
|
||||
D.dropItemToGround(D.get_active_held_item())
|
||||
D.apply_damage(5, BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM))
|
||||
D.Knockdown(60)//CIT CHANGE - makes sleepingcarp use knockdown() for its stuns instead of stun()
|
||||
D.DefaultCombatKnockdown(60)//CIT CHANGE - makes sleepingcarp use knockdown() for its stuns instead of stun()
|
||||
return TRUE
|
||||
return basic_hit(A,D)
|
||||
|
||||
/datum/martial_art/the_sleeping_carp/proc/backKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(!D.stat && !D.IsKnockdown())
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
if(A.dir == D.dir)
|
||||
log_combat(A, D, "back-kicked (Sleeping Carp)")
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
|
||||
D.visible_message("<span class='warning'>[A] kicks [D] in the back!</span>", \
|
||||
"<span class='userdanger'>[A] kicks you in the back, making you stumble and fall!</span>")
|
||||
step_to(D,get_step(D,D.dir),1)
|
||||
D.Knockdown(80)
|
||||
D.DefaultCombatKnockdown(80)
|
||||
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
|
||||
return TRUE
|
||||
else
|
||||
@@ -68,20 +68,20 @@
|
||||
return basic_hit(A,D)
|
||||
|
||||
/datum/martial_art/the_sleeping_carp/proc/kneeStomach(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(!D.stat && !D.IsKnockdown())
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
log_combat(A, D, "stomach kneed (Sleeping Carp)")
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
|
||||
D.visible_message("<span class='warning'>[A] knees [D] in the stomach!</span>", \
|
||||
"<span class='userdanger'>[A] winds you with a knee in the stomach!</span>")
|
||||
D.audible_message("<b>[D]</b> gags!")
|
||||
D.losebreath += 3
|
||||
D.Knockdown(40)//CIT CHANGE - makes sleepingcarp use knockdown() for its stuns instead of stun()
|
||||
D.DefaultCombatKnockdown(40)//CIT CHANGE - makes sleepingcarp use knockdown() for its stuns instead of stun()
|
||||
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
|
||||
return TRUE
|
||||
return basic_hit(A,D)
|
||||
|
||||
/datum/martial_art/the_sleeping_carp/proc/headKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(!D.stat && !D.IsKnockdown())
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
log_combat(A, D, "head kicked (Sleeping Carp)")
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
|
||||
D.visible_message("<span class='warning'>[A] kicks [D] in the head!</span>", \
|
||||
@@ -89,12 +89,12 @@
|
||||
D.apply_damage(20, BRUTE, BODY_ZONE_HEAD)
|
||||
D.drop_all_held_items()
|
||||
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
|
||||
D.Knockdown(80)//CIT CHANGE - makes sleepingcarp use knockdown() for its stuns instead of stun()
|
||||
D.DefaultCombatKnockdown(80)//CIT CHANGE - makes sleepingcarp use knockdown() for its stuns instead of stun()
|
||||
return TRUE
|
||||
return basic_hit(A,D)
|
||||
|
||||
/datum/martial_art/the_sleeping_carp/proc/elbowDrop(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(D.IsKnockdown() || D.resting || D.stat)
|
||||
if(!CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
log_combat(A, D, "elbow dropped (Sleeping Carp)")
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
|
||||
D.visible_message("<span class='warning'>[A] elbow drops [D]!</span>", \
|
||||
@@ -115,7 +115,7 @@
|
||||
D.grabbedby(A, 1)
|
||||
if(old_grab_state == GRAB_PASSIVE)
|
||||
D.drop_all_held_items()
|
||||
A.grab_state = GRAB_AGGRESSIVE //Instant agressive grab if on grab intent
|
||||
A.setGrabState(GRAB_AGGRESSIVE) //Instant agressive grab if on grab intent
|
||||
log_combat(A, D, "grabbed", addition="aggressively")
|
||||
D.visible_message("<span class='warning'>[A] violently grabs [D]!</span>", \
|
||||
"<span class='userdanger'>[A] violently grabs you!</span>")
|
||||
@@ -134,7 +134,7 @@
|
||||
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, 1, -1)
|
||||
if(prob(D.getBruteLoss()) && !D.lying)
|
||||
D.visible_message("<span class='warning'>[D] stumbles and falls!</span>", "<span class='userdanger'>The blow sends you to the ground!</span>")
|
||||
D.Knockdown(80)
|
||||
D.DefaultCombatKnockdown(80)
|
||||
log_combat(A, D, "[atk_verb] (Sleeping Carp)")
|
||||
return TRUE
|
||||
|
||||
@@ -192,7 +192,7 @@
|
||||
add_fingerprint(user)
|
||||
if((HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50))
|
||||
to_chat(user, "<span class ='warning'>You club yourself over the head with [src].</span>")
|
||||
user.Knockdown(60)
|
||||
user.DefaultCombatKnockdown(60)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.apply_damage(2*force, BRUTE, BODY_ZONE_HEAD)
|
||||
@@ -226,7 +226,7 @@
|
||||
if(prob(10))
|
||||
H.visible_message("<span class='warning'>[H] collapses!</span>", \
|
||||
"<span class='userdanger'>Your legs give out!</span>")
|
||||
H.Knockdown(80)
|
||||
H.DefaultCombatKnockdown(80)
|
||||
if(H.staminaloss && !H.IsSleeping())
|
||||
var/total_health = (H.health - H.staminaloss)
|
||||
if(total_health <= HEALTH_THRESHOLD_CRIT && !H.stat)
|
||||
|
||||
@@ -207,7 +207,7 @@
|
||||
if (T && isturf(T))
|
||||
if (!D.stat)
|
||||
D.emote("scream")
|
||||
D.throw_at(T, 10, 4, A, TRUE, TRUE, callback = CALLBACK(D, /mob/living/carbon/human.proc/Knockdown, 20))
|
||||
D.throw_at(T, 10, 4, A, TRUE, TRUE, callback = CALLBACK(D, /mob/living/carbon/human.proc/DefaultCombatKnockdown, 20))
|
||||
log_combat(A, D, "has thrown with wrestling")
|
||||
return 0
|
||||
|
||||
@@ -303,7 +303,7 @@
|
||||
playsound(A.loc, "swing_hit", 50, 1)
|
||||
if (!D.stat)
|
||||
D.emote("scream")
|
||||
D.Knockdown(40)
|
||||
D.DefaultCombatKnockdown(40)
|
||||
|
||||
switch(rand(1,3))
|
||||
if (2)
|
||||
@@ -361,7 +361,7 @@
|
||||
|
||||
var/turf/T = get_edge_target_turf(A, get_dir(A, get_step_away(D, A)))
|
||||
if (T && isturf(T))
|
||||
D.Knockdown(20)
|
||||
D.DefaultCombatKnockdown(20)
|
||||
D.throw_at(T, 3, 2)
|
||||
log_combat(A, D, "roundhouse-kicked")
|
||||
|
||||
@@ -400,7 +400,7 @@
|
||||
if (falling == 1)
|
||||
A.visible_message("<span class = 'danger'><B>...and dives head-first into the ground, ouch!</b></span>")
|
||||
A.adjustBruteLoss(rand(10,20))
|
||||
A.Knockdown(60)
|
||||
A.DefaultCombatKnockdown(60)
|
||||
to_chat(A, "[D] is too far away!")
|
||||
return 0
|
||||
|
||||
@@ -429,7 +429,7 @@
|
||||
else
|
||||
D.adjustBruteLoss(rand(20,30))
|
||||
|
||||
D.Knockdown(40)
|
||||
D.DefaultCombatKnockdown(40)
|
||||
|
||||
A.pixel_y = 0
|
||||
|
||||
|
||||
@@ -41,20 +41,21 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
|
||||
///This proc is called when the material is added to an object specifically.
|
||||
/datum/material/proc/on_applied_obj(var/obj/o, amount, material_flags)
|
||||
var/new_max_integrity = CEILING(o.max_integrity * integrity_modifier, 1)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force *= strength_modifier
|
||||
o.throwforce *= strength_modifier
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
var/new_max_integrity = CEILING(o.max_integrity * integrity_modifier, 1)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force *= strength_modifier
|
||||
o.throwforce *= strength_modifier
|
||||
|
||||
var/list/temp_armor_list = list() //Time to add armor modifiers!
|
||||
var/list/temp_armor_list = list() //Time to add armor modifiers!
|
||||
|
||||
if(!istype(o.armor))
|
||||
return
|
||||
var/list/current_armor = o.armor?.getList()
|
||||
if(!istype(o.armor))
|
||||
return
|
||||
var/list/current_armor = o.armor?.getList()
|
||||
|
||||
for(var/i in current_armor)
|
||||
temp_armor_list[i] = current_armor[i] * armor_modifiers[i]
|
||||
o.armor = getArmor(arglist(temp_armor_list))
|
||||
for(var/i in current_armor)
|
||||
temp_armor_list[i] = current_armor[i] * armor_modifiers[i]
|
||||
o.armor = getArmor(arglist(temp_armor_list))
|
||||
|
||||
///This proc is called when the material is removed from an object.
|
||||
/datum/material/proc/on_removed(atom/source, material_flags)
|
||||
@@ -71,7 +72,8 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
|
||||
///This proc is called when the material is removed from an object specifically.
|
||||
/datum/material/proc/on_removed_obj(var/obj/o, amount, material_flags)
|
||||
var/new_max_integrity = initial(o.max_integrity)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force = initial(o.force)
|
||||
o.throwforce = initial(o.throwforce)
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
var/new_max_integrity = initial(o.max_integrity)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force = initial(o.force)
|
||||
o.throwforce = initial(o.throwforce)
|
||||
|
||||
@@ -617,6 +617,10 @@
|
||||
if(!(has_antag_datum(/datum/antagonist/traitor)))
|
||||
add_antag_datum(/datum/antagonist/traitor)
|
||||
|
||||
/datum/mind/proc/make_Contractor_Support()
|
||||
if(!(has_antag_datum(/datum/antagonist/traitor/contractor_support)))
|
||||
add_antag_datum(/datum/antagonist/traitor/contractor_support)
|
||||
|
||||
/datum/mind/proc/make_Changeling()
|
||||
var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling)
|
||||
if(!C)
|
||||
|
||||
+96
-40
@@ -1,58 +1,55 @@
|
||||
GLOBAL_LIST_EMPTY(mutations_list)
|
||||
|
||||
/datum/mutation
|
||||
|
||||
var/name
|
||||
|
||||
/datum/mutation/New()
|
||||
GLOB.mutations_list[name] = src
|
||||
|
||||
/datum/mutation/human
|
||||
var/dna_block
|
||||
name = "mutation"
|
||||
var/desc = "A mutation."
|
||||
var/locked
|
||||
var/quality
|
||||
var/get_chance = 100
|
||||
var/lowest_value = 256 * 8
|
||||
var/text_gain_indication = ""
|
||||
var/text_lose_indication = ""
|
||||
var/list/mutable_appearance/visual_indicators = list()
|
||||
var/obj/effect/proc_holder/spell/power
|
||||
var/layer_used = MUTATIONS_LAYER //which mutation layer to use
|
||||
var/list/species_allowed = list() //to restrict mutation to only certain species
|
||||
var/health_req //minimum health required to acquire the mutation
|
||||
var/limb_req //required limbs to acquire this mutation
|
||||
var/time_coeff = 1 //coefficient for timed mutations
|
||||
var/datum/dna/dna
|
||||
var/mob/living/carbon/human/owner
|
||||
var/instability = 0 //instability the holder gets when the mutation is not native
|
||||
var/blocks = 4 //Amount of those big blocks with gene sequences
|
||||
var/difficulty = 8 //Amount of missing sequences. Sometimes it removes an entire pair for 2 points
|
||||
var/timed = FALSE //Boolean to easily check if we're going to self destruct
|
||||
var/alias //'Mutation #49', decided every round to get some form of distinction between undiscovered mutations
|
||||
var/scrambled = FALSE //Wheter we can read it if it's active. To avoid cheesing with mutagen
|
||||
var/class //Decides player accesibility, sorta
|
||||
//MUT_NORMAL - A mutation that can be activated and deactived by completing a sequence
|
||||
//MUT_EXTRA - A mutation that is in the mutations tab, and can be given and taken away through though the DNA console. Has a 0 before it's name in the mutation section of the dna console
|
||||
//MUT_OTHER Cannot be interacted with by players through normal means. I.E. wizards mutate
|
||||
|
||||
/datum/mutation/human/proc/force_give(mob/living/carbon/human/owner)
|
||||
set_block(owner)
|
||||
. = on_acquiring(owner)
|
||||
var/can_chromosome = CHROMOSOME_NONE //can we take chromosomes? 0: CHROMOSOME_NEVER never, 1:CHROMOSOME_NONE yeah, 2: CHROMOSOME_USED no, already have one
|
||||
var/chromosome_name //purely cosmetic
|
||||
var/modified = FALSE //ugly but we really don't want chromosomes and on_acquiring to overlap and apply double the powers
|
||||
var/mutadone_proof = FALSE
|
||||
|
||||
/datum/mutation/human/proc/force_lose(mob/living/carbon/human/owner)
|
||||
set_block(owner, 0)
|
||||
. = on_losing(owner)
|
||||
//Chromosome stuff - set to -1 to prevent people from changing it. Example: It'd be a waste to decrease cooldown on mutism
|
||||
var/stabilizer_coeff = 1 //genetic stability coeff
|
||||
var/synchronizer_coeff = -1 //makes the mutation hurt the user less
|
||||
var/power_coeff = -1 //boosts mutation strength
|
||||
var/energy_coeff = -1 //lowers mutation cooldown
|
||||
|
||||
/datum/mutation/human/proc/set_se(se_string, on = 1)
|
||||
if(!se_string || length(se_string) < DNA_STRUC_ENZYMES_BLOCKS * DNA_BLOCK_SIZE)
|
||||
return
|
||||
var/before = copytext_char(se_string, 1, ((dna_block - 1) * DNA_BLOCK_SIZE) + 1)
|
||||
var/injection = num2hex(on ? rand(lowest_value, (256 * 16) - 1) : rand(0, lowest_value - 1), DNA_BLOCK_SIZE)
|
||||
var/after = copytext_char(se_string, (dna_block * DNA_BLOCK_SIZE) + 1, 0)
|
||||
return before + injection + after
|
||||
|
||||
/datum/mutation/human/proc/set_block(mob/living/carbon/owner, on = 1)
|
||||
if(owner && owner.has_dna())
|
||||
owner.dna.struc_enzymes = set_se(owner.dna.struc_enzymes, on)
|
||||
|
||||
/datum/mutation/human/proc/check_block_string(se_string)
|
||||
if(!se_string || length(se_string) < DNA_STRUC_ENZYMES_BLOCKS * DNA_BLOCK_SIZE)
|
||||
return 0
|
||||
if(hex2num(getblock(se_string, dna_block)) >= lowest_value)
|
||||
return 1
|
||||
|
||||
/datum/mutation/human/proc/check_block(mob/living/carbon/human/owner, force_powers=0)
|
||||
if(check_block_string(owner.dna.struc_enzymes))
|
||||
if(prob(get_chance)||force_powers)
|
||||
. = on_acquiring(owner)
|
||||
else
|
||||
. = on_losing(owner)
|
||||
/datum/mutation/human/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
|
||||
. = ..()
|
||||
class = class_
|
||||
if(timer)
|
||||
addtimer(CALLBACK(src, .proc/remove), timer)
|
||||
timed = TRUE
|
||||
if(copymut && istype(copymut, /datum/mutation/human))
|
||||
copy_mutation(copymut)
|
||||
|
||||
/datum/mutation/human/proc/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(!owner || !istype(owner) || owner.stat == DEAD || (src in owner.dna.mutations))
|
||||
@@ -63,7 +60,8 @@ GLOBAL_LIST_EMPTY(mutations_list)
|
||||
return TRUE
|
||||
if(limb_req && !owner.get_bodypart(limb_req))
|
||||
return TRUE
|
||||
owner.dna.mutations.Add(src)
|
||||
dna = owner.dna
|
||||
dna.mutations += src
|
||||
if(text_gain_indication)
|
||||
to_chat(owner, text_gain_indication)
|
||||
if(visual_indicators.len)
|
||||
@@ -75,6 +73,10 @@ GLOBAL_LIST_EMPTY(mutations_list)
|
||||
owner.overlays_standing[layer_used] = mut_overlay
|
||||
owner.apply_overlay(layer_used)
|
||||
|
||||
grant_spell(owner)
|
||||
if(!modified)
|
||||
addtimer(CALLBACK(src, .proc/modify, 5)) //gonna want children calling ..() to run first
|
||||
|
||||
/datum/mutation/human/proc/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return
|
||||
|
||||
@@ -102,26 +104,80 @@ GLOBAL_LIST_EMPTY(mutations_list)
|
||||
mut_overlay.Remove(get_visual_indicator(owner))
|
||||
owner.overlays_standing[layer_used] = mut_overlay
|
||||
owner.apply_overlay(layer_used)
|
||||
if(power)
|
||||
owner.RemoveSpell(power)
|
||||
qdel(src)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/datum/mutation/human/proc/say_mod(message)
|
||||
if(message)
|
||||
return message
|
||||
|
||||
/datum/mutation/human/proc/get_spans()
|
||||
return list()
|
||||
|
||||
/mob/living/carbon/proc/update_mutations_overlay()
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/update_mutations_overlay()
|
||||
for(var/datum/mutation/human/CM in dna.mutations)
|
||||
if(CM.species_allowed.len && !CM.species_allowed.Find(dna.species.id))
|
||||
CM.force_lose(src) //shouldn't have that mutation at all
|
||||
dna.force_lose(CM) //shouldn't have that mutation at all
|
||||
continue
|
||||
if(CM.visual_indicators.len)
|
||||
var/list/mut_overlay = list()
|
||||
if(overlays_standing[CM.layer_used])
|
||||
mut_overlay = overlays_standing[CM.layer_used]
|
||||
var/mutable_appearance/V = CM.get_visual_indicator(src)
|
||||
var/mutable_appearance/V = CM.get_visual_indicator()
|
||||
if(!mut_overlay.Find(V)) //either we lack the visual indicator or we have the wrong one
|
||||
remove_overlay(CM.layer_used)
|
||||
for(var/mutable_appearance/MA in CM.visual_indicators)
|
||||
for(var/mutable_appearance/MA in CM.visual_indicators[CM.type])
|
||||
mut_overlay.Remove(MA)
|
||||
mut_overlay |= V
|
||||
overlays_standing[CM.layer_used] = mut_overlay
|
||||
apply_overlay(CM.layer_used)
|
||||
|
||||
|
||||
/datum/mutation/human/proc/modify() //called when a genome is applied so we can properly update some stats without having to remove and reapply the mutation from someone
|
||||
if(modified || !power || !owner)
|
||||
return
|
||||
power.charge_max *= GET_MUTATION_ENERGY(src)
|
||||
power.charge_counter *= GET_MUTATION_ENERGY(src)
|
||||
modified = TRUE
|
||||
|
||||
/datum/mutation/human/proc/copy_mutation(datum/mutation/human/HM)
|
||||
if(!HM)
|
||||
return
|
||||
chromosome_name = HM.chromosome_name
|
||||
stabilizer_coeff = HM.stabilizer_coeff
|
||||
synchronizer_coeff = HM.synchronizer_coeff
|
||||
power_coeff = HM.power_coeff
|
||||
energy_coeff = HM.energy_coeff
|
||||
mutadone_proof = HM.mutadone_proof
|
||||
can_chromosome = HM.can_chromosome
|
||||
|
||||
/datum/mutation/human/proc/remove_chromosome()
|
||||
stabilizer_coeff = initial(stabilizer_coeff)
|
||||
synchronizer_coeff = initial(synchronizer_coeff)
|
||||
power_coeff = initial(power_coeff)
|
||||
energy_coeff = initial(energy_coeff)
|
||||
mutadone_proof = initial(mutadone_proof)
|
||||
can_chromosome = initial(can_chromosome)
|
||||
chromosome_name = null
|
||||
|
||||
/datum/mutation/human/proc/remove()
|
||||
if(dna)
|
||||
dna.force_lose(src)
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/datum/mutation/human/proc/grant_spell(mob/living/carbon/human/owner)
|
||||
if(!ispath(power) || !owner)
|
||||
return FALSE
|
||||
|
||||
power = new power()
|
||||
power.action_background_icon_state = "bg_tech_blue_on"
|
||||
power.panel = "Genetic"
|
||||
owner.AddSpell(power)
|
||||
return TRUE
|
||||
@@ -0,0 +1,503 @@
|
||||
/datum/mutation/human/telepathy
|
||||
name = "Telepathy"
|
||||
desc = "A rare mutation that allows the user to telepathically communicate to others."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>You can hear your own voice echoing in your mind!</span>"
|
||||
text_lose_indication = "<span class='notice'>You don't hear your mind echo anymore.</span>"
|
||||
difficulty = 12
|
||||
power = /obj/effect/proc_holder/spell/targeted/telepathy/genetic
|
||||
instability = 10
|
||||
energy_coeff = 1
|
||||
|
||||
/datum/mutation/human/telepathy/on_acquiring(mob/living/carbon/human/owner)
|
||||
. = ..()
|
||||
|
||||
/datum/mutation/human/telepathy/on_losing(mob/living/carbon/human/owner)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/telepathy/genetic
|
||||
magic_check = FALSE
|
||||
|
||||
/datum/mutation/human/firebreath
|
||||
name = "Fire Breath"
|
||||
desc = "An ancient mutation that gives lizards breath of fire."
|
||||
quality = POSITIVE
|
||||
difficulty = 12
|
||||
locked = TRUE
|
||||
text_gain_indication = "<span class='notice'>Your throat is burning!</span>"
|
||||
text_lose_indication = "<span class='notice'>Your throat is cooling down.</span>"
|
||||
power = /obj/effect/proc_holder/spell/aimed/firebreath
|
||||
instability = 30
|
||||
energy_coeff = 1
|
||||
power_coeff = 1
|
||||
|
||||
/datum/mutation/human/firebreath/modify()
|
||||
if(power)
|
||||
var/obj/effect/proc_holder/spell/aimed/firebreath/S = power
|
||||
S.strength = 4 + GET_MUTATION_POWER(src)
|
||||
|
||||
/obj/effect/proc_holder/spell/aimed/firebreath
|
||||
name = "Fire Breath"
|
||||
desc = "You can breathe fire at a target."
|
||||
school = "evocation"
|
||||
charge_max = 1200
|
||||
clothes_req = FALSE
|
||||
range = 20
|
||||
base_icon_state = "fireball"
|
||||
action_icon_state = "fireball0"
|
||||
sound = 'sound/magic/demon_dies.ogg' //horrifying lizard noises
|
||||
active_msg = "You built up heat in your mouth."
|
||||
deactive_msg = "You swallow the flame."
|
||||
var/strength = 4
|
||||
|
||||
/obj/effect/proc_holder/spell/aimed/firebreath/before_cast(list/targets)
|
||||
. = ..()
|
||||
if(iscarbon(usr))
|
||||
var/mob/living/carbon/C = usr
|
||||
if(C.is_mouth_covered())
|
||||
C.adjust_fire_stacks(2)
|
||||
C.IgniteMob()
|
||||
to_chat(C,"<span class='warning'>Something in front of your mouth caught fire!</span>")
|
||||
return FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/aimed/firebreath/cast(list/targets, mob/living/user)
|
||||
var/turf/T = user.loc
|
||||
if(!isturf(T))
|
||||
return FALSE
|
||||
firecone(T,user.dir,strength)
|
||||
remove_ranged_ability()
|
||||
charge_counter = 0
|
||||
start_recharge()
|
||||
on_deactivation(user)
|
||||
|
||||
/proc/firecone(loc,dir,length)
|
||||
var/addsides = FALSE
|
||||
var/list/turf/recentturf = list(loc)
|
||||
for (var/i = 0;i < length;i++)
|
||||
var/list/turf/h = list()
|
||||
for (var/turf/g in recentturf)
|
||||
var/frontturf = get_step(g,dir)
|
||||
if (addsides)
|
||||
var/rightturf = get_step(frontturf,turn(dir,90))
|
||||
var/leftturf = get_step(frontturf,turn(dir,270))
|
||||
if (!(rightturf in h))
|
||||
h += rightturf
|
||||
if (!(leftturf in h))
|
||||
h += leftturf
|
||||
if (!(frontturf in h))
|
||||
h += frontturf
|
||||
for (var/turf/j in h)
|
||||
if (j.blocks_air)
|
||||
h -= j
|
||||
continue
|
||||
for (var/obj/o in j)
|
||||
if (o.CanAtmosPass == ATMOS_PASS_PROC ? !o.CanAtmosPass(loc) : !o.CanAtmosPass)
|
||||
h -= j
|
||||
continue
|
||||
for (var/turf/l in h)
|
||||
new /obj/effect/hotspot(l)
|
||||
l.hotspot_expose(700,50,1)
|
||||
sleep(1)
|
||||
recentturf = h
|
||||
addsides = !addsides
|
||||
|
||||
/datum/mutation/human/void
|
||||
name = "Void Magnet"
|
||||
desc = "A rare genome that attracts odd forces not usually observed."
|
||||
quality = MINOR_NEGATIVE //upsides and downsides
|
||||
text_gain_indication = "<span class='notice'>You feel a heavy, dull force just beyond the walls watching you.</span>"
|
||||
instability = 30
|
||||
power = /obj/effect/proc_holder/spell/self/void
|
||||
energy_coeff = 1
|
||||
synchronizer_coeff = 1
|
||||
|
||||
/datum/mutation/human/void/on_life(mob/living/carbon/human/owner)
|
||||
if(!isturf(owner.loc))
|
||||
return
|
||||
if(prob((0.5+((100-dna.stability)/20))) * GET_MUTATION_SYNCHRONIZER(src)) //very rare, but enough to annoy you hopefully. +0.5 probability for every 10 points lost in stability
|
||||
new /obj/effect/immortality_talisman/void(get_turf(owner), owner)
|
||||
|
||||
/obj/effect/proc_holder/spell/self/void
|
||||
name = "Convoke Void" //magic the gathering joke here
|
||||
desc = "A rare genome that attracts odd forces not usually observed. May sometimes pull you in randomly."
|
||||
school = "evocation"
|
||||
clothes_req = FALSE
|
||||
charge_max = 600
|
||||
invocation = "DOOOOOOOOOOOOOOOOOOOOM!!!"
|
||||
invocation_type = "shout"
|
||||
action_icon_state = "void_magnet"
|
||||
var/in_use = FALSE //so it doesnt cast while you are already deep innit
|
||||
|
||||
/obj/effect/proc_holder/spell/self/void/can_cast(mob/user = usr)
|
||||
. = ..()
|
||||
if(!isturf(user.loc))
|
||||
return FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/self/void/cast(mob/user = usr)
|
||||
. = ..()
|
||||
new /obj/effect/immortality_talisman/void(get_turf(user), user)
|
||||
|
||||
/datum/mutation/human/shock
|
||||
name = "Shock Touch"
|
||||
desc = "The affected can channel excess electricity through their hands without shocking themselves, allowing them to shock others."
|
||||
quality = POSITIVE
|
||||
locked = TRUE
|
||||
difficulty = 16
|
||||
text_gain_indication = "<span class='notice'>You feel power flow through your hands.</span>"
|
||||
text_lose_indication = "<span class='notice'>The energy in your hands subsides.</span>"
|
||||
power = /obj/effect/proc_holder/spell/targeted/touch/shock
|
||||
instability = 30
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/touch/shock
|
||||
name = "Shock Touch"
|
||||
desc = "Channel electricity to your hand to shock people with."
|
||||
drawmessage = "You channel electricity into your hand."
|
||||
dropmessage = "You let the electricity from your hand dissipate."
|
||||
hand_path = /obj/item/melee/touch_attack/shock
|
||||
charge_max = 400
|
||||
clothes_req = FALSE
|
||||
action_icon_state = "zap"
|
||||
|
||||
/obj/item/melee/touch_attack/shock
|
||||
name = "\improper shock touch"
|
||||
desc = "This is kind of like when you rub your feet on a shag rug so you can zap your friends, only a lot less safe."
|
||||
catchphrase = null
|
||||
on_use_sound = 'sound/weapons/zapbang.ogg'
|
||||
icon_state = "zapper"
|
||||
item_state = "zapper"
|
||||
|
||||
/obj/item/melee/touch_attack/shock/afterattack(atom/target, mob/living/carbon/user, proximity)
|
||||
if(!proximity || !isliving(target))
|
||||
return
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/C = target
|
||||
if(C.electrocute_act(15, user, 1, stun = 0))//doesnt stun. never let this stun
|
||||
C.dropItemToGround(C.get_active_held_item())
|
||||
C.dropItemToGround(C.get_inactive_held_item())
|
||||
C.confused += 10
|
||||
C.visible_message("<span class='danger'>[user] electrocutes [target]!</span>","<span class='userdanger'>[user] electrocutes you!</span>")
|
||||
return ..()
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] fails to electrocute [target]!</span>")
|
||||
return ..()
|
||||
else if(isliving(target))
|
||||
var/mob/living/L = target
|
||||
L.electrocute_act(15, user, 1, stun = 0)
|
||||
L.visible_message("<span class='danger'>[user] electrocutes [target]!</span>","<span class='userdanger'>[user] electrocutes you!</span>")
|
||||
return ..()
|
||||
else
|
||||
to_chat(user,"<span class='warning'>The electricity doesn't seem to affect [target]...</span>")
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/mutation/human/olfaction
|
||||
name = "Transcendent Olfaction"
|
||||
desc = "Your sense of smell is comparable to that of a canine."
|
||||
quality = POSITIVE
|
||||
difficulty = 12
|
||||
text_gain_indication = "<span class='notice'>Smells begin to make more sense...</span>"
|
||||
text_lose_indication = "<span class='notice'>Your sense of smell goes back to normal.</span>"
|
||||
power = /obj/effect/proc_holder/spell/targeted/olfaction
|
||||
instability = 30
|
||||
synchronizer_coeff = 1
|
||||
var/reek = 200
|
||||
|
||||
/datum/mutation/human/olfaction/modify()
|
||||
if(power)
|
||||
var/obj/effect/proc_holder/spell/targeted/olfaction/S = power
|
||||
S.sensitivity = GET_MUTATION_SYNCHRONIZER(src)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/olfaction
|
||||
name = "Remember the Scent"
|
||||
desc = "Get a scent off of the item you're currently holding to track it. With an empty hand, you'll track the scent you've remembered."
|
||||
charge_max = 100
|
||||
clothes_req = FALSE
|
||||
range = -1
|
||||
include_user = TRUE
|
||||
action_icon_state = "nose"
|
||||
var/mob/living/carbon/tracking_target
|
||||
var/list/mob/living/carbon/possible = list()
|
||||
var/sensitivity = 1
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/olfaction/cast(list/targets, mob/living/user = usr)
|
||||
//can we sniff? is there miasma in the air?
|
||||
var/datum/gas_mixture/air = user.loc.return_air()
|
||||
var/list/cached_gases = air.gases
|
||||
|
||||
if(cached_gases[/datum/gas/miasma])
|
||||
user.adjust_disgust(sensitivity * 45)
|
||||
to_chat(user, "<span class='warning'>With your overly sensitive nose, you get a whiff of stench and feel sick! Try moving to a cleaner area!</span>")
|
||||
return
|
||||
|
||||
var/atom/sniffed = user.get_active_held_item()
|
||||
if(sniffed)
|
||||
var/old_target = tracking_target
|
||||
possible = list()
|
||||
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
|
||||
if(md5(H.dna.uni_identity) in sniffed.fingerprints)
|
||||
possible |= H
|
||||
if(!length(possible))
|
||||
to_chat(user,"<span class='warning'>Despite your best efforts, there are no scents to be found on [sniffed]...</span>")
|
||||
return
|
||||
tracking_target = input(user, "Choose a scent to remember.", "Scent Tracking") as null|anything in sortNames(possible)
|
||||
if(!tracking_target)
|
||||
if(!old_target)
|
||||
to_chat(user,"<span class='warning'>You decide against remembering any scents. Instead, you notice your own nose in your peripheral vision. This goes on to remind you of that one time you started breathing manually and couldn't stop. What an awful day that was.</span>")
|
||||
return
|
||||
tracking_target = old_target
|
||||
on_the_trail(user)
|
||||
return
|
||||
to_chat(user,"<span class='notice'>You pick up the scent of [tracking_target]. The hunt begins.</span>")
|
||||
on_the_trail(user)
|
||||
return
|
||||
|
||||
if(!tracking_target)
|
||||
to_chat(user,"<span class='warning'>You're not holding anything to smell, and you haven't smelled anything you can track. You smell your skin instead; it's kinda salty.</span>")
|
||||
return
|
||||
|
||||
on_the_trail(user)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/olfaction/proc/on_the_trail(mob/living/user)
|
||||
if(!tracking_target)
|
||||
to_chat(user,"<span class='warning'>You're not tracking a scent, but the game thought you were. Something's gone wrong! Report this as a bug.</span>")
|
||||
return
|
||||
if(tracking_target == user)
|
||||
to_chat(user,"<span class='warning'>You smell out the trail to yourself. Yep, it's you.</span>")
|
||||
return
|
||||
if(usr.z < tracking_target.z)
|
||||
to_chat(user,"<span class='warning'>The trail leads... way up above you? Huh. They must be really, really far away.</span>")
|
||||
return
|
||||
else if(usr.z > tracking_target.z)
|
||||
to_chat(user,"<span class='warning'>The trail leads... way down below you? Huh. They must be really, really far away.</span>")
|
||||
return
|
||||
var/direction_text = "[dir2text(get_dir(usr, tracking_target))]"
|
||||
if(direction_text)
|
||||
to_chat(user,"<span class='notice'>You consider [tracking_target]'s scent. The trail leads <b>[direction_text].</b></span>")
|
||||
|
||||
|
||||
/datum/mutation/human/self_amputation
|
||||
name = "Autotomy"
|
||||
desc = "Allows a creature to voluntary discard a random appendage."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>Your joints feel loose.</span>"
|
||||
instability = 30
|
||||
power = /obj/effect/proc_holder/spell/self/self_amputation
|
||||
|
||||
energy_coeff = 1
|
||||
synchronizer_coeff = 1
|
||||
|
||||
/obj/effect/proc_holder/spell/self/self_amputation
|
||||
name = "Drop a limb"
|
||||
desc = "Concentrate to make a random limb pop right off your body."
|
||||
clothes_req = FALSE
|
||||
human_req = FALSE
|
||||
charge_max = 100
|
||||
action_icon_state = "autotomy"
|
||||
|
||||
/obj/effect/proc_holder/spell/self/self_amputation/cast(list/targets, mob/user = usr)
|
||||
if(!iscarbon(user))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/C = user
|
||||
if(HAS_TRAIT(C, TRAIT_NODISMEMBER))
|
||||
return
|
||||
|
||||
var/list/parts = list()
|
||||
for(var/X in C.bodyparts)
|
||||
var/obj/item/bodypart/BP = X
|
||||
if(BP.body_part != HEAD && BP.body_part != CHEST)
|
||||
if(BP.dismemberable)
|
||||
parts += BP
|
||||
if(!parts.len)
|
||||
to_chat(usr, "<span class='notice'>You can't shed any more limbs!</span>")
|
||||
return
|
||||
|
||||
var/obj/item/bodypart/BP = pick(parts)
|
||||
BP.dismember()
|
||||
|
||||
//spider webs
|
||||
/datum/mutation/human/webbing
|
||||
name = "Webbing Production"
|
||||
desc = "Allows the user to lay webbing, and travel through it."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>Your skin feels webby.</span>"
|
||||
instability = 15
|
||||
power = /obj/effect/proc_holder/spell/self/lay_genetic_web
|
||||
|
||||
/obj/effect/proc_holder/spell/self/lay_genetic_web
|
||||
name = "Lay Web"
|
||||
desc = "Drops a web. Only you will be able to traverse your web easily, making it pretty good for keeping you safe."
|
||||
clothes_req = FALSE
|
||||
human_req = FALSE
|
||||
charge_max = 4 SECONDS //the same time to lay a web
|
||||
action_icon = 'icons/mob/actions/actions_genetic.dmi'
|
||||
action_icon_state = "lay_web"
|
||||
|
||||
/obj/effect/proc_holder/spell/self/lay_genetic_web/cast(list/targets, mob/user = usr)
|
||||
var/failed = FALSE
|
||||
if(!isturf(user.loc))
|
||||
to_chat(user, "<span class='warning'>You can't lay webs here!</span>")
|
||||
failed = TRUE
|
||||
var/turf/T = get_turf(user)
|
||||
var/obj/structure/spider/stickyweb/genetic/W = locate() in T
|
||||
if(W)
|
||||
to_chat(user, "<span class='warning'>There's already a web here!</span>")
|
||||
failed = TRUE
|
||||
if(failed)
|
||||
revert_cast(user)
|
||||
return FALSE
|
||||
|
||||
user.visible_message("<span class='notice'>[user] begins to secrete a sticky substance.</span>","<span class='notice'>You begin to lay a web.</span>")
|
||||
if(!do_after(user, 4 SECONDS, target = T))
|
||||
to_chat(user, "<span class='warning'>Your web spinning was interrupted!</span>")
|
||||
return
|
||||
else
|
||||
new /obj/structure/spider/stickyweb/genetic(T, user)
|
||||
|
||||
|
||||
/datum/mutation/human/tongue_spike
|
||||
name = "Tongue Spike"
|
||||
desc = "Allows a creature to voluntary shoot their tongue out as a deadly weapon."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>Your feel like you can throw your voice.</span>"
|
||||
instability = 15
|
||||
power = /obj/effect/proc_holder/spell/self/tongue_spike
|
||||
|
||||
energy_coeff = 1
|
||||
synchronizer_coeff = 1
|
||||
|
||||
/obj/effect/proc_holder/spell/self/tongue_spike
|
||||
name = "Launch spike"
|
||||
desc = "Shoot your tongue out in the direction you're facing, embedding it and dealing damage until they remove it."
|
||||
clothes_req = FALSE
|
||||
human_req = TRUE
|
||||
charge_max = 100
|
||||
action_icon = 'icons/mob/actions/actions_genetic.dmi'
|
||||
action_icon_state = "spike"
|
||||
var/spike_path = /obj/item/hardened_spike
|
||||
|
||||
/obj/effect/proc_holder/spell/self/tongue_spike/cast(list/targets, mob/user = usr)
|
||||
if(!iscarbon(user))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/C = user
|
||||
if(HAS_TRAIT(C, TRAIT_NODISMEMBER))
|
||||
return
|
||||
var/obj/item/organ/tongue/tongue
|
||||
for(var/org in C.internal_organs)
|
||||
if(istype(org, /obj/item/organ/tongue))
|
||||
tongue = org
|
||||
break
|
||||
|
||||
if(!tongue)
|
||||
to_chat(C, "<span class='notice'>You don't have a tongue to shoot!</span>")
|
||||
return
|
||||
|
||||
tongue.Remove(C, special = TRUE)
|
||||
var/obj/item/hardened_spike/spike = new spike_path(get_turf(C), C)
|
||||
tongue.forceMove(spike)
|
||||
spike.throw_at(get_edge_target_turf(C,C.dir), 14, 4, C)
|
||||
|
||||
/obj/item/hardened_spike
|
||||
name = "biomass spike"
|
||||
desc = "Hardened biomass, shaped into a spike. Very pointy!"
|
||||
icon_state = "tonguespike"
|
||||
force = 2
|
||||
throwforce = 15 //15 + 2 (WEIGHT_CLASS_SMALL) * 4 (EMBEDDED_IMPACT_PAIN_MULTIPLIER) = i didnt do the math
|
||||
throw_speed = 4
|
||||
embedding = list("embedded_pain_multiplier" = 4, "embed_chance" = 100, "embedded_fall_chance" = 0)
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
sharpness = IS_SHARP
|
||||
var/mob/living/carbon/human/fired_by
|
||||
|
||||
/obj/item/hardened_spike/Initialize(mapload, firedby)
|
||||
. = ..()
|
||||
fired_by = firedby
|
||||
addtimer(CALLBACK(src, .proc/checkembedded), 5 SECONDS)
|
||||
|
||||
/obj/item/hardened_spike/proc/checkembedded()
|
||||
if(ishuman(loc))
|
||||
var/mob/living/carbon/human/embedtest = loc
|
||||
for(var/l in embedtest.bodyparts)
|
||||
var/obj/item/bodypart/limb = l
|
||||
if(src in limb.embedded_objects)
|
||||
return limb
|
||||
unembedded()
|
||||
|
||||
/obj/item/hardened_spike/unembedded()
|
||||
var/turf/T = get_turf(src)
|
||||
visible_message("<span class='warning'>[src] cracks and twists, changing shape!</span>")
|
||||
for(var/i in contents)
|
||||
var/obj/o = i
|
||||
o.forceMove(T)
|
||||
qdel(src)
|
||||
|
||||
/datum/mutation/human/tongue_spike/chem
|
||||
name = "Chem Spike"
|
||||
desc = "Allows a creature to voluntary shoot their tongue out as biomass, allowing a long range transfer of chemicals."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>Your feel like you can really connect with people by throwing your voice.</span>"
|
||||
instability = 15
|
||||
locked = TRUE
|
||||
power = /obj/effect/proc_holder/spell/self/tongue_spike/chem
|
||||
energy_coeff = 1
|
||||
synchronizer_coeff = 1
|
||||
|
||||
/obj/effect/proc_holder/spell/self/tongue_spike/chem
|
||||
name = "Launch chem spike"
|
||||
desc = "Shoot your tongue out in the direction you're facing, embedding it for a very small amount of damage. While the other person has the spike embedded, you can transfer your chemicals to them."
|
||||
action_icon_state = "spikechem"
|
||||
spike_path = /obj/item/hardened_spike/chem
|
||||
|
||||
/obj/item/hardened_spike/chem
|
||||
name = "chem spike"
|
||||
desc = "Hardened biomass, shaped into... something."
|
||||
icon_state = "tonguespikechem"
|
||||
throwforce = 2 //2 + 2 (WEIGHT_CLASS_SMALL) * 0 (EMBEDDED_IMPACT_PAIN_MULTIPLIER) = i didnt do the math again but very low or smthin
|
||||
embedding = list("embedded_pain_multiplier" = 0, "embed_chance" = 100, "embedded_fall_chance" = 0, "embedded_pain_chance" = 0, "embedded_ignore_throwspeed_threshold" = TRUE) //never hurts once it's in you
|
||||
var/been_places = FALSE
|
||||
var/datum/action/innate/send_chems/chems
|
||||
|
||||
/obj/item/hardened_spike/chem/embedded(mob/living/carbon/human/embedded_mob)
|
||||
if(been_places)
|
||||
return
|
||||
been_places = TRUE
|
||||
chems = new
|
||||
chems.transfered = embedded_mob
|
||||
chems.spikey = src
|
||||
to_chat(fired_by, "<span class='notice'>Link established! Use the \"Transfer Chemicals\" ability to send your chemicals to the linked target!</span>")
|
||||
chems.Grant(fired_by)
|
||||
|
||||
/obj/item/hardened_spike/chem/unembedded()
|
||||
to_chat(fired_by, "<span class='warning'>Link lost!</span>")
|
||||
QDEL_NULL(chems)
|
||||
..()
|
||||
|
||||
/datum/action/innate/send_chems
|
||||
icon_icon = 'icons/mob/actions/actions_genetic.dmi'
|
||||
background_icon_state = "bg_spell"
|
||||
check_flags = AB_CHECK_CONSCIOUS
|
||||
button_icon_state = "spikechemswap"
|
||||
name = "Transfer Chemicals"
|
||||
desc = "Send all of your reagents into whomever the chem spike is embedded in. One use."
|
||||
var/obj/item/hardened_spike/chem/spikey
|
||||
var/mob/living/carbon/human/transfered
|
||||
|
||||
/datum/action/innate/send_chems/Activate()
|
||||
if(!ishuman(transfered) || !ishuman(owner))
|
||||
return
|
||||
var/mob/living/carbon/human/transferer = owner
|
||||
|
||||
to_chat(transfered, "<span class='warning'>You feel a tiny prick!</span>")
|
||||
transferer.reagents.trans_to(transfered, transferer.reagents.total_volume, 1, 1, 0)
|
||||
|
||||
var/obj/item/bodypart/L = spikey.checkembedded()
|
||||
|
||||
L.embedded_objects -= spikey
|
||||
//this is where it would deal damage, if it transfers chems it removes itself so no damage
|
||||
spikey.forceMove(get_turf(L))
|
||||
transfered.visible_message("<span class='notice'>[spikey] falls out of [transfered]!</span>")
|
||||
if(!transfered.has_embedded_objects())
|
||||
transfered.clear_alert("embeddedobject")
|
||||
SEND_SIGNAL(transfered, COMSIG_CLEAR_MOOD_EVENT, "embedded")
|
||||
spikey.unembedded()
|
||||
@@ -0,0 +1,108 @@
|
||||
/datum/mutation/human/antenna
|
||||
name = "Antenna"
|
||||
desc = "The affected person sprouts an antenna. This is known to allow them to access common radio channels passively."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>You feel an antenna sprout from your forehead.</span>"
|
||||
text_lose_indication = "<span class='notice'>Your antenna shrinks back down.</span>"
|
||||
instability = 5
|
||||
difficulty = 8
|
||||
var/obj/item/implant/radio/antenna/linked_radio
|
||||
|
||||
/obj/item/implant/radio/antenna
|
||||
name = "internal antenna organ"
|
||||
desc = "The internal organ part of the antenna. Science has not yet given it a good name."
|
||||
icon = 'icons/obj/radio.dmi'//maybe make a unique sprite later. not important
|
||||
icon_state = "walkietalkie"
|
||||
|
||||
/obj/item/implant/radio/antenna/Initialize(mapload)
|
||||
..()
|
||||
if (radio)
|
||||
radio.name = "internal antenna"
|
||||
|
||||
/datum/mutation/human/antenna/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
linked_radio = new(owner)
|
||||
linked_radio.implant(owner, null, TRUE, TRUE)
|
||||
|
||||
/datum/mutation/human/antenna/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
if(linked_radio)
|
||||
linked_radio.Destroy()
|
||||
|
||||
/datum/mutation/human/antenna/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
|
||||
..()
|
||||
if(!(type in visual_indicators))
|
||||
visual_indicators[type] = list(mutable_appearance('icons/effects/genetics.dmi', "antenna", -FRONT_MUTATIONS_LAYER+1))//-MUTATIONS_LAYER+1
|
||||
|
||||
/datum/mutation/human/antenna/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return visual_indicators[type][1]
|
||||
|
||||
/datum/mutation/human/mindreader
|
||||
name = "Mind Reader"
|
||||
desc = "The affected person can look into the recent memories of others."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>You hear distant voices at the corners of your mind.</span>"
|
||||
text_lose_indication = "<span class='notice'>The distant voices fade.</span>"
|
||||
power = /obj/effect/proc_holder/spell/targeted/mindread
|
||||
instability = 40
|
||||
difficulty = 8
|
||||
locked = TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/mindread
|
||||
name = "Mindread"
|
||||
desc = "Read the target's mind."
|
||||
charge_max = 300
|
||||
range = 7
|
||||
clothes_req = FALSE
|
||||
action_icon_state = "mindread"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/mindread/cast(list/targets, mob/living/carbon/human/user = usr)
|
||||
for(var/mob/living/M in targets)
|
||||
if(usr.anti_magic_check(FALSE, FALSE, TRUE, 0) || M.anti_magic_check(FALSE, FALSE, TRUE, 0))
|
||||
to_chat(usr, "<span class='warning'>As you reach out with your mind, you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.</span>")
|
||||
return
|
||||
if(M.stat == DEAD)
|
||||
to_chat(user, "<span class='boldnotice'>[M] is dead!</span>")
|
||||
return
|
||||
if(M.mind)
|
||||
to_chat(user, "<span class='boldnotice'>You plunge into [M]'s mind...</span>")
|
||||
if(prob(20))
|
||||
to_chat(M, "<span class='danger'>You feel something foreign enter your mind.</span>")//chance to alert the read-ee
|
||||
var/list/recent_speech = list()
|
||||
var/list/say_log = list()
|
||||
var/log_source = M.logging
|
||||
for(var/log_type in log_source)//this whole loop puts the read-ee's say logs into say_log in an easy to access way
|
||||
var/nlog_type = text2num(log_type)
|
||||
if(nlog_type & LOG_SAY)
|
||||
var/list/reversed = log_source[log_type]
|
||||
if(islist(reversed))
|
||||
say_log = reverseRange(reversed.Copy())
|
||||
break
|
||||
if(LAZYLEN(say_log))
|
||||
for(var/spoken_memory in say_log)
|
||||
if(recent_speech.len >= 3)//up to 3 random lines of speech, favoring more recent speech
|
||||
break
|
||||
if(prob(50))
|
||||
recent_speech[spoken_memory] = say_log[spoken_memory]
|
||||
if(recent_speech.len)
|
||||
to_chat(user, "<span class='boldnotice'>You catch some drifting memories of their past conversations...</span>")
|
||||
for(var/spoken_memory in recent_speech)
|
||||
to_chat(user, "<span class='notice'>[recent_speech[spoken_memory]]</span>")
|
||||
if(iscarbon(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
to_chat(user, "<span class='boldnotice'>You find that their intent is to [H.a_intent]...</span>")
|
||||
var/datum/dna/the_dna = H.has_dna()
|
||||
if(the_dna)
|
||||
to_chat(user, "<span class='boldnotice'>You uncover that [H.p_their()] true identity is [the_dna.real_name].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You can't find a mind to read inside of [M]!</span>")
|
||||
|
||||
/datum/mutation/human/mindreader/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
|
||||
..()
|
||||
if(!(type in visual_indicators))
|
||||
visual_indicators[type] = list(mutable_appearance('icons/effects/genetics.dmi', "antenna", -FRONT_MUTATIONS_LAYER+1))
|
||||
|
||||
/datum/mutation/human/mindreader/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return visual_indicators[type][1]
|
||||
+232
-10
@@ -3,16 +3,19 @@
|
||||
//Epilepsy gives a very small chance to have a seizure every life tick, knocking you unconscious.
|
||||
/datum/mutation/human/epilepsy
|
||||
name = "Epilepsy"
|
||||
desc = "A genetic defect that sporadically causes seizures."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You get a headache.</span>"
|
||||
synchronizer_coeff = 1
|
||||
power_coeff = 1
|
||||
|
||||
/datum/mutation/human/epilepsy/on_life(mob/living/carbon/human/owner)
|
||||
if(prob(1) && owner.stat == CONSCIOUS)
|
||||
if(prob(1 * GET_MUTATION_SYNCHRONIZER(src)) && owner.stat == CONSCIOUS)
|
||||
owner.visible_message("<span class='danger'>[owner] starts having a seizure!</span>", "<span class='userdanger'>You have a seizure!</span>")
|
||||
owner.Unconscious(200)
|
||||
owner.Jitter(1000)
|
||||
owner.Unconscious(200 * GET_MUTATION_POWER(src))
|
||||
owner.Jitter(1000 * GET_MUTATION_POWER(src))
|
||||
SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "epilepsy", /datum/mood_event/epilepsy)
|
||||
addtimer(CALLBACK(src, .proc/jitter_less, owner), 90)
|
||||
addtimer(CALLBACK(src, .proc/jitter_less), 90)
|
||||
|
||||
/datum/mutation/human/epilepsy/proc/jitter_less(mob/living/carbon/human/owner)
|
||||
if(owner)
|
||||
@@ -22,19 +25,23 @@
|
||||
//Unstable DNA induces random mutations!
|
||||
/datum/mutation/human/bad_dna
|
||||
name = "Unstable DNA"
|
||||
desc = "Strange mutation that causes the holder to randomly mutate."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel strange.</span>"
|
||||
locked = TRUE
|
||||
|
||||
/datum/mutation/human/bad_dna/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
to_chat(owner, text_gain_indication)
|
||||
var/mob/new_mob
|
||||
if(prob(95))
|
||||
if(prob(50))
|
||||
new_mob = owner.randmutb()
|
||||
new_mob = owner.easy_randmut(NEGATIVE + MINOR_NEGATIVE)
|
||||
else
|
||||
new_mob = owner.randmuti()
|
||||
else
|
||||
new_mob = owner.randmutg()
|
||||
new_mob = owner.easy_randmut(POSITIVE)
|
||||
if(new_mob && ismob(new_mob))
|
||||
owner = new_mob
|
||||
. = owner
|
||||
@@ -44,21 +51,31 @@
|
||||
//Cough gives you a chronic cough that causes you to drop items.
|
||||
/datum/mutation/human/cough
|
||||
name = "Cough"
|
||||
desc = "A chronic cough."
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You start coughing.</span>"
|
||||
synchronizer_coeff = 1
|
||||
power_coeff = 1
|
||||
|
||||
/datum/mutation/human/cough/on_life(mob/living/carbon/human/owner)
|
||||
if(prob(5) && owner.stat == CONSCIOUS)
|
||||
if(prob(5 * GET_MUTATION_SYNCHRONIZER(src)) && owner.stat == CONSCIOUS)
|
||||
owner.drop_all_held_items()
|
||||
owner.emote("cough")
|
||||
|
||||
if(GET_MUTATION_POWER(src) > 1)
|
||||
var/cough_range = GET_MUTATION_POWER(src) * 4
|
||||
var/turf/target = get_ranged_target_turf(owner, turn(owner.dir, 180), cough_range)
|
||||
owner.throw_at(target, cough_range, GET_MUTATION_POWER(src))
|
||||
|
||||
|
||||
//Dwarfism shrinks your body and lets you pass tables.
|
||||
/datum/mutation/human/dwarfism
|
||||
name = "Dwarfism"
|
||||
desc = "A mutation believed to be the cause of dwarfism."
|
||||
quality = POSITIVE
|
||||
get_chance = 15
|
||||
lowest_value = 256 * 12
|
||||
difficulty = 16
|
||||
instability = 5
|
||||
locked = TRUE // Default intert species for now, so locked from regular pool.
|
||||
|
||||
/datum/mutation/human/dwarfism/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
@@ -78,6 +95,7 @@
|
||||
//Clumsiness has a very large amount of small drawbacks depending on item.
|
||||
/datum/mutation/human/clumsy
|
||||
name = "Clumsiness"
|
||||
desc = "A genome that inhibits certain brain functions, causing the holder to appear clumsy. Honk"
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel lightheaded.</span>"
|
||||
|
||||
@@ -95,11 +113,13 @@
|
||||
//Tourettes causes you to randomly stand in place and shout.
|
||||
/datum/mutation/human/tourettes
|
||||
name = "Tourette's Syndrome"
|
||||
desc = "A chronic twitch that forces the user to use colorful language."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You twitch.</span>"
|
||||
synchronizer_coeff = 1
|
||||
|
||||
/datum/mutation/human/tourettes/on_life(mob/living/carbon/human/owner)
|
||||
if(prob(10) && owner.stat == CONSCIOUS && !owner.IsStun())
|
||||
if(prob(10 * GET_MUTATION_SYNCHRONIZER(src)) && owner.stat == CONSCIOUS && !owner.IsStun())
|
||||
owner.Stun(200)
|
||||
switch(rand(1, 3))
|
||||
if(1)
|
||||
@@ -117,6 +137,7 @@
|
||||
//Deafness makes you deaf.
|
||||
/datum/mutation/human/deaf
|
||||
name = "Deafness"
|
||||
desc = "The holder of this genome is completely deaf."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You can't seem to hear anything.</span>"
|
||||
|
||||
@@ -134,8 +155,10 @@
|
||||
//Monified turns you into a monkey.
|
||||
/datum/mutation/human/race
|
||||
name = "Monkified"
|
||||
desc = "A strange genome, believing to be what differentiates monkeys from humans."
|
||||
quality = NEGATIVE
|
||||
time_coeff = 2
|
||||
locked = TRUE //Species specific, keep out of actual gene pool
|
||||
|
||||
/datum/mutation/human/race/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
@@ -145,3 +168,202 @@
|
||||
/datum/mutation/human/race/on_losing(mob/living/carbon/monkey/owner)
|
||||
if(owner && istype(owner) && owner.stat != DEAD && (owner.dna.mutations.Remove(src)))
|
||||
. = owner.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
|
||||
|
||||
|
||||
/datum/mutation/human/glow
|
||||
name = "Glowy"
|
||||
desc = "You permanently emit a light with a random color and intensity."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>Your skin begins to glow softly.</span>"
|
||||
instability = 5
|
||||
var/obj/effect/dummy/luminescent_glow/glowth //shamelessly copied from luminescents
|
||||
var/glow = 1.5
|
||||
power_coeff = 1
|
||||
|
||||
/datum/mutation/human/glow/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
glowth = new(owner)
|
||||
glowth.set_light(glow, glow, dna.features["mcolor"])
|
||||
|
||||
/datum/mutation/human/glow/modify(mob/living/carbon/human/owner)
|
||||
if(glowth)
|
||||
glowth.set_light(glow + GET_MUTATION_POWER(src) , glow + GET_MUTATION_POWER(src), dna.features["mcolor"])
|
||||
|
||||
/datum/mutation/human/glow/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
qdel(glowth)
|
||||
|
||||
/datum/mutation/human/strong
|
||||
name = "Strength"
|
||||
desc = "The user's muscles slightly expand."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>You feel strong.</span>"
|
||||
difficulty = 16
|
||||
|
||||
/datum/mutation/human/fire
|
||||
name = "Fiery Sweat"
|
||||
desc = "The user's skin will randomly combust, but is generally alot more resilient to burning."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='warning'>You feel hot.</span>"
|
||||
text_lose_indication = "<span class'notice'>You feel a lot cooler.</span>"
|
||||
difficulty = 14
|
||||
synchronizer_coeff = 1
|
||||
power_coeff = 1
|
||||
|
||||
/datum/mutation/human/fire/on_life(mob/living/carbon/human/owner)
|
||||
if(prob((1+(100-dna.stability)/10)) * GET_MUTATION_SYNCHRONIZER(src))
|
||||
owner.adjust_fire_stacks(2 * GET_MUTATION_POWER(src))
|
||||
owner.IgniteMob()
|
||||
|
||||
/datum/mutation/human/fire/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.physiology.burn_mod *= 0.5
|
||||
|
||||
/datum/mutation/human/fire/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.physiology.burn_mod *= 2
|
||||
|
||||
/datum/mutation/human/insulated
|
||||
name = "Insulated"
|
||||
desc = "The affected person does not conduct electricity."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>Your fingertips go numb.</span>"
|
||||
text_lose_indication = "<span class='notice'>Your fingertips regain feeling.</span>"
|
||||
difficulty = 16
|
||||
instability = 25
|
||||
|
||||
/datum/mutation/human/insulated/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, "genetics")
|
||||
|
||||
/datum/mutation/human/insulated/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, "genetics")
|
||||
|
||||
|
||||
/datum/mutation/human/glow/anti
|
||||
name = "Anti-Glow"
|
||||
desc = "Your skin seems to attract and absorb nearby light creating 'darkness' around you."
|
||||
text_gain_indication = "<span class='notice'>Your light around you seems to disappear.</span>"
|
||||
glow = -3.5 //Slightly stronger, since negating light tends to be harder than making it.
|
||||
locked = TRUE
|
||||
|
||||
/datum/mutation/human/stimmed
|
||||
name = "Stimmed"
|
||||
desc = "The user's chemical balance is more robust."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>You feel stimmed.</span>"
|
||||
difficulty = 16
|
||||
|
||||
/datum/mutation/human/paranoia
|
||||
name = "Paranoia"
|
||||
desc = "Subject is easily terrified, and may suffer from hallucinations."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel screams echo through your mind...</span>"
|
||||
text_lose_indication = "<span class'notice'>The screaming in your mind fades.</span>"
|
||||
|
||||
/datum/mutation/human/paranoia/on_life(mob/living/carbon/human/owner)
|
||||
if(prob(5) && owner.stat == CONSCIOUS)
|
||||
owner.emote("scream")
|
||||
owner.jitteriness = min(max(0, owner.jitteriness + 5), 30)
|
||||
if(prob(25))
|
||||
to_chat(owner,"<span class='warning'>You feel someone creeping in on you...</span>")
|
||||
owner.hallucination += 20
|
||||
|
||||
|
||||
/datum/mutation/human/badblink
|
||||
name = "Spatial Instability"
|
||||
desc = "The victim of the mutation has a very weak link to spatial reality, and may be displaced. Often causes extreme nausea."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='warning'>The space around you twists sickeningly.</span>"
|
||||
text_lose_indication = "<span class'notice'>The space around you settles back to normal.</span>"
|
||||
difficulty = 18//high so it's hard to unlock and abuse
|
||||
instability = 10
|
||||
synchronizer_coeff = 1
|
||||
energy_coeff = 1
|
||||
power_coeff = 1
|
||||
var/warpchance = 0
|
||||
|
||||
/datum/mutation/human/badblink/on_life()
|
||||
if (!owner)
|
||||
return
|
||||
if(prob(warpchance))
|
||||
var/warpmessage = pick(
|
||||
"<span class='warning'>With a sickening 720-degree twist of [owner.p_their()] back, [owner] vanishes into thin air.</span>",
|
||||
"<span class='warning'>[owner] does some sort of strange backflip into another dimension. It looks pretty painful.</span>",
|
||||
"<span class='warning'>[owner] does a jump to the left, a step to the right, and warps out of reality.</span>",
|
||||
"<span class='warning'>[owner]'s torso starts folding inside out until it vanishes from reality, taking [owner] with it.</span>",
|
||||
"<span class='warning'>One moment, you see [owner]. The next, [owner] is gone.</span>")
|
||||
owner.visible_message(warpmessage, "<span class='userdanger'>You feel a wave of nausea as you fall through reality!</span>")
|
||||
var/warpdistance = rand(10,15) * GET_MUTATION_POWER(src)
|
||||
do_teleport(owner, get_turf(owner), warpdistance, channel = TELEPORT_CHANNEL_FREE)
|
||||
owner.adjust_disgust(GET_MUTATION_SYNCHRONIZER(src) * (warpchance * warpdistance))
|
||||
warpchance = 0
|
||||
owner.visible_message("<span class='danger'>[owner] appears out of nowhere!</span>")
|
||||
else
|
||||
warpchance += 0.25 * GET_MUTATION_ENERGY(src)
|
||||
|
||||
/datum/mutation/human/acidflesh
|
||||
name = "Acidic Flesh"
|
||||
desc = "Subject has acidic chemicals building up underneath the skin. This is often lethal."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='userdanger'>A horrible burning sensation envelops you as your flesh turns to acid!</span>"
|
||||
text_lose_indication = "<span class'notice'>A feeling of relief fills you as your flesh goes back to normal.</span>"
|
||||
difficulty = 18//high so it's hard to unlock and use on others
|
||||
var/msgcooldown = 0
|
||||
|
||||
/datum/mutation/human/acidflesh/on_life()
|
||||
if(prob(25))
|
||||
if(world.time > msgcooldown)
|
||||
to_chat(owner, "<span class='danger'>Your acid flesh bubbles...</span>")
|
||||
msgcooldown = world.time + 200
|
||||
if(prob(15))
|
||||
owner.acid_act(rand(30,50), 10)
|
||||
owner.visible_message("<span class='warning'>[owner]'s skin bubbles and pops.</span>", "<span class='userdanger'>Your bubbling flesh pops! It burns!</span>")
|
||||
playsound(owner,'sound/weapons/sear.ogg', 50, TRUE)
|
||||
|
||||
/datum/mutation/human/gigantism
|
||||
name = "Gigantism"//negative version of dwarfism
|
||||
desc = "The cells within the subject spread out to cover more area, making the subject appear larger."
|
||||
quality = MINOR_NEGATIVE
|
||||
difficulty = 12
|
||||
|
||||
/datum/mutation/human/gigantism/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.resize = 1.25
|
||||
owner.update_transform()
|
||||
owner.visible_message("<span class='danger'>[owner] suddenly grows!</span>", "<span class='notice'>Everything around you seems to shrink..</span>")
|
||||
|
||||
/datum/mutation/human/gigantism/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.resize = 0.8
|
||||
owner.update_transform()
|
||||
owner.visible_message("<span class='danger'>[owner] suddenly shrinks!</span>", "<span class='notice'>Everything around you seems to grow..</span>")
|
||||
|
||||
/datum/mutation/human/spastic
|
||||
name = "Spastic"
|
||||
desc = "Subject suffers from muscle spasms."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='warning'>You flinch.</span>"
|
||||
text_lose_indication = "<span class'notice'>Your flinching subsides.</span>"
|
||||
difficulty = 16
|
||||
|
||||
/datum/mutation/human/spastic/on_acquiring()
|
||||
if(..())
|
||||
return
|
||||
if (owner)
|
||||
owner.apply_status_effect(STATUS_EFFECT_SPASMS)
|
||||
|
||||
/datum/mutation/human/spastic/on_losing()
|
||||
if(..())
|
||||
return
|
||||
if (owner)
|
||||
owner.remove_status_effect(STATUS_EFFECT_SPASMS)
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
//Chameleon causes the owner to slowly become transparent when not moving.
|
||||
/datum/mutation/human/chameleon
|
||||
name = "Chameleon"
|
||||
desc = "A genome that causes the holder's skin to become transparent over time."
|
||||
quality = POSITIVE
|
||||
get_chance = 20
|
||||
lowest_value = 256 * 12
|
||||
difficulty = 16
|
||||
text_gain_indication = "<span class='notice'>You feel one with your surroundings.</span>"
|
||||
text_lose_indication = "<span class='notice'>You feel oddly exposed.</span>"
|
||||
time_coeff = 5
|
||||
instability = 25
|
||||
|
||||
/datum/mutation/human/chameleon/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/datum/mutation/human/geladikinesis
|
||||
name = "Geladikinesis"
|
||||
desc = "Allows the user to concentrate moisture and sub-zero forces into snow."
|
||||
quality = POSITIVE
|
||||
text_gain_indication = "<span class='notice'>Your hand feels cold.</span>"
|
||||
instability = 10
|
||||
difficulty = 10
|
||||
synchronizer_coeff = 1
|
||||
power = /obj/effect/proc_holder/spell/targeted/conjure_item/snow
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/conjure_item/snow
|
||||
name = "Create Snow"
|
||||
desc = "Concentrates cryokinetic forces to create snow, useful for snow-like construction."
|
||||
item_type = /obj/item/stack/sheet/mineral/snow
|
||||
charge_max = 50
|
||||
action_icon_state = "snow"
|
||||
delete_old = FALSE
|
||||
|
||||
|
||||
/datum/mutation/human/cryokinesis
|
||||
name = "Cryokinesis"
|
||||
desc = "Draws negative energy from the sub-zero void to freeze surrounding temperatures at subject's will."
|
||||
quality = POSITIVE //upsides and downsides
|
||||
text_gain_indication = "<span class='notice'>Your hand feels cold.</span>"
|
||||
instability = 20
|
||||
difficulty = 12
|
||||
synchronizer_coeff = 1
|
||||
power = /obj/effect/proc_holder/spell/aimed/cryo
|
||||
|
||||
/obj/effect/proc_holder/spell/aimed/cryo
|
||||
name = "Cryobeam"
|
||||
desc = "This power fires a frozen bolt at a target."
|
||||
charge_max = 150
|
||||
cooldown_min = 150
|
||||
clothes_req = FALSE
|
||||
range = 3
|
||||
projectile_type = /obj/item/projectile/temp/cryo
|
||||
base_icon_state = "icebeam"
|
||||
action_icon_state = "icebeam"
|
||||
active_msg = "You focus your cryokinesis!"
|
||||
deactive_msg = "You relax."
|
||||
active = FALSE
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
//Cold Resistance gives your entire body an orange halo, and makes you immune to the effects of vacuum and cold.
|
||||
/datum/mutation/human/cold_resistance
|
||||
name = "Cold Resistance"
|
||||
quality = POSITIVE
|
||||
get_chance = 25
|
||||
lowest_value = 256 * 12
|
||||
text_gain_indication = "<span class='notice'>Your body feels warm!</span>"
|
||||
time_coeff = 5
|
||||
|
||||
/datum/mutation/human/cold_resistance/New()
|
||||
..()
|
||||
visual_indicators |= mutable_appearance('icons/effects/genetics.dmi', "fire", -MUTATIONS_LAYER)
|
||||
|
||||
/datum/mutation/human/cold_resistance/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return visual_indicators[1]
|
||||
|
||||
/datum/mutation/human/cold_resistance/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
ADD_TRAIT(owner, TRAIT_RESISTCOLD, "cold_resistance")
|
||||
// ADD_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "cold_resistance") CITADEL CHANGE
|
||||
|
||||
/datum/mutation/human/cold_resistance/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
REMOVE_TRAIT(owner, TRAIT_RESISTCOLD, "cold_resistance")
|
||||
// REMOVE_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "cold_resistance") CITADEL CHANGE
|
||||
|
||||
/datum/mutation/human/cold_resistance/on_life(mob/living/carbon/human/owner)
|
||||
if(owner.getFireLoss())
|
||||
if(prob(1))
|
||||
owner.heal_bodypart_damage(0,1) //Is this really needed?
|
||||
@@ -0,0 +1,32 @@
|
||||
/datum/generecipe
|
||||
var/required = "" //it hurts so bad but initial is not compatible with lists
|
||||
var/result = null
|
||||
|
||||
/proc/get_mixed_mutation(mutation1, mutation2)
|
||||
if(!mutation1 || !mutation2)
|
||||
return FALSE
|
||||
if(mutation1 == mutation2) //this could otherwise be bad
|
||||
return FALSE
|
||||
for(var/A in GLOB.mutation_recipes)
|
||||
if(findtext(A, "[mutation1]") && findtext(A, "[mutation2]"))
|
||||
return GLOB.mutation_recipes[A]
|
||||
|
||||
/datum/generecipe/x_ray
|
||||
required = "/datum/mutation/human/thermal; /datum/mutation/human/radioactive"
|
||||
result = /datum/mutation/human/thermal/x_ray
|
||||
|
||||
/datum/generecipe/shock
|
||||
required = "/datum/mutation/human/insulated; /datum/mutation/human/radioactive"
|
||||
result = SHOCKTOUCH
|
||||
|
||||
/datum/generecipe/mindread
|
||||
required = "/datum/mutation/human/antenna; /datum/mutation/human/paranoia"
|
||||
result = MINDREAD
|
||||
|
||||
/datum/generecipe/antiglow
|
||||
required = "/datum/mutation/human/glow; /datum/mutation/human/void"
|
||||
result = ANTIGLOWY
|
||||
|
||||
/datum/generecipe/tonguechem
|
||||
required = "/datum/mutation/human/tongue_spike; /datum/mutation/human/stimmed"
|
||||
result = TONGUESPIKECHEM
|
||||
@@ -1,11 +1,13 @@
|
||||
//Hulk turns your skin green, and allows you to punch through walls.
|
||||
/datum/mutation/human/hulk
|
||||
name = "Hulk"
|
||||
desc = "A poorly understood genome that causes the holder's muscles to expand, inhibit speech and gives the person a bad skin condition."
|
||||
quality = POSITIVE
|
||||
get_chance = 15
|
||||
lowest_value = 256 * 12
|
||||
locked = TRUE
|
||||
difficulty = 16
|
||||
text_gain_indication = "<span class='notice'>Your muscles hurt!</span>"
|
||||
health_req = 25
|
||||
instability = 40
|
||||
|
||||
/datum/mutation/human/hulk/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
@@ -17,7 +19,7 @@
|
||||
SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "hulk", /datum/mood_event/hulk)
|
||||
RegisterSignal(owner, COMSIG_MOB_SAY, .proc/handle_speech)
|
||||
|
||||
/datum/mutation/human/hulk/on_attack_hand(mob/living/carbon/human/owner, atom/target, proximity)
|
||||
/datum/mutation/human/hulk/on_attack_hand(mob/living/carbon/human/owner,atom/target, proximity)
|
||||
if(proximity) //no telekinetic hulk attack
|
||||
return target.attack_hulk(owner)
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/datum/mutation/human/radioactive
|
||||
name = "Radioactivity"
|
||||
desc = "A volatile mutation that causes the host to sent out deadly beta radiation. This affects both the hosts and their surroundings."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='warning'>You can feel it in your bones!</span>"
|
||||
time_coeff = 5
|
||||
instability = 5
|
||||
difficulty = 8
|
||||
|
||||
/datum/mutation/human/radioactive/on_life(mob/living/carbon/human/owner)
|
||||
radiation_pulse(owner, 20)
|
||||
|
||||
/datum/mutation/human/radioactive/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
|
||||
..()
|
||||
if(!(type in visual_indicators))
|
||||
visual_indicators[type] = list(mutable_appearance('icons/effects/genetics.dmi', "radiation", -MUTATIONS_LAYER))
|
||||
|
||||
/datum/mutation/human/radioactive/get_visual_indicator()
|
||||
return visual_indicators[type][1]
|
||||
@@ -1,6 +1,7 @@
|
||||
//Nearsightedness restricts your vision by several tiles.
|
||||
/datum/mutation/human/nearsight
|
||||
name = "Near Sightness"
|
||||
desc = "The holder of this mutation has poor eyesight."
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You can't see very well.</span>"
|
||||
|
||||
@@ -18,6 +19,7 @@
|
||||
//Blind makes you blind. Who knew?
|
||||
/datum/mutation/human/blind
|
||||
name = "Blindness"
|
||||
desc = "Renders the subject completely blind."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You can't seem to see anything.</span>"
|
||||
|
||||
@@ -32,43 +34,58 @@
|
||||
owner.cure_blind(GENETIC_MUTATION)
|
||||
|
||||
|
||||
//X-ray Vision lets you see through walls.
|
||||
/datum/mutation/human/x_ray
|
||||
name = "X Ray Vision"
|
||||
///Thermal Vision lets you see mobs through walls
|
||||
/datum/mutation/human/thermal
|
||||
name = "Thermal Vision"
|
||||
desc = "The user of this genome can visually percieve the unique human thermal signature."
|
||||
quality = POSITIVE
|
||||
get_chance = 25
|
||||
lowest_value = 256 * 12
|
||||
text_gain_indication = "<span class='notice'>The walls suddenly disappear!</span>"
|
||||
difficulty = 18
|
||||
text_gain_indication = "<span class='notice'>You can see the heat rising off of your skin...</span>"
|
||||
time_coeff = 2
|
||||
instability = 25
|
||||
var/visionflag = TRAIT_THERMAL_VISION
|
||||
|
||||
/datum/mutation/human/x_ray/on_acquiring(mob/living/carbon/human/owner)
|
||||
/datum/mutation/human/thermal/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
|
||||
ADD_TRAIT(owner, visionflag, GENETIC_MUTATION)
|
||||
owner.update_sight()
|
||||
|
||||
/datum/mutation/human/x_ray/on_losing(mob/living/carbon/human/owner)
|
||||
/datum/mutation/human/thermal/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
REMOVE_TRAIT(owner, visionflag, GENETIC_MUTATION)
|
||||
owner.update_sight()
|
||||
|
||||
///X-ray Vision lets you see through walls.
|
||||
/datum/mutation/human/thermal/x_ray
|
||||
name = "X Ray Vision"
|
||||
desc = "A strange genome that allows the user to see between the spaces of walls." //actual x-ray would mean you'd constantly be blasting rads, wich might be fun for later //hmb
|
||||
text_gain_indication = "<span class='notice'>The walls suddenly disappear!</span>"
|
||||
instability = 35
|
||||
locked = TRUE
|
||||
visionflag = TRAIT_XRAY_VISION
|
||||
|
||||
|
||||
//Laser Eyes lets you shoot lasers from your eyes!
|
||||
/datum/mutation/human/laser_eyes
|
||||
name = "Laser Eyes"
|
||||
desc = "Reflects concentrated light back from the eyes."
|
||||
quality = POSITIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
locked = TRUE
|
||||
difficulty = 16
|
||||
text_gain_indication = "<span class='notice'>You feel pressure building up behind your eyes.</span>"
|
||||
layer_used = FRONT_MUTATIONS_LAYER
|
||||
limb_req = BODY_ZONE_HEAD
|
||||
|
||||
/datum/mutation/human/laser_eyes/New()
|
||||
/datum/mutation/human/laser_eyes/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
|
||||
..()
|
||||
visual_indicators |= mutable_appearance('icons/effects/genetics.dmi', "lasereyes", -FRONT_MUTATIONS_LAYER)
|
||||
|
||||
/datum/mutation/human/laser_eyes/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
/datum/mutation/human/laser_eyes/get_visual_indicator()
|
||||
return visual_indicators[1]
|
||||
|
||||
/datum/mutation/human/laser_eyes/on_ranged_attack(mob/living/carbon/human/owner, atom/target, mouseparams)
|
||||
/datum/mutation/human/laser_eyes/on_ranged_attack(atom/target, mouseparams)
|
||||
if(owner.a_intent == INTENT_HARM)
|
||||
owner.LaserEyes(target, mouseparams)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
//Cold Resistance gives your entire body an orange halo, and makes you immune to the effects of vacuum and cold.
|
||||
/datum/mutation/human/space_adaptation
|
||||
name = "Space Adaptation"
|
||||
desc = "A strange mutation that renders the host immune to the vacuum if space. Will still need an oxygen supply."
|
||||
quality = POSITIVE
|
||||
difficulty = 16
|
||||
text_gain_indication = "<span class='notice'>Your body feels warm!</span>"
|
||||
time_coeff = 5
|
||||
instability = 30
|
||||
|
||||
/datum/mutation/human/space_adaptation/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
|
||||
..()
|
||||
if(!(type in visual_indicators))
|
||||
visual_indicators[type] = list(mutable_appearance('icons/effects/genetics.dmi', "fire", -MUTATIONS_LAYER))
|
||||
|
||||
/datum/mutation/human/space_adaptation/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return visual_indicators[type][1]
|
||||
|
||||
/datum/mutation/human/space_adaptation/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
ADD_TRAIT(owner, TRAIT_RESISTCOLD, "cold_resistance")
|
||||
ADD_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "cold_resistance")
|
||||
|
||||
/datum/mutation/human/space_adaptation/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
REMOVE_TRAIT(owner, TRAIT_RESISTCOLD, "cold_resistance")
|
||||
REMOVE_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "cold_resistance")
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
/datum/mutation/human/nervousness
|
||||
name = "Nervousness"
|
||||
desc = "Causes the holder to stutter."
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel nervous.</span>"
|
||||
|
||||
@@ -13,6 +14,7 @@
|
||||
|
||||
/datum/mutation/human/wacky
|
||||
name = "Wacky"
|
||||
desc = "<span class='sans'>Unknown.</span>"
|
||||
quality = MINOR_NEGATIVE
|
||||
text_gain_indication = "<span class='sans'>You feel an off sensation in your voicebox.</span>"
|
||||
text_lose_indication = "<span class='notice'>The off sensation passes.</span>"
|
||||
@@ -34,6 +36,7 @@
|
||||
|
||||
/datum/mutation/human/mute
|
||||
name = "Mute"
|
||||
desc = "Completely inhibits the vocal section of the brain."
|
||||
quality = NEGATIVE
|
||||
text_gain_indication = "<span class='danger'>You feel unable to express yourself at all.</span>"
|
||||
text_lose_indication = "<span class='danger'>You feel able to speak freely again.</span>"
|
||||
@@ -53,8 +56,8 @@
|
||||
|
||||
/datum/mutation/human/smile
|
||||
name = "Smile"
|
||||
desc = "Causes the user to be in constant mania."
|
||||
quality = MINOR_NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='notice'>You feel so happy. Nothing can be wrong with anything. :)</span>"
|
||||
text_lose_indication = "<span class='notice'>Everything is terrible again. :(</span>"
|
||||
|
||||
@@ -95,7 +98,6 @@
|
||||
message = replacetext(message," ugly "," beautiful ")
|
||||
message = replacetext(message," douchbag "," nice guy ")
|
||||
message = replacetext(message," whore "," lady ")
|
||||
message = replacetext(message," gamer "," intellectual ")
|
||||
message = replacetext(message," nerd "," smarty pants ")
|
||||
message = replacetext(message," moron "," fun person ")
|
||||
message = replacetext(message," IT'S LOOSE "," EVERYTHING IS FINE ")
|
||||
@@ -121,8 +123,8 @@
|
||||
|
||||
/datum/mutation/human/unintelligible
|
||||
name = "Unintelligible"
|
||||
desc = "Partially inhibits the vocal center of the brain, severely distorting speech."
|
||||
quality = NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='danger'>You can't seem to form any coherent thoughts!</span>"
|
||||
text_lose_indication = "<span class='danger'>Your mind feels more clear.</span>"
|
||||
|
||||
@@ -141,8 +143,9 @@
|
||||
|
||||
/datum/mutation/human/swedish
|
||||
name = "Swedish"
|
||||
desc = "A horrible mutation originating from the distant past. Thought to be eradicated after the incident in 2037."
|
||||
quality = MINOR_NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
locked = TRUE
|
||||
text_gain_indication = "<span class='notice'>You feel Swedish, however that works.</span>"
|
||||
text_lose_indication = "<span class='notice'>The feeling of Swedishness passes.</span>"
|
||||
|
||||
@@ -173,8 +176,8 @@
|
||||
|
||||
/datum/mutation/human/chav
|
||||
name = "Chav"
|
||||
desc = "Unknown"
|
||||
quality = MINOR_NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
text_gain_indication = "<span class='notice'>Ye feel like a reet prat like, innit?</span>"
|
||||
text_lose_indication = "<span class='notice'>You no longer feel like being rude and sassy.</span>"
|
||||
|
||||
@@ -220,12 +223,13 @@
|
||||
|
||||
/datum/mutation/human/elvis
|
||||
name = "Elvis"
|
||||
desc = "A terrifying mutation named after its 'patient-zero'."
|
||||
quality = MINOR_NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
locked = TRUE
|
||||
text_gain_indication = "<span class='notice'>You feel pretty good, honeydoll.</span>"
|
||||
text_lose_indication = "<span class='notice'>You feel a little less conversation would be great.</span>"
|
||||
|
||||
/datum/mutation/human/elvis/on_life(mob/living/carbon/human/owner)
|
||||
/datum/mutation/human/elvis/on_life()
|
||||
switch(pick(1,2))
|
||||
if(1)
|
||||
if(prob(15))
|
||||
@@ -266,8 +270,9 @@
|
||||
|
||||
/datum/mutation/human/stoner
|
||||
name = "Stoner"
|
||||
desc = "A common mutation that severely decreases intelligence."
|
||||
quality = NEGATIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
locked = TRUE
|
||||
text_gain_indication = "<span class='notice'>You feel...totally chill, man!</span>"
|
||||
text_lose_indication = "<span class='notice'>You feel like you have a better sense of time.</span>"
|
||||
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
//Telekinesis lets you interact with objects from range, and gives you a light blue halo around your head.
|
||||
/datum/mutation/human/telekinesis
|
||||
name = "Telekinesis"
|
||||
desc = "A strange mutation that allows the holder to interact with objects through thought."
|
||||
quality = POSITIVE
|
||||
get_chance = 20
|
||||
lowest_value = 256 * 12
|
||||
difficulty = 18
|
||||
text_gain_indication = "<span class='notice'>You feel smarter!</span>"
|
||||
limb_req = BODY_ZONE_HEAD
|
||||
instability = 30
|
||||
|
||||
/datum/mutation/human/telekinesis/New()
|
||||
/datum/mutation/human/telekinesis/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
|
||||
..()
|
||||
visual_indicators |= mutable_appearance('icons/effects/genetics.dmi', "telekinesishead", -MUTATIONS_LAYER)
|
||||
if(!(type in visual_indicators))
|
||||
visual_indicators[type] = list(mutable_appearance('icons/effects/genetics.dmi', "telekinesishead", -MUTATIONS_LAYER))
|
||||
|
||||
/datum/mutation/human/telekinesis/get_visual_indicator(mob/living/carbon/human/owner)
|
||||
return visual_indicators[1]
|
||||
return visual_indicators[type][1]
|
||||
|
||||
/datum/mutation/human/telekinesis/on_ranged_attack(mob/living/carbon/human/owner, atom/target)
|
||||
target.attack_tk(owner)
|
||||
target.attack_tk(owner)
|
||||
@@ -11,7 +11,7 @@
|
||||
/datum/progressbar/New(mob/User, goal_number, atom/target)
|
||||
. = ..()
|
||||
if (!istype(target))
|
||||
EXCEPTION("Invalid target given")
|
||||
CRASH("Invalid target given")
|
||||
if (goal_number)
|
||||
goal = goal_number
|
||||
bar = image('icons/effects/progessbar.dmi', target, "prog_bar_0", HUD_LAYER)
|
||||
|
||||
@@ -322,3 +322,70 @@
|
||||
suffix = "advancedlab.dmm"
|
||||
name = "Abductor Replication Lab"
|
||||
description = "Some scientists tried and almost succeeded to recreate abductor tools. Somewhat slower and a bit less modern than their originals, these tools are the best you can get if you aren't an alien."
|
||||
|
||||
//Space ruins for the station z
|
||||
/datum/map_template/ruin/spacenearstation
|
||||
prefix = "_maps/RandomRuins/SpaceRuinsStation/"
|
||||
cost = 1
|
||||
allow_duplicates = FALSE
|
||||
|
||||
/datum/map_template/ruin/spacenearstation/roid1
|
||||
id = "roid1"
|
||||
suffix = "roid1.dmm"
|
||||
name = "Mineable Asteroid 1"
|
||||
description = "Mineral asteroid 1."
|
||||
allow_duplicates = TRUE
|
||||
|
||||
/datum/map_template/ruin/spacenearstation/roid2
|
||||
id = "roid2"
|
||||
suffix = "roid2.dmm"
|
||||
name = "Crab Roid"
|
||||
description = "Mineral asteroid. Ft. Crabs."
|
||||
|
||||
/datum/map_template/ruin/spacenearstation/roid3
|
||||
id = "roid3"
|
||||
suffix = "roid3.dmm"
|
||||
name = "Dorm Roid"
|
||||
description = "Mineral asteroid. Ft. Dorm."
|
||||
|
||||
/datum/map_template/ruin/spacenearstation/roid4
|
||||
id = "roid4"
|
||||
suffix = "roid4.dmm"
|
||||
name = "Mineable Asteroid 2"
|
||||
description = "Mineral asteroid 2."
|
||||
|
||||
/datum/map_template/ruin/spacenearstation/roid5
|
||||
id = "roid5"
|
||||
suffix = "roid5.dmm"
|
||||
name = "Mineable Asteroid 3"
|
||||
description = "Mineral asteroid. Ft. Holofans."
|
||||
|
||||
/datum/map_template/ruin/spacenearstation/roid6
|
||||
id = "roid6"
|
||||
suffix = "roid6.dmm"
|
||||
name = "Mineable Asteroid 4"
|
||||
description = "Mineral asteroid. Ft. Crashed escape pod."
|
||||
|
||||
/datum/map_template/ruin/spacenearstation/roid7
|
||||
id = "roid7"
|
||||
suffix = "roid7.dmm"
|
||||
name = "Mineable Asteroid 5"
|
||||
description = "Mineral asteroid. Ft. Derelict space bar."
|
||||
|
||||
/datum/map_template/ruin/spacenearstation/roid8
|
||||
id = "roid8"
|
||||
suffix = "roid8.dmm"
|
||||
name = "Dead wizard Roid"
|
||||
description = "Mineral asteroid. Ft. Dead wizard and toilet paradox bag."
|
||||
|
||||
/datum/map_template/ruin/spacenearstation/roid9
|
||||
id = "roid9"
|
||||
suffix = "roid9.dmm"
|
||||
name = "Monitoring Roid"
|
||||
description = "Mineral asteroid. Ft. Station monitoring, syndie toolbox and erp."
|
||||
|
||||
/datum/map_template/ruin/spacenearstation/roid10
|
||||
id = "roid10"
|
||||
suffix = "roid10.dmm"
|
||||
name = "Maze Roid"
|
||||
description = "Mineral asteroid. Ft. Brief maze."
|
||||
|
||||
@@ -73,8 +73,7 @@
|
||||
owner.log_message("gained Vanguard stun immunity", LOG_ATTACK)
|
||||
owner.add_stun_absorption("vanguard", INFINITY, 1, "'s yellow aura momentarily intensifies!", "Your ward absorbs the stun!", " radiating with a soft yellow light!")
|
||||
owner.visible_message("<span class='warning'>[owner] begins to faintly glow!</span>", "<span class='brass'>You will absorb all stuns for the next twenty seconds.</span>")
|
||||
owner.SetStun(0, FALSE)
|
||||
owner.SetKnockdown(0)
|
||||
owner.SetAllImmobility(0, FALSE)
|
||||
owner.setStaminaLoss(0, FALSE)
|
||||
progbar = new(owner, duration, owner)
|
||||
progbar.bar.color = list("#FAE48C", "#FAE48C", "#FAE48C", rgb(0,0,0))
|
||||
@@ -97,7 +96,7 @@
|
||||
if(owner.stun_absorption[i]["end_time"] > world.time && owner.stun_absorption[i]["priority"] > vanguard["priority"])
|
||||
otheractiveabsorptions = TRUE
|
||||
if(!GLOB.ratvar_awakens && stuns_blocked && !otheractiveabsorptions)
|
||||
owner.Knockdown(stuns_blocked)
|
||||
owner.DefaultCombatKnockdown(stuns_blocked)
|
||||
message_to_owner = "<span class='boldwarning'>The weight of the Vanguard's protection crashes down upon you!</span>"
|
||||
if(stuns_blocked >= 300)
|
||||
message_to_owner += "\n<span class='userdanger'>You faint from the exertion!</span>"
|
||||
@@ -226,9 +225,8 @@
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/wish_granters_gift/on_remove()
|
||||
owner.revive(full_heal = 1, admin_revive = 1)
|
||||
owner.revive(full_heal = TRUE, admin_revive = TRUE)
|
||||
owner.visible_message("<span class='warning'>[owner] appears to wake from the dead, having healed all wounds!</span>", "<span class='notice'>You have regenerated.</span>")
|
||||
owner.update_canmove()
|
||||
|
||||
/obj/screen/alert/status_effect/wish_granters_gift
|
||||
name = "Wish Granter's Immortality"
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
. = ..()
|
||||
if(.)
|
||||
if(updating_canmove)
|
||||
owner.update_canmove()
|
||||
owner.update_mobility()
|
||||
if(needs_update_stat || issilicon(owner))
|
||||
owner.update_stat()
|
||||
|
||||
/datum/status_effect/incapacitating/on_remove()
|
||||
owner.update_canmove()
|
||||
owner.update_mobility()
|
||||
if(needs_update_stat || issilicon(owner)) //silicons need stat updates in addition to normal canmove updates
|
||||
owner.update_stat()
|
||||
|
||||
@@ -29,10 +29,22 @@
|
||||
/datum/status_effect/incapacitating/knockdown
|
||||
id = "knockdown"
|
||||
|
||||
/datum/status_effect/incapacitating/knockdown/tick()
|
||||
//IMMOBILIZED
|
||||
/datum/status_effect/incapacitating/immobilized
|
||||
id = "immobilized"
|
||||
|
||||
//PARALYZED
|
||||
/datum/status_effect/incapacitating/paralyzed
|
||||
id = "paralyzed"
|
||||
|
||||
/datum/status_effect/incapacitating/paralyzed/tick()
|
||||
if(owner.getStaminaLoss())
|
||||
owner.adjustStaminaLoss(-0.3) //reduce stamina loss by 0.3 per tick, 6 per 2 seconds
|
||||
|
||||
//DAZED
|
||||
/datum/status_effect/incapacitating/dazed
|
||||
id = "dazed"
|
||||
|
||||
//UNCONSCIOUS
|
||||
/datum/status_effect/incapacitating/unconscious
|
||||
id = "unconscious"
|
||||
@@ -116,6 +128,7 @@
|
||||
|
||||
/datum/status_effect/electrode
|
||||
id = "tased"
|
||||
alert_type = null
|
||||
var/slowdown = 1.5
|
||||
var/slowdown_priority = 50 //to make sure the stronger effect overrides
|
||||
var/affect_crawl = FALSE
|
||||
@@ -143,7 +156,11 @@
|
||||
/datum/status_effect/electrode/tick()
|
||||
var/diff = world.time - last_tick
|
||||
if(owner)
|
||||
owner.adjustStaminaLoss(max(0, stamdmg_per_ds * diff)) //if you really want to try to stamcrit someone with a taser alone, you can, but it'll take time and good timing.
|
||||
var/mob/living/carbon/C = owner
|
||||
if(HAS_TRAIT(C, TRAIT_TASED_RESISTANCE))
|
||||
qdel(src)
|
||||
else
|
||||
C.adjustStaminaLoss(max(0, stamdmg_per_ds * diff)) //if you really want to try to stamcrit someone with a taser alone, you can, but it'll take time and good timing.
|
||||
last_tick = world.time
|
||||
|
||||
/datum/status_effect/electrode/nextmove_modifier() //why is this a proc. its no big deal since this doesnt get called often at all but literally w h y
|
||||
@@ -160,6 +177,8 @@
|
||||
. = ..()
|
||||
if(iscarbon(owner))
|
||||
var/mob/living/carbon/C = owner
|
||||
if(HAS_TRAIT(C, TRAIT_TASED_RESISTANCE))
|
||||
return
|
||||
if(C.combatmode)
|
||||
C.toggle_combat_mode(TRUE)
|
||||
|
||||
@@ -211,7 +230,7 @@
|
||||
if(iscarbon(owner) && !is_servant_of_ratvar(owner) && !owner.anti_magic_check(chargecost = 0) && number_legs)
|
||||
if(force_damage || owner.m_intent != MOVE_INTENT_WALK)
|
||||
if(GLOB.ratvar_awakens)
|
||||
owner.Knockdown(20)
|
||||
owner.DefaultCombatKnockdown(20)
|
||||
if(iscultist(owner))
|
||||
owner.apply_damage(cultist_damage_on_toggle * 0.5, BURN, BODY_ZONE_L_LEG)
|
||||
owner.apply_damage(cultist_damage_on_toggle * 0.5, BURN, BODY_ZONE_R_LEG)
|
||||
@@ -558,7 +577,7 @@
|
||||
var/old_oxyloss
|
||||
|
||||
/datum/status_effect/kindle/tick()
|
||||
owner.Knockdown(15, TRUE, FALSE, 15)
|
||||
owner.DefaultCombatKnockdown(15, TRUE, FALSE, 15)
|
||||
if(iscarbon(owner))
|
||||
var/mob/living/carbon/C = owner
|
||||
C.silent = max(2, C.silent)
|
||||
@@ -782,3 +801,26 @@ datum/status_effect/pacify
|
||||
to_chat(owner, "<span class='warning'>Your arm spasms!</span>")
|
||||
owner.log_message("threw [I] due to a Muscle Spasm", LOG_ATTACK)
|
||||
owner.throw_item(pick(targets))
|
||||
|
||||
/datum/status_effect/dna_melt
|
||||
id = "dna_melt"
|
||||
duration = 600
|
||||
status_type = STATUS_EFFECT_REPLACE
|
||||
alert_type = /obj/screen/alert/status_effect/dna_melt
|
||||
var/kill_either_way = FALSE //no amount of removing mutations is gonna save you now
|
||||
|
||||
/datum/status_effect/dna_melt/on_creation(mob/living/new_owner, set_duration, updating_canmove)
|
||||
. = ..()
|
||||
to_chat(new_owner, "<span class='boldwarning'>My body can't handle the mutations! I need to get my mutations removed fast!</span>")
|
||||
|
||||
/datum/status_effect/dna_melt/on_remove()
|
||||
if(!ishuman(owner))
|
||||
owner.gib() //fuck you in particular
|
||||
return
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.something_horrible(kill_either_way)
|
||||
|
||||
/obj/screen/alert/status_effect/dna_melt
|
||||
name = "Genetic Breakdown"
|
||||
desc = "I don't feel so good. Your body can't handle the mutations! You have one minute to remove your mutations, or you will be met with a horrible fate."
|
||||
icon_state = "dna_melt"
|
||||
@@ -17,11 +17,11 @@
|
||||
to_chat(owner, "<span class='userdanger'>You become frozen in a cube!</span>")
|
||||
cube = icon('icons/effects/freeze.dmi', "ice_cube")
|
||||
owner.add_overlay(cube)
|
||||
owner.update_canmove()
|
||||
owner.update_mobility()
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/freon/tick()
|
||||
owner.update_canmove()
|
||||
owner.update_mobility()
|
||||
if(can_melt && owner.bodytemperature >= BODYTEMP_NORMAL)
|
||||
qdel(src)
|
||||
|
||||
@@ -31,14 +31,14 @@
|
||||
if(!QDELETED(src))
|
||||
to_chat(owner, "You break out of the ice cube!")
|
||||
owner.remove_status_effect(/datum/status_effect/freon)
|
||||
owner.update_canmove()
|
||||
owner.update_mobility()
|
||||
|
||||
/datum/status_effect/freon/on_remove()
|
||||
if(!owner.stat)
|
||||
to_chat(owner, "The cube melts!")
|
||||
owner.cut_overlay(cube)
|
||||
owner.adjust_bodytemperature(100)
|
||||
owner.update_canmove()
|
||||
owner.update_mobility()
|
||||
UnregisterSignal(owner, COMSIG_LIVING_RESIST)
|
||||
|
||||
/datum/status_effect/freon/watcher
|
||||
|
||||
@@ -106,9 +106,9 @@
|
||||
|
||||
/datum/quirk/musician/on_spawn()
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
var/obj/item/instrument/guitar/guitar = new(get_turf(H))
|
||||
H.put_in_hands(guitar)
|
||||
H.equip_to_slot(guitar, SLOT_IN_BACKPACK)
|
||||
var/obj/item/choice_beacon/music/B = new(get_turf(H))
|
||||
H.put_in_hands(B)
|
||||
H.equip_to_slot(B, SLOT_IN_BACKPACK)
|
||||
var/obj/item/musicaltuner/musicaltuner = new(get_turf(H))
|
||||
H.put_in_hands(musicaltuner)
|
||||
H.equip_to_slot(musicaltuner, SLOT_IN_BACKPACK)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user