Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into Ghommie-cit765
This commit is contained in:
@@ -22,8 +22,8 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
|
||||
//FLAGS BITMASK
|
||||
///This flag is what recursive_hear_check() uses to determine wether to add an item to the hearer list or not.
|
||||
#define HEAR_1 (1<<3)
|
||||
///Projectiels will check ricochet on things impacted that have this.
|
||||
#define CHECK_RICOCHET_1 (1<<4)
|
||||
///Projectiles will use default chance-based ricochet handling on things with this.
|
||||
#define DEFAULT_RICOCHET_1 (1<<4)
|
||||
///Conducts electricity (metal etc.).
|
||||
#define CONDUCT_1 (1<<5)
|
||||
///For machines and structures that should not break into parts, eg, holodeck stuff.
|
||||
@@ -137,3 +137,12 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
|
||||
|
||||
#define MOBILITY_FLAGS_DEFAULT (MOBILITY_MOVE | MOBILITY_STAND | MOBILITY_PICKUP | MOBILITY_USE | MOBILITY_UI | MOBILITY_STORAGE | MOBILITY_PULL | MOBILITY_RESIST)
|
||||
#define MOBILITY_FLAGS_ANY_INTERACTION (MOBILITY_USE | MOBILITY_PICKUP | MOBILITY_UI | MOBILITY_STORAGE)
|
||||
|
||||
// melee_attack_chain() attackchain_flags
|
||||
/// The attack is from a parry counterattack.
|
||||
#define ATTACKCHAIN_PARRY_COUNTERATTACK (1<<0)
|
||||
|
||||
/// If the thing can reflect light (lasers/energy)
|
||||
#define RICOCHET_SHINY (1<<0)
|
||||
/// If the thing can reflect matter (bullets/bomb shrapnel)
|
||||
#define RICOCHET_HARD (1<<1)
|
||||
@@ -0,0 +1,54 @@
|
||||
// Flags for the item_flags var on /obj/item
|
||||
|
||||
#define BEING_REMOVED (1<<0)
|
||||
///is this item equipped into an inventory slot or hand of a mob? used for tooltips
|
||||
#define IN_INVENTORY (1<<1)
|
||||
///used for tooltips
|
||||
#define FORCE_STRING_OVERRIDE (1<<2)
|
||||
///Used by security bots to determine if this item is safe for public use.
|
||||
#define NEEDS_PERMIT (1<<3)
|
||||
#define SLOWS_WHILE_IN_HAND (1<<4)
|
||||
///Stops you from putting things like an RCD or other items into an ORM or protolathe for materials.
|
||||
#define NO_MAT_REDEMPTION (1<<5)
|
||||
///When dropped, it calls qdel on itself
|
||||
#define DROPDEL (1<<6)
|
||||
///when an item has this it produces no "X has been hit by Y with Z" message in the default attackby()
|
||||
#define NOBLUDGEON (1<<7)
|
||||
///for all things that are technically items but used for various different stuff
|
||||
#define ABSTRACT (1<<8)
|
||||
///When players should not be able to change the slowdown of the item (Speed potions, ect)
|
||||
#define IMMUTABLE_SLOW (1<<9)
|
||||
///Tool commonly used for surgery: won't attack targets in an active surgical operation on help intent (in case of mistakes)
|
||||
#define SURGICAL_TOOL (1<<10)
|
||||
///Can be worn on certain slots (currently belt and id) that would otherwise require an uniform.
|
||||
#define NO_UNIFORM_REQUIRED (1<<11)
|
||||
///Damage when attacking people is not affected by combat mode.
|
||||
#define NO_COMBAT_MODE_FORCE_MODIFIER (1<<12)
|
||||
/// This item can be used to parry. Only a basic check used to determine if we should proceed with parry chain at all.
|
||||
#define ITEM_CAN_PARRY (1<<13)
|
||||
/// This item can be used in the directional blocking system. Only a basic check used to determine if we should proceed with directional block handling at all.
|
||||
#define ITEM_CAN_BLOCK (1<<14)
|
||||
|
||||
// Flags for the clothing_flags var on /obj/item/clothing
|
||||
|
||||
#define LAVAPROTECT (1<<0)
|
||||
#define STOPSPRESSUREDAMAGE (1<<1) //SUIT and HEAD items which stop pressure damage. To stop you taking all pressure damage you must have both a suit and head item with this flag.
|
||||
#define BLOCK_GAS_SMOKE_EFFECT (1<<2) //blocks the effect that chemical clouds would have on a mob --glasses, mask and helmets ONLY!
|
||||
#define ALLOWINTERNALS (1<<3) //mask allows internals
|
||||
#define NOSLIP (1<<4) //prevents from slipping on wet floors, in space etc
|
||||
#define NOSLIP_ICE (1<<5) //prevents from slipping on frozen floors
|
||||
#define THICKMATERIAL (1<<6) //prevents syringes, parapens and hypos if the external suit or helmet (if targeting head) has this flag. Example: space suits, biosuit, bombsuits, thick suits that cover your body.
|
||||
#define VOICEBOX_TOGGLABLE (1<<7) //The voicebox in this clothing can be toggled.
|
||||
#define VOICEBOX_DISABLED (1<<8) //The voicebox is currently turned off.
|
||||
#define IGNORE_HAT_TOSS (1<<9) //Hats with negative effects when worn (i.e the tinfoil hat).
|
||||
#define SCAN_REAGENTS (1<<10) // Allows helmets and glasses to scan reagents.
|
||||
|
||||
// Flags for the organ_flags var on /obj/item/organ
|
||||
|
||||
#define ORGAN_SYNTHETIC (1<<0) //Synthetic organs, or cybernetic organs. Reacts to EMPs and don't deteriorate or heal
|
||||
#define ORGAN_FROZEN (1<<1) //Frozen organs, don't deteriorate
|
||||
#define ORGAN_FAILING (1<<2) //Failing organs perform damaging effects until replaced or fixed
|
||||
#define ORGAN_EXTERNAL (1<<3) //Was this organ implanted/inserted/etc, if true will not be removed during species change.
|
||||
#define ORGAN_VITAL (1<<4) //Currently only the brain
|
||||
#define ORGAN_NO_SPOIL (1<<5) //Do not spoil under any circumstances
|
||||
#define ORGAN_NO_DISMEMBERMENT (1<<6) //Immune to disembowelment.
|
||||
@@ -0,0 +1,15 @@
|
||||
// Flags for the obj_flags var on /obj
|
||||
|
||||
#define EMAGGED (1<<0)
|
||||
#define IN_USE (1<<1) //If we have a user using us, this will be set on. We will check if the user has stopped using us, and thus stop updating and LAGGING EVERYTHING!
|
||||
#define CAN_BE_HIT (1<<2) //can this be bludgeoned by items?
|
||||
#define BEING_SHOCKED (1<<3) //Whether this thing is currently (already) being shocked by a tesla
|
||||
#define DANGEROUS_POSSESSION (1<<4) //Admin possession yes/no
|
||||
#define ON_BLUEPRINTS (1<<5) //Are we visible on the station blueprints at roundstart?
|
||||
#define UNIQUE_RENAME (1<<6) //can you customize the description/name of the thing?
|
||||
#define USES_TGUI (1<<7) //put on things that use tgui on ui_interact instead of custom/old UI.
|
||||
#define FROZEN (1<<8)
|
||||
#define SHOVABLE_ONTO (1<<9) //called on turf.shove_act() to consider whether an object should have a niche effect (defined in their own shove_act()) when someone is pushed onto it, or do a sanity CanPass() check.
|
||||
#define BLOCK_Z_FALL (1<<10)
|
||||
|
||||
// If you add new ones, be sure to add them to /obj/Initialize as well for complete mapping support
|
||||
@@ -11,6 +11,17 @@
|
||||
#define NUKE_RESULT_WRONG_STATION 7
|
||||
#define NUKE_RESULT_WRONG_STATION_DEAD 8
|
||||
|
||||
//fugitive end results
|
||||
#define FUGITIVE_RESULT_BADASS_HUNTER 0
|
||||
#define FUGITIVE_RESULT_POSTMORTEM_HUNTER 1
|
||||
#define FUGITIVE_RESULT_MAJOR_HUNTER 2
|
||||
#define FUGITIVE_RESULT_HUNTER_VICTORY 3
|
||||
#define FUGITIVE_RESULT_MINOR_HUNTER 4
|
||||
#define FUGITIVE_RESULT_STALEMATE 5
|
||||
#define FUGITIVE_RESULT_MINOR_FUGITIVE 6
|
||||
#define FUGITIVE_RESULT_FUGITIVE_VICTORY 7
|
||||
#define FUGITIVE_RESULT_MAJOR_FUGITIVE 8
|
||||
|
||||
#define APPRENTICE_DESTRUCTION "destruction"
|
||||
#define APPRENTICE_BLUESPACE "bluespace"
|
||||
#define APPRENTICE_ROBELESS "robeless"
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#define ANTAG_HUD_CLOCKWORK 22
|
||||
#define ANTAG_HUD_BROTHER 23
|
||||
#define ANTAG_HUD_BLOODSUCKER 24
|
||||
#define ANTAG_HUD_FUGITIVE 25
|
||||
|
||||
// Notification action types
|
||||
#define NOTIFY_JUMP "jump"
|
||||
|
||||
@@ -32,4 +32,8 @@
|
||||
list("", "\improper S.T.E.A.L.T.H. pod MKVII", "A supply pod that, under normal circumstances, is completely invisible to conventional methods of detection. How are you even seeing this?"),\
|
||||
list("gondolapod", "gondola", "The silent walker. This one seems to be part of a delivery agency."),\
|
||||
list("", "", "")\
|
||||
)
|
||||
)
|
||||
|
||||
#define PACK_GOODY_NONE 0
|
||||
#define PACK_GOODY_PUBLIC 1 //can be bought by both privates and cargo
|
||||
#define PACK_GOODY_PRIVATE 2 //can be bought only by privates
|
||||
+60
-87
@@ -29,10 +29,11 @@
|
||||
#define EFFECT_DROWSY "drowsy"
|
||||
#define EFFECT_JITTER "jitter"
|
||||
|
||||
// mob/living/var/combat_flags variable.
|
||||
/// Default combat flags for those affected by sprinting (combat mode has been made into its own component)
|
||||
#define COMBAT_FLAGS_DEFAULT NONE
|
||||
#define COMBAT_FLAGS_DEFAULT (COMBAT_FLAG_PARRY_CAPABLE | COMBAT_FLAG_BLOCK_CAPABLE)
|
||||
/// Default combat flags for everyone else (so literally everyone but humans).
|
||||
#define COMBAT_FLAGS_SPRINT_EXEMPT (COMBAT_FLAG_SPRINT_ACTIVE | COMBAT_FLAG_SPRINT_TOGGLED | COMBAT_FLAG_SPRINT_FORCED)
|
||||
#define COMBAT_FLAGS_SPRINT_EXEMPT (COMBAT_FLAG_SPRINT_ACTIVE | COMBAT_FLAG_SPRINT_TOGGLED | COMBAT_FLAG_SPRINT_FORCED | COMBAT_FLAG_PARRY_CAPABLE | COMBAT_FLAG_BLOCK_CAPABLE)
|
||||
|
||||
/// The user wants sprint mode on
|
||||
#define COMBAT_FLAG_SPRINT_TOGGLED (1<<0)
|
||||
@@ -50,6 +51,16 @@
|
||||
#define COMBAT_FLAG_SOFT_STAMCRIT (1<<6)
|
||||
/// Force sprint mode on at all times, overrides everything including sprint disable traits.
|
||||
#define COMBAT_FLAG_SPRINT_FORCED (1<<7)
|
||||
/// This mob is capable of using the active parrying system.
|
||||
#define COMBAT_FLAG_PARRY_CAPABLE (1<<8)
|
||||
/// This mob is capable of using the active blocking system.
|
||||
#define COMBAT_FLAG_BLOCK_CAPABLE (1<<9)
|
||||
/// This mob is capable of unarmed parrying
|
||||
#define COMBAT_FLAG_UNARMED_PARRY (1<<10)
|
||||
/// This mob is currently actively blocking
|
||||
#define COMBAT_FLAG_ACTIVE_BLOCKING (1<<11)
|
||||
/// This mob is currently starting an active block
|
||||
#define COMBAT_FLAG_ACTIVE_BLOCK_STARTING (1<<12)
|
||||
|
||||
// Helpers for getting someone's stamcrit state. Cast to living.
|
||||
#define NOT_STAMCRIT 0
|
||||
@@ -61,10 +72,18 @@
|
||||
#define CHECK_STAMCRIT(mob) ((mob.combat_flags & COMBAT_FLAG_HARD_STAMCRIT)? HARD_STAMCRIT : ((mob.combat_flags & COMBAT_FLAG_SOFT_STAMCRIT)? SOFT_STAMCRIT : NOT_STAMCRIT))
|
||||
|
||||
//stamina stuff
|
||||
#define STAMINA_SOFTCRIT 100 //softcrit for stamina damage. prevents standing up, prevents performing actions that cost stamina, etc, but doesn't force a rest or stop movement
|
||||
#define STAMINA_CRIT 140 //crit for stamina damage. forces a rest, and stops movement until stamina goes back to stamina softcrit
|
||||
#define STAMINA_SOFTCRIT_TRADITIONAL 0 //same as STAMINA_SOFTCRIT except for the more traditional health calculations
|
||||
#define STAMINA_CRIT_TRADITIONAL -40 //ditto, but for STAMINA_CRIT
|
||||
///Threshold over which attacks start being hindered.
|
||||
#define STAMINA_NEAR_SOFTCRIT 90
|
||||
///softcrit for stamina damage. prevents standing up, some actions that cost stamina, etc, but doesn't force a rest or stop movement
|
||||
#define STAMINA_SOFTCRIT 100
|
||||
///sanity cap to prevent stamina actions (that are still performable) from sending you into crit.
|
||||
#define STAMINA_NEAR_CRIT 130
|
||||
///crit for stamina damage. forces a rest, and stops movement until stamina goes back to stamina softcrit
|
||||
#define STAMINA_CRIT 140
|
||||
///same as STAMINA_SOFTCRIT except for the more traditional health calculations
|
||||
#define STAMINA_SOFTCRIT_TRADITIONAL 0
|
||||
///ditto, but for STAMINA_CRIT
|
||||
#define STAMINA_CRIT_TRADITIONAL -40
|
||||
|
||||
#define CRAWLUNDER_DELAY 30 //Delay for crawling under a standing mob
|
||||
|
||||
@@ -104,18 +123,6 @@
|
||||
#define GRAB_NECK 2
|
||||
#define GRAB_KILL 3
|
||||
|
||||
/// Attack types for check_block()/run_block(). Flags, combinable.
|
||||
/// Attack was melee, whether or not armed.
|
||||
#define ATTACK_TYPE_MELEE (1<<0)
|
||||
/// Attack was with a gun or something that should count as a gun (but not if a gun shouldn't count for a gun, crazy right?)
|
||||
#define ATTACK_TYPE_PROJECTILE (1<<1)
|
||||
/// Attack was unarmed.. this usually means hand to hand combat.
|
||||
#define ATTACK_TYPE_UNARMED (1<<2)
|
||||
/// Attack was a thrown atom hitting the victim.
|
||||
#define ATTACK_TYPE_THROWN (1<<3)
|
||||
/// Attack was a bodyslam/leap/tackle. See: Xenomorph leap tackles.
|
||||
#define ATTACK_TYPE_TACKLE (1<<4)
|
||||
|
||||
//attack visual effects
|
||||
#define ATTACK_EFFECT_PUNCH "punch"
|
||||
#define ATTACK_EFFECT_KICK "kick"
|
||||
@@ -156,9 +163,8 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
|
||||
/obj/item/gun)))
|
||||
|
||||
|
||||
//Combat object defines
|
||||
|
||||
//Embedded objects
|
||||
|
||||
#define EMBEDDED_PAIN_CHANCE 15 //Chance for embedded objects to cause pain (damage user)
|
||||
#define EMBEDDED_ITEM_FALLOUT 5 //Chance for embedded object to fall out (causing pain but removing the object)
|
||||
#define EMBED_CHANCE 45 //Chance for an object to embed into somebody when thrown (if it's sharp)
|
||||
@@ -167,7 +173,16 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
|
||||
#define EMBEDDED_IMPACT_PAIN_MULTIPLIER 4 //Coefficient of multiplication for the damage the item does when it first embeds (this*item.w_class)
|
||||
#define EMBED_THROWSPEED_THRESHOLD 4 //The minimum value of an item's throw_speed for it to embed (Unless it has embedded_ignore_throwspeed_threshold set to 1)
|
||||
#define EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER 8 //Coefficient of multiplication for the damage the item does when removed without a surgery (this*item.w_class)
|
||||
#define EMBEDDED_UNSAFE_REMOVAL_TIME 150 //A Time in ticks, total removal time = (this/item.w_class)
|
||||
#define EMBEDDED_UNSAFE_REMOVAL_TIME 30 //A Time in ticks, total removal time = (this*item.w_class)
|
||||
#define EMBEDDED_JOSTLE_CHANCE 5 //Chance for embedded objects to cause pain every time they move (jostle)
|
||||
#define EMBEDDED_JOSTLE_PAIN_MULTIPLIER 1 //Coefficient of multiplication for the damage the item does while
|
||||
#define EMBEDDED_PAIN_STAM_PCT 0.0 //This percentage of all pain will be dealt as stam damage rather than brute (0-1)
|
||||
#define EMBED_CHANCE_TURF_MOD -15 //You are this many percentage points less likely to embed into a turf (good for things glass shards and spears vs walls)
|
||||
|
||||
#define EMBED_HARMLESS list("pain_mult" = 0, "jostle_pain_mult" = 0, "ignore_throwspeed_threshold" = TRUE)
|
||||
#define EMBED_HARMLESS_SUPERIOR list("pain_mult" = 0, "jostle_pain_mult" = 0, "ignore_throwspeed_threshold" = TRUE, "embed_chance" = 100, "fall_chance" = 0.1)
|
||||
#define EMBED_POINTY list("ignore_throwspeed_threshold" = TRUE)
|
||||
#define EMBED_POINTY_SUPERIOR list("embed_chance" = 100, "ignore_throwspeed_threshold" = TRUE)
|
||||
|
||||
//Gun weapon weight
|
||||
#define WEAPON_LIGHT 1
|
||||
@@ -182,6 +197,17 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
|
||||
#define EGUN_SELFCHARGE 1
|
||||
#define EGUN_SELFCHARGE_BORG 2
|
||||
|
||||
//Gun suppression
|
||||
#define SUPPRESSED_NONE 0
|
||||
#define SUPPRESSED_QUIET 1 ///standard suppressed
|
||||
#define SUPPRESSED_VERY 2 /// no message
|
||||
|
||||
//Nice shot bonus
|
||||
#define NICE_SHOT_RICOCHET_BONUS 10 //if the shooter has the NICE_SHOT trait and they fire a ricocheting projectile, add this to the ricochet chance and auto aim angle
|
||||
|
||||
///Time to spend without clicking on other things required for your shots to become accurate.
|
||||
#define GUN_AIMING_TIME (2 SECONDS)
|
||||
|
||||
//Object/Item sharpness
|
||||
#define IS_BLUNT 0
|
||||
#define IS_SHARP 1
|
||||
@@ -249,70 +275,17 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
|
||||
#define STAM_COST_W_CLASS_MULT 1.25
|
||||
#define STAM_COST_THROW_MULT 2
|
||||
|
||||
///Multiplier of the (STAMINA_NEAR_CRIT - user current stamina loss) : (STAMINA_NEAR_CRIT - STAMINA_SOFTCRIT) ratio used in damage penalties when stam soft-critted.
|
||||
#define STAM_CRIT_ITEM_ATTACK_PENALTY 0.66
|
||||
/// changeNext_move penalty multiplier of the above.
|
||||
#define STAM_CRIT_ITEM_ATTACK_DELAY 1.75
|
||||
/// Damage penalty when fighting prone.
|
||||
#define LYING_DAMAGE_PENALTY 0.5
|
||||
/// Added delay when firing guns stam-softcritted. Summed with a hardset CLICK_CD_RANGE delay, similar to STAM_CRIT_DAMAGE_DELAY otherwise.
|
||||
#define STAM_CRIT_GUN_DELAY 2.75
|
||||
|
||||
//bullet_act() return values
|
||||
#define BULLET_ACT_HIT "HIT" //It's a successful hit, whatever that means in the context of the thing it's hitting.
|
||||
#define BULLET_ACT_BLOCK "BLOCK" //It's a blocked hit, whatever that means in the context of the thing it's hitting.
|
||||
#define BULLET_ACT_FORCE_PIERCE "PIERCE" //It pierces through the object regardless of the bullet being piercing by default.
|
||||
#define BULLET_ACT_TURF "TURF" //It hit us but it should hit something on the same turf too. Usually used for turfs.
|
||||
|
||||
/// Check whether or not we can block, without "triggering" a block. Basically run checks without effects like depleting shields.
|
||||
/// Wrapper for do_run_block(). The arguments on that means the same as for this.
|
||||
#define mob_check_block(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list)\
|
||||
do_run_block(FALSE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list)
|
||||
|
||||
/// Runs a block "sequence", effectively checking and then doing effects if necessary.
|
||||
/// Wrapper for do_run_block(). The arguments on that means the same as for this.
|
||||
#define mob_run_block(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list)\
|
||||
do_run_block(TRUE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list)
|
||||
|
||||
/// Bitflags for check_block() and run_block(). Meant to be combined. You can be hit and still reflect, for example, if you do not use BLOCK_SUCCESS.
|
||||
/// Attack was not blocked
|
||||
#define BLOCK_NONE NONE
|
||||
/// Attack was blocked, do not do damage. THIS FLAG MUST BE THERE FOR DAMAGE/EFFECT PREVENTION!
|
||||
#define BLOCK_SUCCESS (1<<1)
|
||||
|
||||
/// The below are for "metadata" on "how" the attack was blocked.
|
||||
|
||||
/// Attack was and should be redirected according to list argument REDIRECT_METHOD (NOTE: the SHOULD here is important, as it says "the thing blocking isn't handling the reflecting for you so do it yourself"!)
|
||||
#define BLOCK_SHOULD_REDIRECT (1<<2)
|
||||
/// Attack was redirected (whether by us or by SHOULD_REDIRECT flagging for automatic handling)
|
||||
#define BLOCK_REDIRECTED (1<<3)
|
||||
/// Attack was blocked by something like a shield.
|
||||
#define BLOCK_PHYSICAL_EXTERNAL (1<<4)
|
||||
/// Attack was blocked by something worn on you.
|
||||
#define BLOCK_PHYSICAL_INTERNAL (1<<5)
|
||||
/// Attack outright missed because the target dodged. Should usually be combined with redirection passthrough or something (see martial arts)
|
||||
#define BLOCK_TARGET_DODGED (1<<7)
|
||||
/// Meta-flag for run_block/do_run_block : By default, BLOCK_SUCCESS tells do_run_block() to assume the attack is completely blocked and not continue the block chain. If this is present, it will continue to check other items in the chain rather than stopping.
|
||||
#define BLOCK_CONTINUE_CHAIN (1<<8)
|
||||
|
||||
/// For keys in associative list/block_return as we don't want to saturate our (somewhat) limited flags.
|
||||
#define BLOCK_RETURN_REDIRECT_METHOD "REDIRECT_METHOD"
|
||||
/// Pass through victim
|
||||
#define REDIRECT_METHOD_PASSTHROUGH "passthrough"
|
||||
/// Deflect at randomish angle
|
||||
#define REDIRECT_METHOD_DEFLECT "deflect"
|
||||
/// reverse 180 angle, basically (as opposed to "realistic" wall reflections)
|
||||
#define REDIRECT_METHOD_REFLECT "reflect"
|
||||
/// "do not taser the bad man with the desword" - actually aims at the firer/attacker rather than just reversing
|
||||
#define REDIRECT_METHOD_RETURN_TO_SENDER "no_you"
|
||||
|
||||
/// These keys are generally only applied to the list if real_attack is FALSE. Used incase we want to make "smarter" mob AI in the future or something.
|
||||
/// Tells the caller how likely from 0 (none) to 100 (always) we are to reflect energy projectiles
|
||||
#define BLOCK_RETURN_REFLECT_PROJECTILE_CHANCE "reflect_projectile_chance"
|
||||
/// Tells the caller how likely we are to block attacks from 0 to 100 in general
|
||||
#define BLOCK_RETURN_NORMAL_BLOCK_CHANCE "normal_block_chance"
|
||||
/// Tells the caller about how many hits we can soak on average before our blocking fails.
|
||||
#define BLOCK_RETURN_BLOCK_CAPACITY "block_capacity"
|
||||
|
||||
/// Default if the above isn't set in the list.
|
||||
#define DEFAULT_REDIRECT_METHOD_PROJECTILE REDIRECT_METHOD_DEFLECT
|
||||
|
||||
/// Block priorities
|
||||
#define BLOCK_PRIORITY_HELD_ITEM 100
|
||||
#define BLOCK_PRIORITY_WEAR_SUIT 75
|
||||
#define BLOCK_PRIORITY_CLOTHING 50
|
||||
#define BLOCK_PRIORITY_UNIFORM 25
|
||||
|
||||
#define BLOCK_PRIORITY_DEFAULT BLOCK_PRIORITY_HELD_ITEM
|
||||
/**
|
||||
* should the current-attack-damage be lower than the item force multiplied by this value,
|
||||
* a "inefficiently" prefix will be added to the message.
|
||||
*/
|
||||
#define FEEBLE_ATTACK_MSG_THRESHOLD 0.5
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// Attack types for check_block()/run_block(). Flags, combinable.
|
||||
/// Attack was melee, whether or not armed.
|
||||
#define ATTACK_TYPE_MELEE (1<<0)
|
||||
/// Attack was with a gun or something that should count as a gun (but not if a gun shouldn't count for a gun, crazy right?)
|
||||
#define ATTACK_TYPE_PROJECTILE (1<<1)
|
||||
/// Attack was unarmed.. this usually means hand to hand combat.
|
||||
#define ATTACK_TYPE_UNARMED (1<<2)
|
||||
/// Attack was a thrown atom hitting the victim.
|
||||
#define ATTACK_TYPE_THROWN (1<<3)
|
||||
/// Attack was a bodyslam/leap/tackle. See: Xenomorph leap tackles.
|
||||
#define ATTACK_TYPE_TACKLE (1<<4)
|
||||
/// Attack was from a parry counterattack. Do not attempt to parry-this!
|
||||
#define ATTACK_TYPE_PARRY_COUNTERATTACK (1<<5)
|
||||
|
||||
// Requires for datum definitions to not error with must be a constant statement when used in lists as text associative keys.
|
||||
// KEEP IN SYNC WITH ABOVE!
|
||||
|
||||
#define TEXT_ATTACK_TYPE_MELEE "1"
|
||||
#define TEXT_ATTACK_TYPE_PROJECTILE "2"
|
||||
#define TEXT_ATTACK_TYPE_UNARMED "4"
|
||||
#define TEXT_ATTACK_TYPE_THROWN "8"
|
||||
#define TEXT_ATTACK_TYPE_TACKLE "16"
|
||||
#define TEXT_ATTACK_TYPE_PARRY_COUNTERATTACK "32"
|
||||
|
||||
GLOBAL_LIST_INIT(attack_type_names, list(
|
||||
TEXT_ATTACK_TYPE_MELEE = "Melee",
|
||||
TEXT_ATTACK_TYPE_PROJECTILE = "Projectile",
|
||||
TEXT_ATTACK_TYPE_UNARMED = "Unarmed",
|
||||
TEXT_ATTACK_TYPE_THROWN = "Thrown",
|
||||
TEXT_ATTACK_TYPE_TACKLE = "Tackle",
|
||||
TEXT_ATTACK_TYPE_PARRY_COUNTERATTACK = "Parry Counterattack"
|
||||
))
|
||||
@@ -0,0 +1,80 @@
|
||||
/// Check whether or not we can block, without "triggering" a block. Basically run checks without effects like depleting shields.
|
||||
/// Wrapper for do_run_block(). The arguments on that means the same as for this.
|
||||
#define mob_check_block(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list)\
|
||||
do_run_block(FALSE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list)
|
||||
|
||||
/// Runs a block "sequence", effectively checking and then doing effects if necessary.
|
||||
/// Wrapper for do_run_block(). The arguments on that means the same as for this.
|
||||
#define mob_run_block(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list)\
|
||||
do_run_block(TRUE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list)
|
||||
|
||||
// Don't ask why there's block_parry.dm and this. This is for the run_block() system, which is the "parent" system of the directional block and parry systems.
|
||||
|
||||
/// Bitflags for check_block() and handle_block(). Meant to be combined. You can be hit and still reflect, for example, if you do not use BLOCK_SUCCESS.
|
||||
/// Attack was not blocked
|
||||
#define BLOCK_NONE NONE
|
||||
/// Attack was blocked, do not do damage. THIS FLAG MUST BE THERE FOR DAMAGE/EFFECT PREVENTION!
|
||||
#define BLOCK_SUCCESS (1<<1)
|
||||
|
||||
/// The below are for "metadata" on "how" the attack was blocked.
|
||||
|
||||
/// Attack was and should be redirected according to list argument REDIRECT_METHOD (NOTE: the SHOULD here is important, as it says "the thing blocking isn't handling the reflecting for you so do it yourself"!)
|
||||
#define BLOCK_SHOULD_REDIRECT (1<<2)
|
||||
/// Attack was redirected (whether by us or by SHOULD_REDIRECT flagging for automatic handling)
|
||||
#define BLOCK_REDIRECTED (1<<3)
|
||||
/// Attack was blocked by something like a shield.
|
||||
#define BLOCK_PHYSICAL_EXTERNAL (1<<4)
|
||||
/// Attack was blocked by something worn on you.
|
||||
#define BLOCK_PHYSICAL_INTERNAL (1<<5)
|
||||
/// Attack outright missed because the target dodged. Should usually be combined with redirection passthrough or something (see martial arts)
|
||||
#define BLOCK_TARGET_DODGED (1<<7)
|
||||
/// Meta-flag for run_block/do_run_block : By default, BLOCK_SUCCESS tells do_run_block() to assume the attack is completely blocked and not continue the block chain. If this is present, it will continue to check other items in the chain rather than stopping.
|
||||
#define BLOCK_CONTINUE_CHAIN (1<<8)
|
||||
/// Attack should change the amount of damage incurred. This means something calling run_block() has to handle it!
|
||||
#define BLOCK_SHOULD_CHANGE_DAMAGE (1<<9)
|
||||
/// Attack should scale by this percent, 0 for no block and 100 for full blocked
|
||||
#define BLOCK_SHOULD_PARTIAL_MITIGATE (1<<10)
|
||||
|
||||
/// For keys in associative list/block_return as we don't want to saturate our (somewhat) limited flags.
|
||||
#define BLOCK_RETURN_REDIRECT_METHOD "REDIRECT_METHOD"
|
||||
/// Pass through victim
|
||||
#define REDIRECT_METHOD_PASSTHROUGH "passthrough"
|
||||
/// Deflect at randomish angle
|
||||
#define REDIRECT_METHOD_DEFLECT "deflect"
|
||||
/// reverse 180 angle, basically (as opposed to "realistic" wall reflections)
|
||||
#define REDIRECT_METHOD_REFLECT "reflect"
|
||||
/// "do not taser the bad man with the desword" - actually aims at the firer/attacker rather than just reversing
|
||||
#define REDIRECT_METHOD_RETURN_TO_SENDER "no_you"
|
||||
|
||||
/// These keys are generally only applied to the list if real_attack is FALSE. Used incase we want to make "smarter" mob AI in the future or something.
|
||||
/// Tells the caller how likely from 0 (none) to 100 (always) we are to reflect energy projectiles
|
||||
#define BLOCK_RETURN_REFLECT_PROJECTILE_CHANCE "reflect_projectile_chance"
|
||||
/// Tells the caller how likely we are to block attacks from 0 to 100 in general
|
||||
#define BLOCK_RETURN_NORMAL_BLOCK_CHANCE "normal_block_chance"
|
||||
/// Tells the caller about how many hits we can soak on average before our blocking fails.
|
||||
#define BLOCK_RETURN_BLOCK_CAPACITY "block_capacity"
|
||||
/// Tells the caller we got blocked by active directional block.
|
||||
#define BLOCK_RETURN_ACTIVE_BLOCK "active_block"
|
||||
/// Tells the caller our damage mitigation for their attack.
|
||||
#define BLOCK_RETURN_ACTIVE_BLOCK_DAMAGE_MITIGATED "damage_mitigated"
|
||||
/// For [BLOCK_CHANGE_DAMAGE]. Set damage to this.
|
||||
#define BLOCK_RETURN_SET_DAMAGE_TO "set_damage_to"
|
||||
/// For [BLOCK_SHOULD_PARTIAL_MITIGATE]. Percentage mitigation.
|
||||
#define BLOCK_RETURN_MITIGATION_PERCENT "partial_mitigation"
|
||||
/// Used internally by run_parry proc, use on an on_active_parry() proc to override parrying efficiency.
|
||||
#define BLOCK_RETURN_OVERRIDE_PARRY_EFFICIENCY "override_parry_efficiency"
|
||||
/// Always set to 100 by run_block() if BLOCK_SUCCESS is in return value. Otherwise, defaults to mitigation percent if not set. Used by projectile/proc/on_hit().
|
||||
#define BLOCK_RETURN_PROJECTILE_BLOCK_PERCENTAGE "projectile_block_percentage"
|
||||
|
||||
/// Default if the above isn't set in the list.
|
||||
#define DEFAULT_REDIRECT_METHOD_PROJECTILE REDIRECT_METHOD_DEFLECT
|
||||
|
||||
/// Block priorities. Higher means it's checked sooner.
|
||||
// THESE MUST NEVER BE 0! Block code uses ! instead of isnull for the speed boost.
|
||||
#define BLOCK_PRIORITY_ACTIVE_BLOCK 200
|
||||
#define BLOCK_PRIORITY_HELD_ITEM 100
|
||||
#define BLOCK_PRIORITY_CLOTHING 50
|
||||
#define BLOCK_PRIORITY_WEAR_SUIT 75
|
||||
#define BLOCK_PRIORITY_UNIFORM 25
|
||||
|
||||
#define BLOCK_PRIORITY_DEFAULT BLOCK_PRIORITY_HELD_ITEM
|
||||
@@ -0,0 +1,72 @@
|
||||
// We can't determine things like NORTHEAST vs NORTH *and* EAST without making our own flags :(
|
||||
#define BLOCK_DIR_NORTH (1<<0)
|
||||
#define BLOCK_DIR_NORTHEAST (1<<1)
|
||||
#define BLOCK_DIR_NORTHWEST (1<<2)
|
||||
#define BLOCK_DIR_WEST (1<<3)
|
||||
#define BLOCK_DIR_EAST (1<<4)
|
||||
#define BLOCK_DIR_SOUTH (1<<5)
|
||||
#define BLOCK_DIR_SOUTHEAST (1<<6)
|
||||
#define BLOCK_DIR_SOUTHWEST (1<<7)
|
||||
#define BLOCK_DIR_ONTOP (1<<8)
|
||||
|
||||
GLOBAL_LIST_INIT(dir2blockdir, list(
|
||||
"[NORTH]" = BLOCK_DIR_NORTH,
|
||||
"[NORTHEAST]" = BLOCK_DIR_NORTHEAST,
|
||||
"[NORTHWEST]" = BLOCK_DIR_NORTHWEST,
|
||||
"[WEST]" = BLOCK_DIR_WEST,
|
||||
"[EAST]" = BLOCK_DIR_EAST,
|
||||
"[SOUTH]" = BLOCK_DIR_SOUTH,
|
||||
"[SOUTHEAST]" = BLOCK_DIR_SOUTHEAST,
|
||||
"[SOUTHWEST]" = BLOCK_DIR_SOUTHWEST,
|
||||
"[NONE]" = BLOCK_DIR_ONTOP
|
||||
))
|
||||
|
||||
#define DIR2BLOCKDIR(d) (GLOB.dir2blockdir["[d]"])
|
||||
|
||||
GLOBAL_LIST_INIT(block_direction_names, list(
|
||||
"[BLOCK_DIR_NORTH]" = "Front",
|
||||
"[BLOCK_DIR_NORTHEAST]" = "Front Right",
|
||||
"[BLOCK_DIR_NORTHWEST]" = "Front Left",
|
||||
"[BLOCK_DIR_WEST]" = "Left",
|
||||
"[BLOCK_DIR_EAST]" = "Right",
|
||||
"[BLOCK_DIR_SOUTH]" = "Behind",
|
||||
"[BLOCK_DIR_SOUTHEAST]" = "Behind Right",
|
||||
"[BLOCK_DIR_SOUTHWEST]" = "Behind Left",
|
||||
"[BLOCK_DIR_ONTOP]" = "Ontop"
|
||||
))
|
||||
|
||||
/// If this is the value of active_block_starting it signals we want to interrupt the start
|
||||
#define ACTIVE_BLOCK_STARTING_INTERRUPT "INTERRUPT"
|
||||
|
||||
/// ""types"" of parry "items"
|
||||
#define UNARMED_PARRY "unarmed"
|
||||
#define MARTIAL_PARRY "martial"
|
||||
#define ITEM_PARRY "item"
|
||||
|
||||
/// Parry phase we're in
|
||||
#define NOT_PARRYING 0
|
||||
#define PARRY_WINDUP 1
|
||||
#define PARRY_ACTIVE 2
|
||||
#define PARRY_SPINDOWN 3
|
||||
|
||||
// /datum/block_parry_data/var/parry_flags
|
||||
/// Default handling for audio/visual feedback
|
||||
#define PARRY_DEFAULT_HANDLE_FEEDBACK (1<<0)
|
||||
/// Lock sprinting while parrying
|
||||
#define PARRY_LOCK_SPRINTING (1<<1)
|
||||
/// Lock attacking while parrying
|
||||
#define PARRY_LOCK_ATTACKING (1<<2)
|
||||
|
||||
/// Parry effects.
|
||||
/// Automatically melee attacks back normally, LMB equivalent action of an harm intent attack. List association should be defaulting to 1, being the attack damage multiplier for said counterattack
|
||||
#define PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN "melee_counterattack_chain"
|
||||
/// List association should be TRUE.
|
||||
#define PARRY_DISARM_ATTACKER "disarm_attacker"
|
||||
/// List association should be duration or null for just plain knockdown.
|
||||
#define PARRY_KNOCKDOWN_ATTACKER "knockdown_attacker"
|
||||
/// List association should be duration.
|
||||
#define PARRY_STAGGER_ATTACKER "stagger_attacker"
|
||||
/// List association should be amount of time to daze attacker.
|
||||
#define PARRY_DAZE_ATTACKER "daze_attacker"
|
||||
/// Set to TRUE in list association to ignore adjacency checks
|
||||
#define PARRY_COUNTERATTACK_IGNORE_ADJACENCY "ignore_adjacency"
|
||||
@@ -67,7 +67,9 @@
|
||||
//tablecrafting defines
|
||||
#define CAT_NONE ""
|
||||
#define CAT_WEAPONRY "Weaponry"
|
||||
#define CAT_WEAPON "Weapons"
|
||||
#define CAT_WEAPON "Ranged Weapons"
|
||||
#define CAT_MELEE "Melee Weapons"
|
||||
#define CAT_OTHER "Misc"
|
||||
#define CAT_AMMO "Ammunition"
|
||||
#define CAT_PARTS "Weapon Parts"
|
||||
#define CAT_ROBOT "Robots"
|
||||
|
||||
@@ -26,6 +26,11 @@
|
||||
#define COMPONENT_ADD_TRAIT (1<<0)
|
||||
#define COMPONENT_REMOVE_TRAIT (1<<1)
|
||||
|
||||
/// fires on the target datum when an element is attached to it (/datum/element)
|
||||
#define COMSIG_ELEMENT_ATTACH "element_attach"
|
||||
/// fires on the target datum when an element is attached to it (/datum/element)
|
||||
#define COMSIG_ELEMENT_DETACH "element_detach"
|
||||
|
||||
// /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
|
||||
@@ -229,10 +234,16 @@
|
||||
#define COMSIG_LIVING_STATUS_STAGGER "living_stagger" //from base of mob/living/Stagger() (amount, update, ignore)
|
||||
#define COMPONENT_NO_STUN 1 //For all of them
|
||||
|
||||
#define COMSIG_LIVING_LIFE "life_tick" //from base of mob/living/Life() (seconds, times_fired)
|
||||
#define COMPONENT_INTERRUPT_LIFE_BIOLOGICAL 1 // interrupt biological processes
|
||||
#define COMPONENT_INTERRUPT_LIFE_PHYSICAL 2 // interrupt physical handling
|
||||
|
||||
// /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)
|
||||
#define COMSIG_CARBON_TACKLED "carbon_tackled" //sends from tackle.dm on tackle completion
|
||||
#define COMSIG_CARBON_EMBED_RIP "item_embed_start_rip" // defined twice, in carbon and human's topics, fired when interacting with a valid embedded_object to pull it out (mob/living/carbon/target, /obj/item, /obj/item/bodypart/L)
|
||||
#define COMSIG_CARBON_EMBED_REMOVAL "item_embed_remove_safe" // called when removing a given item from a mob, from mob/living/carbon/remove_embedded_object(mob/living/carbon/target, /obj/item)
|
||||
|
||||
// /mob/living/silicon signals
|
||||
#define COMSIG_ROBOT_UPDATE_ICONS "robot_update_icons" //from base of robot/update_icons(): ()
|
||||
@@ -284,9 +295,15 @@
|
||||
#define COMSIG_ITEM_MOUSE_EXIT "item_mouse_exit" //from base of obj/item/MouseExited(): (location, control, params)
|
||||
#define COMSIG_ITEM_MOUSE_ENTER "item_mouse_enter" //from base of obj/item/MouseEntered(): (location, control, params)
|
||||
#define COMSIG_ITEM_DECONSTRUCTOR_DEEPSCAN "deconstructor_deepscan" //Called by deconstructive analyzers deepscanning an item: (obj/machinery/rnd/destructive_analyzer/analyzer_machine, mob/user, list/information_list)
|
||||
#define COMSIG_ITEM_DISABLE_EMBED "item_disable_embed" ///from [/obj/item/proc/disableEmbedding]:
|
||||
#define COMSIG_MINE_TRIGGERED "minegoboom" ///from [/obj/effect/mine/proc/triggermine]:
|
||||
// Uncovered information
|
||||
#define COMPONENT_DEEPSCAN_UNCOVERED_INFORMATION 1
|
||||
|
||||
// /obj/item/grenade signals
|
||||
#define COMSIG_GRENADE_PRIME "grenade_prime" //called in /obj/item/gun/process_fire (user, target, params, zone_override)
|
||||
#define COMSIG_GRENADE_ARMED "grenade_armed" //called in /obj/item/gun/process_fire (user, target, params, zone_override)
|
||||
|
||||
// /obj/item/clothing signals
|
||||
#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): ()
|
||||
#define COMSIG_SUIT_MADE_HELMET "suit_made_helmet" //from base of obj/item/clothing/suit/MakeHelmet(): (helmet)
|
||||
@@ -314,8 +331,15 @@
|
||||
#define COMSIG_PEN_ROTATED "pen_rotated" //called after rotation in /obj/item/pen/attack_self(): (rotation, mob/living/carbon/user)
|
||||
|
||||
// /obj/item/projectile signals (sent to the firer)
|
||||
#define COMSIG_PROJECTILE_SELF_ON_HIT "projectile_self_on_hit" // from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle)
|
||||
#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit" // from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle)
|
||||
#define COMSIG_PROJECTILE_BEFORE_FIRE "projectile_before_fire" // from base of /obj/item/projectile/proc/fire(): (obj/item/projectile, atom/original_target)
|
||||
#define COMSIG_PROJECTILE_FIRE "projectile_fire" ///from the base of /obj/projectile/proc/fire(): ()
|
||||
#define COMSIG_PROJECTILE_RANGE_OUT "projectile_range_out" // sent to targets during the process_hit proc of projectiles
|
||||
#define COMSIG_EMBED_TRY_FORCE "item_try_embed" // sent when trying to force an embed (mainly for projectiles, only used in the embed element)
|
||||
#define COMSIG_PROJECTILE_PREHIT "com_proj_prehit" ///sent to targets during the process_hit proc of projectiles
|
||||
|
||||
#define COMSIG_PELLET_CLOUD_INIT "pellet_cloud_init" // sent to targets during the process_hit proc of projectiles
|
||||
|
||||
// /mob/living/carbon/human signals
|
||||
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target)
|
||||
|
||||
@@ -33,3 +33,19 @@
|
||||
#define ID_NO_BANK_ACCOUNT 0
|
||||
#define ID_FREE_BANK_ACCOUNT 1
|
||||
#define ID_LOCKED_BANK_ACCOUNT 2
|
||||
|
||||
//Some price defines to help standarize the intended vending value of items. Do not bother adding too many examples.
|
||||
#define PRICE_FREE 0 // Sustainance/soviet vendor stuff.
|
||||
#define PRICE_CHEAP_AS_FREE 10 // Cheap lighters, syringes, soft drinks etc.
|
||||
#define PRICE_REALLY_CHEAP 20 // Snacks, hot drinks, tools.
|
||||
#define PRICE_PRETTY_CHEAP 30 // Some snacks, beer.
|
||||
#define PRICE_CHEAP 40 // Clothings. some electronics
|
||||
#define PRICE_ALMOST_CHEAP 60 // Fancy clothing, cig packs, booze-o-mat, seeds, medical.
|
||||
#define PRICE_BELOW_NORMAL 80 // Clothesmate and kinkmate premium stuff.
|
||||
#define PRICE_NORMAL 100 // Kitchen knife, other stuff.
|
||||
#define PRICE_ABOVE_NORMAL 150 // Liberation (capitalism ahoy) and donksoft vendors.
|
||||
#define PRICE_ALMOST_EXPENSIVE 200 // Butcher knife, cartridges, some premium stuff.
|
||||
#define PRICE_EXPENSIVE 325 // Premium stuff.
|
||||
#define PRICE_ABOVE_EXPENSIVE 500 // RCD, Crew pinpointer/monitor, galoshes
|
||||
#define PRICE_REALLY_EXPENSIVE 700 // More premium stuff.
|
||||
#define PRICE_ALMOST_ONE_GRAND 900 // $$$ Insulated gloves, backpack water-tank spray $$$
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/// Requires absolute stillness from the user
|
||||
#define DO_AFTER_DISALLOW_MOVING_ABSOLUTE_USER (1<<0)
|
||||
/// Requires absolute stillness from the target
|
||||
#define DO_AFTER_DISALLOW_MOVING_ABSOLUTE_TARGET (1<<1)
|
||||
/// Requires that the user is on a turf.
|
||||
#define DO_AFTER_REQUIRES_USER_ON_TURF (1<<2)
|
||||
/// Requires relative stillness to our target via dx and dy coordinate difference but only if both are spacedrifting. Specify DO_AFTER_ALLOW_NONSPACEDRIFT_RELATIVITY to say otherwise.
|
||||
#define DO_AFTER_DISALLOW_MOVING_RELATIVE (1<<3)
|
||||
/// Breaks if active hand item changes. Requires a tool be specified, otherwise defaults to active item
|
||||
#define DO_AFTER_DISALLOW_ACTIVE_ITEM_CHANGE (1<<4)
|
||||
/// Breaks if the user has no free hands. If a tool is specified, allows that as well.
|
||||
#define DO_AFTER_REQUIRE_FREE_HAND_OR_TOOL (1<<5)
|
||||
/// Do not display progressbar.
|
||||
#define DO_AFTER_NO_PROGRESSBAR (1<<6)
|
||||
/// Do not check do_after_coefficient()
|
||||
#define DO_AFTER_NO_COEFFICIENT (1<<7)
|
||||
/// For relative stillness, allow non spacedrift relative movement
|
||||
#define DO_AFTER_ALLOW_NONSPACEDRIFT_RELATIVITY (1<<8)
|
||||
|
||||
/// Ignores checks.
|
||||
#define DO_AFTER_PROCEED "PROCEED"
|
||||
/// Uses all other checks
|
||||
#define DO_AFTER_CONTINUE "CONTINUE"
|
||||
/// Breaks
|
||||
#define DO_AFTER_STOP "STOP"
|
||||
|
||||
/// Stage - initiating a do_after
|
||||
#define DO_AFTER_STARTING 1
|
||||
/// Stage - main loop of a do_after
|
||||
#define DO_AFTER_PROGRESSING 2
|
||||
/// Stage - Last check of a do_after
|
||||
#define DO_AFTER_FINISHING 3
|
||||
@@ -1,3 +1,6 @@
|
||||
/// Checks if something is a BYOND object datatype rather than a primitive, or whatever's closest to one.
|
||||
#define is_object_datatype(object) (object && !ispath(object) && !istext(object) && !isnum(object))
|
||||
|
||||
// simple is_type and similar inline helpers
|
||||
|
||||
#define in_range(source, user) (get_dist(source, user) <= 1 && (get_step(source, 0)?:z) == (get_step(user, 0)?:z))
|
||||
@@ -177,6 +180,12 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
|
||||
|
||||
#define isitem(A) (istype(A, /obj/item))
|
||||
|
||||
#define isgrenade(A) (istype(A, /obj/item/grenade))
|
||||
|
||||
#define islandmine(A) (istype(A, /obj/effect/mine))
|
||||
|
||||
#define isammocasing(A) (istype(A, /obj/item/ammo_casing))
|
||||
|
||||
#define isidcard(I) (istype(I, /obj/item/card/id))
|
||||
|
||||
#define isstructure(A) (istype(A, /obj/structure))
|
||||
|
||||
@@ -88,3 +88,28 @@
|
||||
#define EMISSIVE_BLOCK_GENERIC 1
|
||||
/// Uses a dedicated render_target object to copy the entire appearance in real time to the blocking layer. For things that can change in appearance a lot from the base state, like humans.
|
||||
#define EMISSIVE_BLOCK_UNIQUE 2
|
||||
|
||||
|
||||
/// Returns the red part of a #RRGGBB hex sequence as number
|
||||
#define GETREDPART(hexa) hex2num(copytext(hexa, 2, 4))
|
||||
|
||||
/// Returns the green part of a #RRGGBB hex sequence as number
|
||||
#define GETGREENPART(hexa) hex2num(copytext(hexa, 4, 6))
|
||||
|
||||
/// Returns the blue part of a #RRGGBB hex sequence as number
|
||||
#define GETBLUEPART(hexa) hex2num(copytext(hexa, 6, 8))
|
||||
|
||||
/// Parse the hexadecimal color into lumcounts of each perspective.
|
||||
#define PARSE_LIGHT_COLOR(source) \
|
||||
do { \
|
||||
if (source.light_color) { \
|
||||
var/__light_color = source.light_color; \
|
||||
source.lum_r = GETREDPART(__light_color) / 255; \
|
||||
source.lum_g = GETGREENPART(__light_color) / 255; \
|
||||
source.lum_b = GETBLUEPART(__light_color) / 255; \
|
||||
} else { \
|
||||
source.lum_r = 1; \
|
||||
source.lum_g = 1; \
|
||||
source.lum_b = 1; \
|
||||
}; \
|
||||
} while (FALSE)
|
||||
|
||||
@@ -8,5 +8,68 @@
|
||||
//ids
|
||||
#define MOVESPEED_ID_SANITY "mood_sanity"
|
||||
|
||||
#define MOVESPEED_ID_MOB_GRAB_STATE "mob_grab_state"
|
||||
#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"
|
||||
#define MOVESPEED_ID_SLIME_HEALTHMOD "SLIME_HEALTH_MODIFIER"
|
||||
#define MOVESPEED_ID_SLIME_TEMPMOD "SLIME_TEMPERATURE_MODIFIER"
|
||||
|
||||
#define MOVESPEED_ID_SLIME_STATUS "SLIME_STATUS"
|
||||
|
||||
#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"
|
||||
|
||||
#define MOVESPEED_ID_DNA_VAULT "DNA_VAULT"
|
||||
|
||||
#define MOVESPEED_ID_YELLOW_ORB "YELLOW_ORB"
|
||||
|
||||
#define MOVESPEED_ID_TARFOOT "TARFOOT"
|
||||
|
||||
#define MOVESPEED_ID_SEPIA "SEPIA"
|
||||
|
||||
#define MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD "MONKEY_REAGENT_SPEEDMOD"
|
||||
#define MOVESPEED_ID_MONKEY_TEMPERATURE_SPEEDMOD "MONKEY_TEMPERATURE_SPEEDMOD"
|
||||
#define MOVESPEED_ID_MONKEY_HEALTH_SPEEDMOD "MONKEY_HEALTH_SPEEDMOD"
|
||||
|
||||
#define MOVESPEED_ID_CHANGELING_MUSCLES "CHANGELING_MUSCLES"
|
||||
|
||||
#define MOVESPEED_ID_SIMPLEMOB_VARSPEED "SIMPLEMOB_VARSPEED_MODIFIER"
|
||||
#define MOVESPEED_ID_ADMIN_VAREDIT "ADMIN_VAREDIT_MODIFIER"
|
||||
|
||||
#define MOVESPEED_ID_PAI_SPACEWALK_SPEEDMOD "PAI_SPACEWALK_MODIFIER"
|
||||
|
||||
#define MOVESPEED_ID_SPECIES "SPECIES_SPEED_MOD"
|
||||
|
||||
#define MOVESPEED_ID_PRONE_DRAGGING "PRONE_DRAG"
|
||||
#define MOVESPEED_ID_HUMAN_CARRYING "HUMAN_CARRY"
|
||||
#define MOVESPEED_ID_SHRINK_RAY "SHRUNKEN_SPEED_MODIFIER"
|
||||
|
||||
#define MOVESPEED_ID_SLAUGHTER "SLAUGHTER"
|
||||
|
||||
#define MOVESPEED_ID_CYBER_THRUSTER "CYBER_IMPLANT_THRUSTER"
|
||||
#define MOVESPEED_ID_JETPACK "JETPACK"
|
||||
|
||||
#define MOVESPEED_ID_MKULTRA "MKULTRA"
|
||||
|
||||
#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"
|
||||
|
||||
#define MOVESPEED_ID_ACTIVE_BLOCK "ACTIVE_BLOCK"
|
||||
|
||||
#define MOVESPEED_ID_MOB_WALK_RUN "mob_walk_run"
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
// Flags for the obj_flags var on /obj
|
||||
|
||||
|
||||
#define EMAGGED (1<<0)
|
||||
#define IN_USE (1<<1) //If we have a user using us, this will be set on. We will check if the user has stopped using us, and thus stop updating and LAGGING EVERYTHING!
|
||||
#define CAN_BE_HIT (1<<2) //can this be bludgeoned by items?
|
||||
#define BEING_SHOCKED (1<<3) //Whether this thing is currently (already) being shocked by a tesla
|
||||
#define DANGEROUS_POSSESSION (1<<4) //Admin possession yes/no
|
||||
#define ON_BLUEPRINTS (1<<5) //Are we visible on the station blueprints at roundstart?
|
||||
#define UNIQUE_RENAME (1<<6) //can you customize the description/name of the thing?
|
||||
#define USES_TGUI (1<<7) //put on things that use tgui on ui_interact instead of custom/old UI.
|
||||
#define FROZEN (1<<8)
|
||||
#define SHOVABLE_ONTO (1<<9) //called on turf.shove_act() to consider whether an object should have a niche effect (defined in their own shove_act()) when someone is pushed onto it, or do a sanity CanPass() check.
|
||||
#define BLOCK_Z_FALL (1<<10)
|
||||
|
||||
// If you add new ones, be sure to add them to /obj/Initialize as well for complete mapping support
|
||||
|
||||
// Flags for the item_flags var on /obj/item
|
||||
|
||||
#define BEING_REMOVED (1<<0)
|
||||
#define IN_INVENTORY (1<<1) //is this item equipped into an inventory slot or hand of a mob? used for tooltips
|
||||
#define FORCE_STRING_OVERRIDE (1<<2) //used for tooltips
|
||||
#define NEEDS_PERMIT (1<<3) //Used by security bots to determine if this item is safe for public use.
|
||||
#define SLOWS_WHILE_IN_HAND (1<<4)
|
||||
#define NO_MAT_REDEMPTION (1<<5) //Stops you from putting things like an RCD or other items into an ORM or protolathe for materials.
|
||||
#define DROPDEL (1<<6) //When dropped, it calls qdel on itself
|
||||
#define NOBLUDGEON (1<<7) //when an item has this it produces no "X has been hit by Y with Z" message in the default attackby()
|
||||
#define ABSTRACT (1<<8) //for all things that are technically items but used for various different stuff
|
||||
#define IMMUTABLE_SLOW (1<<9) //When players should not be able to change the slowdown of the item (Speed potions, ect)
|
||||
#define SURGICAL_TOOL (1<<10) //Tool commonly used for surgery: won't attack targets in an active surgical operation on help intent (in case of mistakes)
|
||||
#define NO_UNIFORM_REQUIRED (1<<11) //Can be worn on certain slots (currently belt and id) that would otherwise require an uniform.
|
||||
#define NO_ATTACK_CHAIN_SOFT_STAMCRIT (1<<12) //Entirely blocks melee_attack_chain() if user is soft stamcritted. Uses getStaminaLoss() to check at this point in time. THIS DOES NOT BLOCK RANGED AFTERATTACK()S, ONLY MELEE RANGE AFTERATTACK()S.
|
||||
|
||||
// Flags for the clothing_flags var on /obj/item/clothing
|
||||
|
||||
#define LAVAPROTECT (1<<0)
|
||||
#define STOPSPRESSUREDAMAGE (1<<1) //SUIT and HEAD items which stop pressure damage. To stop you taking all pressure damage you must have both a suit and head item with this flag.
|
||||
#define BLOCK_GAS_SMOKE_EFFECT (1<<2) //blocks the effect that chemical clouds would have on a mob --glasses, mask and helmets ONLY!
|
||||
#define ALLOWINTERNALS (1<<3) //mask allows internals
|
||||
#define NOSLIP (1<<4) //prevents from slipping on wet floors, in space etc
|
||||
#define NOSLIP_ICE (1<<5) //prevents from slipping on frozen floors
|
||||
#define THICKMATERIAL (1<<6) //prevents syringes, parapens and hypos if the external suit or helmet (if targeting head) has this flag. Example: space suits, biosuit, bombsuits, thick suits that cover your body.
|
||||
#define VOICEBOX_TOGGLABLE (1<<7) //The voicebox in this clothing can be toggled.
|
||||
#define VOICEBOX_DISABLED (1<<8) //The voicebox is currently turned off.
|
||||
#define IGNORE_HAT_TOSS (1<<9) //Hats with negative effects when worn (i.e the tinfoil hat).
|
||||
#define SCAN_REAGENTS (1<<10) // Allows helmets and glasses to scan reagents.
|
||||
|
||||
// Flags for the organ_flags var on /obj/item/organ
|
||||
|
||||
#define ORGAN_SYNTHETIC (1<<0) //Synthetic organs, or cybernetic organs. Reacts to EMPs and don't deteriorate or heal
|
||||
#define ORGAN_FROZEN (1<<1) //Frozen organs, don't deteriorate
|
||||
#define ORGAN_FAILING (1<<2) //Failing organs perform damaging effects until replaced or fixed
|
||||
#define ORGAN_EXTERNAL (1<<3) //Was this organ implanted/inserted/etc, if true will not be removed during species change.
|
||||
#define ORGAN_VITAL (1<<4) //Currently only the brain
|
||||
#define ORGAN_NO_SPOIL (1<<5) //Do not spoil under any circumstances
|
||||
#define ORGAN_NO_DISMEMBERMENT (1<<6) //Immune to disembowelment.
|
||||
@@ -0,0 +1,14 @@
|
||||
/// This atom should be ricocheted off of from its inherent properties using standard % chance handling.
|
||||
#define PROJECTILE_RICOCHET_YES 1
|
||||
/// This atom should not be ricocheted off of from its inherent properties.
|
||||
#define PROJECTILE_RICOCHET_NO 2
|
||||
/// This atom should prevent any kind of projectile ricochet from its inherent properties.
|
||||
#define PROJECTILE_RICOCHET_PREVENT 3
|
||||
/// This atom should force a projectile ricochet from its inherent properties.
|
||||
#define PROJECTILE_RICOCHET_FORCE 4
|
||||
|
||||
//bullet_act() return values
|
||||
#define BULLET_ACT_HIT "HIT" //It's a successful hit, whatever that means in the context of the thing it's hitting.
|
||||
#define BULLET_ACT_BLOCK "BLOCK" //It's a blocked hit, whatever that means in the context of the thing it's hitting.
|
||||
#define BULLET_ACT_FORCE_PIERCE "PIERCE" //It pierces through the object regardless of the bullet being piercing by default.
|
||||
#define BULLET_ACT_TURF "TURF" //It hit us but it should hit something on the same turf too. Usually used for turfs.
|
||||
@@ -27,6 +27,7 @@
|
||||
#define BOT_NAV 15 // computing navigation
|
||||
#define BOT_WAIT_FOR_NAV 16 // waiting for nav computation
|
||||
#define BOT_NO_ROUTE 17 // no destination beacon found (or no route)
|
||||
#define BOT_TIPPED 18 // someone tipped a medibot over ;_;
|
||||
|
||||
//Bot types
|
||||
#define SEC_BOT (1<<0) // Secutritrons (Beepsky) and ED-209s
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#define SHUTTLE_STRANDED "stranded"
|
||||
#define SHUTTLE_ESCAPE "escape"
|
||||
#define SHUTTLE_ENDGAME "endgame: game over"
|
||||
#define SHUTTLE_RECHARGING "recharging"
|
||||
#define SHUTTLE_PREARRIVAL "landing"
|
||||
|
||||
#define EMERGENCY_IDLE_OR_RECALLED (SSshuttle.emergency && ((SSshuttle.emergency.mode == SHUTTLE_IDLE) || (SSshuttle.emergency.mode == SHUTTLE_RECALL)))
|
||||
#define EMERGENCY_ESCAPED_OR_ENDGAMED (SSshuttle.emergency && ((SSshuttle.emergency.mode == SHUTTLE_ESCAPE) || (SSshuttle.emergency.mode == SHUTTLE_ENDGAME)))
|
||||
|
||||
@@ -6,10 +6,26 @@
|
||||
#define RETURN_TYPE(X) set SpacemanDMM_return_type = X
|
||||
#define SHOULD_CALL_PARENT(X) set SpacemanDMM_should_call_parent = X
|
||||
#define UNLINT(X) SpacemanDMM_unlint(X)
|
||||
#define SHOULD_NOT_OVERRIDE(X) set SpacemanDMM_should_not_override = X
|
||||
#define SHOULD_NOT_SLEEP(X) set SpacemanDMM_should_not_sleep = X
|
||||
#define SHOULD_BE_PURE(X) set SpacemanDMM_should_be_pure = X
|
||||
#define PRIVATE_PROC(X) set SpacemanDMM_private_proc = X
|
||||
#define PROTECTED_PROC(X) set SpacemanDMM_protected_proc = X
|
||||
#define VAR_FINAL var/SpacemanDMM_final
|
||||
#define VAR_PRIVATE var/SpacemanDMM_private
|
||||
#define VAR_PROTECTED var/SpacemanDMM_protected
|
||||
#else
|
||||
#define RETURN_TYPE(X)
|
||||
#define SHOULD_CALL_PARENT(X)
|
||||
#define UNLINT(X) X
|
||||
#define SHOULD_NOT_OVERRIDE(X)
|
||||
#define SHOULD_NOT_SLEEP(X)
|
||||
#define SHOULD_BE_PURE(X)
|
||||
#define PRIVATE_PROC(X)
|
||||
#define PROTECTED_PROC(X)
|
||||
#define VAR_FINAL var
|
||||
#define VAR_PRIVATE var
|
||||
#define VAR_PROTECTED var
|
||||
#endif
|
||||
|
||||
/world/proc/enable_debugger()
|
||||
|
||||
@@ -96,6 +96,8 @@
|
||||
|
||||
#define STATUS_EFFECT_SPASMS /datum/status_effect/spasms //causes random muscle spasms
|
||||
|
||||
#define STATUS_EFFECT_FAKE_VIRUS /datum/status_effect/fake_virus //gives you fluff messages for cough, sneeze, headache, etc but without an actual virus
|
||||
|
||||
#define STATUS_EFFECT_BREASTS_ENLARGEMENT /datum/status_effect/chem/breast_enlarger //Applied slowdown due to the ominous bulk.
|
||||
|
||||
#define STATUS_EFFECT_PENIS_ENLARGEMENT /datum/status_effect/chem/penis_enlarger //More applied slowdown, just like the above.
|
||||
|
||||
@@ -24,7 +24,7 @@ GLOBAL_LIST_INIT(default_weight_class_to_volume, list(
|
||||
// Let's keep all of this in one place. given what we put above anyways..
|
||||
|
||||
// volume amount for items
|
||||
#define ITEM_VOLUME_DISK DEFAULT_VOLUME_TINY
|
||||
#define ITEM_VOLUME_DISK 1
|
||||
|
||||
// #define SAMPLE_VOLUME_AMOUNT 2
|
||||
|
||||
@@ -36,4 +36,5 @@ GLOBAL_LIST_INIT(default_weight_class_to_volume, list(
|
||||
#define STORAGE_VOLUME_BACKPACK (DEFAULT_VOLUME_NORMAL * 7)
|
||||
#define STORAGE_VOLUME_DUFFLEBAG (DEFAULT_VOLUME_NORMAL * 10)
|
||||
#define STORAGE_VOLUME_BAG_OF_HOLDING (DEFAULT_VOLUME_NORMAL * 20)
|
||||
|
||||
#define STORAGE_VOLUME_CHEMISTRY_BAG (DEFAULT_VOLUME_TINY * 50)
|
||||
#define STORAGE_VOLUME_PILL_BOTTLE (DEFAULT_VOLUME_TINY * 7)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#define VALENTINES "Valentine's Day"
|
||||
#define APRIL_FOOLS "April Fool's Day"
|
||||
#define EASTER "Easter"
|
||||
#define PRIDE_MONTH "Pride Month"
|
||||
#define HALLOWEEN "Halloween"
|
||||
#define CHRISTMAS "Christmas"
|
||||
#define FESTIVE_SEASON "Festive Season"
|
||||
@@ -38,6 +39,8 @@ When using time2text(), please use "DDD" to find the weekday. Refrain from using
|
||||
#define SATURDAY "Sat"
|
||||
#define SUNDAY "Sun"
|
||||
|
||||
#define WEEKDAY2NUM(D) (D == SUNDAY ? 1 : D == MONDAY ? 2 : D == TUESDAY ? 3 : D == WEDNESDAY ? 4 : D == THURSDAY ? 5 : D == FRIDAY ? 6 : 7) //this looks ugly, but switch statements can't be used as vars, so *shrug
|
||||
|
||||
#define SECONDS *10
|
||||
|
||||
#define MINUTES SECONDS*60
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
#define TRAIT_BLIND "blind"
|
||||
#define TRAIT_MUTE "mute"
|
||||
#define TRAIT_EMOTEMUTE "emotemute"
|
||||
#define TRAIT_LOOC_MUTE "looc_mute" //Just like unconsciousness, it disables LOOC salt.
|
||||
#define TRAIT_AOOC_MUTE "aooc_mute" //Same as above but for AOOC.
|
||||
#define TRAIT_DEAF "deaf"
|
||||
#define TRAIT_NEARSIGHT "nearsighted"
|
||||
#define TRAIT_FAT "fat"
|
||||
@@ -194,6 +196,7 @@
|
||||
#define TRAIT_NO_ALCOHOL "alcohol_intolerance"
|
||||
#define TRAIT_MUTATION_STASIS "mutation_stasis" //Prevents processed genetics mutations from processing.
|
||||
#define TRAIT_FAST_PUMP "fast_pump"
|
||||
#define TRAIT_NICE_SHOT "nice_shot" //hnnnnnnnggggg..... you're pretty good....
|
||||
|
||||
// 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)
|
||||
@@ -254,7 +257,7 @@
|
||||
#define BOOK_TRAIT "granter (book)" // knowledge is power
|
||||
|
||||
// unique trait sources, still defines
|
||||
#define STATUE_MUTE "statue"
|
||||
#define STATUE_TRAIT "statue"
|
||||
#define CLONING_POD_TRAIT "cloning-pod"
|
||||
#define VIRTUAL_REALITY_TRAIT "vr_trait"
|
||||
#define CHANGELING_DRAIN "drain"
|
||||
@@ -295,3 +298,8 @@
|
||||
#define CLOWNOP_TRAIT "clown-op"
|
||||
#define MEGAFAUNA_TRAIT "megafauna"
|
||||
#define DEATHSQUAD_TRAIT "deathsquad"
|
||||
/// This trait is added by the active directional block system.
|
||||
#define ACTIVE_BLOCK_TRAIT "active_block"
|
||||
/// This trait is added by the parry system.
|
||||
#define ACTIVE_PARRY_TRAIT "active_parry"
|
||||
#define STICKY_NODROP "sticky-nodrop" //sticky nodrop sounds like a bad soundcloud rapper's name
|
||||
@@ -55,7 +55,7 @@
|
||||
WRITE_LOG(GLOB.world_game_log, "ADMIN: DSAY: [text]")
|
||||
|
||||
/proc/log_consent(text)
|
||||
WRITE_LOG(GLOB.world_game_log,"CONSENT: [text]")
|
||||
WRITE_LOG(GLOB.world_game_log, "CONSENT: [text]")
|
||||
|
||||
/* All other items are public. */
|
||||
/proc/log_game(text)
|
||||
@@ -66,6 +66,9 @@
|
||||
if (CONFIG_GET(flag/log_virus))
|
||||
WRITE_LOG(GLOB.world_virus_log, "VIRUS: [text]")
|
||||
|
||||
/proc/log_asset(text)
|
||||
WRITE_LOG(GLOB.world_asset_log, "ASSET: [text]")
|
||||
|
||||
/proc/log_access(text)
|
||||
if (CONFIG_GET(flag/log_access))
|
||||
WRITE_LOG(GLOB.world_game_log, "ACCESS: [text]")
|
||||
|
||||
@@ -170,6 +170,7 @@ GLOBAL_LIST_INIT(typecache_powerfailure_safe_areas, typecacheof(/area/engine/eng
|
||||
newA.setup(str)
|
||||
newA.set_dynamic_lighting()
|
||||
newA.has_gravity = oldA.has_gravity
|
||||
newA.noteleport = oldA.noteleport
|
||||
else
|
||||
newA = area_choice
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ GLOBAL_VAR_INIT(cmp_field, "name")
|
||||
var/a_sign = num2sign(initial(A.value) * -1)
|
||||
var/b_sign = num2sign(initial(B.value) * -1)
|
||||
|
||||
// Neutral traits go last.
|
||||
// Neutral traits go last
|
||||
if(a_sign == 0)
|
||||
a_sign = 2
|
||||
if(b_sign == 0)
|
||||
|
||||
@@ -0,0 +1,323 @@
|
||||
/**
|
||||
* Higher overhead "advanced" version of do_after.
|
||||
* @params
|
||||
* - atom/user is the atom doing the action or the "physical" user
|
||||
* - delay is time in deciseconds
|
||||
* - atom/target is the atom the action is being done to, defaults to user
|
||||
* - do_after_flags see __DEFINES/flags/do_after.dm for details.
|
||||
* - datum/callback/extra_checks - Every time this ticks, extra_checks() is invoked with (user, delay, target, time_left, do_after_flags, required_mobility_flags, required_combat_flags, mob_redirect, stage, initially_held_item, tool).
|
||||
* Stage can be DO_AFTER_STARTING, DO_AFTER_PROGRESSING, DO_AFTER_FINISHING
|
||||
* If it returns DO_AFTER_STOP, this breaks.
|
||||
* If it returns nothing, all other checks are done.
|
||||
* If it returns DO_AFTER_PROCEED, all other checks are ignored.
|
||||
* - required_mobility_flags is checked with CHECK_ALL_MOBILITY. Will immediately fail if the user isn't a mob.
|
||||
* - requried_combat_flags is checked with CHECK_MULTIPLE_BITFIELDS. Will immediately fail if the user isn't a mob.
|
||||
* - mob/living/mob_redirect - advanced option: If this is specified, movement and mobility/combat flag checks will use this instead of user. Progressbars will also go to this.
|
||||
* - obj/item/tool - The tool we're using. See do_after flags for details.
|
||||
*/
|
||||
#define INVOKE_CALLBACK cb_return = extra_checks?.Invoke(user, delay, target, world.time - starttime, do_after_flags, required_mobility_flags, required_combat_flags, mob_redirect, stage, initially_held_item, tool)
|
||||
#define CHECK_FLAG_FAILURE ((required_mobility_flags || required_combat_flags) && (!living_user || (required_mobility_flags && !CHECK_ALL_MOBILITY(living_user, required_mobility_flags)) || (required_combat_flags && !CHECK_MULTIPLE_BITFIELDS(living_user.combat_flags, required_combat_flags))))
|
||||
#define TIMELEFT (world.time - starttime)
|
||||
/proc/do_after_advanced(atom/user, delay, atom/target, do_after_flags, datum/callback/extra_checks, required_mobility_flags, required_combat_flags, mob/living/mob_redirect, obj/item/tool)
|
||||
// CHECK AND SET VARIABLES
|
||||
if(!user)
|
||||
return FALSE
|
||||
if(!target)
|
||||
target = user
|
||||
if((user.loc == null) || (target.loc == null))
|
||||
return FALSE
|
||||
var/mob/living/living_user = mob_redirect
|
||||
if(!living_user && isliving(user))
|
||||
living_user = user
|
||||
var/stage = DO_AFTER_STARTING
|
||||
var/startlocuser = user.loc
|
||||
var/startloctarget = target.loc
|
||||
var/turf/userturf = get_turf(user)
|
||||
var/turf/targetturf = get_turf(target)
|
||||
if(!userturf || !targetturf)
|
||||
return FALSE
|
||||
if((do_after_flags & DO_AFTER_REQUIRES_USER_ON_TURF) && !isturf(user.loc))
|
||||
return FALSE
|
||||
var/starttime = world.time
|
||||
var/endtime = world.time + delay
|
||||
var/obj/item/initially_held_item = mob_redirect?.get_active_held_item()
|
||||
if(!(do_after_flags & DO_AFTER_NO_COEFFICIENT) && living_user)
|
||||
delay *= living_user.do_after_coefficent()
|
||||
var/atom/movable/AM_user = ismovable(user) && user
|
||||
var/drifting = AM_user?.Process_Spacemove(NONE) && AM_user.inertia_dir
|
||||
var/initial_dx = targetturf.x - userturf.x
|
||||
var/initial_dy = targetturf.y - userturf.y
|
||||
var/dx = initial_dx
|
||||
var/dy = initial_dy
|
||||
// DO OUR STARTING CHECKS
|
||||
var/cb_return
|
||||
INVOKE_CALLBACK
|
||||
if(cb_return == DO_AFTER_STOP)
|
||||
return FALSE
|
||||
else if(cb_return != DO_AFTER_PROCEED)
|
||||
if(CHECK_FLAG_FAILURE)
|
||||
return FALSE
|
||||
// SETUP LOOP
|
||||
var/datum/progressbar/progbar
|
||||
if(living_user)
|
||||
if(!(do_after_flags & DO_AFTER_NO_PROGRESSBAR))
|
||||
progbar = new(living_user, delay, target)
|
||||
// MAIN LOOP
|
||||
. = TRUE
|
||||
if(!delay)
|
||||
return
|
||||
var/obj/item/held
|
||||
var/locchanged
|
||||
var/ctu
|
||||
var/ctt
|
||||
while(world.time < endtime)
|
||||
stoplag(1)
|
||||
progbar?.update(TIMELEFT)
|
||||
if(QDELETED(user) || QDELETED(target) || (user.loc == null) || (target.loc == null))
|
||||
. = FALSE
|
||||
break
|
||||
INVOKE_CALLBACK
|
||||
if(cb_return == DO_AFTER_STOP)
|
||||
. = FALSE
|
||||
break
|
||||
else if(cb_return == DO_AFTER_PROCEED)
|
||||
continue
|
||||
// otherwise, go through our normal checks.
|
||||
if(((do_after_flags & DO_AFTER_DISALLOW_MOVING_ABSOLUTE_USER) && (user.loc != startlocuser)) || ((do_after_flags & DO_AFTER_DISALLOW_MOVING_ABSOLUTE_TARGET) && (target.loc != startloctarget)))
|
||||
. = FALSE
|
||||
break
|
||||
else if(do_after_flags & DO_AFTER_DISALLOW_MOVING_RELATIVE)
|
||||
ctu = get_turf(user)
|
||||
ctt = get_turf(target)
|
||||
locchanged = (userturf != ctu) || (targetturf != ctt)
|
||||
userturf = ctu
|
||||
targetturf = ctt
|
||||
dx = targetturf.x - userturf.x
|
||||
dy = targetturf.y - userturf.y
|
||||
if((dx != initial_dx) || (dy != initial_dy))
|
||||
. = FALSE
|
||||
break
|
||||
if(locchanged && !drifting && !(do_after_flags & DO_AFTER_ALLOW_NONSPACEDRIFT_RELATIVITY))
|
||||
. = FALSE
|
||||
break
|
||||
if(!AM_user.inertia_dir)
|
||||
drifting = FALSE
|
||||
if((do_after_flags & DO_AFTER_REQUIRES_USER_ON_TURF) && !isturf(user.loc))
|
||||
return FALSE
|
||||
if(CHECK_FLAG_FAILURE)
|
||||
. = FALSE
|
||||
break
|
||||
held = living_user?.get_active_held_item()
|
||||
if((do_after_flags & DO_AFTER_DISALLOW_ACTIVE_ITEM_CHANGE) && (held != (tool || initially_held_item)))
|
||||
. = FALSE
|
||||
break
|
||||
if((do_after_flags & DO_AFTER_REQUIRE_FREE_HAND_OR_TOOL) && (!living_user?.is_holding(tool) && !length(living_user?.get_empty_held_indexes())))
|
||||
. = FALSE
|
||||
break
|
||||
|
||||
// CLEANUP
|
||||
qdel(progbar)
|
||||
// If we failed, just return.
|
||||
if(!.)
|
||||
return FALSE
|
||||
// DO FINISHING CHECKS
|
||||
if(QDELETED(user) || QDELETED(target))
|
||||
return FALSE
|
||||
INVOKE_CALLBACK
|
||||
if(cb_return == DO_AFTER_STOP)
|
||||
return FALSE
|
||||
else if(cb_return == DO_AFTER_PROCEED)
|
||||
return TRUE
|
||||
if(CHECK_FLAG_FAILURE)
|
||||
return FALSE
|
||||
if(((do_after_flags & DO_AFTER_DISALLOW_MOVING_ABSOLUTE_USER) && (user.loc != startlocuser)) || ((do_after_flags & DO_AFTER_DISALLOW_MOVING_ABSOLUTE_TARGET) && (target.loc != startloctarget)))
|
||||
return FALSE
|
||||
else if(do_after_flags & DO_AFTER_DISALLOW_MOVING_RELATIVE)
|
||||
ctu = get_turf(user)
|
||||
ctt = get_turf(target)
|
||||
locchanged = (userturf != ctu) || (targetturf != ctt)
|
||||
userturf = ctu
|
||||
targetturf = ctt
|
||||
dx = targetturf.x - userturf.x
|
||||
dy = targetturf.y - userturf.y
|
||||
if((dx != initial_dx) || (dy != initial_dy))
|
||||
return FALSE
|
||||
if(locchanged && !drifting && !(do_after_flags & DO_AFTER_ALLOW_NONSPACEDRIFT_RELATIVITY))
|
||||
return FALSE
|
||||
if((do_after_flags & DO_AFTER_REQUIRES_USER_ON_TURF) && !isturf(user.loc))
|
||||
return FALSE
|
||||
held = living_user?.get_active_held_item()
|
||||
if((do_after_flags & DO_AFTER_DISALLOW_ACTIVE_ITEM_CHANGE) && (held != (tool || initially_held_item)))
|
||||
return FALSE
|
||||
if((do_after_flags & DO_AFTER_REQUIRE_FREE_HAND_OR_TOOL) && (!living_user?.is_holding(tool) && !length(living_user?.get_empty_held_indexes())))
|
||||
return FALSE
|
||||
|
||||
#undef INVOKE_CALLBACK
|
||||
#undef CHECK_FLAG_FAILURE
|
||||
|
||||
/proc/do_mob(mob/user , mob/target, time = 30, uninterruptible = 0, progress = 1, datum/callback/extra_checks = null, ignorehelditem = FALSE, resume_time = 0 SECONDS)
|
||||
if(!user || !target)
|
||||
return 0
|
||||
var/user_loc = user.loc
|
||||
|
||||
var/drifting = 0
|
||||
if(!user.Process_Spacemove(0) && user.inertia_dir)
|
||||
drifting = 1
|
||||
|
||||
var/target_loc = target.loc
|
||||
|
||||
var/holding = user.get_active_held_item()
|
||||
var/datum/progressbar/progbar
|
||||
if (progress)
|
||||
progbar = new(user, time, target)
|
||||
|
||||
var/endtime = world.time+time
|
||||
var/starttime = world.time
|
||||
. = 1
|
||||
while (world.time + resume_time < endtime)
|
||||
stoplag(1)
|
||||
if (progress)
|
||||
progbar.update(world.time - starttime + resume_time)
|
||||
if(QDELETED(user) || QDELETED(target))
|
||||
. = 0
|
||||
break
|
||||
if(uninterruptible)
|
||||
continue
|
||||
|
||||
if(drifting && !user.inertia_dir)
|
||||
drifting = 0
|
||||
user_loc = user.loc
|
||||
|
||||
if((!drifting && user.loc != user_loc) || target.loc != target_loc || (!ignorehelditem && user.get_active_held_item() != holding) || user.incapacitated() || user.lying || (extra_checks && !extra_checks.Invoke()))
|
||||
. = 0
|
||||
break
|
||||
if (progress)
|
||||
qdel(progbar)
|
||||
|
||||
|
||||
//some additional checks as a callback for for do_afters that want to break on losing health or on the mob taking action
|
||||
/mob/proc/break_do_after_checks(list/checked_health, check_clicks)
|
||||
if(check_clicks && next_move > world.time)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
//pass a list in the format list("health" = mob's health var) to check health during this
|
||||
/mob/living/break_do_after_checks(list/checked_health, check_clicks)
|
||||
if(islist(checked_health))
|
||||
if(health < checked_health["health"])
|
||||
return FALSE
|
||||
checked_health["health"] = health
|
||||
return ..()
|
||||
|
||||
/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), resume_time = 0 SECONDS)
|
||||
if(!user)
|
||||
return 0
|
||||
var/atom/Tloc = null
|
||||
if(target && !isturf(target))
|
||||
Tloc = target.loc
|
||||
|
||||
var/atom/Uloc = user.loc
|
||||
|
||||
var/drifting = 0
|
||||
if(!user.Process_Spacemove(0) && user.inertia_dir)
|
||||
drifting = 1
|
||||
|
||||
var/holding = user.get_active_held_item()
|
||||
|
||||
var/holdingnull = 1 //User's hand started out empty, check for an empty hand
|
||||
if(holding)
|
||||
holdingnull = 0 //Users hand started holding something, check to see if it's still holding that
|
||||
|
||||
delay *= user.do_after_coefficent()
|
||||
|
||||
var/datum/progressbar/progbar
|
||||
if (progress)
|
||||
progbar = new(user, delay, target)
|
||||
|
||||
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 + resume_time < endtime)
|
||||
stoplag(1)
|
||||
if (progress)
|
||||
progbar.update(world.time - starttime + resume_time)
|
||||
|
||||
if(drifting && !user.inertia_dir)
|
||||
drifting = 0
|
||||
Uloc = user.loc
|
||||
|
||||
if(L && !CHECK_ALL_MOBILITY(L, required_mobility_flags))
|
||||
. = 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)
|
||||
. = 0
|
||||
break
|
||||
|
||||
if(needhand)
|
||||
//This might seem like an odd check, but you can still need a hand even when it's empty
|
||||
//i.e the hand is used to pull some item/tool out of the construction
|
||||
if(!holdingnull)
|
||||
if(!holding)
|
||||
. = 0
|
||||
break
|
||||
if(user.get_active_held_item() != holding)
|
||||
. = 0
|
||||
break
|
||||
if (progress)
|
||||
qdel(progbar)
|
||||
|
||||
/mob/proc/do_after_coefficent() // This gets added to the delay on a do_after, default 1
|
||||
. = 1
|
||||
return
|
||||
|
||||
/proc/do_after_mob(mob/user, var/list/targets, time = 30, uninterruptible = 0, progress = 1, datum/callback/extra_checks)
|
||||
if(!user || !targets)
|
||||
return 0
|
||||
if(!islist(targets))
|
||||
targets = list(targets)
|
||||
var/user_loc = user.loc
|
||||
|
||||
var/drifting = 0
|
||||
if(!user.Process_Spacemove(0) && user.inertia_dir)
|
||||
drifting = 1
|
||||
|
||||
var/list/originalloc = list()
|
||||
for(var/atom/target in targets)
|
||||
originalloc[target] = target.loc
|
||||
|
||||
var/holding = user.get_active_held_item()
|
||||
var/datum/progressbar/progbar
|
||||
if(progress)
|
||||
progbar = new(user, time, targets[1])
|
||||
|
||||
var/endtime = world.time + time
|
||||
var/starttime = world.time
|
||||
. = 1
|
||||
mainloop:
|
||||
while(world.time < endtime)
|
||||
stoplag(1)
|
||||
if(progress)
|
||||
progbar.update(world.time - starttime)
|
||||
if(QDELETED(user) || !targets)
|
||||
. = 0
|
||||
break
|
||||
if(uninterruptible)
|
||||
continue
|
||||
|
||||
if(drifting && !user.inertia_dir)
|
||||
drifting = 0
|
||||
user_loc = user.loc
|
||||
|
||||
for(var/atom/target in targets)
|
||||
if((!drifting && user_loc != user.loc) || QDELETED(target) || originalloc[target] != target.loc || user.get_active_held_item() != holding || user.incapacitated() || user.lying || (extra_checks && !extra_checks.Invoke()))
|
||||
. = 0
|
||||
break mainloop
|
||||
if(progbar)
|
||||
qdel(progbar)
|
||||
@@ -544,22 +544,6 @@
|
||||
var/obj/machinery/announcement_system/announcer = pick(GLOB.announcement_systems)
|
||||
announcer.announce("ARRIVAL", character.real_name, rank, list()) //make the list empty to make it announce it in common
|
||||
|
||||
/proc/GetHexColors(const/hexa)
|
||||
return list(
|
||||
GetRedPart(hexa)/ 255,
|
||||
GetGreenPart(hexa)/ 255,
|
||||
GetBluePart(hexa)/ 255
|
||||
)
|
||||
|
||||
/proc/GetRedPart(const/hexa)
|
||||
return hex2num(copytext(hexa, 2, 4))
|
||||
|
||||
/proc/GetGreenPart(const/hexa)
|
||||
return hex2num(copytext(hexa, 4, 6))
|
||||
|
||||
/proc/GetBluePart(const/hexa)
|
||||
return hex2num(copytext(hexa, 6, 8))
|
||||
|
||||
/proc/lavaland_equipment_pressure_check(turf/T)
|
||||
. = FALSE
|
||||
if(!istype(T))
|
||||
|
||||
+1
-167
@@ -216,6 +216,7 @@
|
||||
"ipc_screen" = snowflake_ipc_antenna_list ? pick(snowflake_ipc_antenna_list) : "None",
|
||||
"ipc_antenna" = "None",
|
||||
"flavor_text" = "",
|
||||
"silicon_flavor_text" = "",
|
||||
"meat_type" = "Mammalian",
|
||||
"body_model" = body_model,
|
||||
"body_size" = RESIZE_DEFAULT_SIZE
|
||||
@@ -319,173 +320,6 @@ GLOBAL_LIST_EMPTY(species_list)
|
||||
else
|
||||
return "unknown"
|
||||
|
||||
/proc/do_mob(mob/user , mob/target, time = 30, uninterruptible = 0, progress = 1, datum/callback/extra_checks = null, ignorehelditem = FALSE, resume_time = 0 SECONDS)
|
||||
if(!user || !target)
|
||||
return 0
|
||||
var/user_loc = user.loc
|
||||
|
||||
var/drifting = 0
|
||||
if(!user.Process_Spacemove(0) && user.inertia_dir)
|
||||
drifting = 1
|
||||
|
||||
var/target_loc = target.loc
|
||||
|
||||
var/holding = user.get_active_held_item()
|
||||
var/datum/progressbar/progbar
|
||||
if (progress)
|
||||
progbar = new(user, time, target)
|
||||
|
||||
var/endtime = world.time+time
|
||||
var/starttime = world.time
|
||||
. = 1
|
||||
while (world.time + resume_time < endtime)
|
||||
stoplag(1)
|
||||
if (progress)
|
||||
progbar.update(world.time - starttime + resume_time)
|
||||
if(QDELETED(user) || QDELETED(target))
|
||||
. = 0
|
||||
break
|
||||
if(uninterruptible)
|
||||
continue
|
||||
|
||||
if(drifting && !user.inertia_dir)
|
||||
drifting = 0
|
||||
user_loc = user.loc
|
||||
|
||||
if((!drifting && user.loc != user_loc) || target.loc != target_loc || (!ignorehelditem && user.get_active_held_item() != holding) || user.incapacitated() || user.lying || (extra_checks && !extra_checks.Invoke()))
|
||||
. = 0
|
||||
break
|
||||
if (progress)
|
||||
qdel(progbar)
|
||||
|
||||
|
||||
//some additional checks as a callback for for do_afters that want to break on losing health or on the mob taking action
|
||||
/mob/proc/break_do_after_checks(list/checked_health, check_clicks)
|
||||
if(check_clicks && next_move > world.time)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
//pass a list in the format list("health" = mob's health var) to check health during this
|
||||
/mob/living/break_do_after_checks(list/checked_health, check_clicks)
|
||||
if(islist(checked_health))
|
||||
if(health < checked_health["health"])
|
||||
return FALSE
|
||||
checked_health["health"] = health
|
||||
return ..()
|
||||
|
||||
/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), resume_time = 0 SECONDS)
|
||||
if(!user)
|
||||
return 0
|
||||
var/atom/Tloc = null
|
||||
if(target && !isturf(target))
|
||||
Tloc = target.loc
|
||||
|
||||
var/atom/Uloc = user.loc
|
||||
|
||||
var/drifting = 0
|
||||
if(!user.Process_Spacemove(0) && user.inertia_dir)
|
||||
drifting = 1
|
||||
|
||||
var/holding = user.get_active_held_item()
|
||||
|
||||
var/holdingnull = 1 //User's hand started out empty, check for an empty hand
|
||||
if(holding)
|
||||
holdingnull = 0 //Users hand started holding something, check to see if it's still holding that
|
||||
|
||||
delay *= user.do_after_coefficent()
|
||||
|
||||
var/datum/progressbar/progbar
|
||||
if (progress)
|
||||
progbar = new(user, delay, target)
|
||||
|
||||
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 + resume_time < endtime)
|
||||
stoplag(1)
|
||||
if (progress)
|
||||
progbar.update(world.time - starttime + resume_time)
|
||||
|
||||
if(drifting && !user.inertia_dir)
|
||||
drifting = 0
|
||||
Uloc = user.loc
|
||||
|
||||
if(L && !CHECK_ALL_MOBILITY(L, required_mobility_flags))
|
||||
. = 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)
|
||||
. = 0
|
||||
break
|
||||
|
||||
if(needhand)
|
||||
//This might seem like an odd check, but you can still need a hand even when it's empty
|
||||
//i.e the hand is used to pull some item/tool out of the construction
|
||||
if(!holdingnull)
|
||||
if(!holding)
|
||||
. = 0
|
||||
break
|
||||
if(user.get_active_held_item() != holding)
|
||||
. = 0
|
||||
break
|
||||
if (progress)
|
||||
qdel(progbar)
|
||||
|
||||
/mob/proc/do_after_coefficent() // This gets added to the delay on a do_after, default 1
|
||||
. = 1
|
||||
return
|
||||
|
||||
/proc/do_after_mob(mob/user, var/list/targets, time = 30, uninterruptible = 0, progress = 1, datum/callback/extra_checks)
|
||||
if(!user || !targets)
|
||||
return 0
|
||||
if(!islist(targets))
|
||||
targets = list(targets)
|
||||
var/user_loc = user.loc
|
||||
|
||||
var/drifting = 0
|
||||
if(!user.Process_Spacemove(0) && user.inertia_dir)
|
||||
drifting = 1
|
||||
|
||||
var/list/originalloc = list()
|
||||
for(var/atom/target in targets)
|
||||
originalloc[target] = target.loc
|
||||
|
||||
var/holding = user.get_active_held_item()
|
||||
var/datum/progressbar/progbar
|
||||
if(progress)
|
||||
progbar = new(user, time, targets[1])
|
||||
|
||||
var/endtime = world.time + time
|
||||
var/starttime = world.time
|
||||
. = 1
|
||||
mainloop:
|
||||
while(world.time < endtime)
|
||||
stoplag(1)
|
||||
if(progress)
|
||||
progbar.update(world.time - starttime)
|
||||
if(QDELETED(user) || !targets)
|
||||
. = 0
|
||||
break
|
||||
if(uninterruptible)
|
||||
continue
|
||||
|
||||
if(drifting && !user.inertia_dir)
|
||||
drifting = 0
|
||||
user_loc = user.loc
|
||||
|
||||
for(var/atom/target in targets)
|
||||
if((!drifting && user_loc != user.loc) || QDELETED(target) || originalloc[target] != target.loc || user.get_active_held_item() != holding || user.incapacitated() || user.lying || (extra_checks && !extra_checks.Invoke()))
|
||||
. = 0
|
||||
break mainloop
|
||||
if(progbar)
|
||||
qdel(progbar)
|
||||
|
||||
/proc/is_species(A, species_datum)
|
||||
. = FALSE
|
||||
if(ishuman(A))
|
||||
|
||||
@@ -675,12 +675,6 @@ Turf and target are separate in case you want to teleport some distance from a t
|
||||
loc = loc.loc
|
||||
return null
|
||||
|
||||
//For objects that should embed, but make no sense being is_sharp or is_pointed()
|
||||
//e.g: rods
|
||||
GLOBAL_LIST_INIT(can_embed_types, typecacheof(list(
|
||||
/obj/item/stack/rods,
|
||||
/obj/item/pipe)))
|
||||
|
||||
/*
|
||||
Checks if that loc and dir has an item on the wall
|
||||
*/
|
||||
|
||||
@@ -49,6 +49,8 @@ GLOBAL_LIST_INIT(bitfields, list(
|
||||
"DROPDEL" = DROPDEL,
|
||||
"NOBLUDGEON" = NOBLUDGEON,
|
||||
"ABSTRACT" = ABSTRACT,
|
||||
"ITEM_CAN_BLOCK" = ITEM_CAN_BLOCK,
|
||||
"ITEM_CAN_PARRY" = ITEM_CAN_PARRY
|
||||
),
|
||||
"admin_flags" = list(
|
||||
"BUILDMODE" = R_BUILDMODE,
|
||||
@@ -123,7 +125,7 @@ GLOBAL_LIST_INIT(bitfields, list(
|
||||
"UNUSED_RESERVATION_TURF_1" = UNUSED_RESERVATION_TURF_1,
|
||||
"CAN_BE_DIRTY_1" = CAN_BE_DIRTY_1,
|
||||
"HEAR_1" = HEAR_1,
|
||||
"CHECK_RICOCHET_1" = CHECK_RICOCHET_1,
|
||||
"DEFAULT_RICOCHET_1" = DEFAULT_RICOCHET_1,
|
||||
"CONDUCT_1" = CONDUCT_1,
|
||||
"NO_LAVA_GEN_1" = NO_LAVA_GEN_1,
|
||||
"NODECONSTRUCT_1" = NODECONSTRUCT_1,
|
||||
@@ -138,6 +140,10 @@ GLOBAL_LIST_INIT(bitfields, list(
|
||||
"BLOCK_FACE_ATOM_1" = BLOCK_FACE_ATOM_1,
|
||||
"PREVENT_CONTENTS_EXPLOSION_1" = PREVENT_CONTENTS_EXPLOSION_1
|
||||
),
|
||||
"flags_ricochet" = list(
|
||||
"RICOCHET_SHINY" = RICOCHET_SHINY,
|
||||
"RICOCHET_HARD" = RICOCHET_HARD
|
||||
),
|
||||
"clothing_flags" = list(
|
||||
"LAVAPROTECT" = LAVAPROTECT,
|
||||
"STOPSPRESSUREDAMAGE" = STOPSPRESSUREDAMAGE,
|
||||
|
||||
@@ -223,3 +223,6 @@ GLOBAL_LIST_INIT(station_numerals, greek_letters + phonetic_alphabet + numbers_a
|
||||
GLOBAL_LIST_INIT(admiral_messages, list("Do you know how expensive these stations are?","Stop wasting my time.","I was sleeping, thanks a lot.","Stand and fight you cowards!","You knew the risks coming in.","Stop being paranoid.","Whatever's broken just build a new one.","No.", "<i>null</i>","<i>Error: No comment given.</i>", "It's a good day to die!"))
|
||||
|
||||
GLOBAL_LIST_INIT(redacted_strings, list("\[REDACTED\]", "\[CLASSIFIED\]", "\[ARCHIVED\]", "\[EXPLETIVE DELETED\]", "\[EXPUNGED\]", "\[INFORMATION ABOVE YOUR SECURITY CLEARANCE\]", "\[MOVE ALONG CITIZEN\]", "\[NOTHING TO SEE HERE\]", "\[ACCESS DENIED\]"))
|
||||
|
||||
|
||||
GLOBAL_LIST_INIT(wisdoms, world.file2list("strings/wisdoms.txt"))
|
||||
|
||||
@@ -51,7 +51,7 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
|
||||
/obj/item/airlock_painter = 1,
|
||||
/obj/item/stack/cable_coil/random = 4,
|
||||
/obj/item/stack/cable_coil/random/five = 6,
|
||||
/obj/item/stack/medical/bruise_pack = 1,
|
||||
/obj/item/stack/medical/suture = 1,
|
||||
/obj/item/stack/rods/ten = 9,
|
||||
/obj/item/stack/rods/twentyfive = 1,
|
||||
/obj/item/stack/rods/fifty = 1,
|
||||
@@ -116,5 +116,24 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
|
||||
/obj/item/autosurgeon/testicles = 1,
|
||||
/obj/item/storage/box/marshmallow = 2,
|
||||
/obj/item/clothing/gloves/tackler/offbrand = 1,
|
||||
/obj/item/stack/sticky_tape = 1,
|
||||
"" = 3
|
||||
))
|
||||
|
||||
GLOBAL_LIST_INIT(ratking_trash, list(//Garbage: used by the regal rat mob when spawning garbage.
|
||||
/obj/item/cigbutt,
|
||||
/obj/item/trash/cheesie,
|
||||
/obj/item/trash/candy,
|
||||
/obj/item/trash/chips,
|
||||
/obj/item/trash/pistachios,
|
||||
/obj/item/trash/plate,
|
||||
/obj/item/trash/popcorn,
|
||||
/obj/item/trash/raisins,
|
||||
/obj/item/trash/sosjerky,
|
||||
/obj/item/trash/syndi_cakes))
|
||||
|
||||
GLOBAL_LIST_INIT(ratking_coins, list(//Coins: Used by the regal rat mob when spawning coins.
|
||||
/obj/item/coin/iron,
|
||||
/obj/item/coin/silver,
|
||||
/obj/item/coin/plastic,
|
||||
/obj/item/coin/titanium))
|
||||
@@ -19,6 +19,7 @@
|
||||
#define POLL_IGNORE_WIZARD "wizard"
|
||||
#define POLL_IGNORE_CLONE "clone"
|
||||
#define POLL_IGNORE_CONTRACTOR_SUPPORT "contractor_support"
|
||||
#define POLL_IGNORE_FUGITIVE "fugitive"
|
||||
|
||||
GLOBAL_LIST_INIT(poll_ignore_desc, list(
|
||||
POLL_IGNORE_SENTIENCE_POTION = "Sentience potion",
|
||||
@@ -39,7 +40,8 @@ GLOBAL_LIST_INIT(poll_ignore_desc, list(
|
||||
POLL_IGNORE_DEMON = "Demons",
|
||||
POLL_IGNORE_WIZARD = "Wizards",
|
||||
POLL_IGNORE_CLONE = "Defective/SDGF clones",
|
||||
POLL_IGNORE_CONTRACTOR_SUPPORT = "Contractor Support Unit"
|
||||
POLL_IGNORE_CONTRACTOR_SUPPORT = "Contractor Support Unit",
|
||||
POLL_IGNORE_FUGITIVE = "Fugitive Hunter"
|
||||
))
|
||||
GLOBAL_LIST_INIT(poll_ignore, init_poll_ignore())
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ GLOBAL_VAR(world_job_debug_log)
|
||||
GLOBAL_PROTECT(world_job_debug_log)
|
||||
GLOBAL_VAR(world_virus_log)
|
||||
GLOBAL_PROTECT(world_virus_log)
|
||||
GLOBAL_VAR(world_asset_log)
|
||||
GLOBAL_PROTECT(world_asset_log)
|
||||
GLOBAL_VAR(world_map_error_log)
|
||||
GLOBAL_PROTECT(world_map_error_log)
|
||||
GLOBAL_VAR(subsystem_log)
|
||||
|
||||
@@ -93,6 +93,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_PASSTABLE" = TRAIT_PASSTABLE,
|
||||
"TRAIT_GIANT" = TRAIT_GIANT,
|
||||
"TRAIT_DWARF" = TRAIT_DWARF,
|
||||
"TRAIT_NICE_SHOT" = TRAIT_NICE_SHOT,
|
||||
"TRAIT_COMBAT_MODE_LOCKED" = TRAIT_COMBAT_MODE_LOCKED,
|
||||
"TRAIT_SPRINT_LOCKED" = TRAIT_SPRINT_LOCKED,
|
||||
"TRAIT_AUTO_CATCH_ITEM" = TRAIT_AUTO_CATCH_ITEM,
|
||||
@@ -116,7 +117,8 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_MASO" = TRAIT_MASO,
|
||||
"TRAIT_HIGH_BLOOD" = TRAIT_HIGH_BLOOD,
|
||||
"TRAIT_EMPATH" = TRAIT_EMPATH,
|
||||
"TRAIT_FRIENDLY" = TRAIT_FRIENDLY
|
||||
"TRAIT_FRIENDLY" = TRAIT_FRIENDLY,
|
||||
"TRAIT_NICE_SHOT" = TRAIT_NICE_SHOT
|
||||
),
|
||||
/obj/item/bodypart = list(
|
||||
"TRAIT_PARALYSIS" = TRAIT_PARALYSIS
|
||||
|
||||
@@ -17,10 +17,14 @@
|
||||
// eg: 10*0.5 = 5 deciseconds of delay
|
||||
// DOES NOT EFFECT THE BASE 1 DECISECOND DELAY OF NEXT_CLICK
|
||||
|
||||
/mob/proc/timeToNextMove()
|
||||
return max(0, next_move - world.time)
|
||||
|
||||
/mob/proc/changeNext_move(num)
|
||||
next_move = world.time + ((num+next_move_adjust)*next_move_modifier)
|
||||
|
||||
/mob/living/changeNext_move(num)
|
||||
last_click_move = next_move
|
||||
var/mod = next_move_modifier
|
||||
var/adj = next_move_adjust
|
||||
for(var/i in status_effects)
|
||||
@@ -72,7 +76,7 @@
|
||||
if(check_click_intercept(params,A))
|
||||
return
|
||||
|
||||
if(notransform)
|
||||
if(mob_transforming)
|
||||
return
|
||||
|
||||
if(SEND_SIGNAL(src, COMSIG_MOB_CLICKON, A, params) & COMSIG_MOB_CANCEL_CLICKON)
|
||||
|
||||
@@ -242,7 +242,7 @@ If you're feeling frisky, examine yourself and click the underlined item to pull
|
||||
|
||||
/obj/screen/alert/embeddedobject/Click()
|
||||
if(isliving(usr))
|
||||
var/mob/living/carbon/human/M = usr
|
||||
var/mob/living/carbon/M = usr
|
||||
return M.help_shake_act(M)
|
||||
|
||||
/obj/screen/alert/weightless
|
||||
|
||||
@@ -7,21 +7,17 @@
|
||||
*and lastly
|
||||
*afterattack. The return value does not matter.
|
||||
*/
|
||||
/obj/item/proc/melee_attack_chain(mob/user, atom/target, params)
|
||||
/obj/item/proc/melee_attack_chain(mob/user, atom/target, params, flags, damage_multiplier = 1)
|
||||
if(isliving(user))
|
||||
var/mob/living/L = user
|
||||
if(item_flags & NO_ATTACK_CHAIN_SOFT_STAMCRIT)
|
||||
if(IS_STAMCRIT(L))
|
||||
to_chat(L, "<span class='warning'>You are too exhausted to swing [src]!</span>")
|
||||
return
|
||||
if(!CHECK_MOBILITY(L, MOBILITY_USE))
|
||||
if(!CHECK_MOBILITY(L, MOBILITY_USE) && !(flags & ATTACKCHAIN_PARRY_COUNTERATTACK))
|
||||
to_chat(L, "<span class='warning'>You are unable to swing [src] right now!</span>")
|
||||
return
|
||||
if(tool_behaviour && target.tool_act(user, src, tool_behaviour))
|
||||
return
|
||||
if(pre_attack(target, user, params))
|
||||
return
|
||||
if(target.attackby(src,user, params))
|
||||
if(target.attackby(src, user, params, flags, damage_multiplier))
|
||||
return
|
||||
if(QDELETED(src) || QDELETED(target))
|
||||
return
|
||||
@@ -56,23 +52,20 @@
|
||||
/obj/attackby(obj/item/I, mob/living/user, params)
|
||||
return ..() || ((obj_flags & CAN_BE_HIT) && I.attack_obj(src, user))
|
||||
|
||||
/mob/living/attackby(obj/item/I, mob/living/user, params)
|
||||
/mob/living/attackby(obj/item/I, mob/living/user, params, attackchain_flags, damage_multiplier)
|
||||
if(..())
|
||||
return TRUE
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
return I.attack(src, user)
|
||||
I.attack_delay_done = FALSE //Should be set TRUE in pre_attacked_by()
|
||||
. = I.attack(src, user, attackchain_flags, damage_multiplier)
|
||||
if(!I.attack_delay_done) //Otherwise, pre_attacked_by() should handle it.
|
||||
user.changeNext_move(I.click_delay)
|
||||
|
||||
/obj/item/proc/attack(mob/living/M, mob/living/user)
|
||||
/obj/item/proc/attack(mob/living/M, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user) & COMPONENT_ITEM_NO_ATTACK)
|
||||
return
|
||||
SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, M, user)
|
||||
if(item_flags & NOBLUDGEON)
|
||||
return
|
||||
|
||||
if(IS_STAMCRIT(user)) // CIT CHANGE - makes it impossible to attack in stamina softcrit
|
||||
to_chat(user, "<span class='warning'>You're too exhausted.</span>") // CIT CHANGE - ditto
|
||||
return // CIT CHANGE - ditto
|
||||
|
||||
if(force && damtype != STAMINA && HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
to_chat(user, "<span class='warning'>You don't want to harm other living beings!</span>")
|
||||
return
|
||||
@@ -86,12 +79,14 @@
|
||||
M.lastattackerckey = user.ckey
|
||||
|
||||
user.do_attack_animation(M)
|
||||
M.attacked_by(src, user)
|
||||
M.attacked_by(src, user, attackchain_flags, damage_multiplier)
|
||||
|
||||
log_combat(user, M, "attacked", src.name, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])")
|
||||
add_fingerprint(user)
|
||||
|
||||
user.adjustStaminaLossBuffered(getweight(user, STAM_COST_ATTACK_MOB_MULT))//CIT CHANGE - makes attacking things cause stamina loss
|
||||
var/weight = getweight(user, STAM_COST_ATTACK_MOB_MULT) //CIT CHANGE - makes attacking things cause stamina loss
|
||||
if(weight)
|
||||
user.adjustStaminaLossBuffered(weight)
|
||||
|
||||
//the equivalent of the standard version of attack() but for object targets.
|
||||
/obj/item/proc/attack_obj(obj/O, mob/living/user)
|
||||
@@ -99,23 +94,31 @@
|
||||
return
|
||||
if(item_flags & NOBLUDGEON)
|
||||
return
|
||||
if(IS_STAMCRIT(user)) // CIT CHANGE - makes it impossible to attack in stamina softcrit
|
||||
to_chat(user, "<span class='warning'>You're too exhausted.</span>") // CIT CHANGE - ditto
|
||||
return // CIT CHANGE - ditto
|
||||
user.adjustStaminaLossBuffered(getweight(user, STAM_COST_ATTACK_OBJ_MULT))//CIT CHANGE - makes attacking things cause stamina loss
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
user.do_attack_animation(O)
|
||||
O.attacked_by(src, user)
|
||||
if(!O.attacked_by(src, user))
|
||||
user.changeNext_move(click_delay)
|
||||
var/weight = getweight(user, STAM_COST_ATTACK_OBJ_MULT)
|
||||
if(weight)
|
||||
user.adjustStaminaLossBuffered(weight)//CIT CHANGE - makes attacking things cause stamina loss
|
||||
|
||||
/atom/movable/proc/attacked_by()
|
||||
return
|
||||
|
||||
/obj/attacked_by(obj/item/I, mob/living/user)
|
||||
var/totitemdamage = I.force
|
||||
/obj/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
var/totitemdamage = I.force * damage_multiplier
|
||||
var/bad_trait
|
||||
if(!SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
totitemdamage *= 0.5
|
||||
|
||||
var/stamloss = user.getStaminaLoss()
|
||||
var/next_move_mult = 1
|
||||
if(stamloss > STAMINA_NEAR_SOFTCRIT) //The more tired you are, the less damage you do.
|
||||
var/penalty = (stamloss - STAMINA_NEAR_SOFTCRIT)/(STAMINA_NEAR_CRIT - STAMINA_NEAR_SOFTCRIT)*STAM_CRIT_ITEM_ATTACK_PENALTY
|
||||
totitemdamage *= 1 - penalty
|
||||
next_move_mult += penalty*STAM_CRIT_ITEM_ATTACK_DELAY
|
||||
user.changeNext_move(I.click_delay*next_move_mult)
|
||||
|
||||
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
bad_trait = SKILL_COMBAT_MODE //blacklist combat skills.
|
||||
|
||||
if(I.used_skills && user.mind)
|
||||
if(totitemdamage)
|
||||
totitemdamage = user.mind.item_action_skills_mod(I, totitemdamage, I.skill_difficulty, SKILL_ATTACK_OBJ, bad_trait)
|
||||
@@ -123,17 +126,21 @@
|
||||
if(!(I.used_skills[skill] & SKILL_TRAIN_ATTACK_OBJ))
|
||||
continue
|
||||
user.mind.auto_gain_experience(skill, I.skill_gain)
|
||||
|
||||
if(totitemdamage)
|
||||
visible_message("<span class='danger'>[user] has hit [src] with [I]!</span>", null, null, COMBAT_MESSAGE_RANGE)
|
||||
//only witnesses close by and the victim see a hit message.
|
||||
log_combat(user, src, "attacked", I)
|
||||
take_damage(totitemdamage, I.damtype, "melee", 1)
|
||||
return TRUE
|
||||
|
||||
/mob/living/attacked_by(obj/item/I, mob/living/user)
|
||||
var/totitemdamage = pre_attacked_by(I, user)
|
||||
if((user != src) && mob_run_block(I, totitemdamage, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user, null, null) & BLOCK_SUCCESS)
|
||||
/mob/living/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
var/list/block_return = list()
|
||||
var/totitemdamage = pre_attacked_by(I, user) * damage_multiplier
|
||||
if((user != src) && mob_run_block(I, totitemdamage, "the [I.name]", ((attackchain_flags & ATTACKCHAIN_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE) | ATTACK_TYPE_MELEE, I.armour_penetration, user, null, block_return) & BLOCK_SUCCESS)
|
||||
return FALSE
|
||||
send_item_attack_message(I, user)
|
||||
totitemdamage = block_calculate_resultant_damage(totitemdamage, block_return)
|
||||
send_item_attack_message(I, user, null, totitemdamage)
|
||||
I.do_stagger_action(src, user, totitemdamage)
|
||||
if(I.force)
|
||||
apply_damage(totitemdamage, I.damtype)
|
||||
@@ -146,22 +153,40 @@
|
||||
user.add_mob_blood(src)
|
||||
return TRUE //successful attack
|
||||
|
||||
/mob/living/simple_animal/attacked_by(obj/item/I, mob/living/user)
|
||||
/mob/living/simple_animal/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
if(I.force < force_threshold || I.damtype == STAMINA)
|
||||
playsound(loc, 'sound/weapons/tap.ogg', I.get_clamped_volume(), 1, -1)
|
||||
user.changeNext_move(I.click_delay) //pre_attacked_by not called
|
||||
else
|
||||
return ..()
|
||||
|
||||
/mob/living/proc/pre_attacked_by(obj/item/I, mob/living/user)
|
||||
. = I.force
|
||||
if(!.)
|
||||
return
|
||||
|
||||
var/stamloss = user.getStaminaLoss()
|
||||
var/stam_mobility_mult = 1
|
||||
var/next_move_mult = 1
|
||||
if(stamloss > STAMINA_NEAR_SOFTCRIT) //The more tired you are, the less damage you do.
|
||||
var/penalty = (stamloss - STAMINA_NEAR_SOFTCRIT)/(STAMINA_NEAR_CRIT - STAMINA_NEAR_SOFTCRIT)*STAM_CRIT_ITEM_ATTACK_PENALTY
|
||||
stam_mobility_mult -= penalty
|
||||
next_move_mult += penalty*STAM_CRIT_ITEM_ATTACK_DELAY
|
||||
if(stam_mobility_mult > LYING_DAMAGE_PENALTY && !CHECK_MOBILITY(user, MOBILITY_STAND)) //damage penalty for fighting prone, doesn't stack with the above.
|
||||
stam_mobility_mult = LYING_DAMAGE_PENALTY
|
||||
. *= stam_mobility_mult
|
||||
user.changeNext_move(I.click_delay*next_move_mult)
|
||||
I.attack_delay_done = TRUE
|
||||
|
||||
var/bad_trait
|
||||
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
. *= 0.5
|
||||
bad_trait = SKILL_COMBAT_MODE //blacklist combat skills.
|
||||
if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
. *= 1.5
|
||||
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
|
||||
. *= 0.5
|
||||
if(!(I.item_flags & NO_COMBAT_MODE_FORCE_MODIFIER))
|
||||
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
bad_trait = SKILL_COMBAT_MODE //blacklist combat skills.
|
||||
if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE))
|
||||
. *= 0.5
|
||||
else if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
. *= 1.5
|
||||
|
||||
if(!user.mind || !I.used_skills)
|
||||
return
|
||||
if(.)
|
||||
@@ -171,7 +196,6 @@
|
||||
continue
|
||||
user.mind.auto_gain_experience(skill, I.skill_gain)
|
||||
|
||||
|
||||
// Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person.
|
||||
// Click parameters is the params string from byond Click() code, see that documentation.
|
||||
/obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
@@ -185,10 +209,12 @@
|
||||
else
|
||||
return clamp(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100
|
||||
|
||||
/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area)
|
||||
/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area, current_force)
|
||||
var/message_verb = "attacked"
|
||||
if(I.attack_verb && I.attack_verb.len)
|
||||
message_verb = "[pick(I.attack_verb)]"
|
||||
if(current_force < I.force * FEEBLE_ATTACK_MSG_THRESHOLD)
|
||||
message_verb = "[pick("feebly", "limply", "saplessly")] [message_verb]"
|
||||
else if(!I.force)
|
||||
return
|
||||
var/message_hit_area = ""
|
||||
@@ -215,6 +241,8 @@
|
||||
bad_trait = SKILL_COMBAT_MODE
|
||||
if(used_skills && user.mind)
|
||||
. = user.mind.item_action_skills_mod(src, ., skill_difficulty, trait, bad_trait, FALSE)
|
||||
var/total_health = user.getStaminaLoss()
|
||||
. = clamp(., 0, STAMINA_NEAR_CRIT - total_health)
|
||||
|
||||
/// How long this staggers for. 0 and negatives supported.
|
||||
/obj/item/proc/melee_stagger_duration(force_override)
|
||||
|
||||
@@ -435,6 +435,10 @@
|
||||
config_entry_value = 64
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/ratcap
|
||||
config_entry_value = 64
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/flag/disable_stambuffer
|
||||
|
||||
/datum/config_entry/keyed_list/box_random_engine
|
||||
@@ -517,3 +521,10 @@
|
||||
* Camera mobs, AIs, ghosts and some other are of course exempt from this. This also doesn't influence simplemob AI, for the best.
|
||||
*/
|
||||
/datum/config_entry/flag/use_field_of_vision
|
||||
|
||||
//Shuttle size limiter
|
||||
/datum/config_entry/number/max_shuttle_count
|
||||
config_entry_value = 6
|
||||
|
||||
/datum/config_entry/number/max_shuttle_size
|
||||
config_entry_value = 250
|
||||
|
||||
@@ -76,6 +76,8 @@ SUBSYSTEM_DEF(air)
|
||||
var/list/pipenet_rebuilds = pipenets_needing_rebuilt
|
||||
for(var/thing in pipenet_rebuilds)
|
||||
var/obj/machinery/atmospherics/AT = thing
|
||||
if(!istype(AT))
|
||||
continue
|
||||
AT.build_network()
|
||||
cost_rebuilds = MC_AVERAGE(cost_rebuilds, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
|
||||
pipenets_needing_rebuilt.Cut()
|
||||
|
||||
@@ -6,17 +6,7 @@ SUBSYSTEM_DEF(assets)
|
||||
var/list/preload = list()
|
||||
|
||||
/datum/controller/subsystem/assets/Initialize(timeofday)
|
||||
|
||||
var/list/priority_assets = list(
|
||||
/datum/asset/simple/oui_theme_nano,
|
||||
/datum/asset/simple/goonchat
|
||||
)
|
||||
|
||||
for(var/type in priority_assets)
|
||||
var/datum/asset/A = new type()
|
||||
A.register()
|
||||
|
||||
for(var/type in typesof(/datum/asset) - (priority_assets | list(/datum/asset, /datum/asset/simple)))
|
||||
for(var/type in typesof(/datum/asset))
|
||||
var/datum/asset/A = type
|
||||
if (type != initial(A._abstract))
|
||||
get_asset_datum(type)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
SUBSYSTEM_DEF(minimaps)
|
||||
name = "Minimaps"
|
||||
flags = SS_NO_FIRE
|
||||
var/list/station_minimaps
|
||||
var/datum/minimap_group/station_minimap
|
||||
var/list/station_minimaps = list()
|
||||
var/datum/minimap_group/station_minimap = null
|
||||
|
||||
/datum/controller/subsystem/minimaps/Initialize()
|
||||
if(!CONFIG_GET(flag/minimaps_enabled))
|
||||
@@ -12,9 +12,9 @@ SUBSYSTEM_DEF(minimaps)
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/minimaps/proc/build_minimaps()
|
||||
station_minimaps = list()
|
||||
for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION))
|
||||
var/datum/space_level/SL = SSmapping.get_level(z)
|
||||
var/name = (SL.name == initial(SL.name))? "[z] - Station" : "[z] - [SL.name]"
|
||||
station_minimaps += new /datum/minimap(z, name = name)
|
||||
|
||||
station_minimap = new(station_minimaps, "Station")
|
||||
|
||||
@@ -8,6 +8,7 @@ SUBSYSTEM_DEF(mobs)
|
||||
var/static/list/clients_by_zlevel[][]
|
||||
var/static/list/dead_players_by_zlevel[][] = list(list()) // Needs to support zlevel 1 here, MaxZChanged only happens when z2 is created and new_players can login before that.
|
||||
var/static/list/cubemonkeys = list()
|
||||
var/static/list/cheeserats = list()
|
||||
|
||||
/datum/controller/subsystem/mobs/stat_entry()
|
||||
..("P:[GLOB.mob_living_list.len]")
|
||||
|
||||
@@ -23,7 +23,7 @@ SUBSYSTEM_DEF(npcpool)
|
||||
var/mob/living/simple_animal/SA = currentrun[currentrun.len]
|
||||
--currentrun.len
|
||||
|
||||
if(!SA.ckey && !SA.notransform)
|
||||
if(!SA.ckey && !SA.mob_transforming)
|
||||
if(SA.stat != DEAD)
|
||||
SA.handle_automated_movement()
|
||||
if(SA.stat != DEAD)
|
||||
|
||||
@@ -307,7 +307,11 @@ SUBSYSTEM_DEF(research)
|
||||
for(var/A in subtypesof(/obj/item/seeds))
|
||||
var/obj/item/seeds/S = A
|
||||
var/list/L = list()
|
||||
L[TECHWEB_POINT_TYPE_GENERIC] = 50 + initial(S.rarity) * 2
|
||||
//First we get are yield and rarity and times it by two
|
||||
//Then we subtract production and maturation, making it so faster growing plants are better for RnD
|
||||
//Then we add in lifespan and potency,
|
||||
//A basic seed can be worth 268 points if its the best it can be.
|
||||
L[TECHWEB_POINT_TYPE_GENERIC] = 50 + initial(S.rarity) * 2 + initial(S.yield) * 2 - initial(S.maturation) - initial(S.production) + initial(S.lifespan) + initial(S.potency)
|
||||
techweb_point_items[S] = L
|
||||
|
||||
return ..()
|
||||
|
||||
@@ -409,7 +409,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
var/mob/living = player.transfer_character()
|
||||
if(living)
|
||||
qdel(player)
|
||||
living.notransform = TRUE
|
||||
living.mob_transforming = TRUE
|
||||
if(living.client)
|
||||
if (living.client.prefs && living.client.prefs.auto_ooc)
|
||||
if (living.client.prefs.chat_toggles & CHAT_OOC)
|
||||
@@ -423,7 +423,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
/datum/controller/subsystem/ticker/proc/release_characters(list/livings)
|
||||
for(var/I in livings)
|
||||
var/mob/living/L = I
|
||||
L.notransform = FALSE
|
||||
L.mob_transforming = FALSE
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/send_tip_of_the_round()
|
||||
var/m
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
paralysis_type = "legs"
|
||||
resilience = TRAUMA_RESILIENCE_ABSOLUTE
|
||||
|
||||
/datum/brain_trauma/severe/paralysis/spinesnapped
|
||||
random_gain = FALSE
|
||||
paralysis_type = "legs"
|
||||
resilience = TRAUMA_RESILIENCE_LOBOTOMY
|
||||
|
||||
/datum/brain_trauma/severe/narcolepsy
|
||||
name = "Narcolepsy"
|
||||
desc = "Patient may involuntarily fall asleep during normal activities."
|
||||
|
||||
@@ -123,7 +123,9 @@
|
||||
trauma = _trauma
|
||||
return ..()
|
||||
|
||||
/mob/living/split_personality/Life()
|
||||
/mob/living/split_personality/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(QDELETED(body))
|
||||
qdel(src) //in case trauma deletion doesn't already do it
|
||||
|
||||
@@ -132,8 +134,6 @@
|
||||
trauma.switch_personalities()
|
||||
qdel(trauma)
|
||||
|
||||
..()
|
||||
|
||||
/mob/living/split_personality/Login()
|
||||
..()
|
||||
to_chat(src, "<span class='notice'>As a split personality, you cannot do anything but observe. However, you will eventually gain control of your body, switching places with the current personality.</span>")
|
||||
|
||||
@@ -97,20 +97,20 @@
|
||||
[get_footer()]
|
||||
"}
|
||||
|
||||
/datum/browser/proc/open(use_onclose = 1)
|
||||
/datum/browser/proc/open(use_onclose = TRUE)
|
||||
if(isnull(window_id)) //null check because this can potentially nuke goonchat
|
||||
WARNING("Browser [title] tried to open with a null ID")
|
||||
to_chat(user, "<span class='userdanger'>The [title] browser you tried to open failed a sanity check! Please report this on github!</span>")
|
||||
return
|
||||
var/window_size = ""
|
||||
if (width && height)
|
||||
if(width && height)
|
||||
window_size = "size=[width]x[height];"
|
||||
if (stylesheets.len)
|
||||
send_asset_list(user, stylesheets, verify=FALSE)
|
||||
if (scripts.len)
|
||||
send_asset_list(user, scripts, verify=FALSE)
|
||||
if(stylesheets.len)
|
||||
send_asset_list(user, stylesheets)
|
||||
if(scripts.len)
|
||||
send_asset_list(user, scripts)
|
||||
user << browse(get_content(), "window=[window_id];[window_size][window_options]")
|
||||
if (use_onclose)
|
||||
if(use_onclose)
|
||||
setup_onclose()
|
||||
|
||||
/datum/browser/proc/setup_onclose()
|
||||
@@ -157,7 +157,7 @@
|
||||
close()
|
||||
|
||||
//designed as a drop in replacement for alert(); functions the same. (outside of needing User specified)
|
||||
/proc/tgalert(var/mob/User, Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000)
|
||||
/proc/tgalert(mob/User, Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000)
|
||||
if (!User)
|
||||
User = usr
|
||||
switch(askuser(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout))
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
// BYOND Bug #2563917
|
||||
// Construct text
|
||||
var/static/regex/html_metachars = new(@"&[A-Za-z]{1,7};", "g")
|
||||
var/complete_text = "<span class='center maptext [extra_classes.Join(" ")]' style='color: [tgt_color]'>[text]</span>"
|
||||
var/complete_text = "<span class='center maptext [extra_classes.Join(" ")]' style='color: [tgt_color]'>[owner.say_emphasis(text)]</span>"
|
||||
var/mheight = WXH_TO_HEIGHT(owned_by.MeasureText(replacetext(complete_text, html_metachars, "m"), null, CHAT_MESSAGE_WIDTH))
|
||||
approx_lines = max(1, mheight / CHAT_MESSAGE_APPROX_LHEIGHT)
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ GLOBAL_LIST_EMPTY(cinematics)
|
||||
/datum/cinematic
|
||||
var/id = CINEMATIC_DEFAULT
|
||||
var/list/watching = list() //List of clients watching this
|
||||
var/list/locked = list() //Who had notransform set during the cinematic
|
||||
var/list/locked = list() //Who had mob_transforming set during the cinematic
|
||||
var/is_global = FALSE //Global cinematics will override mob-specific ones
|
||||
var/obj/screen/cinematic/screen
|
||||
var/datum/callback/special_callback //For special effects synced with animation (explosions after the countdown etc)
|
||||
@@ -45,7 +45,7 @@ GLOBAL_LIST_EMPTY(cinematics)
|
||||
GLOB.cinematics -= src
|
||||
QDEL_NULL(screen)
|
||||
for(var/mob/M in locked)
|
||||
M.notransform = FALSE
|
||||
M.mob_transforming = FALSE
|
||||
return ..()
|
||||
|
||||
/datum/cinematic/proc/play(watchers)
|
||||
@@ -70,7 +70,7 @@ GLOBAL_LIST_EMPTY(cinematics)
|
||||
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
if(M in watchers)
|
||||
M.notransform = TRUE //Should this be done for non-global cinematics or even at all ?
|
||||
M.mob_transforming = TRUE //Should this be done for non-global cinematics or even at all ?
|
||||
locked += M
|
||||
//Close watcher ui's
|
||||
SStgui.close_user_uis(M)
|
||||
@@ -79,7 +79,7 @@ GLOBAL_LIST_EMPTY(cinematics)
|
||||
M.client.screen += screen
|
||||
else
|
||||
if(is_global)
|
||||
M.notransform = TRUE
|
||||
M.mob_transforming = TRUE
|
||||
locked += M
|
||||
|
||||
//Actually play it
|
||||
@@ -254,4 +254,4 @@ Nuke.Explosion()
|
||||
|
||||
Narsie()
|
||||
-> Cinematic(CULT,world)
|
||||
*/
|
||||
*/
|
||||
|
||||
@@ -38,8 +38,9 @@
|
||||
parent = raw_args[1]
|
||||
var/list/arguments = raw_args.Copy(2)
|
||||
if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE)
|
||||
stack_trace("Incompatible [type] assigned to a [parent.type]! args: [json_encode(arguments)]")
|
||||
qdel(src, TRUE, TRUE)
|
||||
CRASH("Incompatible [type] assigned to a [parent.type]! args: [json_encode(arguments)]")
|
||||
return
|
||||
|
||||
_JoinParent(parent)
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
AM.visible_message("<span class='boldwarning'>[AM] falls into [parent]!</span>", "<span class='userdanger'>[oblivion_message]</span>")
|
||||
if (isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
L.notransform = TRUE
|
||||
L.mob_transforming = TRUE
|
||||
L.Paralyze(200)
|
||||
|
||||
var/oldtransform = AM.transform
|
||||
|
||||
@@ -119,6 +119,8 @@
|
||||
if(hud_icon)
|
||||
hud_icon.combat_on = FALSE
|
||||
hud_icon.update_icon()
|
||||
source.stop_active_blocking()
|
||||
source.end_parry_sequence()
|
||||
|
||||
///Changes the user direction to (try) keep match the pointer.
|
||||
/datum/component/combat_mode/proc/on_move(atom/movable/source, dir, atom/oldloc, forced)
|
||||
|
||||
@@ -35,17 +35,34 @@ k// PARTS //
|
||||
desc = "A twenty bore shotgun barrel."
|
||||
icon_state = "barrel_shotgun"
|
||||
|
||||
/obj/item/weaponcrafting/improvised_parts/barrel_pistol
|
||||
name = "pistol barrel"
|
||||
desc = "A pipe with a small diameter and some holes finely cut into it. It fits .32 ACP bullets. Probably."
|
||||
icon_state = "barrel_pistol"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
// RECEIVERS
|
||||
|
||||
/obj/item/weaponcrafting/improvised_parts/rifle_receiver
|
||||
name = "bolt action receiver"
|
||||
desc = "A crudely constructed receiver to create an improvised bolt-action breechloaded rifle."
|
||||
desc = "A crudely constructed receiver to create an improvised bolt-action breechloaded rifle. It's generic enough to modify to create other rifles, potentially."
|
||||
icon_state = "receiver_rifle"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
/obj/item/weaponcrafting/improvised_parts/pistol_receiver
|
||||
name = "pistol receiver"
|
||||
desc = "A receiver to connect house and connects all the parts to make an improvised pistol."
|
||||
icon_state = "receiver_pistol"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
/obj/item/weaponcrafting/improvised_parts/laser_receiver
|
||||
name = "energy emitter assembly"
|
||||
desc = "A mixture of components haphazardly wired together to form an energy emitter."
|
||||
icon_state = "laser_assembly"
|
||||
|
||||
/obj/item/weaponcrafting/improvised_parts/shotgun_receiver
|
||||
name = "break-action assembly"
|
||||
desc = "An improvised receiver to create a break-action breechloaded shotgun."
|
||||
desc = "An improvised receiver to create a break-action breechloaded shotgun. Parts of this are still useful if you want to make another type of shotgun, however."
|
||||
icon_state = "receiver_shotgun"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
@@ -62,3 +79,14 @@ k// PARTS //
|
||||
desc = "A crudely fashioned wooden body to help keep higher calibre improvised weapons from blowing themselves apart."
|
||||
icon_state = "wooden_body"
|
||||
|
||||
/obj/item/weaponcrafting/improvised_parts/wooden_grip
|
||||
name = "wooden pistol grip"
|
||||
desc = "A nice wooden grip hollowed out for pistol magazines."
|
||||
icon_state = "wooden_pistolgrip"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
/obj/item/weaponcrafting/improvised_parts/makeshift_lens
|
||||
name = "makeshift focusing lens"
|
||||
desc = "A properly made lens made with actual glassworking tools would perform much better, but this will have to do."
|
||||
icon_state = "focusing_lens"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
|
||||
@@ -124,9 +124,9 @@
|
||||
category = CAT_MISC
|
||||
subcategory = CAT_TOOL
|
||||
|
||||
/datum/crafting_recipe/bruise_pack
|
||||
name = "Bruise Pack"
|
||||
result = /obj/item/stack/medical/bruise_pack/one
|
||||
/datum/crafting_recipe/brute_pack
|
||||
name = "Suture Pack"
|
||||
result = /obj/item/stack/medical/suture/one
|
||||
time = 1
|
||||
reqs = list(/obj/item/stack/medical/gauze = 1,
|
||||
/datum/reagent/medicine/styptic_powder = 10)
|
||||
@@ -134,8 +134,8 @@
|
||||
subcategory = CAT_TOOL
|
||||
|
||||
/datum/crafting_recipe/burn_pack
|
||||
name = "Burn Ointment"
|
||||
result = /obj/item/stack/medical/ointment/one
|
||||
name = "Regenerative Mesh"
|
||||
result = /obj/item/stack/medical/mesh/one
|
||||
time = 1
|
||||
reqs = list(/obj/item/stack/medical/gauze = 1,
|
||||
/datum/reagent/medicine/silver_sulfadiazine = 10)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
|
||||
time = 50
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
subcategory = CAT_OTHER
|
||||
|
||||
/datum/crafting_recipe/pin_removal/check_requirements(mob/user, list/collected_requirements)
|
||||
var/obj/item/gun/G = collected_requirements[/obj/item/gun][1]
|
||||
@@ -22,7 +22,7 @@
|
||||
/obj/item/shield/riot = 1)
|
||||
time = 40
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
subcategory = CAT_MELEE
|
||||
|
||||
/datum/crafting_recipe/strobeshield/New()
|
||||
..()
|
||||
@@ -38,7 +38,7 @@
|
||||
tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
|
||||
time = 100
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
subcategory = CAT_MELEE
|
||||
|
||||
/datum/crafting_recipe/spear
|
||||
name = "Spear"
|
||||
@@ -49,7 +49,7 @@
|
||||
parts = list(/obj/item/shard = 1)
|
||||
time = 40
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
subcategory = CAT_MELEE
|
||||
|
||||
/datum/crafting_recipe/stunprod
|
||||
name = "Stunprod"
|
||||
@@ -59,7 +59,7 @@
|
||||
/obj/item/assembly/igniter = 1)
|
||||
time = 40
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
subcategory = CAT_MELEE
|
||||
|
||||
/datum/crafting_recipe/teleprod
|
||||
name = "Teleprod"
|
||||
@@ -70,7 +70,7 @@
|
||||
/obj/item/stack/ore/bluespace_crystal = 1)
|
||||
time = 40
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
subcategory = CAT_MELEE
|
||||
|
||||
/datum/crafting_recipe/bola
|
||||
name = "Bola"
|
||||
@@ -88,7 +88,7 @@
|
||||
/obj/item/stack/sheet/metal = 1)
|
||||
time = 40
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
subcategory = CAT_MELEE
|
||||
|
||||
/datum/crafting_recipe/tailwhip
|
||||
name = "Liz O' Nine Tails"
|
||||
@@ -97,7 +97,7 @@
|
||||
/obj/item/stack/cable_coil = 1)
|
||||
time = 40
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
subcategory = CAT_MELEE
|
||||
|
||||
/datum/crafting_recipe/catwhip
|
||||
name = "Cat O' Nine Tails"
|
||||
@@ -106,7 +106,7 @@
|
||||
/obj/item/stack/cable_coil = 1)
|
||||
time = 40
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
subcategory = CAT_MELEE
|
||||
|
||||
/datum/crafting_recipe/chainsaw
|
||||
name = "Chainsaw"
|
||||
@@ -117,7 +117,7 @@
|
||||
tools = list(TOOL_WELDER)
|
||||
time = 50
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
subcategory = CAT_MELEE
|
||||
|
||||
//////////////////
|
||||
///BOMB CRAFTING//
|
||||
@@ -134,7 +134,7 @@
|
||||
parts = list(/obj/item/stock_parts/matter_bin = 1, /obj/item/grenade/chem_grenade = 2)
|
||||
time = 30
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
subcategory = CAT_OTHER
|
||||
|
||||
/datum/crafting_recipe/chemical_payload2
|
||||
name = "Chemical Payload (Gibtonite)"
|
||||
@@ -147,7 +147,7 @@
|
||||
parts = list(/obj/item/stock_parts/matter_bin = 1, /obj/item/grenade/chem_grenade = 2)
|
||||
time = 50
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
subcategory = CAT_OTHER
|
||||
|
||||
/datum/crafting_recipe/molotov
|
||||
name = "Molotov"
|
||||
@@ -169,7 +169,7 @@
|
||||
parts = list(/obj/item/reagent_containers/food/drinks/soda_cans = 1)
|
||||
time = 15
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
subcategory = CAT_OTHER
|
||||
|
||||
/datum/crafting_recipe/lance
|
||||
name = "Explosive Lance (Grenade)"
|
||||
@@ -180,7 +180,7 @@
|
||||
/obj/item/grenade = 1)
|
||||
time = 15
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
subcategory = CAT_MELEE
|
||||
|
||||
//////////////////
|
||||
///GUNS CRAFTING//
|
||||
@@ -276,6 +276,49 @@
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
/datum/crafting_recipe/ipistol
|
||||
name = "Improvised Pistol (.32)"
|
||||
result = /obj/item/gun/ballistic/automatic/pistol/improvised/nomag
|
||||
reqs = list(/obj/item/weaponcrafting/improvised_parts/barrel_pistol = 1,
|
||||
/obj/item/weaponcrafting/improvised_parts/pistol_receiver = 1,
|
||||
/obj/item/weaponcrafting/improvised_parts/trigger_assembly = 1,
|
||||
/obj/item/weaponcrafting/improvised_parts/wooden_grip = 1,
|
||||
/obj/item/stack/sheet/plastic = 15,
|
||||
/obj/item/stack/sheet/plasteel = 1)
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WELDER, TOOL_WIRECUTTER)
|
||||
time = 100
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
/datum/crafting_recipe/ilaser
|
||||
name = "Improvised Energy Gun"
|
||||
result = /obj/item/gun/energy/e_gun/old/improvised
|
||||
reqs = list(/obj/item/weaponcrafting/improvised_parts/laser_receiver = 1,
|
||||
/obj/item/weaponcrafting/improvised_parts/trigger_assembly = 1,
|
||||
/obj/item/weaponcrafting/improvised_parts/makeshift_lens = 1,
|
||||
/obj/item/stock_parts/cell = 1,
|
||||
/obj/item/stack/sheet/metal = 10,
|
||||
/obj/item/stack/sheet/plasteel = 5,
|
||||
/obj/item/stack/cable_coil = 10)
|
||||
tools = list(TOOL_SCREWDRIVER)
|
||||
time = 100
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
/datum/crafting_recipe/ilaser/upgraded
|
||||
name = "Improvised Energy Gun Upgrade"
|
||||
result = /obj/item/gun/energy/e_gun/old/improvised/upgraded
|
||||
reqs = list(/obj/item/gun/energy/e_gun/old/improvised = 1,
|
||||
/obj/item/glasswork/glass_base/lens = 1,
|
||||
/obj/item/stock_parts/capacitor/quadratic = 2,
|
||||
/obj/item/stock_parts/micro_laser/ultra = 1,
|
||||
/obj/item/stock_parts/cell/bluespace = 1,
|
||||
/obj/item/stack/cable_coil = 5)
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_MULTITOOL)
|
||||
time = 100
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
//////////////////
|
||||
///AMMO CRAFTING//
|
||||
//////////////////
|
||||
@@ -399,6 +442,17 @@
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_AMMO
|
||||
|
||||
/datum/crafting_recipe/m32acp
|
||||
name = ".32ACP Empty Magazine"
|
||||
result = /obj/item/ammo_box/magazine/m32acp/empty
|
||||
reqs = list(/obj/item/stack/sheet/metal = 3,
|
||||
/obj/item/stack/sheet/plasteel = 1,
|
||||
/obj/item/stack/packageWrap = 1)
|
||||
tools = list(TOOL_WELDER,TOOL_SCREWDRIVER)
|
||||
time = 5
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_AMMO
|
||||
|
||||
////////////////////
|
||||
// PARTS CRAFTING //
|
||||
////////////////////
|
||||
@@ -423,13 +477,24 @@
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_PARTS
|
||||
|
||||
/datum/crafting_recipe/pistol_barrel
|
||||
name = "Improvised Pistol Barrel"
|
||||
result = /obj/item/weaponcrafting/improvised_parts/barrel_pistol
|
||||
reqs = list(/obj/item/pipe = 1,
|
||||
/obj/item/stack/sheet/plasteel = 1)
|
||||
tools = list(TOOL_WELDER,TOOL_SAW)
|
||||
time = 150
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_PARTS
|
||||
|
||||
// RECEIVERS
|
||||
|
||||
/datum/crafting_recipe/rifle_receiver
|
||||
name = "Improvised Rifle Receiver"
|
||||
result = /obj/item/weaponcrafting/improvised_parts/rifle_receiver
|
||||
reqs = list(/obj/item/stack/sheet/metal = 20)
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WELDER) // Rifle is the easiest to craft and can be made at an autolathe, this is a very light kick in the shin for dual-wielding ishotguns.
|
||||
reqs = list(/obj/item/stack/sheet/metal = 10,
|
||||
/obj/item/stack/sheet/plasteel = 1)
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WELDER)
|
||||
time = 50
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_PARTS
|
||||
@@ -439,11 +504,33 @@
|
||||
result = /obj/item/weaponcrafting/improvised_parts/shotgun_receiver
|
||||
reqs = list(/obj/item/stack/sheet/metal = 10,
|
||||
/obj/item/stack/sheet/plasteel = 1)
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WELDER) // Increased cost is to stop dual-wield alpha striking. ishotgun is a rvolver and can be duel-wielded
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WELDER) // Dual wielding has been removed, plasteel is a soft timesink to obtain for most to make mass production harder.
|
||||
time = 50
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_PARTS
|
||||
|
||||
/datum/crafting_recipe/pistol_receiver
|
||||
name = "Improvised Pistol Receiver"
|
||||
result = /obj/item/weaponcrafting/improvised_parts/pistol_receiver
|
||||
reqs = list(/obj/item/stack/sheet/metal = 5,
|
||||
/obj/item/stack/sheet/plasteel = 1)
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WELDER, TOOL_SAW)
|
||||
time = 50
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_PARTS
|
||||
|
||||
/datum/crafting_recipe/laser_receiver
|
||||
name = "Energy Weapon Assembly"
|
||||
result = /obj/item/weaponcrafting/improvised_parts/laser_receiver
|
||||
reqs = list(/obj/item/stack/sheet/metal = 10,
|
||||
/obj/item/stock_parts/capacitor = 2,
|
||||
/obj/item/stock_parts/micro_laser = 1,
|
||||
/obj/item/assembly/prox_sensor = 1)
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_MULTITOOL, TOOL_WELDER) // Prox sensor and multitool for the circuit board, welder for extremely ghetto soldering.
|
||||
time = 150
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_PARTS
|
||||
|
||||
// MISC
|
||||
|
||||
/datum/crafting_recipe/trigger_assembly
|
||||
@@ -455,3 +542,13 @@
|
||||
time = 150
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_PARTS
|
||||
|
||||
/datum/crafting_recipe/makeshift_lens
|
||||
name = "Makeshift Lens"
|
||||
result = /obj/item/weaponcrafting/improvised_parts/makeshift_lens
|
||||
reqs = list(/obj/item/stack/sheet/metal = 1,
|
||||
/obj/item/stack/sheet/glass = 2)
|
||||
tools = list(TOOL_WELDER) // Glassmaking lets you make non-makeshift lenses.
|
||||
time = 50
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_PARTS
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/datum/component/decal
|
||||
dupe_mode = COMPONENT_DUPE_ALLOWED
|
||||
can_transfer = TRUE
|
||||
var/cleanable
|
||||
var/description
|
||||
var/mutable_appearance/pic
|
||||
|
||||
var/first_dir // This only stores the dir arg from init
|
||||
|
||||
/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description, _alpha=255)
|
||||
if(!isatom(parent) || !generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
first_dir = _dir
|
||||
description = _description
|
||||
cleanable = _cleanable
|
||||
|
||||
apply()
|
||||
|
||||
/datum/component/decal/RegisterWithParent()
|
||||
. = ..()
|
||||
if(first_dir)
|
||||
RegisterSignal(parent, COMSIG_ATOM_DIR_CHANGE, .proc/rotate_react)
|
||||
if(cleanable)
|
||||
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_react)
|
||||
if(description)
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/examine)
|
||||
|
||||
/datum/component/decal/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE))
|
||||
|
||||
/datum/component/decal/Destroy()
|
||||
remove()
|
||||
return ..()
|
||||
|
||||
/datum/component/decal/PreTransfer()
|
||||
remove()
|
||||
|
||||
/datum/component/decal/PostTransfer()
|
||||
remove()
|
||||
apply()
|
||||
|
||||
/datum/component/decal/proc/generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha)
|
||||
if(!_icon || !_icon_state)
|
||||
return FALSE
|
||||
// It has to be made from an image or dir breaks because of a byond bug
|
||||
var/temp_image = image(_icon, null, _icon_state, _layer, _dir)
|
||||
pic = new(temp_image)
|
||||
pic.color = _color
|
||||
pic.alpha = _alpha
|
||||
return TRUE
|
||||
|
||||
/datum/component/decal/proc/apply(atom/thing)
|
||||
var/atom/master = thing || parent
|
||||
master.add_overlay(pic, TRUE)
|
||||
if(isitem(master))
|
||||
addtimer(CALLBACK(master, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
|
||||
|
||||
/datum/component/decal/proc/remove(atom/thing)
|
||||
var/atom/master = thing || parent
|
||||
master.cut_overlay(pic, TRUE)
|
||||
if(isitem(master))
|
||||
addtimer(CALLBACK(master, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
|
||||
|
||||
/datum/component/decal/proc/rotate_react(datum/source, old_dir, new_dir)
|
||||
if(old_dir == new_dir)
|
||||
return
|
||||
remove()
|
||||
pic.dir = turn(pic.dir, dir2angle(old_dir) - dir2angle(new_dir))
|
||||
apply()
|
||||
|
||||
/datum/component/decal/proc/clean_react(datum/source, strength)
|
||||
if(strength >= cleanable)
|
||||
qdel(src)
|
||||
|
||||
/datum/component/decal/proc/examine(datum/source, mob/user, list/examine_list)
|
||||
examine_list += description
|
||||
@@ -1,13 +0,0 @@
|
||||
/datum/component/decal/blood
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE
|
||||
|
||||
/datum/component/decal/blood/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_STRENGTH_BLOOD, _color, _layer=ABOVE_OBJ_LAYER)
|
||||
if(!isitem(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
. = ..()
|
||||
RegisterSignal(parent, COMSIG_ATOM_GET_EXAMINE_NAME, .proc/get_examine_name)
|
||||
|
||||
/datum/component/decal/blood/proc/get_examine_name(datum/source, mob/user, list/override)
|
||||
var/atom/A = parent
|
||||
|
||||
return COMPONENT_EXNAME_CHANGED
|
||||
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
This component is responsible for handling individual instances of embedded objects. The embeddable element is what allows an item to be embeddable and stores its embedding stats,
|
||||
and when it impacts and meets the requirements to stick into something, it instantiates an embedded component. Once the item falls out, the component is destroyed, while the
|
||||
element survives to embed another day.
|
||||
|
||||
There are 2 different things that can be embedded presently: carbons, and closed turfs (see: walls)
|
||||
|
||||
- Carbon embedding has all the classical embedding behavior, and tracks more events and signals. The main behaviors and hooks to look for are:
|
||||
-- Every process tick, there is a chance to randomly proc pain, controlled by pain_chance. There may also be a chance for the object to fall out randomly, per fall_chance
|
||||
-- Every time the mob moves, there is a chance to proc jostling pain, controlled by jostle_chance (and only 50% as likely if the mob is walking or crawling)
|
||||
-- Various signals hooking into carbon topic() and the embed removal surgery in order to handle removals.
|
||||
|
||||
- Turf embedding is much simpler. All we do here is draw an overlay of the item's inhand on the turf, hide the item, and create an HTML link in the turf's inspect
|
||||
that allows you to rip the item out. There's nothing dynamic about this, so far less checks.
|
||||
|
||||
|
||||
In addition, there are 2 cases of embedding: embedding, and sticking
|
||||
|
||||
- Embedding involves harmful and dangerous embeds, whether they cause brute damage, stamina damage, or a mix. This is the default behavior for embeddings, for when something is "pointy"
|
||||
|
||||
- Sticking occurs when an item should not cause any harm while embedding (imagine throwing a sticky ball of tape at someone, rather than a shuriken). An item is considered "sticky"
|
||||
when it has 0 for both pain multiplier and jostle pain multiplier. It's a bit arbitrary, but fairly straightforward.
|
||||
|
||||
Stickables differ from embeds in the following ways:
|
||||
-- Text descriptors use phrasing like "X is stuck to Y" rather than "X is embedded in Y"
|
||||
-- There is no slicing sound on impact
|
||||
-- All damage checks and bloodloss are skipped for carbons
|
||||
-- Pointy objects create sparks when embedding into a turf
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/datum/component/embedded
|
||||
dupe_mode = COMPONENT_DUPE_ALLOWED
|
||||
var/obj/item/bodypart/limb
|
||||
var/obj/item/weapon
|
||||
|
||||
// all of this stuff is explained in _DEFINES/combat.dm
|
||||
var/embed_chance // not like we really need it once we're already stuck in but hey
|
||||
var/fall_chance
|
||||
var/pain_chance
|
||||
var/pain_mult
|
||||
var/impact_pain_mult
|
||||
var/remove_pain_mult
|
||||
var/rip_time
|
||||
var/ignore_throwspeed_threshold
|
||||
var/jostle_chance
|
||||
var/jostle_pain_mult
|
||||
var/pain_stam_pct
|
||||
var/embed_chance_turf_mod
|
||||
|
||||
///if both our pain multiplier and jostle pain multiplier are 0, we're harmless and can omit most of the damage related stuff
|
||||
var/harmful
|
||||
var/mutable_appearance/overlay
|
||||
|
||||
/datum/component/embedded/Initialize(obj/item/I,
|
||||
datum/thrownthing/throwingdatum,
|
||||
obj/item/bodypart/part,
|
||||
embed_chance = EMBED_CHANCE,
|
||||
fall_chance = EMBEDDED_ITEM_FALLOUT,
|
||||
pain_chance = EMBEDDED_PAIN_CHANCE,
|
||||
pain_mult = EMBEDDED_PAIN_MULTIPLIER,
|
||||
remove_pain_mult = EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER,
|
||||
impact_pain_mult = EMBEDDED_IMPACT_PAIN_MULTIPLIER,
|
||||
rip_time = EMBEDDED_UNSAFE_REMOVAL_TIME,
|
||||
ignore_throwspeed_threshold = FALSE,
|
||||
jostle_chance = EMBEDDED_JOSTLE_CHANCE,
|
||||
jostle_pain_mult = EMBEDDED_JOSTLE_PAIN_MULTIPLIER,
|
||||
pain_stam_pct = EMBEDDED_PAIN_STAM_PCT,
|
||||
embed_chance_turf_mod = EMBED_CHANCE_TURF_MOD)
|
||||
|
||||
if((!iscarbon(parent) && !isclosedturf(parent)) || !isitem(I))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
if(part)
|
||||
limb = part
|
||||
src.embed_chance = embed_chance
|
||||
src.fall_chance = fall_chance
|
||||
src.pain_chance = pain_chance
|
||||
src.pain_mult = pain_mult
|
||||
src.remove_pain_mult = remove_pain_mult
|
||||
src.rip_time = rip_time
|
||||
src.impact_pain_mult = impact_pain_mult
|
||||
src.ignore_throwspeed_threshold = ignore_throwspeed_threshold
|
||||
src.jostle_chance = jostle_chance
|
||||
src.jostle_pain_mult = jostle_pain_mult
|
||||
src.pain_stam_pct = pain_stam_pct
|
||||
src.embed_chance_turf_mod = embed_chance_turf_mod
|
||||
|
||||
src.weapon = I
|
||||
|
||||
if(!weapon.isEmbedHarmless())
|
||||
harmful = TRUE
|
||||
|
||||
weapon.embedded(parent)
|
||||
|
||||
if(iscarbon(parent))
|
||||
initCarbon()
|
||||
else if(isclosedturf(parent))
|
||||
initTurf(throwingdatum)
|
||||
|
||||
/datum/component/embedded/RegisterWithParent()
|
||||
if(iscarbon(parent))
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/jostleCheck)
|
||||
RegisterSignal(parent, COMSIG_CARBON_EMBED_RIP, .proc/ripOutCarbon)
|
||||
RegisterSignal(parent, COMSIG_CARBON_EMBED_REMOVAL, .proc/safeRemoveCarbon)
|
||||
else if(isclosedturf(parent))
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/examineTurf)
|
||||
RegisterSignal(parent, COMSIG_PARENT_QDELETING, .proc/itemMoved)
|
||||
|
||||
/datum/component/embedded/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(COMSIG_MOVABLE_MOVED, COMSIG_CARBON_EMBED_RIP, COMSIG_CARBON_EMBED_REMOVAL, COMSIG_PARENT_EXAMINE))
|
||||
|
||||
/datum/component/embedded/process()
|
||||
if(iscarbon(parent))
|
||||
processCarbon()
|
||||
|
||||
/datum/component/embedded/Destroy()
|
||||
if(weapon)
|
||||
UnregisterSignal(weapon, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING))
|
||||
if(overlay)
|
||||
var/atom/A = parent
|
||||
A.cut_overlay(overlay, TRUE)
|
||||
qdel(overlay)
|
||||
|
||||
return ..()
|
||||
|
||||
////////////////////////////////////////
|
||||
/////////////HUMAN PROCS////////////////
|
||||
////////////////////////////////////////
|
||||
|
||||
/// Set up an instance of embedding for a carbon. This is basically an extension of Initialize() so not much to say
|
||||
/datum/component/embedded/proc/initCarbon()
|
||||
START_PROCESSING(SSdcs, src)
|
||||
var/mob/living/carbon/victim = parent
|
||||
if(!istype(limb))
|
||||
limb = pick(victim.bodyparts)
|
||||
|
||||
limb.embedded_objects |= weapon // on the inside... on the inside...
|
||||
weapon.forceMove(victim)
|
||||
RegisterSignal(weapon, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING), .proc/byeItemCarbon)
|
||||
|
||||
if(harmful)
|
||||
victim.visible_message("<span class='danger'>[weapon] embeds itself in [victim]'s [limb.name]!</span>",ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='userdanger'>[weapon] embeds itself in your [limb.name]!</span>")
|
||||
victim.throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
|
||||
playsound(victim,'sound/weapons/bladeslice.ogg', 40)
|
||||
weapon.add_mob_blood(victim)//it embedded itself in you, of course it's bloody!
|
||||
var/damage = weapon.w_class * impact_pain_mult
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage)
|
||||
SEND_SIGNAL(victim, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
|
||||
else
|
||||
victim.visible_message("<span class='danger'>[weapon] sticks itself to [victim]'s [limb.name]!</span>",ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='userdanger'>[weapon] sticks itself to your [limb.name]!</span>")
|
||||
|
||||
/// Called every time a carbon with a harmful embed moves, rolling a chance for the item to cause pain. The chance is halved if the carbon is crawling or walking.
|
||||
/datum/component/embedded/proc/jostleCheck()
|
||||
var/mob/living/carbon/victim = parent
|
||||
|
||||
var/chance = jostle_chance
|
||||
if(victim.m_intent == MOVE_INTENT_WALK || !(victim.mobility_flags & MOBILITY_STAND))
|
||||
chance *= 0.5
|
||||
|
||||
if(harmful && prob(chance))
|
||||
var/damage = weapon.w_class * jostle_pain_mult
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage)
|
||||
to_chat(victim, "<span class='userdanger'>[weapon] embedded in your [limb.name] jostles and stings!</span>")
|
||||
|
||||
|
||||
/// Called when then item randomly falls out of a carbon. This handles the damage and descriptors, then calls safe_remove()
|
||||
/datum/component/embedded/proc/fallOutCarbon()
|
||||
var/mob/living/carbon/victim = parent
|
||||
|
||||
if(harmful)
|
||||
var/damage = weapon.w_class * remove_pain_mult
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage)
|
||||
victim.visible_message("<span class='danger'>[weapon] falls out of [victim.name]'s [limb.name]!</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='userdanger'>[weapon] falls out of your [limb.name]!</span>")
|
||||
else
|
||||
victim.visible_message("<span class='danger'>[weapon] falls off of [victim.name]'s [limb.name]!</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='userdanger'>[weapon] falls off of your [limb.name]!</span>")
|
||||
|
||||
safeRemoveCarbon()
|
||||
|
||||
|
||||
/// Called when a carbon with an object embedded/stuck to them inspects themselves and clicks the appropriate link to begin ripping the item out. This handles the ripping attempt, descriptors, and dealing damage, then calls safe_remove()
|
||||
/datum/component/embedded/proc/ripOutCarbon(datum/source, obj/item/I, obj/item/bodypart/limb)
|
||||
if(I != weapon || src.limb != limb)
|
||||
return
|
||||
|
||||
var/mob/living/carbon/victim = parent
|
||||
var/time_taken = rip_time * weapon.w_class
|
||||
|
||||
victim.visible_message("<span class='warning'>[victim] attempts to remove [weapon] from [victim.p_their()] [limb.name].</span>","<span class='notice'>You attempt to remove [weapon] from your [limb.name]... (It will take [DisplayTimeText(time_taken)].)</span>")
|
||||
if(do_after(victim, time_taken, target = victim))
|
||||
if(!weapon || !limb || weapon.loc != victim || !(weapon in limb.embedded_objects))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(harmful)
|
||||
var/damage = weapon.w_class * remove_pain_mult
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage) //It hurts to rip it out, get surgery you dingus.
|
||||
victim.emote("scream")
|
||||
victim.visible_message("<span class='notice'>[victim] successfully rips [weapon] out of [victim.p_their()] [limb.name]!</span>", "<span class='notice'>You successfully remove [weapon] from your [limb.name].</span>")
|
||||
else
|
||||
victim.visible_message("<span class='notice'>[victim] successfully rips [weapon] off of [victim.p_their()] [limb.name]!</span>", "<span class='notice'>You successfully remove [weapon] from your [limb.name].</span>")
|
||||
|
||||
safeRemoveCarbon(TRUE)
|
||||
|
||||
|
||||
/// This proc handles the final step and actual removal of an embedded/stuck item from a carbon, whether or not it was actually removed safely.
|
||||
/// Pass TRUE for to_hands if we want it to go to the victim's hands when they pull it out
|
||||
/datum/component/embedded/proc/safeRemoveCarbon(to_hands)
|
||||
var/mob/living/carbon/victim = parent
|
||||
limb.embedded_objects -= weapon
|
||||
|
||||
UnregisterSignal(weapon, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING)) // have to unhook these here so they don't also register as having disappeared
|
||||
|
||||
if(!weapon)
|
||||
if(!victim.has_embedded_objects())
|
||||
victim.clear_alert("embeddedobject")
|
||||
SEND_SIGNAL(victim, COMSIG_CLEAR_MOOD_EVENT, "embedded")
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(weapon.unembedded()) // if it deleted itself
|
||||
weapon = null
|
||||
if(!victim.has_embedded_objects())
|
||||
victim.clear_alert("embeddedobject")
|
||||
SEND_SIGNAL(victim, COMSIG_CLEAR_MOOD_EVENT, "embedded")
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(to_hands)
|
||||
victim.put_in_hands(weapon)
|
||||
else
|
||||
weapon.forceMove(get_turf(victim))
|
||||
|
||||
if(!victim.has_embedded_objects())
|
||||
victim.clear_alert("embeddedobject")
|
||||
SEND_SIGNAL(victim, COMSIG_CLEAR_MOOD_EVENT, "embedded")
|
||||
qdel(src)
|
||||
|
||||
|
||||
/// Something deleted or moved our weapon while it was embedded, how rude!
|
||||
/datum/component/embedded/proc/byeItemCarbon()
|
||||
var/mob/living/carbon/victim = parent
|
||||
limb.embedded_objects -= weapon
|
||||
UnregisterSignal(weapon, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING))
|
||||
|
||||
if(victim)
|
||||
to_chat(victim, "<span class='userdanger'>\The [weapon] that was embedded in your [limb.name] disappears!</span>")
|
||||
if(!victim.has_embedded_objects())
|
||||
victim.clear_alert("embeddedobject")
|
||||
SEND_SIGNAL(victim, COMSIG_CLEAR_MOOD_EVENT, "embedded")
|
||||
weapon = null
|
||||
qdel(src)
|
||||
|
||||
|
||||
/// Items embedded/stuck to carbons both check whether they randomly fall out (if applicable), as well as if the target mob and limb still exists.
|
||||
/// Items harmfully embedded in carbons have an additional check for random pain (if applicable)
|
||||
/datum/component/embedded/proc/processCarbon()
|
||||
var/mob/living/carbon/victim = parent
|
||||
|
||||
if(!victim || !limb) // in case the victim and/or their limbs exploded (say, due to a sticky bomb)
|
||||
weapon.forceMove(get_turf(weapon))
|
||||
qdel(src)
|
||||
|
||||
if(victim.stat == DEAD)
|
||||
return
|
||||
|
||||
var/damage = weapon.w_class * pain_mult
|
||||
var/chance = pain_chance
|
||||
if(pain_stam_pct && IS_STAMCRIT(victim)) //if it's a less-lethal embed, give them a break if they're already stamcritted
|
||||
chance *= 0.3
|
||||
damage *= 0.7
|
||||
|
||||
if(harmful && prob(chance))
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage)
|
||||
to_chat(victim, "<span class='userdanger'>[weapon] embedded in your [limb.name] hurts!</span>")
|
||||
|
||||
if(prob(fall_chance))
|
||||
fallOutCarbon()
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
//////////////TURF PROCS////////////////
|
||||
////////////////////////////////////////
|
||||
|
||||
/// Turfs are much lower maintenance, since we don't care if they're in pain, but since they don't bleed or scream, we draw an overlay to show their status.
|
||||
/// The only difference pointy/sticky items make here is text descriptors and pointy objects making a spark shower on impact.
|
||||
/datum/component/embedded/proc/initTurf(datum/thrownthing/throwingdatum)
|
||||
var/turf/closed/hit = parent
|
||||
|
||||
// we can't store the item IN the turf (cause turfs are just kinda... there), so we fake it by making the item invisible and bailing if it moves due to a blast
|
||||
weapon.forceMove(hit)
|
||||
weapon.invisibility = INVISIBILITY_ABSTRACT
|
||||
RegisterSignal(weapon, COMSIG_MOVABLE_MOVED, .proc/itemMoved)
|
||||
|
||||
var/pixelX = rand(-2, 2)
|
||||
var/pixelY = rand(-1, 3) // bias this upwards since in-hands are usually on the lower end of the sprite
|
||||
|
||||
switch(throwingdatum.init_dir)
|
||||
if(NORTH)
|
||||
pixelY -= 2
|
||||
if(SOUTH)
|
||||
pixelY += 2
|
||||
if(WEST)
|
||||
pixelX += 2
|
||||
if(EAST)
|
||||
pixelX -= 2
|
||||
|
||||
if(throwingdatum.init_dir in list(NORTH, WEST, NORTHWEST, SOUTHWEST))
|
||||
overlay = mutable_appearance(icon=weapon.righthand_file,icon_state=weapon.item_state)
|
||||
else
|
||||
overlay = mutable_appearance(icon=weapon.lefthand_file,icon_state=weapon.item_state)
|
||||
|
||||
var/matrix/M = matrix()
|
||||
M.Translate(pixelX, pixelY)
|
||||
overlay.transform = M
|
||||
hit.add_overlay(overlay, TRUE)
|
||||
|
||||
if(harmful)
|
||||
hit.visible_message("<span class='danger'>[weapon] embeds itself in [hit]!</span>")
|
||||
playsound(hit,'sound/weapons/bladeslice.ogg', 70)
|
||||
|
||||
var/datum/effect_system/spark_spread/sparks = new
|
||||
sparks.set_up(1, 1, parent)
|
||||
sparks.attach(parent)
|
||||
sparks.start()
|
||||
else
|
||||
hit.visible_message("<span class='danger'>[weapon] sticks itself to [hit]!</span>")
|
||||
|
||||
|
||||
/datum/component/embedded/proc/examineTurf(datum/source, mob/user, list/examine_list)
|
||||
if(harmful)
|
||||
examine_list += "\t <a href='?src=[REF(src)];embedded_object=[REF(weapon)]' class='warning'>There is \a [weapon] embedded in [parent]!</a>"
|
||||
else
|
||||
examine_list += "\t <a href='?src=[REF(src)];embedded_object=[REF(weapon)]' class='warning'>There is \a [weapon] stuck to [parent]!</a>"
|
||||
|
||||
|
||||
/// Someone is ripping out the item from the turf by hand
|
||||
/datum/component/embedded/Topic(datum/source, href_list)
|
||||
var/mob/living/us = usr
|
||||
if(in_range(us, parent) && locate(href_list["embedded_object"]) == weapon)
|
||||
if(harmful)
|
||||
us.visible_message("<span class='notice'>[us] begins unwedging [weapon] from [parent].</span>", "<span class='notice'>You begin unwedging [weapon] from [parent]...</span>")
|
||||
else
|
||||
us.visible_message("<span class='notice'>[us] begins unsticking [weapon] from [parent].</span>", "<span class='notice'>You begin unsticking [weapon] from [parent]...</span>")
|
||||
|
||||
if(do_after(us, 30, target = parent))
|
||||
us.put_in_hands(weapon)
|
||||
weapon.unembedded()
|
||||
qdel(src)
|
||||
|
||||
|
||||
/// This proc handles if something knocked the invisible item loose from the turf somehow (probably an explosion). Just make it visible and say it fell loose, then get outta here.
|
||||
/datum/component/embedded/proc/itemMoved()
|
||||
weapon.invisibility = initial(weapon.invisibility)
|
||||
weapon.visible_message("<span class='notice'>[weapon] falls loose from [parent].</span>")
|
||||
weapon.unembedded()
|
||||
qdel(src)
|
||||
@@ -144,7 +144,7 @@
|
||||
var/obj/item/projectile/picked_projectiletype = pickweight(weighted_projectile_types)
|
||||
|
||||
var/obj/item/master = comp.parent
|
||||
comp.appliedComponents += master.AddComponent(/datum/component/shrapnel, picked_projectiletype)
|
||||
comp.appliedComponents += master.AddComponent(/datum/component/mirv, picked_projectiletype)
|
||||
return "[newName] of [initial(picked_projectiletype.name)] shrapnel"
|
||||
|
||||
/datum/fantasy_affix/strength
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
if(!material_amount)
|
||||
to_chat(user, "<span class='warning'>[I] does not contain sufficient materials to be accepted by [parent].</span>")
|
||||
return
|
||||
if((!precise_insertion || !GLOB.typecache_stack[I]) && !has_space(material_amount))
|
||||
if((!precise_insertion || !GLOB.typecache_stack[I.type]) && !has_space(material_amount))
|
||||
to_chat(user, "<span class='warning'>[parent] has not enough space. Please remove materials from [parent] in order to insert more.</span>")
|
||||
return
|
||||
user_insert(I, user)
|
||||
|
||||
@@ -1,36 +1,37 @@
|
||||
|
||||
/datum/component/shrapnel
|
||||
/datum/component/mirv
|
||||
var/projectile_type
|
||||
var/radius // shoots a projectile for every turf on this radius from the hit target
|
||||
var/override_projectile_range
|
||||
|
||||
/datum/component/shrapnel/Initialize(projectile_type, radius=1, override_projectile_range)
|
||||
if(!isgun(parent) && !ismachinery(parent) && !isstructure(parent))
|
||||
/datum/component/mirv/Initialize(projectile_type, radius=1, override_projectile_range)
|
||||
if(!isgun(parent) && !ismachinery(parent) && !isstructure(parent) && !isgrenade(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
src.projectile_type = projectile_type
|
||||
src.radius = radius
|
||||
src.override_projectile_range = override_projectile_range
|
||||
if(isgrenade(parent))
|
||||
parent.AddComponent(/datum/component/pellet_cloud, projectile_type=projectile_type)
|
||||
|
||||
/datum/component/shrapnel/RegisterWithParent()
|
||||
/datum/component/mirv/RegisterWithParent()
|
||||
. = ..()
|
||||
if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc
|
||||
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
|
||||
|
||||
/datum/component/shrapnel/UnregisterFromParent()
|
||||
/datum/component/mirv/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, list(COMSIG_PROJECTILE_ON_HIT))
|
||||
|
||||
/datum/component/shrapnel/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
|
||||
/datum/component/mirv/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
|
||||
do_shrapnel(firer, target)
|
||||
|
||||
/datum/component/shrapnel/proc/do_shrapnel(mob/firer, atom/target)
|
||||
/datum/component/mirv/proc/do_shrapnel(mob/firer, atom/target)
|
||||
if(radius < 1)
|
||||
return
|
||||
var/turf/target_turf = get_turf(target)
|
||||
for(var/turf/shootat_turf in RANGE_TURFS(radius, target) - RANGE_TURFS(radius-1, target))
|
||||
var/obj/item/projectile/P = new projectile_type(target_turf)
|
||||
|
||||
var/obj/item/projectile/P = new projectile_type(target_turf)
|
||||
//Shooting Code:
|
||||
P.range = radius+1
|
||||
if(override_projectile_range)
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
var/mob/living/owner = parent
|
||||
if(owner.stat != DEAD)
|
||||
START_PROCESSING(SSdcs, src)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
RegisterSignal(parent, COMSIG_ADD_MOOD_EVENT, .proc/add_event)
|
||||
RegisterSignal(parent, COMSIG_CLEAR_MOOD_EVENT, .proc/clear_event)
|
||||
@@ -40,12 +40,12 @@
|
||||
hud.show_hud(hud.hud_version)
|
||||
|
||||
/datum/component/mood/Destroy()
|
||||
STOP_PROCESSING(SSdcs, src)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
unmodify_hud()
|
||||
return ..()
|
||||
|
||||
/datum/component/mood/proc/stop_processing()
|
||||
STOP_PROCESSING(SSdcs, src)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
/datum/component/mood/proc/print_mood(mob/user)
|
||||
var/msg = "<span class='info'>*---------*\n<EM>Your current mood</EM>\n"
|
||||
@@ -138,7 +138,7 @@
|
||||
else
|
||||
screen_obj.icon_state = "mood[mood_level]"
|
||||
|
||||
/datum/component/mood/process() //Called on SSdcs process
|
||||
/datum/component/mood/process() //Called on SSobj process
|
||||
if(QDELETED(parent)) // workaround to an obnoxious sneaky periodical runtime.
|
||||
qdel(src)
|
||||
return
|
||||
@@ -345,7 +345,7 @@
|
||||
|
||||
///Called when parent is revived.
|
||||
/datum/component/mood/proc/on_revive(datum/source, full_heal)
|
||||
START_PROCESSING(SSdcs, src)
|
||||
START_PROCESSING(SSobj, src)
|
||||
if(!full_heal)
|
||||
return
|
||||
remove_temp_moods()
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* omen.dm: For when you want someone to have a really bad day
|
||||
*
|
||||
* When you attach an omen component to someone, they start running the risk of all sorts of bad environmental injuries, like nearby vending machines randomly falling on you,
|
||||
* or hitting your head really hard when you slip and fall, or... well, for now those two are all I have. More will come.
|
||||
*
|
||||
* Omens are removed once the victim is either maimed by one of the possible injuries, or if they receive a blessing (read: bashing with a bible) from the chaplain.
|
||||
*/
|
||||
/datum/component/omen
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE
|
||||
|
||||
/// Whatever's causing the omen, if there is one. Destroying the vessel won't stop the omen, but we destroy the vessel (if one exists) upon the omen ending
|
||||
var/obj/vessel
|
||||
|
||||
/datum/component/omen/Initialize(silent=FALSE, vessel)
|
||||
if(!isliving(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
var/mob/person = parent
|
||||
if(!silent)
|
||||
to_chat(person, "<span class='warning'>You get a bad feeling...</span>")
|
||||
src.vessel = vessel
|
||||
|
||||
/datum/component/omen/Destroy(force, silent)
|
||||
if(vessel)
|
||||
vessel.visible_message("<span class='warning'>[vessel] burns up in a sinister flash, taking an evil energy with it...</span>")
|
||||
vessel = null
|
||||
return ..()
|
||||
|
||||
/datum/component/omen/RegisterWithParent()
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/check_accident)
|
||||
RegisterSignal(parent, COMSIG_LIVING_STATUS_KNOCKDOWN, .proc/check_slip)
|
||||
RegisterSignal(parent, COMSIG_ADD_MOOD_EVENT, .proc/check_bless)
|
||||
|
||||
/datum/component/omen/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(COMSIG_LIVING_STATUS_KNOCKDOWN, COMSIG_MOVABLE_MOVED, COMSIG_ADD_MOOD_EVENT))
|
||||
|
||||
/**
|
||||
* check_accident() is called each step we take
|
||||
*
|
||||
* While we're walking around, roll to see if there's any environmental hazards (currently only vending machines) on one of the adjacent tiles we can trigger.
|
||||
* We do the prob() at the beginning to A. add some tension for /when/ it will strike, and B. (more importantly) ameliorate the fact that we're checking up to 5 turfs's contents each time
|
||||
*/
|
||||
/datum/component/omen/proc/check_accident(atom/movable/our_guy)
|
||||
if(!prob(15))
|
||||
return
|
||||
for(var/t in get_adjacent_open_turfs(our_guy))
|
||||
var/turf/the_turf = t
|
||||
for(var/obj/machinery/vending/darth_vendor in the_turf)
|
||||
if(darth_vendor.tiltable)
|
||||
darth_vendor.tilt(our_guy)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/// If we get knocked down, see if we have a really bad slip and bash our head hard
|
||||
/datum/component/omen/proc/check_slip(mob/living/our_guy, amount)
|
||||
if(amount <= 0 || prob(50)) // 50% chance to bonk our head
|
||||
return
|
||||
|
||||
var/obj/item/bodypart/the_head = our_guy.get_bodypart(BODY_ZONE_HEAD)
|
||||
if(!the_head)
|
||||
return
|
||||
|
||||
playsound(get_turf(our_guy), "sound/effects/tableheadsmash.ogg", 90, TRUE)
|
||||
our_guy.visible_message("<span class='danger'>[our_guy] hits [our_guy.p_their()] head really badly falling down!</span>", "<span class='userdanger'>You hit your head really badly falling down!</span>")
|
||||
the_head.receive_damage(75)
|
||||
our_guy.adjustOrganLoss(ORGAN_SLOT_BRAIN, 100)
|
||||
qdel(src)
|
||||
|
||||
/// Hijack the mood system to see if we get the blessing mood event to cancel the omen
|
||||
/datum/component/omen/proc/check_bless(mob/living/our_guy, category)
|
||||
if(category != "blessing")
|
||||
return
|
||||
to_chat(our_guy, "<span class='nicegreen'>You feel a horrible omen lifted off your shoulders!</span>")
|
||||
qdel(src)
|
||||
@@ -62,7 +62,9 @@
|
||||
orbiters[orbiter] = TRUE
|
||||
orbiter.orbiting = src
|
||||
RegisterSignal(orbiter, COMSIG_MOVABLE_MOVED, .proc/orbiter_move_react)
|
||||
|
||||
var/matrix/initial_transform = matrix(orbiter.transform)
|
||||
orbiters[orbiter] = initial_transform
|
||||
|
||||
// Head first!
|
||||
if(pre_rotation)
|
||||
@@ -79,8 +81,6 @@
|
||||
|
||||
orbiter.SpinAnimation(rotation_speed, -1, clockwise, rotation_segments, parallel = FALSE)
|
||||
|
||||
//we stack the orbits up client side, so we can assign this back to normal server side without it breaking the orbit
|
||||
orbiter.transform = initial_transform
|
||||
orbiter.forceMove(get_turf(parent))
|
||||
to_chat(orbiter, "<span class='notice'>Now orbiting [parent].</span>")
|
||||
|
||||
@@ -89,6 +89,8 @@
|
||||
return
|
||||
UnregisterSignal(orbiter, COMSIG_MOVABLE_MOVED)
|
||||
orbiter.SpinAnimation(0, 0)
|
||||
if(istype(orbiters[orbiter],/matrix)) //This is ugly.
|
||||
orbiter.transform = orbiters[orbiter]
|
||||
orbiters -= orbiter
|
||||
orbiter.stop_orbit(src)
|
||||
orbiter.orbiting = null
|
||||
|
||||
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* This component is used when you want to create a bunch of shrapnel or projectiles (say, shrapnel from a fragmentation grenade, or buckshot from a shotgun) from a central point,
|
||||
* without necessarily printing a separate message for every single impact. This component should be instantiated right when you need it (like the moment of firing), then activated
|
||||
* by signal.
|
||||
*
|
||||
* Pellet cloud currently works on two classes of sources: directed (ammo casings), and circular (grenades, landmines).
|
||||
* -Directed: This means you're shooting multiple pellets, like buckshot. If an ammo casing is defined as having multiple pellets, it will automatically create a pellet cloud
|
||||
* and call COMSIG_PELLET_CLOUD_INIT (see [/obj/item/ammo_casing/proc/fire_casing]). Thus, the only projectiles fired will be the ones fired here.
|
||||
* The magnitude var controls how many pellets are created.
|
||||
* -Circular: This results in a big spray of shrapnel flying all around the detonation point when the grenade fires COMSIG_GRENADE_PRIME or landmine triggers COMSIG_MINE_TRIGGERED.
|
||||
* The magnitude var controls how big the detonation radius is (the bigger the magnitude, the more shrapnel is created). Grenades can be covered with bodies to reduce shrapnel output.
|
||||
*
|
||||
* Once all of the fired projectiles either hit a target or disappear due to ranging out/whatever else, we resolve the list of all the things we hit and print aggregate messages so we get
|
||||
* one "You're hit by 6 buckshot pellets" vs 6x "You're hit by the buckshot blah blah" messages.
|
||||
*
|
||||
* Note that this is how all guns handle shooting ammo casings with multiple pellets, in case such a thing comes up.
|
||||
*/
|
||||
|
||||
/datum/component/pellet_cloud
|
||||
/// What's the projectile path of the shrapnel we're shooting?
|
||||
var/projectile_type
|
||||
|
||||
/// How many shrapnel projectiles are we responsible for tracking? May be reduced for grenades if someone dives on top of it. Defined by ammo casing for casings, derived from magnitude otherwise
|
||||
var/num_pellets
|
||||
/// For grenades/landmines, how big is the radius of turfs we're targeting? Note this does not effect the projectiles range, only how many we generate
|
||||
var/radius = 4
|
||||
|
||||
/// The list of pellets we're responsible for tracking, once these are all accounted for, we finalize.
|
||||
var/list/pellets = list()
|
||||
/// An associated list with the atom hit as the key and how many pellets they've eaten for the value, for printing aggregate messages
|
||||
var/list/targets_hit = list()
|
||||
/// For grenades, any /mob/living's the grenade is moved onto, see [/datum/component/pellet_cloud/proc/handle_martyrs()]
|
||||
var/list/bodies
|
||||
/// For grenades, tracking people who die covering a grenade for achievement purposes, see [/datum/component/pellet_cloud/proc/handle_martyrs()]
|
||||
var/list/purple_hearts
|
||||
|
||||
/// For grenades, tracking how many pellets are removed due to martyrs and how many pellets are added due to the last person to touch it being on top of it
|
||||
var/pellet_delta = 0
|
||||
/// how many pellets ranged out without hitting anything
|
||||
var/terminated
|
||||
/// how many pellets impacted something
|
||||
var/hits
|
||||
/// If the parent tried deleting and we're not done yet, we send it to nullspace then delete it after
|
||||
var/queued_delete = FALSE
|
||||
|
||||
/// for if we're an ammo casing being fired
|
||||
var/mob/living/shooter
|
||||
|
||||
/datum/component/pellet_cloud/Initialize(projectile_type=/obj/item/shrapnel, magnitude=5)
|
||||
if(!isammocasing(parent) && !isgrenade(parent) && !islandmine(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
if(magnitude < 1)
|
||||
stack_trace("Invalid magnitude [magnitude] < 1 on pellet_cloud, parent: [parent]")
|
||||
magnitude = 1
|
||||
|
||||
src.projectile_type = projectile_type
|
||||
|
||||
if(isammocasing(parent))
|
||||
num_pellets = magnitude
|
||||
else if(isgrenade(parent) || islandmine(parent))
|
||||
radius = magnitude
|
||||
|
||||
/datum/component/pellet_cloud/Destroy(force, silent)
|
||||
purple_hearts = null
|
||||
pellets = null
|
||||
targets_hit = null
|
||||
bodies = null
|
||||
return ..()
|
||||
|
||||
/datum/component/pellet_cloud/RegisterWithParent()
|
||||
RegisterSignal(parent, COMSIG_PARENT_PREQDELETED, .proc/nullspace_parent)
|
||||
if(isammocasing(parent))
|
||||
RegisterSignal(parent, COMSIG_PELLET_CLOUD_INIT, .proc/create_casing_pellets)
|
||||
else if(isgrenade(parent))
|
||||
RegisterSignal(parent, COMSIG_GRENADE_ARMED, .proc/grenade_armed)
|
||||
RegisterSignal(parent, COMSIG_GRENADE_PRIME, .proc/create_blast_pellets)
|
||||
else if(islandmine(parent))
|
||||
RegisterSignal(parent, COMSIG_MINE_TRIGGERED, .proc/create_blast_pellets)
|
||||
|
||||
/datum/component/pellet_cloud/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(COMSIG_PARENT_PREQDELETED, COMSIG_PELLET_CLOUD_INIT, COMSIG_GRENADE_PRIME, COMSIG_GRENADE_ARMED, COMSIG_MOVABLE_MOVED, COMSIG_MOVABLE_UNCROSSED, COMSIG_MINE_TRIGGERED, COMSIG_ITEM_DROPPED))
|
||||
|
||||
/**
|
||||
* create_casing_pellets() is for directed pellet clouds for ammo casings that have multiple pellets (buckshot and scatter lasers for instance)
|
||||
*
|
||||
* Honestly this is mostly just a rehash of [/obj/item/ammo_casing/proc/fire_casing()] for pellet counts > 1, except this lets us tamper with the pellets and hook onto them for tracking purposes.
|
||||
* The arguments really don't matter, this proc is triggered by COMSIG_PELLET_CLOUD_INIT which is only for this really, it's just a big mess of the state vars we need for doing the stuff over here.
|
||||
*/
|
||||
/datum/component/pellet_cloud/proc/create_casing_pellets(obj/item/ammo_casing/shell, atom/target, mob/living/user, fired_from, randomspread, spread, zone_override, params, distro)
|
||||
shooter = user
|
||||
var/targloc = get_turf(target)
|
||||
if(!zone_override)
|
||||
zone_override = shooter.zone_selected
|
||||
|
||||
for(var/i in 1 to num_pellets)
|
||||
shell.ready_proj(target, user, SUPPRESSED_VERY, zone_override, fired_from)
|
||||
if(distro)
|
||||
if(randomspread)
|
||||
spread = round((rand() - 0.5) * distro)
|
||||
else //Smart spread
|
||||
spread = round((i / num_pellets - 0.5) * distro)
|
||||
|
||||
RegisterSignal(shell.BB, COMSIG_PROJECTILE_SELF_ON_HIT, .proc/pellet_hit)
|
||||
RegisterSignal(shell.BB, list(COMSIG_PROJECTILE_RANGE_OUT, COMSIG_PARENT_QDELETING), .proc/pellet_range)
|
||||
pellets += shell.BB
|
||||
if(!shell.throw_proj(target, targloc, shooter, params, spread))
|
||||
return
|
||||
if(i != num_pellets)
|
||||
shell.newshot()
|
||||
|
||||
/**
|
||||
* create_blast_pellets() is for when we have a central point we want to shred the surroundings of with a ring of shrapnel, namely frag grenades and landmines.
|
||||
*
|
||||
* Note that grenades have extra handling for someone throwing themselves/being thrown on top of it, while landmines do not (obviously, it's a landmine!). See [/datum/component/pellet_cloud/proc/handle_martyrs()]
|
||||
*/
|
||||
/datum/component/pellet_cloud/proc/create_blast_pellets(obj/O, mob/living/lanced_by)
|
||||
var/atom/A = parent
|
||||
|
||||
if(isgrenade(parent)) // handle_martyrs can reduce the radius and thus the number of pellets we produce if someone dives on top of a frag grenade
|
||||
handle_martyrs(lanced_by) // note that we can modify radius in this proc
|
||||
|
||||
if(radius < 1)
|
||||
return
|
||||
|
||||
var/list/all_the_turfs_were_gonna_lacerate = RANGE_TURFS(radius, A) - RANGE_TURFS(radius-1, A)
|
||||
num_pellets = all_the_turfs_were_gonna_lacerate.len + pellet_delta
|
||||
|
||||
for(var/T in all_the_turfs_were_gonna_lacerate)
|
||||
var/turf/shootat_turf = T
|
||||
pew(shootat_turf)
|
||||
|
||||
/**
|
||||
* handle_martyrs() is used for grenades that shoot shrapnel to check if anyone threw themselves/were thrown on top of the grenade, thus absorbing a good chunk of the shrapnel
|
||||
*
|
||||
* Between the time the grenade is armed and the actual detonation, we set var/list/bodies to the list of mobs currently on the new tile, as if the grenade landed on top of them, tracking if any of them move off the tile and removing them from the "under" list
|
||||
* Once the grenade detonates, handle_martyrs() is called and gets all the new mobs on the tile, and add the ones not in var/list/bodies to var/list/martyrs
|
||||
* We then iterate through the martyrs and reduce the shrapnel magnitude for each mob on top of it, shredding each of them with some of the shrapnel they helped absorb. This can snuff out all of the shrapnel if there's enough bodies
|
||||
*
|
||||
* Note we track anyone who's alive and client'd when they get shredded in var/list/purple_hearts, for achievement checking later
|
||||
*/
|
||||
/datum/component/pellet_cloud/proc/handle_martyrs(mob/living/lanced_by)
|
||||
var/magnitude_absorbed
|
||||
var/list/martyrs = list()
|
||||
|
||||
var/self_harm_radius_mult = 3
|
||||
|
||||
if(lanced_by && prob(60))
|
||||
to_chat(lanced_by, "<span class='userdanger'>Your plan to whack someone with a grenade on a stick backfires on you, literally!</span>")
|
||||
self_harm_radius_mult = 1 // we'll still give the guy who got hit some extra shredding, but not 3*radius
|
||||
pellet_delta += radius
|
||||
for(var/i in 1 to radius)
|
||||
pew(lanced_by) // thought you could be tricky and lance someone with no ill effects!!
|
||||
|
||||
for(var/mob/living/body in get_turf(parent))
|
||||
if(body == shooter)
|
||||
pellet_delta += radius * self_harm_radius_mult
|
||||
for(var/i in 1 to radius * self_harm_radius_mult)
|
||||
pew(body) // free shrapnel if it goes off in your hand, and it doesn't even count towards the absorbed. fun!
|
||||
else if(!(body in bodies))
|
||||
martyrs += body // promoted from a corpse to a hero
|
||||
|
||||
for(var/M in martyrs)
|
||||
var/mob/living/martyr = M
|
||||
if(radius > 4)
|
||||
martyr.visible_message("<b><span class='danger'>[martyr] heroically covers \the [parent] with [martyr.p_their()] body, absorbing a load of the shrapnel!</span></b>", "<span class='userdanger'>You heroically cover \the [parent] with your body, absorbing a load of the shrapnel!</span>")
|
||||
magnitude_absorbed += round(radius * 0.5)
|
||||
else if(radius >= 2)
|
||||
martyr.visible_message("<b><span class='danger'>[martyr] heroically covers \the [parent] with [martyr.p_their()] body, absorbing some of the shrapnel!</span></b>", "<span class='userdanger'>You heroically cover \the [parent] with your body, absorbing some of the shrapnel!</span>")
|
||||
magnitude_absorbed += 2
|
||||
else
|
||||
martyr.visible_message("<b><span class='danger'>[martyr] heroically covers \the [parent] with [martyr.p_their()] body, snuffing out the shrapnel!</span></b>", "<span class='userdanger'>You heroically cover \the [parent] with your body, snuffing out the shrapnel!</span>")
|
||||
magnitude_absorbed = radius
|
||||
|
||||
var/pellets_absorbed = (radius ** 2) - ((radius - magnitude_absorbed - 1) ** 2)
|
||||
radius -= magnitude_absorbed
|
||||
pellet_delta -= round(pellets_absorbed * 0.5)
|
||||
|
||||
if(martyr.stat != DEAD && martyr.client)
|
||||
LAZYADD(purple_hearts, martyr)
|
||||
RegisterSignal(martyr, COMSIG_PARENT_QDELETING, .proc/on_target_qdel, override=TRUE)
|
||||
|
||||
for(var/i in 1 to round(pellets_absorbed * 0.5))
|
||||
pew(martyr)
|
||||
|
||||
if(radius < 1)
|
||||
break
|
||||
|
||||
///One of our pellets hit something, record what it was and check if we're done (terminated == num_pellets)
|
||||
/datum/component/pellet_cloud/proc/pellet_hit(obj/item/projectile/P, atom/movable/firer, atom/target, Angle)
|
||||
pellets -= P
|
||||
terminated++
|
||||
hits++
|
||||
targets_hit[target]++
|
||||
if(targets_hit[target] == 1)
|
||||
RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/on_target_qdel, override=TRUE)
|
||||
UnregisterSignal(P, list(COMSIG_PARENT_QDELETING, COMSIG_PROJECTILE_RANGE_OUT, COMSIG_PROJECTILE_SELF_ON_HIT))
|
||||
if(terminated == num_pellets)
|
||||
finalize()
|
||||
|
||||
///One of our pellets disappeared due to hitting their max range (or just somehow got qdel'd), remove it from our list and check if we're done (terminated == num_pellets)
|
||||
/datum/component/pellet_cloud/proc/pellet_range(obj/item/projectile/P)
|
||||
pellets -= P
|
||||
terminated++
|
||||
UnregisterSignal(P, list(COMSIG_PARENT_QDELETING, COMSIG_PROJECTILE_RANGE_OUT, COMSIG_PROJECTILE_SELF_ON_HIT))
|
||||
if(terminated == num_pellets)
|
||||
finalize()
|
||||
|
||||
/// Minor convenience function for creating each shrapnel piece with circle explosions, mostly stolen from the MIRV component
|
||||
/datum/component/pellet_cloud/proc/pew(atom/target, spread=0)
|
||||
var/obj/item/projectile/P = new projectile_type(get_turf(parent))
|
||||
|
||||
//Shooting Code:
|
||||
P.spread = spread
|
||||
P.original = target
|
||||
P.fired_from = parent
|
||||
P.firer = parent // don't hit ourself that would be really annoying
|
||||
P.permutated += parent // don't hit the target we hit already with the flak
|
||||
P.suppressed = SUPPRESSED_VERY // set the projectiles to make no message so we can do our own aggregate message
|
||||
P.preparePixelProjectile(target, parent)
|
||||
RegisterSignal(P, COMSIG_PROJECTILE_SELF_ON_HIT, .proc/pellet_hit)
|
||||
RegisterSignal(P, list(COMSIG_PROJECTILE_RANGE_OUT, COMSIG_PARENT_QDELETING), .proc/pellet_range)
|
||||
pellets += P
|
||||
P.fire()
|
||||
|
||||
///All of our pellets are accounted for, time to go target by target and tell them how many things they got hit by.
|
||||
/datum/component/pellet_cloud/proc/finalize()
|
||||
var/obj/item/projectile/P = projectile_type
|
||||
var/proj_name = initial(P.name)
|
||||
|
||||
for(var/atom/target in targets_hit)
|
||||
var/num_hits = targets_hit[target]
|
||||
UnregisterSignal(target, COMSIG_PARENT_QDELETING)
|
||||
if(num_hits > 1)
|
||||
target.visible_message("<span class='danger'>[target] is hit by [num_hits] [proj_name]s!</span>", null, null, COMBAT_MESSAGE_RANGE, target)
|
||||
to_chat(target, "<span class='userdanger'>You're hit by [num_hits] [proj_name]s!</span>")
|
||||
else
|
||||
target.visible_message("<span class='danger'>[target] is hit by a [proj_name]!</span>", null, null, COMBAT_MESSAGE_RANGE, target)
|
||||
to_chat(target, "<span class='userdanger'>You're hit by a [proj_name]!</span>")
|
||||
|
||||
UnregisterSignal(parent, COMSIG_PARENT_PREQDELETED)
|
||||
if(queued_delete)
|
||||
qdel(parent)
|
||||
qdel(src)
|
||||
|
||||
/// Look alive, we're armed! Now we start watching to see if anyone's covering us
|
||||
/datum/component/pellet_cloud/proc/grenade_armed(obj/item/nade)
|
||||
if(ismob(nade.loc))
|
||||
shooter = nade.loc
|
||||
LAZYINITLIST(bodies)
|
||||
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/grenade_dropped)
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/grenade_moved)
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_UNCROSSED, .proc/grenade_uncrossed)
|
||||
|
||||
/// Someone dropped the grenade, so set them to the shooter in case they're on top of it when it goes off
|
||||
/datum/component/pellet_cloud/proc/grenade_dropped(obj/item/nade, mob/living/slick_willy)
|
||||
shooter = slick_willy
|
||||
grenade_moved()
|
||||
|
||||
/// Our grenade has moved, reset var/list/bodies so we're "on top" of any mobs currently on the tile
|
||||
/datum/component/pellet_cloud/proc/grenade_moved()
|
||||
LAZYCLEARLIST(bodies)
|
||||
for(var/mob/living/L in get_turf(parent))
|
||||
RegisterSignal(L, COMSIG_PARENT_QDELETING, .proc/on_target_qdel, override=TRUE)
|
||||
bodies += L
|
||||
|
||||
/// Someone who was originally "under" the grenade has moved off the tile and is now eligible for being a martyr and "covering" it
|
||||
/datum/component/pellet_cloud/proc/grenade_uncrossed(datum/source, atom/movable/AM)
|
||||
bodies -= AM
|
||||
|
||||
/// Our grenade or landmine or caseless shell or whatever tried deleting itself, so we intervene and nullspace it until we're done here
|
||||
/datum/component/pellet_cloud/proc/nullspace_parent()
|
||||
var/atom/movable/AM = parent
|
||||
AM.moveToNullspace()
|
||||
queued_delete = TRUE
|
||||
return TRUE
|
||||
|
||||
/// Someone who was originally "under" the grenade has moved off the tile and is now eligible for being a martyr and "covering" it
|
||||
/datum/component/pellet_cloud/proc/on_target_qdel(atom/target)
|
||||
UnregisterSignal(target, COMSIG_PARENT_QDELETING)
|
||||
targets_hit -= target
|
||||
bodies -= target
|
||||
purple_hearts -= target
|
||||
@@ -57,7 +57,7 @@
|
||||
/obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/dropper,
|
||||
/obj/item/implanter, /obj/item/screwdriver, /obj/item/weldingtool/mini,
|
||||
/obj/item/firing_pin, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/automatic/magrifle/pistol,
|
||||
/obj/item/toy/plush/snakeplushie
|
||||
/obj/item/toy/plush/snakeplushie, /obj/item/gun/energy/e_gun/mini
|
||||
))
|
||||
|
||||
/datum/component/storage/concrete/pockets/shoes/clown/Initialize()
|
||||
@@ -68,7 +68,7 @@
|
||||
/obj/item/scalpel, /obj/item/reagent_containers/syringe, /obj/item/dnainjector,
|
||||
/obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/dropper,
|
||||
/obj/item/implanter, /obj/item/screwdriver, /obj/item/weldingtool/mini,
|
||||
/obj/item/firing_pin, /obj/item/bikehorn, /obj/item/gun/ballistic/automatic/pistol))
|
||||
/obj/item/firing_pin, /obj/item/bikehorn, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/energy/e_gun/mini))
|
||||
|
||||
/datum/component/storage/concrete/pockets/pocketprotector
|
||||
max_items = 3
|
||||
|
||||
@@ -11,6 +11,17 @@
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/join_swarm)
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_UNCROSSED, .proc/leave_swarm)
|
||||
|
||||
/datum/component/swarming/Destroy()
|
||||
if(is_swarming)
|
||||
for(var/A in swarm_members)
|
||||
var/datum/component/swarming/other_swarm = A
|
||||
other_swarm.swarm_members -= src
|
||||
swarm_members -= other_swarm
|
||||
if(!length(other_swarm.swarm_members))
|
||||
other_swarm.unswarm()
|
||||
unswarm()
|
||||
return ..()
|
||||
|
||||
/datum/component/swarming/proc/join_swarm(datum/source, atom/movable/AM)
|
||||
var/datum/component/swarming/other_swarm = AM.GetComponent(/datum/component/swarming)
|
||||
if(!other_swarm)
|
||||
|
||||
@@ -163,24 +163,24 @@
|
||||
if(-4 to -2) // glancing blow at best
|
||||
user.visible_message("<span class='warning'>[user] lands a weak [tackle_word] on [target], briefly knocking [target.p_them()] off-balance!</span>", "<span class='userdanger'>You land a weak [tackle_word] on [target], briefly knocking [target.p_them()] off-balance!</span>", target)
|
||||
to_chat(target, "<span class='userdanger'>[user] lands a weak [tackle_word] on you, briefly knocking you off-balance!</span>")
|
||||
|
||||
user.Knockdown(30)
|
||||
target.adjustStaminaLoss(15)
|
||||
target.apply_status_effect(STATUS_EFFECT_TASED_WEAK, 6 SECONDS)
|
||||
|
||||
if(-1 to 0) // decent hit, both parties are about equally inconvenienced
|
||||
user.visible_message("<span class='warning'>[user] lands a passable [tackle_word] on [target], sending them both tumbling!</span>", "<span class='userdanger'>You land a passable [tackle_word] on [target], sending you both tumbling!</span>", target)
|
||||
to_chat(target, "<span class='userdanger'>[user] lands a passable [tackle_word] on you, sending you both tumbling!</span>")
|
||||
|
||||
target.adjustStaminaLoss(stamina_cost)
|
||||
target.adjustStaminaLoss(stamina_cost * 1.5)
|
||||
target.Paralyze(5)
|
||||
user.Knockdown(20)
|
||||
target.Knockdown(25)
|
||||
target.Knockdown(30)
|
||||
|
||||
if(1 to 2) // solid hit, tackler has a slight advantage
|
||||
user.visible_message("<span class='warning'>[user] lands a solid [tackle_word] on [target], knocking them both down hard!</span>", "<span class='userdanger'>You land a solid [tackle_word] on [target], knocking you both down hard!</span>", target)
|
||||
to_chat(target, "<span class='userdanger'>[user] lands a solid [tackle_word] on you, knocking you both down hard!</span>")
|
||||
|
||||
target.adjustStaminaLoss(30)
|
||||
target.adjustStaminaLoss(40)
|
||||
target.Paralyze(5)
|
||||
user.Knockdown(10)
|
||||
target.Knockdown(20)
|
||||
@@ -192,9 +192,9 @@
|
||||
user.SetKnockdown(0)
|
||||
user.set_resting(FALSE, TRUE, FALSE)
|
||||
user.forceMove(get_turf(target))
|
||||
target.adjustStaminaLoss(40)
|
||||
target.Paralyze(5)
|
||||
target.Knockdown(30)
|
||||
target.adjustStaminaLoss(50)
|
||||
target.Paralyze(3) //Otherwise the victim can just instantly get out of the grab.
|
||||
target.DefaultCombatKnockdown(20) //So they cant get up instantly.
|
||||
if(ishuman(target) && iscarbon(user))
|
||||
target.grabbedby(user)
|
||||
|
||||
@@ -205,9 +205,9 @@
|
||||
user.SetKnockdown(0)
|
||||
user.set_resting(FALSE, TRUE, FALSE)
|
||||
user.forceMove(get_turf(target))
|
||||
target.adjustStaminaLoss(40)
|
||||
target.Paralyze(5)
|
||||
target.Knockdown(30)
|
||||
target.adjustStaminaLoss(65)
|
||||
target.Paralyze(10)
|
||||
target.DefaultCombatKnockdown(20)
|
||||
if(ishuman(target) && iscarbon(user))
|
||||
target.grabbedby(user)
|
||||
target.grippedby(user, instant = TRUE)
|
||||
@@ -354,7 +354,7 @@
|
||||
playsound(user, 'sound/effects/blobattack.ogg', 60, TRUE)
|
||||
playsound(user, 'sound/effects/splat.ogg', 70, TRUE)
|
||||
user.emote("scream")
|
||||
user.gain_trauma(/datum/brain_trauma/severe/paralysis/paraplegic) // oopsie indeed!
|
||||
user.gain_trauma(/datum/brain_trauma/severe/paralysis/spinesnapped) // oopsie indeed!
|
||||
shake_camera(user, 7, 7)
|
||||
user.overlay_fullscreen("flash", /obj/screen/fullscreen/flash)
|
||||
user.clear_fullscreen("flash", 4.5)
|
||||
@@ -415,10 +415,10 @@
|
||||
for(var/i = 0, i < speed, i++)
|
||||
var/obj/item/shard/shard = new /obj/item/shard(get_turf(user))
|
||||
//shard.embedding = list(embed_chance = 100, ignore_throwspeed_threshold = TRUE, impact_pain_mult=3, pain_chance=5)
|
||||
//shard.AddElement(/datum/element/embed, shard.embedding)
|
||||
shard.updateEmbedding()
|
||||
user.hitby(shard, skipcatch = TRUE, hitpush = FALSE)
|
||||
//shard.embedding = list()
|
||||
//shard.AddElement(/datum/element/embed, shard.embedding)
|
||||
shard.embedding = list()
|
||||
shard.updateEmbedding()
|
||||
W.obj_destruction()
|
||||
user.adjustStaminaLoss(10 * speed)
|
||||
user.DefaultCombatKnockdown(40)
|
||||
|
||||
@@ -52,9 +52,9 @@
|
||||
to_chat(affected_mob, pick(stage5))
|
||||
if(QDELETED(affected_mob))
|
||||
return
|
||||
if(affected_mob.notransform)
|
||||
if(affected_mob.mob_transforming)
|
||||
return
|
||||
affected_mob.notransform = 1
|
||||
affected_mob.mob_transforming = 1
|
||||
for(var/obj/item/W in affected_mob.get_equipped_items(TRUE))
|
||||
affected_mob.dropItemToGround(W)
|
||||
for(var/obj/item/I in affected_mob.held_items)
|
||||
|
||||
@@ -175,11 +175,6 @@
|
||||
name = "Trooper REAL_NAME"
|
||||
desc = "That's not red paint. That's real corgi blood."
|
||||
|
||||
/datum/dog_fashion/head/colour
|
||||
name = "Stylish REAL_NAME"
|
||||
desc = "From the tips of their paws to the top of their head, they look like a made bed."
|
||||
emote_see = list("tries to tap dances.","looks sadly at others outfits...","barks at bad fashion!")
|
||||
|
||||
/datum/dog_fashion/head/telegram
|
||||
name = "Messenger REAL_NAME"
|
||||
desc = "Dont shoot the messenger..."
|
||||
|
||||
@@ -19,11 +19,13 @@
|
||||
SHOULD_CALL_PARENT(1)
|
||||
if(type == /datum/element)
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
SEND_SIGNAL(target, COMSIG_ELEMENT_ATTACH, src)
|
||||
if(element_flags & ELEMENT_DETACH)
|
||||
RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/Detach, override = TRUE)
|
||||
|
||||
/// Deactivates the functionality defines by the element on the given datum
|
||||
/datum/element/proc/Detach(datum/source, force)
|
||||
SEND_SIGNAL(source, COMSIG_ELEMENT_DETACH, src)
|
||||
SHOULD_CALL_PARENT(1)
|
||||
UnregisterSignal(source, COMSIG_PARENT_QDELETING)
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/datum/element/decal
|
||||
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
|
||||
id_arg_index = 2
|
||||
var/cleanable
|
||||
var/description
|
||||
var/mutable_appearance/pic
|
||||
var/list/num_decals_per_atom
|
||||
|
||||
var/first_dir // This stores the direction of the decal compared to the parent facing NORTH
|
||||
|
||||
/datum/element/decal/Attach(datum/target, _icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description, _alpha=255)
|
||||
. = ..()
|
||||
if(. == ELEMENT_INCOMPATIBLE || !_icon || !_icon_state || !isatom(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
var/atom/A = target
|
||||
if(!pic)
|
||||
// It has to be made from an image or dir breaks because of a byond bug
|
||||
var/temp_image = image(_icon, null, _icon_state, _layer, _dir)
|
||||
pic = new(temp_image)
|
||||
pic.color = _color
|
||||
pic.alpha = _alpha
|
||||
first_dir = _dir
|
||||
description = _description
|
||||
cleanable = _cleanable
|
||||
|
||||
LAZYINITLIST(num_decals_per_atom)
|
||||
|
||||
if(!num_decals_per_atom[A])
|
||||
if(first_dir)
|
||||
RegisterSignal(A, COMSIG_ATOM_DIR_CHANGE, .proc/rotate_react)
|
||||
if(cleanable)
|
||||
RegisterSignal(A, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_react)
|
||||
if(description)
|
||||
RegisterSignal(A, COMSIG_PARENT_EXAMINE, .proc/examine)
|
||||
|
||||
apply(A, TRUE)
|
||||
|
||||
num_decals_per_atom[A]++
|
||||
|
||||
/datum/element/decal/Detach(datum/target)
|
||||
var/atom/A = target
|
||||
remove(A, A.dir)
|
||||
UnregisterSignal(A, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE))
|
||||
LAZYREMOVE(num_decals_per_atom, A)
|
||||
return ..()
|
||||
|
||||
/datum/element/decal/proc/remove(atom/target, old_dir)
|
||||
pic.dir = first_dir == NORTH ? target.dir : turn(first_dir, dir2angle(old_dir))
|
||||
for(var/i in 1 to num_decals_per_atom[target])
|
||||
target.cut_overlay(pic, TRUE)
|
||||
if(isitem(target))
|
||||
addtimer(CALLBACK(target, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
|
||||
|
||||
/datum/element/decal/proc/apply(atom/target, init = FALSE)
|
||||
pic.dir = first_dir == NORTH ? target.dir : turn(first_dir, dir2angle(target.dir))
|
||||
if(init)
|
||||
target.add_overlay(pic, TRUE)
|
||||
else
|
||||
for(var/i in 1 to num_decals_per_atom[target])
|
||||
target.add_overlay(pic, TRUE)
|
||||
if(isitem(target))
|
||||
addtimer(CALLBACK(target, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
|
||||
|
||||
/datum/element/decal/proc/rotate_react(datum/source, old_dir, new_dir)
|
||||
if(old_dir == new_dir)
|
||||
return
|
||||
remove(source, old_dir)
|
||||
apply(source)
|
||||
|
||||
/datum/element/decal/proc/clean_react(datum/source, strength)
|
||||
if(strength >= cleanable)
|
||||
Detach(source)
|
||||
|
||||
/datum/element/decal/proc/examine(datum/source, mob/user, list/examine_list)
|
||||
examine_list += description
|
||||
@@ -4,7 +4,7 @@
|
||||
var/list/user_by_item = list()
|
||||
|
||||
/datum/element/earhealing/New()
|
||||
START_PROCESSING(SSdcs, src)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/datum/element/earhealing/Attach(datum/target)
|
||||
. = ..()
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
The presence of this element allows an item (or a projectile carrying an item) to embed itself in a human or turf when it is thrown into a target (whether by hand, gun, or explosive wave) with either
|
||||
at least 4 throwspeed (EMBED_THROWSPEED_THRESHOLD) or ignore_throwspeed_threshold set to TRUE. Items meant to be used as shrapnel for projectiles should have ignore_throwspeed_threshold set to true.
|
||||
|
||||
Whether we're dealing with a direct /obj/item (throwing a knife at someone) or an /obj/projectile with a shrapnel_type, how we handle things plays out the same, with one extra step separating them.
|
||||
Items simply make their COMSIG_MOVABLE_IMPACT or COMSIG_MOVABLE_IMPACT_ZONE check (against a closed turf or a carbon, respectively), while projectiles check on COMSIG_PROJECTILE_SELF_ON_HIT.
|
||||
Upon a projectile hitting a valid target, it spawns whatever type of payload it has defined, then has that try to embed itself in the target on its own.
|
||||
|
||||
Otherwise non-embeddable or stickable items can be made embeddable/stickable through wizard events/sticky tape/admin memes.
|
||||
*/
|
||||
|
||||
#define STANDARD_WALL_HARDNESS 40
|
||||
|
||||
/datum/element/embed
|
||||
element_flags = ELEMENT_BESPOKE
|
||||
id_arg_index = 2
|
||||
var/initialized = FALSE /// whether we can skip assigning all the vars (since these are bespoke elements, we don't have to reset the vars every time we attach to something, we already know what we are!)
|
||||
|
||||
// all of this stuff is explained in _DEFINES/combat.dm
|
||||
var/embed_chance
|
||||
var/fall_chance
|
||||
var/pain_chance
|
||||
var/pain_mult
|
||||
var/remove_pain_mult
|
||||
var/impact_pain_mult
|
||||
var/rip_time
|
||||
var/ignore_throwspeed_threshold
|
||||
var/jostle_chance
|
||||
var/jostle_pain_mult
|
||||
var/pain_stam_pct
|
||||
var/payload_type
|
||||
var/embed_chance_turf_mod
|
||||
|
||||
/datum/element/embed/Attach(datum/target, embed_chance, fall_chance, pain_chance, pain_mult, remove_pain_mult, impact_pain_mult, rip_time, ignore_throwspeed_threshold, jostle_chance, jostle_pain_mult, pain_stam_pct, embed_chance_turf_mod, projectile_payload=/obj/item/shard)
|
||||
. = ..()
|
||||
|
||||
if(!isitem(target) && !isprojectile(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
|
||||
if(isitem(target))
|
||||
RegisterSignal(target, COMSIG_MOVABLE_IMPACT_ZONE, .proc/checkEmbedMob)
|
||||
RegisterSignal(target, COMSIG_MOVABLE_IMPACT, .proc/checkEmbedOther)
|
||||
RegisterSignal(target, COMSIG_ELEMENT_ATTACH, .proc/severancePackage)
|
||||
RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/examined)
|
||||
RegisterSignal(target, COMSIG_EMBED_TRY_FORCE, .proc/tryForceEmbed)
|
||||
RegisterSignal(target, COMSIG_ITEM_DISABLE_EMBED, .proc/detachFromWeapon)
|
||||
if(!initialized)
|
||||
src.embed_chance = embed_chance
|
||||
src.fall_chance = fall_chance
|
||||
src.pain_chance = pain_chance
|
||||
src.pain_mult = pain_mult
|
||||
src.remove_pain_mult = remove_pain_mult
|
||||
src.rip_time = rip_time
|
||||
src.impact_pain_mult = impact_pain_mult
|
||||
src.ignore_throwspeed_threshold = ignore_throwspeed_threshold
|
||||
src.jostle_chance = jostle_chance
|
||||
src.jostle_pain_mult = jostle_pain_mult
|
||||
src.pain_stam_pct = pain_stam_pct
|
||||
src.embed_chance_turf_mod = embed_chance_turf_mod
|
||||
initialized = TRUE
|
||||
else
|
||||
payload_type = projectile_payload
|
||||
RegisterSignal(target, COMSIG_PROJECTILE_SELF_ON_HIT, .proc/checkEmbedProjectile)
|
||||
|
||||
|
||||
/datum/element/embed/Detach(obj/target)
|
||||
. = ..()
|
||||
if(isitem(target))
|
||||
UnregisterSignal(target, list(COMSIG_MOVABLE_IMPACT_ZONE, COMSIG_ELEMENT_ATTACH, COMSIG_MOVABLE_IMPACT, COMSIG_PARENT_EXAMINE, COMSIG_EMBED_TRY_FORCE, COMSIG_ITEM_DISABLE_EMBED))
|
||||
else
|
||||
UnregisterSignal(target, list(COMSIG_PROJECTILE_SELF_ON_HIT))
|
||||
|
||||
|
||||
/// Checking to see if we're gonna embed into a human
|
||||
/datum/element/embed/proc/checkEmbedMob(obj/item/weapon, mob/living/carbon/victim, hit_zone, datum/thrownthing/throwingdatum, blocked = FALSE, forced = FALSE)
|
||||
if(blocked || !istype(victim) || HAS_TRAIT(victim, TRAIT_PIERCEIMMUNE))
|
||||
return
|
||||
|
||||
var/actual_chance = embed_chance
|
||||
|
||||
if(!weapon.isEmbedHarmless()) // all the armor in the world won't save you from a kick me sign
|
||||
var/armor = max(victim.run_armor_check(hit_zone, "bullet", silent=TRUE), victim.run_armor_check(hit_zone, "bomb", silent=TRUE)) // we'll be nice and take the better of bullet and bomb armor
|
||||
|
||||
if(armor) // we only care about armor penetration if there's actually armor to penetrate
|
||||
var/pen_mod = -armor + weapon.armour_penetration // even a little bit of armor can make a big difference for shrapnel with large negative armor pen
|
||||
actual_chance += pen_mod // doing the armor pen as a separate calc just in case this ever gets expanded on
|
||||
if(actual_chance <= 0)
|
||||
victim.visible_message("<span class='danger'>[weapon] bounces off [victim]'s armor!</span>", "<span class='notice'>[weapon] bounces off your armor!</span>", vision_distance = COMBAT_MESSAGE_RANGE)
|
||||
return
|
||||
|
||||
var/roll_embed = prob(actual_chance)
|
||||
var/pass = forced || ((((throwingdatum ? throwingdatum.speed : weapon.throw_speed) >= EMBED_THROWSPEED_THRESHOLD) || ignore_throwspeed_threshold) && roll_embed && (!HAS_TRAIT(victim, TRAIT_AUTO_CATCH_ITEM) || victim.incapacitated() || victim.get_active_held_item()))
|
||||
if(!pass)
|
||||
return
|
||||
|
||||
var/obj/item/bodypart/limb = victim.get_bodypart(hit_zone) || pick(victim.bodyparts)
|
||||
victim.AddComponent(/datum/component/embedded,\
|
||||
weapon,\
|
||||
throwingdatum,\
|
||||
part = limb,\
|
||||
embed_chance = embed_chance,\
|
||||
fall_chance = fall_chance,\
|
||||
pain_chance = pain_chance,\
|
||||
pain_mult = pain_mult,\
|
||||
remove_pain_mult = remove_pain_mult,\
|
||||
rip_time = rip_time,\
|
||||
ignore_throwspeed_threshold = ignore_throwspeed_threshold,\
|
||||
jostle_chance = jostle_chance,\
|
||||
jostle_pain_mult = jostle_pain_mult,\
|
||||
pain_stam_pct = pain_stam_pct,\
|
||||
embed_chance_turf_mod = embed_chance_turf_mod)
|
||||
|
||||
return TRUE
|
||||
|
||||
/// We need the hit_zone if we're embedding into a human, so this proc only handles if we're embedding into a turf
|
||||
/datum/element/embed/proc/checkEmbedOther(obj/item/weapon, turf/closed/hit, datum/thrownthing/throwingdatum, forced=FALSE)
|
||||
if(!istype(hit))
|
||||
return
|
||||
|
||||
var/chance = embed_chance + embed_chance_turf_mod
|
||||
if(iswallturf(hit))
|
||||
var/turf/closed/wall/W = hit
|
||||
chance += 2 * (W.hardness - STANDARD_WALL_HARDNESS)
|
||||
|
||||
if(!forced && chance <= 0 || embed_chance_turf_mod <= -100)
|
||||
return
|
||||
|
||||
var/pass = ((((throwingdatum ? throwingdatum.speed : weapon.throw_speed) >= EMBED_THROWSPEED_THRESHOLD) || ignore_throwspeed_threshold) && prob(chance))
|
||||
if(!pass)
|
||||
return
|
||||
|
||||
hit.AddComponent(/datum/component/embedded,\
|
||||
weapon,\
|
||||
throwingdatum,\
|
||||
embed_chance = embed_chance,\
|
||||
fall_chance = fall_chance,\
|
||||
pain_chance = pain_chance,\
|
||||
pain_mult = pain_mult,\
|
||||
remove_pain_mult = remove_pain_mult,\
|
||||
rip_time = rip_time,\
|
||||
ignore_throwspeed_threshold = ignore_throwspeed_threshold,\
|
||||
jostle_chance = jostle_chance,\
|
||||
jostle_pain_mult = jostle_pain_mult,\
|
||||
pain_stam_pct = pain_stam_pct,\
|
||||
embed_chance_turf_mod = embed_chance_turf_mod)
|
||||
|
||||
return TRUE
|
||||
|
||||
///A different embed element has been attached, so we'll detach and let them handle things
|
||||
/datum/element/embed/proc/severancePackage(obj/item/weapon, datum/element/E)
|
||||
if(istype(E, /datum/element/embed))
|
||||
Detach(weapon)
|
||||
|
||||
///If we don't want to be embeddable anymore (deactivating an e-dagger for instance)
|
||||
/datum/element/embed/proc/detachFromWeapon(obj/weapon)
|
||||
Detach(weapon)
|
||||
|
||||
///Someone inspected our embeddable item
|
||||
/datum/element/embed/proc/examined(obj/item/I, mob/user, list/examine_list)
|
||||
if(I.isEmbedHarmless())
|
||||
examine_list += "[I] feels sticky, and could probably get stuck to someone if thrown properly!"
|
||||
else
|
||||
examine_list += "[I] has a fine point, and could probably embed in someone if thrown properly!"
|
||||
|
||||
/**
|
||||
* checkEmbedProjectile() is what we get when a projectile with a defined shrapnel_type impacts a target.
|
||||
*
|
||||
* If we hit a valid target (carbon or closed turf), we create the shrapnel_type object and immediately call tryEmbed() on it, targeting what we impacted. That will lead
|
||||
* it to call tryForceEmbed() on its own embed element (it's out of our hands here, our projectile is done), where it will run through all the checks it needs to.
|
||||
*/
|
||||
/datum/element/embed/proc/checkEmbedProjectile(obj/item/projectile/P, atom/movable/firer, atom/hit, angle, hit_zone)
|
||||
if(!iscarbon(hit) && !isclosedturf(hit))
|
||||
Detach(P)
|
||||
return // we don't care
|
||||
|
||||
var/obj/item/payload = new payload_type(get_turf(hit))
|
||||
var/did_embed
|
||||
if(iscarbon(hit))
|
||||
var/mob/living/carbon/C = hit
|
||||
var/obj/item/bodypart/limb
|
||||
limb = C.get_bodypart(hit_zone)
|
||||
if(!limb)
|
||||
limb = C.get_bodypart()
|
||||
did_embed = payload.tryEmbed(limb)
|
||||
else
|
||||
did_embed = payload.tryEmbed(hit)
|
||||
|
||||
if(!did_embed)
|
||||
payload.failedEmbed()
|
||||
Detach(P)
|
||||
|
||||
/**
|
||||
* tryForceEmbed() is called here when we fire COMSIG_EMBED_TRY_FORCE from [/obj/item/proc/tryEmbed]. Mostly, this means we're a piece of shrapnel from a projectile that just impacted something, and we're trying to embed in it.
|
||||
*
|
||||
* The reason for this extra mucking about is avoiding having to do an extra hitby(), and annoying the target by impacting them once with the projectile, then again with the shrapnel (which likely represents said bullet), and possibly
|
||||
* AGAIN if we actually embed. This way, we save on at least one message. Runs the standard embed checks on the mob/turf.
|
||||
*
|
||||
* Arguments:
|
||||
* * I- what we're trying to embed, obviously
|
||||
* * target- what we're trying to shish-kabob, either a bodypart, a carbon, or a closed turf
|
||||
* * hit_zone- if our target is a carbon, try to hit them in this zone, if we don't have one, pick a random one. If our target is a bodypart, we already know where we're hitting.
|
||||
* * forced- if we want this to succeed 100%
|
||||
*/
|
||||
/datum/element/embed/proc/tryForceEmbed(obj/item/I, atom/target, hit_zone, forced=FALSE)
|
||||
var/obj/item/bodypart/limb
|
||||
var/mob/living/carbon/C
|
||||
var/turf/closed/T
|
||||
|
||||
if(!forced && !prob(embed_chance))
|
||||
return
|
||||
|
||||
if(iscarbon(target))
|
||||
C = target
|
||||
if(!hit_zone)
|
||||
limb = pick(C.bodyparts)
|
||||
hit_zone = limb.body_zone
|
||||
else if(isbodypart(target))
|
||||
limb = target
|
||||
hit_zone = limb.body_zone
|
||||
C = limb.owner
|
||||
else if(isclosedturf(target))
|
||||
T = target
|
||||
|
||||
if(C)
|
||||
return checkEmbedMob(I, C, hit_zone, forced=TRUE)
|
||||
else if(T)
|
||||
return checkEmbedOther(I, T, forced=TRUE)
|
||||
@@ -117,9 +117,9 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
|
||||
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)
|
||||
var/new_text = stripped_multiline_input(user, "Set the [lower_name] displayed on 'examine'. [addendum]", flavor_name, html_decode(texts_by_atom[usr]), max_len, TRUE)
|
||||
if(!isnull(new_text) && (user in texts_by_atom))
|
||||
texts_by_atom[user] = html_decode(new_text)
|
||||
texts_by_atom[user] = new_text
|
||||
to_chat(src, "Your [lower_name] has been updated.")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/datum/element/photosynthesis
|
||||
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
|
||||
id_arg_index = 2
|
||||
///how much brute damage (or integrity, for objects) is healed (taken if positive) at maximum luminosity. (if lum_minus were 0)
|
||||
var/light_bruteheal = -1
|
||||
///how much burn damage is restored/taken at maximum luminosity. Mobs only.
|
||||
var/light_burnheal = -1
|
||||
///how much tox damage is restored/taken at maximum luminosity. Mobs only.
|
||||
var/light_toxheal = -1
|
||||
///how much oxy damage is restored/taken at maximum luminosity. Mobs only.
|
||||
var/light_oxyheal = -1
|
||||
///how nutrition recovery/expenses factor, not affected by bonus_lum and malus_lum. Mobs only.
|
||||
var/light_nutrition_gain = 4
|
||||
///A value subtracted to the lum count, which allows targets to wilt or heal in the darkness.
|
||||
var/lum_minus = 0.5
|
||||
///the minimum lum count over which where the target damage is adjusted.
|
||||
var/bonus_lum = 0.2
|
||||
///the maximum lum count under which the target damage is inversely adjusted.
|
||||
var/malus_lum = 0
|
||||
///List of atoms this element is attached to. Doubles as a multiplier if the same element is attached multiple times to a target multiple times.
|
||||
var/list/attached_atoms
|
||||
|
||||
/datum/element/photosynthesis/Attach(datum/target, brute = -1, burn = -1, tox = -1, oxy = -1, nutri = 4, minus = 0.2, bonus = 0.3, malus = -0.1)
|
||||
. = ..()
|
||||
if(. == ELEMENT_INCOMPATIBLE || !(isliving(target) || (isobj(target) && light_bruteheal)))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
light_bruteheal = brute
|
||||
light_burnheal = burn
|
||||
light_toxheal = tox
|
||||
light_oxyheal = oxy
|
||||
light_nutrition_gain = nutri
|
||||
lum_minus = minus
|
||||
bonus_lum = bonus
|
||||
malus_lum = malus
|
||||
|
||||
if(!attached_atoms)
|
||||
attached_atoms = list()
|
||||
START_PROCESSING(SSobj, src)
|
||||
attached_atoms[target]++
|
||||
|
||||
/datum/element/photosynthesis/Detach(datum/target)
|
||||
attached_atoms[target]--
|
||||
if(!attached_atoms[target])
|
||||
attached_atoms -= target
|
||||
if(!length(attached_atoms))
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
attached_atoms = null
|
||||
return ..()
|
||||
|
||||
/datum/element/photosynthesis/process()
|
||||
for(var/A in attached_atoms)
|
||||
var/atom/movable/AM = A
|
||||
var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing
|
||||
if(isturf(AM.loc)) //else, there's considered to be no light
|
||||
var/turf/T = AM.loc
|
||||
light_amount = (T.get_lumcount() - lum_minus)
|
||||
|
||||
if(isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
if(L.stat == DEAD)
|
||||
continue
|
||||
if(light_nutrition_gain)
|
||||
L.adjust_nutrition(light_amount * light_nutrition_gain * attached_atoms[AM], NUTRITION_LEVEL_FULL)
|
||||
if(light_amount > bonus_lum || light_amount < malus_lum)
|
||||
var/mult = ((light_amount > bonus_lum) ? 1 : -1) * attached_atoms[AM]
|
||||
if(light_bruteheal)
|
||||
L.adjustBruteLoss(light_bruteheal * mult)
|
||||
if(light_burnheal)
|
||||
L.adjustFireLoss(light_burnheal * mult)
|
||||
if(light_toxheal)
|
||||
L.adjustToxLoss(light_toxheal * mult)
|
||||
if(light_oxyheal)
|
||||
L.adjustOxyLoss(light_oxyheal * mult)
|
||||
|
||||
else if(light_amount > bonus_lum || light_amount < malus_lum)
|
||||
var/obj/O = AM
|
||||
var/damage = light_bruteheal * ((light_amount > bonus_lum) ? 1 : -1) * attached_atoms[AM]
|
||||
if(damage < 0 && O.obj_integrity < O.max_integrity)
|
||||
O.obj_integrity = min(O.obj_integrity + damage, O.max_integrity) //Till we get a obj heal proc...
|
||||
else
|
||||
O.take_damage(damage, BRUTE, FALSE, FALSE, null, 100)
|
||||
@@ -1,53 +0,0 @@
|
||||
#define EMBEDID "embed-[embed_chance]-[embedded_fall_chance]-[embedded_pain_chance]-[embedded_pain_multiplier]-[embedded_fall_pain_multiplier]-[embedded_impact_pain_multiplier]-[embedded_unsafe_removal_pain_multiplier]-[embedded_unsafe_removal_time]"
|
||||
|
||||
/proc/getEmbeddingBehavior(embed_chance = EMBED_CHANCE,
|
||||
embedded_fall_chance = EMBEDDED_ITEM_FALLOUT,
|
||||
embedded_pain_chance = EMBEDDED_PAIN_CHANCE,
|
||||
embedded_pain_multiplier = EMBEDDED_PAIN_MULTIPLIER,
|
||||
embedded_fall_pain_multiplier = EMBEDDED_FALL_PAIN_MULTIPLIER,
|
||||
embedded_impact_pain_multiplier = EMBEDDED_IMPACT_PAIN_MULTIPLIER,
|
||||
embedded_unsafe_removal_pain_multiplier = EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER,
|
||||
embedded_unsafe_removal_time = EMBEDDED_UNSAFE_REMOVAL_TIME)
|
||||
. = locate(EMBEDID)
|
||||
if (!.)
|
||||
. = new /datum/embedding_behavior(embed_chance, embedded_fall_chance, embedded_pain_chance, embedded_pain_multiplier, embedded_fall_pain_multiplier, embedded_impact_pain_multiplier, embedded_unsafe_removal_pain_multiplier, embedded_unsafe_removal_time)
|
||||
|
||||
/datum/embedding_behavior
|
||||
var/embed_chance
|
||||
var/embedded_fall_chance
|
||||
var/embedded_pain_chance
|
||||
var/embedded_pain_multiplier //The coefficient of multiplication for the damage this item does while embedded (this*w_class)
|
||||
var/embedded_fall_pain_multiplier //The coefficient of multiplication for the damage this item does when falling out of a limb (this*w_class)
|
||||
var/embedded_impact_pain_multiplier //The coefficient of multiplication for the damage this item does when first embedded (this*w_class)
|
||||
var/embedded_unsafe_removal_pain_multiplier //The coefficient of multiplication for the damage removing this without surgery causes (this*w_class)
|
||||
var/embedded_unsafe_removal_time //A time in ticks, multiplied by the w_class.
|
||||
|
||||
/datum/embedding_behavior/New(embed_chance = EMBED_CHANCE,
|
||||
embedded_fall_chance = EMBEDDED_ITEM_FALLOUT,
|
||||
embedded_pain_chance = EMBEDDED_PAIN_CHANCE,
|
||||
embedded_pain_multiplier = EMBEDDED_PAIN_MULTIPLIER,
|
||||
embedded_fall_pain_multiplier = EMBEDDED_FALL_PAIN_MULTIPLIER,
|
||||
embedded_impact_pain_multiplier = EMBEDDED_IMPACT_PAIN_MULTIPLIER,
|
||||
embedded_unsafe_removal_pain_multiplier = EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER,
|
||||
embedded_unsafe_removal_time = EMBEDDED_UNSAFE_REMOVAL_TIME)
|
||||
src.embed_chance = embed_chance
|
||||
src.embedded_fall_chance = embedded_fall_chance
|
||||
src.embedded_pain_chance = embedded_pain_chance
|
||||
src.embedded_pain_multiplier = embedded_pain_multiplier
|
||||
src.embedded_fall_pain_multiplier = embedded_fall_pain_multiplier
|
||||
src.embedded_impact_pain_multiplier = embedded_impact_pain_multiplier
|
||||
src.embedded_unsafe_removal_pain_multiplier = embedded_unsafe_removal_pain_multiplier
|
||||
src.embedded_unsafe_removal_time = embedded_unsafe_removal_time
|
||||
tag = EMBEDID
|
||||
|
||||
/datum/embedding_behavior/proc/setRating(embed_chance, embedded_fall_chance, embedded_pain_chance, embedded_pain_multiplier, embedded_fall_pain_multiplier, embedded_impact_pain_multiplier, embedded_unsafe_removal_pain_multiplier, embedded_unsafe_removal_time)
|
||||
return getEmbeddingBehavior((isnull(embed_chance) ? src.embed_chance : embed_chance),\
|
||||
(isnull(embedded_fall_chance) ? src.embedded_fall_chance : embedded_fall_chance),\
|
||||
(isnull(embedded_pain_chance) ? src.embedded_pain_chance : embedded_pain_chance),\
|
||||
(isnull(embedded_pain_multiplier) ? src.embedded_pain_multiplier : embedded_pain_multiplier),\
|
||||
(isnull(embedded_fall_pain_multiplier) ? src.embedded_fall_pain_multiplier : embedded_fall_pain_multiplier),\
|
||||
(isnull(embedded_impact_pain_multiplier) ? src.embedded_impact_pain_multiplier : embedded_impact_pain_multiplier),\
|
||||
(isnull(embedded_unsafe_removal_pain_multiplier) ? src.embedded_unsafe_removal_pain_multiplier : embedded_unsafe_removal_pain_multiplier),\
|
||||
(isnull(embedded_unsafe_removal_time) ? src.embedded_unsafe_removal_time : embedded_unsafe_removal_time))
|
||||
|
||||
#undef EMBEDID
|
||||
+2
-1
@@ -27,7 +27,8 @@ GLOBAL_LIST_INIT(huds, list(
|
||||
ANTAG_HUD_SOULLESS = new/datum/atom_hud/antag/hidden(),
|
||||
ANTAG_HUD_CLOCKWORK = new/datum/atom_hud/antag(),
|
||||
ANTAG_HUD_BROTHER = new/datum/atom_hud/antag/hidden(),
|
||||
ANTAG_HUD_BLOODSUCKER = new/datum/atom_hud/antag/bloodsucker()
|
||||
ANTAG_HUD_BLOODSUCKER = new/datum/atom_hud/antag/bloodsucker(),
|
||||
ANTAG_HUD_FUGITIVE = new/datum/atom_hud/antag()
|
||||
))
|
||||
|
||||
/datum/atom_hud
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
var/help_verb
|
||||
var/pacifism_check = TRUE //are the martial arts combos/attacks unable to be used by pacifist.
|
||||
var/allow_temp_override = TRUE //if this martial art can be overridden by temporary martial arts
|
||||
/// Can we be used to unarmed parry?
|
||||
var/can_martial_parry = FALSE
|
||||
/// Set this variable to something not null, this'll be the preferred unarmed parry in most cases if [can_martial_parry] is TRUE. YOU MUST RUN [get_block_parry_data(this)] INSTEAD OF DIRECTLY ACCESSING!
|
||||
var/datum/block_parry_data/block_parry_data
|
||||
var/pugilist = FALSE
|
||||
|
||||
/datum/martial_art/proc/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
@@ -91,4 +95,4 @@
|
||||
|
||||
///Gets called when a projectile hits the owner. Returning anything other than BULLET_ACT_HIT will stop the projectile from hitting the mob.
|
||||
/datum/martial_art/proc/on_projectile_hit(mob/living/carbon/human/A, obj/item/projectile/P, def_zone)
|
||||
return BULLET_ACT_HIT
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
@@ -66,9 +66,9 @@
|
||||
return
|
||||
|
||||
/obj/item/clothing/gloves/boxing/dropped(mob/user)
|
||||
. = ..()
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.get_item_by_slot(SLOT_GLOVES) == src)
|
||||
style.remove(H)
|
||||
return
|
||||
|
||||
@@ -203,6 +203,7 @@
|
||||
style.teach(H,1)
|
||||
|
||||
/obj/item/clothing/gloves/krav_maga/dropped(mob/user)
|
||||
. = ..()
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/H = user
|
||||
|
||||
@@ -480,12 +480,12 @@
|
||||
return
|
||||
|
||||
/obj/item/storage/belt/champion/wrestling/dropped(mob/user)
|
||||
. = ..()
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.get_item_by_slot(SLOT_BELT) == src)
|
||||
style.remove(H)
|
||||
return
|
||||
|
||||
//Subtype of wrestling, reserved for the wrestling belts found in the holodeck
|
||||
/datum/martial_art/wrestling/holodeck
|
||||
|
||||
+8
-2
@@ -331,14 +331,20 @@
|
||||
|
||||
/datum/mind/proc/enslave_mind_to_creator(mob/living/creator)
|
||||
if(iscultist(creator))
|
||||
SSticker.mode.add_cultist(src)
|
||||
if(iscultist(creator, TRUE))
|
||||
SSticker.mode.add_cultist(src)
|
||||
else
|
||||
src.add_antag_datum(/datum/antagonist/cult/neutered/traitor)
|
||||
|
||||
else if(is_revolutionary(creator))
|
||||
var/datum/antagonist/rev/converter = creator.mind.has_antag_datum(/datum/antagonist/rev,TRUE)
|
||||
converter.add_revolutionary(src,FALSE)
|
||||
|
||||
else if(is_servant_of_ratvar(creator))
|
||||
add_servant_of_ratvar(current)
|
||||
if(is_servant_of_ratvar(creator, TRUE))
|
||||
add_servant_of_ratvar(current)
|
||||
else
|
||||
add_servant_of_ratvar(current, FALSE, FALSE, /datum/antagonist/clockcult/neutered/traitor)
|
||||
|
||||
else if(is_nuclear_operative(creator))
|
||||
var/datum/antagonist/nukeop/converter = creator.mind.has_antag_datum(/datum/antagonist/nukeop,TRUE)
|
||||
|
||||
@@ -406,6 +406,8 @@
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
sharpness = IS_SHARP
|
||||
var/mob/living/carbon/human/fired_by
|
||||
/// if we missed our target
|
||||
var/missed = TRUE
|
||||
|
||||
/obj/item/hardened_spike/Initialize(mapload, firedby)
|
||||
. = ..()
|
||||
@@ -413,13 +415,12 @@
|
||||
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()
|
||||
if(missed)
|
||||
unembedded()
|
||||
|
||||
/obj/item/hardened_spike/embedded(atom/target)
|
||||
if(isbodypart(target))
|
||||
missed = FALSE
|
||||
|
||||
/obj/item/hardened_spike/unembedded()
|
||||
var/turf/T = get_turf(src)
|
||||
@@ -490,11 +491,7 @@
|
||||
|
||||
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()
|
||||
|
||||
|
||||
@@ -162,6 +162,10 @@
|
||||
port_id = "pirate"
|
||||
can_be_bought = FALSE
|
||||
|
||||
/datum/map_template/shuttle/hunter
|
||||
port_id = "hunter"
|
||||
can_be_bought = FALSE
|
||||
|
||||
/datum/map_template/shuttle/ruin //For random shuttles in ruins
|
||||
port_id = "ruin"
|
||||
can_be_bought = FALSE
|
||||
@@ -170,6 +174,11 @@
|
||||
port_id = "snowdin"
|
||||
can_be_bought = FALSE
|
||||
|
||||
/datum/map_template/shuttle/snow_taxi
|
||||
port_id = "snow"
|
||||
can_be_bought = FALSE
|
||||
suffix = "taxi"
|
||||
|
||||
// Shuttles start here:
|
||||
|
||||
/datum/map_template/shuttle/emergency/backup
|
||||
@@ -557,6 +566,10 @@
|
||||
suffix = "cog"
|
||||
name = "arrival shuttle (Cog)"
|
||||
|
||||
/datum/map_template/shuttle/arrival/snaxi
|
||||
suffix = "snaxi"
|
||||
name = "arrival shuttle (Snaxi)"
|
||||
|
||||
/datum/map_template/shuttle/aux_base/default
|
||||
suffix = "default"
|
||||
name = "auxilliary base (Default)"
|
||||
@@ -604,3 +617,15 @@
|
||||
/datum/map_template/shuttle/snowdin/excavation
|
||||
suffix = "excavation"
|
||||
name = "Snowdin Excavation Elevator"
|
||||
|
||||
/datum/map_template/shuttle/hunter/space_cop
|
||||
suffix = "space_cop"
|
||||
name = "Police Spacevan"
|
||||
|
||||
/datum/map_template/shuttle/hunter/russian
|
||||
suffix = "russian"
|
||||
name = "Russian Cargo Ship"
|
||||
|
||||
/datum/map_template/shuttle/hunter/bounty
|
||||
suffix = "bounty"
|
||||
name = "Bounty Hunter Ship"
|
||||
@@ -191,7 +191,7 @@
|
||||
/datum/mind/proc/skill_html_readout()
|
||||
var/list/out = list("<center><h1>Skills</h1></center><hr>")
|
||||
out += "<table style=\"width:100%\"><tr><th><b>Skill</b><th><b>Value</b></tr>"
|
||||
for(var/path in skill_holder.skills|skill_holder.skill_value_mods|skill_holder.skill_level_mods)
|
||||
for(var/path in GLOB.skill_datums)
|
||||
var/datum/skill/S = GLOB.skill_datums[path]
|
||||
var/skill_value = get_skill_value(path)
|
||||
var/skill_level = get_skill_level(path, round = TRUE)
|
||||
|
||||
@@ -795,3 +795,44 @@ datum/status_effect/pacify
|
||||
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"
|
||||
|
||||
/datum/status_effect/fake_virus
|
||||
id = "fake_virus"
|
||||
duration = 1800//3 minutes
|
||||
status_type = STATUS_EFFECT_REPLACE
|
||||
tick_interval = 1
|
||||
alert_type = null
|
||||
var/msg_stage = 0//so you dont get the most intense messages immediately
|
||||
|
||||
/datum/status_effect/fake_virus/tick()
|
||||
var/fake_msg = ""
|
||||
var/fake_emote = ""
|
||||
switch(msg_stage)
|
||||
if(0 to 300)
|
||||
if(prob(1))
|
||||
fake_msg = pick("<span class='warning'>[pick("Your head hurts.", "Your head pounds.")]</span>",
|
||||
"<span class='warning'>[pick("You're having difficulty breathing.", "Your breathing becomes heavy.")]</span>",
|
||||
"<span class='warning'>[pick("You feel dizzy.", "Your head spins.")]</span>",
|
||||
"<span notice='warning'>[pick("You swallow excess mucus.", "You lightly cough.")]</span>",
|
||||
"<span class='warning'>[pick("Your head hurts.", "Your mind blanks for a moment.")]</span>",
|
||||
"<span class='warning'>[pick("Your throat hurts.", "You clear your throat.")]</span>")
|
||||
if(301 to 600)
|
||||
if(prob(2))
|
||||
fake_msg = pick("<span class='warning'>[pick("Your head hurts a lot.", "Your head pounds incessantly.")]</span>",
|
||||
"<span class='warning'>[pick("Your windpipe feels like a straw.", "Your breathing becomes tremendously difficult.")]</span>",
|
||||
"<span class='warning'>You feel very [pick("dizzy","woozy","faint")].</span>",
|
||||
"<span class='warning'>[pick("You hear a ringing in your ear.", "Your ears pop.")]</span>",
|
||||
"<span class='warning'>You nod off for a moment.</span>")
|
||||
else
|
||||
if(prob(3))
|
||||
if(prob(50))// coin flip to throw a message or an emote
|
||||
fake_msg = pick("<span class='userdanger'>[pick("Your head hurts!", "You feel a burning knife inside your brain!", "A wave of pain fills your head!")]</span>",
|
||||
"<span class='userdanger'>[pick("Your lungs hurt!", "It hurts to breathe!")]</span>",
|
||||
"<span class='warning'>[pick("You feel nauseated.", "You feel like you're going to throw up!")]</span>")
|
||||
else
|
||||
fake_emote = pick("cough", "sniff", "sneeze")
|
||||
if(fake_emote)
|
||||
owner.emote(fake_emote)
|
||||
else if(fake_msg)
|
||||
to_chat(owner, fake_msg)
|
||||
msg_stage++
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
area_type = /area
|
||||
protected_areas = list(/area/maintenance, /area/ai_monitored/turret_protected/ai_upload, /area/ai_monitored/turret_protected/ai_upload_foyer,
|
||||
/area/ai_monitored/turret_protected/ai, /area/storage/emergency/starboard, /area/storage/emergency/port, /area/shuttle, /area/security/prison, /area/ruin, /area/space/nearstation)
|
||||
/area/ai_monitored/turret_protected/ai, /area/storage/emergency/starboard, /area/storage/emergency/port, /area/shuttle, /area/security/prison, /area/ruin, /area/space/nearstation, /area/icemoon)
|
||||
target_trait = ZTRAIT_STATION
|
||||
|
||||
immunity_type = "rad"
|
||||
|
||||
@@ -93,6 +93,13 @@
|
||||
/area/shuttle/abandoned/pod
|
||||
name = "Abandoned Ship Pod"
|
||||
|
||||
////////////////////////////Bounty Hunter Shuttles////////////////////////////
|
||||
/area/shuttle/hunter
|
||||
name = "Hunter Shuttle"
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
|
||||
blob_allowed = FALSE
|
||||
canSmoothWithAreas = /area/shuttle/hunter
|
||||
|
||||
////////////////////////////Single-area shuttles////////////////////////////
|
||||
|
||||
/area/shuttle/transit
|
||||
@@ -103,6 +110,10 @@
|
||||
/area/shuttle/custom
|
||||
name = "Custom player shuttle"
|
||||
|
||||
/area/shuttle/custom/powered
|
||||
name = "Custom Powered player shuttle"
|
||||
requires_power = FALSE
|
||||
|
||||
/area/shuttle/arrival
|
||||
name = "Arrival Shuttle"
|
||||
unique = TRUE // SSjob refers to this area for latejoiners
|
||||
@@ -200,4 +211,7 @@
|
||||
name = "Tiny Freighter"
|
||||
|
||||
/area/shuttle/caravan/freighter3
|
||||
name = "Tiny Freighter"
|
||||
name = "Tiny Freighter"
|
||||
|
||||
/area/shuttle/snowtaxi
|
||||
name = "Snow Taxi"
|
||||
|
||||
+38
-1
@@ -8,6 +8,13 @@
|
||||
var/interaction_flags_atom = NONE
|
||||
var/datum/reagents/reagents = null
|
||||
|
||||
var/flags_ricochet = NONE
|
||||
|
||||
///When a projectile tries to ricochet off this atom, the projectile ricochet chance is multiplied by this
|
||||
var/ricochet_chance_mod = 1
|
||||
///When a projectile ricochets off this atom, it deals the normal damage * this modifier to this atom
|
||||
var/ricochet_damage_mod = 0.33
|
||||
|
||||
//This atom's HUD (med/sec, etc) images. Associative list.
|
||||
var/list/image/hud_list = null
|
||||
//HUD images that this atom can provide.
|
||||
@@ -141,8 +148,27 @@
|
||||
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Checks if a projectile should ricochet off of us. Projectiles get final say.
|
||||
* [__DEFINES/projectiles.dm] for return values.
|
||||
*/
|
||||
/atom/proc/check_projectile_ricochet(obj/item/projectile/P)
|
||||
return (flags_1 & DEFAULT_RICOCHET_1)? PROJECTILE_RICOCHET_YES : PROJECTILE_RICOCHET_NO
|
||||
|
||||
/atom/proc/handle_ricochet(obj/item/projectile/P)
|
||||
return
|
||||
var/turf/p_turf = get_turf(P)
|
||||
var/face_direction = get_dir(src, p_turf)
|
||||
var/face_angle = dir2angle(face_direction)
|
||||
var/incidence_s = GET_ANGLE_OF_INCIDENCE(face_angle, (P.Angle + 180))
|
||||
var/a_incidence_s = abs(incidence_s)
|
||||
if(a_incidence_s > 90 && a_incidence_s < 270)
|
||||
return FALSE
|
||||
if((P.flag in list("bullet", "bomb")) && P.ricochet_incidence_leeway)
|
||||
if((a_incidence_s < 90 && a_incidence_s < 90 - P.ricochet_incidence_leeway) || (a_incidence_s > 270 && a_incidence_s -270 > P.ricochet_incidence_leeway))
|
||||
return
|
||||
var/new_angle_s = SIMPLIFY_DEGREES(face_angle + incidence_s)
|
||||
P.setAngle(new_angle_s)
|
||||
return TRUE
|
||||
|
||||
/atom/proc/CanPass(atom/movable/mover, turf/target)
|
||||
return !density
|
||||
@@ -846,6 +872,17 @@
|
||||
/atom/proc/GenerateTag()
|
||||
return
|
||||
|
||||
/**
|
||||
* Called after a shuttle is loaded **from map template initially**.
|
||||
*
|
||||
* @params
|
||||
* * port - Mobile port/shuttle
|
||||
* * dock - Stationary dock the shuttle's at
|
||||
* * idnum - ID number of the shuttle
|
||||
*/
|
||||
/atom/proc/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
return
|
||||
|
||||
// Generic logging helper
|
||||
/atom/proc/log_message(message, message_type, color=null, log_globally=TRUE)
|
||||
if(!log_globally)
|
||||
|
||||
@@ -202,7 +202,7 @@
|
||||
icon_state = "moustacheg"
|
||||
clumsy_check = GRENADE_NONCLUMSY_FUMBLE
|
||||
|
||||
/obj/item/grenade/chem_grenade/teargas/moustache/prime()
|
||||
/obj/item/grenade/chem_grenade/teargas/moustache/prime(mob/living/lanced_by)
|
||||
var/list/check_later = list()
|
||||
for(var/mob/living/carbon/C in get_turf(src))
|
||||
check_later += C
|
||||
|
||||
@@ -145,9 +145,9 @@
|
||||
new /obj/item/stack/sheet/plasteel(src.loc)
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/dominator/attacked_by(obj/item/I, mob/living/user)
|
||||
/obj/machinery/dominator/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
add_fingerprint(user)
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/dominator/attack_hand(mob/user)
|
||||
if(operating || (stat & BROKEN))
|
||||
@@ -240,4 +240,4 @@
|
||||
|
||||
#undef DOM_BLOCKED_SPAM_CAP
|
||||
#undef DOM_REQUIRED_TURFS
|
||||
#undef DOM_HULK_HITS_REQUIRED
|
||||
#undef DOM_HULK_HITS_REQUIRED
|
||||
|
||||
@@ -288,7 +288,7 @@ datum/gang_item/clothing/shades //Addition: Why not have cool shades on a gang m
|
||||
name = "Fragmentation Grenade"
|
||||
id = "frag nade"
|
||||
cost = 5
|
||||
item_path = /obj/item/grenade/syndieminibomb/concussion/frag
|
||||
item_path = /obj/item/grenade/frag
|
||||
|
||||
/datum/gang_item/equipment/implant_breaker
|
||||
name = "Implant Breaker"
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
targetitem = /obj/item/gun/energy/e_gun/hos
|
||||
difficulty = 10
|
||||
excludefromjob = list("Head Of Security")
|
||||
altitems = list(/obj/item/gun/ballistic/revolver/mws)
|
||||
altitems = list(/obj/item/gun/ballistic/revolver/mws, /obj/item/choice_beacon/hosgun) //We now look for eather the alt verson of the hos gun or the beacon picker.
|
||||
|
||||
/datum/objective_item/steal/handtele
|
||||
name = "a hand teleporter."
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user