Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into dynamic-lings-2
This commit is contained in:
@@ -114,12 +114,17 @@
|
||||
//slowdown when in softcrit
|
||||
#define SOFTCRIT_ADD_SLOWDOWN 6
|
||||
|
||||
//Attack types for checking shields/hit reactions
|
||||
#define MELEE_ATTACK 1
|
||||
#define UNARMED_ATTACK 2
|
||||
#define PROJECTILE_ATTACK 3
|
||||
#define THROWN_PROJECTILE_ATTACK 4
|
||||
#define LEAP_ATTACK 5
|
||||
/// 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"
|
||||
@@ -252,4 +257,53 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
|
||||
#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.
|
||||
|
||||
/// 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)
|
||||
|
||||
/// 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_CLOTHING 50
|
||||
#define BLOCK_PRIORITY_WEAR_SUIT 75
|
||||
#define BLOCK_PRIORITY_UNIFORM 25
|
||||
|
||||
#define BLOCK_PRIORITY_DEFAULT BLOCK_PRIORITY_HELD_ITEM
|
||||
|
||||
@@ -192,6 +192,8 @@
|
||||
#define COMSIG_MOB_CLIENT_LOGIN "comsig_mob_client_login" //sent when a mob/login() finishes: (client)
|
||||
#define COMSIG_MOB_CLIENT_MOVE "comsig_mob_client_move" //sent when client/Move() finishes with no early returns: (client, direction, n, oldloc)
|
||||
#define COMSIG_LIVING_GUN_PROCESS_FIRE "living_gun_process_fire" //from base of /obj/item/gun/proc/process_fire(): (atom/target, params, zone_override)
|
||||
// This returns flags as defined for block in __DEFINES/combat.dm!
|
||||
#define COMSIG_LIVING_RUN_BLOCK "living_do_run_block" //from base of mob/living/do_run_block(): (real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone)
|
||||
#define COMSIG_LIVING_COMBAT_ENABLED "combatmode_enabled" //from base of mob/living/enable_combat_mode() (was_forced)
|
||||
#define COMSIG_LIVING_COMBAT_DISABLED "combatmode_disabled" //from base of mob/living/disable_combat_mode() (was_forced)
|
||||
|
||||
@@ -240,6 +242,9 @@
|
||||
#define COMSIG_ITEM_IMBUE_SOUL "item_imbue_soul" //return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/targeted/lichdom/cast(): (mob/user)
|
||||
#define COMSIG_ITEM_HIT_REACT "item_hit_react" //from base of obj/item/hit_reaction(): (list/args)
|
||||
#define COMSIG_ITEM_WEARERCROSSED "wearer_crossed" //called on item when crossed by something (): (/atom/movable)
|
||||
// THE FOLLOWING TWO BLOCKS SHOULD RETURN BLOCK FLAGS AS DEFINED IN __DEFINES/combat.dm!
|
||||
#define COMSIG_ITEM_CHECK_BLOCK "check_block" //from base of obj/item/check_block(): (mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
#define COMSIG_ITEM_RUN_BLOCK "run_block" //from base of obj/item/run_block(): (mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
|
||||
// /obj/item/clothing signals
|
||||
#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): ()
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define WAROPS_ALWAYS_ALLOWED (1<<1)
|
||||
#define USE_PREF_WEIGHTS (1<<2)
|
||||
#define FORCE_IF_WON (1<<3)
|
||||
#define USE_PREV_ROUND_WEIGHTS (1<<4)
|
||||
|
||||
#define ONLY_RULESET (1<<0)
|
||||
#define HIGHLANDER_RULESET (1<<1)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#define INSTRUMENT_MIN_OCTAVE 1
|
||||
#define INSTRUMENT_MAX_OCTAVE 9
|
||||
#define INSTRUMENT_MIN_KEY 0
|
||||
#define INSTRUMENT_MAX_KEY 127
|
||||
|
||||
/// Max number of playing notes per instrument.
|
||||
#define CHANNELS_PER_INSTRUMENT 128
|
||||
|
||||
/// Distance multiplier that makes us not be impacted by 3d sound as much. This is a multiplier so lower it is the closer we will pretend to be to people.
|
||||
#define INSTRUMENT_DISTANCE_FALLOFF_BUFF 0.2
|
||||
/// How many tiles instruments have no falloff for
|
||||
#define INSTRUMENT_DISTANCE_NO_FALLOFF 3
|
||||
|
||||
/// Maximum length a note should ever go for
|
||||
#define INSTRUMENT_MAX_TOTAL_SUSTAIN (5 SECONDS)
|
||||
|
||||
/// These are per decisecond.
|
||||
#define INSTRUMENT_EXP_FALLOFF_MIN 1.025 //100/(1.025^50) calculated for [INSTRUMENT_MIN_SUSTAIN_DROPOFF] to be 30.
|
||||
#define INSTRUMENT_EXP_FALLOFF_MAX 10
|
||||
|
||||
/// Minimum volume for when the sound is considered dead.
|
||||
#define INSTRUMENT_MIN_SUSTAIN_DROPOFF 0
|
||||
|
||||
#define SUSTAIN_LINEAR 1
|
||||
#define SUSTAIN_EXPONENTIAL 2
|
||||
|
||||
// /datum/instrument instrument_flags
|
||||
#define INSTRUMENT_LEGACY (1<<0) //Legacy instrument. Implies INSTRUMENT_DO_NOT_AUTOSAMPLE
|
||||
#define INSTRUMENT_DO_NOT_AUTOSAMPLE (1<<1) //Do not automatically sample
|
||||
@@ -465,7 +465,7 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
|
||||
#define EGG_LAYING_MESSAGES list("lays an egg.","squats down and croons.","begins making a huge racket.","begins clucking raucously.")
|
||||
|
||||
// list of all null rod weapons
|
||||
#define HOLY_WEAPONS /obj/item/nullrod, /obj/item/twohanded/dualsaber/hypereutactic/chaplain, /obj/item/gun/energy/laser/redtag/hitscan/chaplain, /obj/item/multitool/chaplain, /obj/item/melee/baseball_bat/chaplain
|
||||
#define HOLY_WEAPONS /obj/item/nullrod, /obj/item/twohanded/dualsaber/hypereutactic/chaplain, /obj/item/gun/energy/laser/redtag/hitscan/chaplain, /obj/item/multitool/chaplain, /obj/item/clothing/gloves/fingerless/pugilist/chaplain, /obj/item/melee/baseball_bat/chaplain
|
||||
|
||||
// Used by PDA and cartridge code to reduce repetitiveness of spritesheets
|
||||
#define PDAIMG(what) {"<span class="pda16x16 [#what]"></span>"}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#define CHANNEL_HIGHEST_AVAILABLE 1008 //CIT CHANGE - COMPENSATES FOR VORESOUND CHANNELS
|
||||
|
||||
#define MAX_INSTRUMENT_CHANNELS (128 * 6)
|
||||
|
||||
#define SOUND_MINIMUM_PRESSURE 10
|
||||
#define FALLOFF_SOUNDS 1
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
#define STATUS_EFFECT_PENIS_ENLARGEMENT /datum/status_effect/chem/penis_enlarger //More applied slowdown, just like the above.
|
||||
|
||||
#define STATUS_EFFECT_NO_COMBAT_MODE /datum/status_effect/no_combat_mode //Wont allow combat mode and will disable it
|
||||
#define STATUS_EFFECT_MESMERIZE /datum/status_effect/no_combat_mode/mesmerize //Just reskinned no_combat_mode
|
||||
#define STATUS_EFFECT_MESMERIZE /datum/status_effect/mesmerize //Just reskinned no_combat_mode
|
||||
|
||||
#define STATUS_EFFECT_ELECTROSTAFF /datum/status_effect/electrostaff //slows down victim
|
||||
|
||||
|
||||
@@ -50,17 +50,19 @@
|
||||
#define INIT_ORDER_PROFILER 100
|
||||
#define INIT_ORDER_FAIL2TOPIC 99
|
||||
#define INIT_ORDER_TITLE 98
|
||||
#define INIT_ORDER_GARBAGE 97
|
||||
#define INIT_ORDER_DBCORE 95
|
||||
#define INIT_ORDER_BLACKBOX 94
|
||||
#define INIT_ORDER_SERVER_MAINT 93
|
||||
#define INIT_ORDER_INPUT 85
|
||||
#define INIT_ORDER_GARBAGE 95
|
||||
#define INIT_ORDER_DBCORE 93
|
||||
#define INIT_ORDER_BLACKBOX 92
|
||||
#define INIT_ORDER_SERVER_MAINT 91
|
||||
#define INIT_ORDER_INPUT 90
|
||||
#define INIT_ORDER_SOUNDS 85
|
||||
#define INIT_ORDER_VIS 80
|
||||
#define INIT_ORDER_RESEARCH 75
|
||||
#define INIT_ORDER_EVENTS 70
|
||||
#define INIT_ORDER_JOBS 65
|
||||
#define INIT_ORDER_QUIRKS 60
|
||||
#define INIT_ORDER_TICKER 55
|
||||
#define INIT_ORDER_INSTRUMENTS 53
|
||||
#define INIT_ORDER_MAPPING 50
|
||||
#define INIT_ORDER_NETWORKS 45
|
||||
#define INIT_ORDER_ATOMS 30
|
||||
@@ -100,6 +102,7 @@
|
||||
#define FIRE_PRIORITY_PROCESS 25
|
||||
#define FIRE_PRIORITY_THROWING 25
|
||||
#define FIRE_PRIORITY_SPACEDRIFT 30
|
||||
#define FIRE_PRIORITY_INSTRUMENTS 30
|
||||
#define FIRE_PRIORITY_FIELDS 30
|
||||
#define FIRE_PRIOTITY_SMOOTHING 35
|
||||
#define FIRE_PRIORITY_NETWORKS 40
|
||||
|
||||
@@ -147,6 +147,8 @@
|
||||
#define TRAIT_NOPULSE "nopulse" // Your heart doesn't beat.
|
||||
#define TRAIT_EXEMPT_HEALTH_EVENTS "exempt-health-events"
|
||||
#define TRAIT_NO_MIDROUND_ANTAG "no-midround-antag" //can't be turned into an antag by random events
|
||||
#define TRAIT_PUGILIST "pugilist" //This guy punches people for a living
|
||||
#define TRAIT_KI_VAMPIRE "ki-vampire" //when someone with this trait rolls maximum damage on a punch and stuns the target, they regain some stamina and do clone damage
|
||||
#define TRAIT_PASSTABLE "passtable"
|
||||
|
||||
// mobility flag traits
|
||||
@@ -240,8 +242,8 @@
|
||||
#define GHOSTROLE_TRAIT "ghostrole"
|
||||
#define APHRO_TRAIT "aphro"
|
||||
#define BLOODSUCKER_TRAIT "bloodsucker"
|
||||
#define CLOTHING_TRAIT "clothing" //used for quirky carrygloves
|
||||
#define SHOES_TRAIT "shoes" //inherited from your sweet kicks
|
||||
#define GLOVE_TRAIT "glove" //inherited by your cool gloves
|
||||
|
||||
// unique trait sources, still defines
|
||||
#define STATUE_MUTE "statue"
|
||||
@@ -275,6 +277,7 @@
|
||||
#define LOCKED_HELMET_TRAIT "locked-helmet"
|
||||
#define NINJA_SUIT_TRAIT "ninja-suit"
|
||||
#define ANTI_DROP_IMPLANT_TRAIT "anti-drop-implant"
|
||||
#define MARTIAL_ARTIST_TRAIT "martial_artist"
|
||||
#define SLEEPING_CARP_TRAIT "sleeping_carp"
|
||||
#define RISING_BASS_TRAIT "rising_bass"
|
||||
#define ABDUCTOR_ANTAGONIST "abductor-antagonist"
|
||||
|
||||
@@ -112,7 +112,7 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
|
||||
set desc = "Toggles seeing LocalOutOfCharacter chat"
|
||||
prefs.chat_toggles ^= CHAT_LOOC
|
||||
prefs.save_preferences()
|
||||
src << "You will [(prefs.chat_toggles & CHAT_LOOC) ? "now" : "no longer"] see messages on the LOOC channel."
|
||||
to_chat(src, "You will [(prefs.chat_toggles & CHAT_LOOC) ? "now" : "no longer"] see messages on the LOOC channel.")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/mob/living/carbon/proc/has_penis()
|
||||
|
||||
@@ -116,4 +116,7 @@ GLOBAL_VAR_INIT(cmp_field, "name")
|
||||
if(a_sign != b_sign)
|
||||
return a_sign - b_sign
|
||||
else
|
||||
return sorttext(b_name, a_name)
|
||||
return sorttext(b_name, a_name)
|
||||
|
||||
/proc/cmp_item_block_priority_asc(obj/item/A, obj/item/B)
|
||||
return A.block_priority - B.block_priority
|
||||
|
||||
@@ -425,8 +425,7 @@
|
||||
candidates -= M
|
||||
|
||||
/proc/pollGhostCandidates(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, ignore_category = null, flashwindow = TRUE)
|
||||
var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility))
|
||||
var/list/candidates = eligibility.get_all_ghost_role_eligible()
|
||||
var/list/candidates = get_all_ghost_role_eligible()
|
||||
return pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category, flashwindow, candidates)
|
||||
|
||||
/proc/pollCandidates(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, ignore_category = null, flashwindow = TRUE, list/group = null)
|
||||
@@ -581,4 +580,4 @@
|
||||
var/area/A = C.area
|
||||
if(GLOB.typecache_powerfailure_safe_areas[A.type])
|
||||
continue
|
||||
C.energy_fail(rand(duration_min,duration_max))
|
||||
C.energy_fail(rand(duration_min,duration_max))
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
/proc/radiation_pulse(atom/source, intensity, range_modifier, log=FALSE, can_contaminate=TRUE)
|
||||
if(!SSradiation.can_fire)
|
||||
return
|
||||
var/area/A = get_area(source)
|
||||
var/atom/nested_loc = source.loc
|
||||
while(nested_loc != A)
|
||||
if(nested_loc.rad_flags & RAD_PROTECT_CONTENTS)
|
||||
return
|
||||
nested_loc = nested_loc.loc
|
||||
for(var/dir in GLOB.cardinals)
|
||||
new /datum/radiation_wave(source, dir, intensity, range_modifier, can_contaminate)
|
||||
|
||||
|
||||
@@ -320,8 +320,10 @@
|
||||
parts += "[FOURSPACES]<i>Nobody died this shift!</i>"
|
||||
if(istype(SSticker.mode, /datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
mode.update_playercounts()
|
||||
parts += "[FOURSPACES]Final threat level: [mode.threat_level]"
|
||||
parts += "[FOURSPACES]Final threat: [mode.threat]"
|
||||
parts += "[FOURSPACES]Average threat: [mode.threat_average]"
|
||||
parts += "[FOURSPACES]Executed rules:"
|
||||
for(var/datum/dynamic_ruleset/rule in mode.executed_rules)
|
||||
parts += "[FOURSPACES][FOURSPACES][rule.ruletype] - <b>[rule.name]</b>: -[rule.cost + rule.scaled_times * rule.scaling_cost] threat"
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
message_admins("[ADMIN_LOOKUPFLW(src)] might be running a modified client! (failed can_see on AI click of [A] (Turf Loc: [ADMIN_VERBOSEJMP(pixel_turf)]))")
|
||||
var/message = "[key_name(src)] might be running a modified client! (failed can_see on AI click of [A] (Turf Loc: [AREACOORD(pixel_turf)]))"
|
||||
log_admin(message)
|
||||
to_chat(src, "<span class='warning'>You're experiencing a bug. Reconnect immediately to fix it. Admins have been notified.</span>")
|
||||
if(REALTIMEOFDAY >= chnotify + 9000)
|
||||
chnotify = REALTIMEOFDAY
|
||||
send2irc_adminless_only("NOCHEAT", message)
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
|
||||
totitemdamage *= 0.5
|
||||
//CIT CHANGES END HERE
|
||||
if(user != src && check_shields(I, totitemdamage, "the [I.name]", MELEE_ATTACK, I.armour_penetration))
|
||||
if((user != src) && run_block(I, totitemdamage, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user) & BLOCK_SUCCESS)
|
||||
return FALSE
|
||||
send_item_attack_message(I, user)
|
||||
I.do_stagger_action(src, user)
|
||||
|
||||
@@ -14,6 +14,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
var/list/saved_modes = list(1,2,3)
|
||||
var/list/saved_dynamic_rules = list(list(),list(),list())
|
||||
var/list/saved_storytellers = list("foo","bar","baz")
|
||||
var/list/average_dynamic_threat = 50
|
||||
var/list/saved_maps
|
||||
var/list/saved_trophies = list()
|
||||
var/list/spawned_objects = list()
|
||||
@@ -436,9 +437,10 @@ SUBSYSTEM_DEF(persistence)
|
||||
saved_storytellers[3] = saved_storytellers[2]
|
||||
saved_storytellers[2] = saved_storytellers[1]
|
||||
saved_storytellers[1] = mode.storyteller.name
|
||||
average_dynamic_threat = (mode.threat_average + average_dynamic_threat) / 2
|
||||
var/json_file = file("data/RecentStorytellers.json")
|
||||
var/list/file_data = list()
|
||||
file_data["data"] = saved_storytellers
|
||||
file_data["data"] = saved_storytellers + average_dynamic_threat
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
PROCESSING_SUBSYSTEM_DEF(chemistry)
|
||||
wait = 5
|
||||
flags = SS_KEEP_TIMING
|
||||
|
||||
|
||||
name = "Chemistry"
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
PROCESSING_SUBSYSTEM_DEF(instruments)
|
||||
name = "Instruments"
|
||||
wait = 0.5
|
||||
init_order = INIT_ORDER_INSTRUMENTS
|
||||
flags = SS_KEEP_TIMING
|
||||
priority = FIRE_PRIORITY_INSTRUMENTS
|
||||
var/static/list/datum/instrument/instrument_data = list() //id = datum
|
||||
var/static/list/datum/song/songs = list()
|
||||
var/static/musician_maxlines = 600
|
||||
var/static/musician_maxlinechars = 300
|
||||
var/static/musician_hearcheck_mindelay = 5
|
||||
var/static/max_instrument_channels = MAX_INSTRUMENT_CHANNELS
|
||||
var/static/current_instrument_channels = 0
|
||||
|
||||
/datum/controller/subsystem/processing/instruments/Initialize()
|
||||
initialize_instrument_data()
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/processing/instruments/proc/on_song_new(datum/song/S)
|
||||
songs += S
|
||||
|
||||
/datum/controller/subsystem/processing/instruments/proc/on_song_del(datum/song/S)
|
||||
songs -= S
|
||||
|
||||
/datum/controller/subsystem/processing/instruments/proc/initialize_instrument_data()
|
||||
for(var/path in subtypesof(/datum/instrument))
|
||||
var/datum/instrument/I = path
|
||||
if(initial(I.abstract_type) == path)
|
||||
continue
|
||||
I = new path
|
||||
I.Initialize()
|
||||
instrument_data[I.id || "[I.type]"] = I
|
||||
CHECK_TICK
|
||||
|
||||
/datum/controller/subsystem/processing/instruments/proc/get_instrument(id_or_path)
|
||||
return instrument_data["[id_or_path]"]
|
||||
|
||||
/datum/controller/subsystem/processing/instruments/proc/reserve_instrument_channel(datum/instrument/I)
|
||||
if(current_instrument_channels > max_instrument_channels)
|
||||
return
|
||||
. = SSsounds.reserve_sound_channel(I)
|
||||
if(!isnull(.))
|
||||
current_instrument_channels++
|
||||
@@ -1,3 +1,4 @@
|
||||
PROCESSING_SUBSYSTEM_DEF(status_effects)
|
||||
wait = 1
|
||||
flags = SS_TICKER
|
||||
name = "Status Effects"
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
#define DATUMLESS "NO_DATUM"
|
||||
|
||||
SUBSYSTEM_DEF(sounds)
|
||||
name = "Sounds"
|
||||
flags = SS_NO_FIRE
|
||||
init_order = INIT_ORDER_SOUNDS
|
||||
var/static/using_channels_max = CHANNEL_HIGHEST_AVAILABLE //BYOND max channels
|
||||
|
||||
// Hey uh these two needs to be initialized fast because the whole "things get deleted before init" thing.
|
||||
/// Assoc list, "[channel]" = either the datum using it or TRUE for an unsafe-reserved (datumless reservation) channel
|
||||
var/list/using_channels = list()
|
||||
/// Assoc list datum = list(channel1, channel2, ...) for what channels something reserved.
|
||||
var/list/using_channels_by_datum = list()
|
||||
/// List of all available channels with associations set to TRUE for fast lookups/allocation.
|
||||
var/list/available_channels
|
||||
|
||||
/datum/controller/subsystem/sounds/Initialize()
|
||||
setup_available_channels()
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/sounds/proc/setup_available_channels()
|
||||
available_channels = list()
|
||||
for(var/i in 1 to using_channels_max)
|
||||
available_channels[num2text(i)] = TRUE
|
||||
|
||||
/// Removes a channel from using list.
|
||||
/datum/controller/subsystem/sounds/proc/free_sound_channel(channel)
|
||||
channel = num2text(channel)
|
||||
var/using = using_channels[channel]
|
||||
using_channels -= channel
|
||||
if(using)
|
||||
using_channels_by_datum[using] -= channel
|
||||
if(!length(using_channels_by_datum[using]))
|
||||
using_channels_by_datum -= using
|
||||
available_channels[channel] = TRUE
|
||||
|
||||
/// Frees all the channels a datum is using.
|
||||
/datum/controller/subsystem/sounds/proc/free_datum_channels(datum/D)
|
||||
var/list/L = using_channels_by_datum[D]
|
||||
if(!L)
|
||||
return
|
||||
for(var/channel in L)
|
||||
using_channels -= channel
|
||||
available_channels[channel] = TRUE
|
||||
using_channels_by_datum -= D
|
||||
|
||||
/// Frees all datumless channels
|
||||
/datum/controller/subsystem/sounds/proc/free_datumless_channels()
|
||||
free_datum_channels(DATUMLESS)
|
||||
|
||||
/// NO AUTOMATIC CLEANUP - If you use this, you better manually free it later! Returns an integer for channel.
|
||||
/datum/controller/subsystem/sounds/proc/reserve_sound_channel_datumless()
|
||||
var/channel = random_available_channel_text()
|
||||
if(!channel) //oh no..
|
||||
return FALSE
|
||||
available_channels -= channel
|
||||
using_channels[channel] = DATUMLESS
|
||||
LAZYINITLIST(using_channels_by_datum[DATUMLESS])
|
||||
using_channels_by_datum[DATUMLESS] += channel
|
||||
return text2num(channel)
|
||||
|
||||
/// Reserves a channel for a datum. Automatic cleanup only when the datum is deleted. Returns an integer for channel.
|
||||
/datum/controller/subsystem/sounds/proc/reserve_sound_channel(datum/D)
|
||||
if(!D) //i don't like typechecks but someone will fuck it up
|
||||
CRASH("Attempted to reserve sound channel without datum using the managed proc.")
|
||||
var/channel = random_available_channel_text()
|
||||
if(!channel)
|
||||
return FALSE
|
||||
available_channels -= channel
|
||||
using_channels[channel] = D
|
||||
LAZYINITLIST(using_channels_by_datum[D])
|
||||
using_channels_by_datum[D] += channel
|
||||
return text2num(channel)
|
||||
|
||||
/// Random available channel, returns text.
|
||||
/datum/controller/subsystem/sounds/proc/random_available_channel_text()
|
||||
return pick(available_channels)
|
||||
|
||||
/// Random available channel, returns number
|
||||
/datum/controller/subsystem/sounds/proc/random_available_channel()
|
||||
return text2num(pick(available_channels))
|
||||
|
||||
/// If a channel is available
|
||||
/datum/controller/subsystem/sounds/proc/is_channel_available(channel)
|
||||
return available_channels[num2text(channel)]
|
||||
|
||||
/// How many channels we have left.
|
||||
/datum/controller/subsystem/sounds/proc/available_channels_left()
|
||||
return length(available_channels)
|
||||
|
||||
#undef DATUMLESS
|
||||
@@ -172,7 +172,7 @@ SUBSYSTEM_DEF(traumas)
|
||||
/obj/item/ammo_box/magazine/pistolm9mm, /obj/item/ammo_box/a357, /obj/item/ammo_box/magazine/m12g, /obj/item/ammo_box/magazine/mm195x129, /obj/item/antag_spawner/nuke_ops, /obj/mecha/combat/gygax/dark, /obj/mecha/combat/marauder/mauler, /obj/item/soap/syndie, /obj/item/gun/syringe/syndicate, /obj/item/cartridge/virus/syndicate,
|
||||
/obj/item/cartridge/virus/frame, /obj/item/chameleon, /obj/item/storage/box/syndie_kit/cutouts, /obj/item/clothing/suit/space/hardsuit/syndi, /obj/item/card/emag, /obj/item/storage/toolbox/syndicate, /obj/item/storage/book/bible/syndicate, /obj/item/encryptionkey/binary, /obj/item/encryptionkey/syndicate, /obj/item/aiModule/syndicate,
|
||||
/obj/item/clothing/shoes/magboots/syndie, /obj/item/powersink, /obj/item/sbeacondrop, /obj/item/sbeacondrop/bomb, /obj/item/syndicatedetonator, /obj/item/shield/energy, /obj/item/assault_pod, /obj/item/slimepotion/slime/sentience/nuclear, /obj/item/stack/telecrystal, /obj/item/jammer, /obj/item/codespeak_manual/unlimited,
|
||||
/obj/item/toy/cards/deck/syndicate, /obj/item/storage/secure/briefcase/syndie, /obj/item/storage/fancy/cigarettes/cigpack_syndicate, /obj/item/toy/syndicateballoon, /obj/item/clothing/gloves/rapid, /obj/item/paper/fluff/ruins/thederelict/syndie_mission, /obj/item/organ/cyberimp/eyes/hud/security/syndicate, /obj/item/clothing/head/HoS/syndicate,
|
||||
/obj/item/toy/cards/deck/syndicate, /obj/item/storage/secure/briefcase/syndie, /obj/item/storage/fancy/cigarettes/cigpack_syndicate, /obj/item/toy/syndicateballoon, /obj/item/clothing/gloves/fingerless/pugilist/rapid, /obj/item/paper/fluff/ruins/thederelict/syndie_mission, /obj/item/organ/cyberimp/eyes/hud/security/syndicate, /obj/item/clothing/head/HoS/syndicate,
|
||||
/obj/machinery/computer/pod/old/syndicate, /obj/machinery/vending/medical/syndicate_access, /obj/item/mmi/syndie, /obj/item/target/syndicate, /obj/machinery/vending/cigarette/syndicate, /obj/item/robot_module/syndicate, /obj/item/clothing/mask/gas/syndicate, /obj/machinery/power/singularity_beacon/syndicate, /obj/item/clothing/head/syndicatefake,
|
||||
/obj/item/radio/headset/syndicate, /obj/item/gun/ballistic/automatic/pistol/antitank/syndicate, /obj/item/pda/syndicate, /obj/item/clothing/suit/armor/vest/capcarapace/syndicate, /obj/item/gun/ballistic/automatic/flechette, /obj/item/ammo_box/magazine/flechette, /obj/item/clothing/suit/toggle/lawyer/black/syndie, /obj/item/melee/transforming/energy/sword/cx/traitor,
|
||||
/obj/structure/sign/poster/contraband/syndicate_pistol, /obj/structure/sign/poster/contraband/syndicate_recruitment, /obj/item/bedsheet/syndie, /obj/item/borg/upgrade/syndicate, /obj/item/tank/jetpack/oxygen/harness, /obj/item/firing_pin/implant/pindicate, /obj/item/reagent_containers/glass/bottle/traitor, /obj/item/storage/belt/military,
|
||||
|
||||
@@ -302,16 +302,6 @@
|
||||
name = "Toggle Friendly Fire \[ON\]"
|
||||
..()
|
||||
|
||||
/datum/action/item_action/synthswitch
|
||||
name = "Change Synthesizer Instrument"
|
||||
desc = "Change the type of instrument your synthesizer is playing as."
|
||||
|
||||
/datum/action/item_action/synthswitch/Trigger()
|
||||
if(istype(target, /obj/item/instrument/piano_synth))
|
||||
var/obj/item/instrument/piano_synth/synth = target
|
||||
return synth.selectInstrument()
|
||||
return ..()
|
||||
|
||||
/datum/action/item_action/vortex_recall
|
||||
name = "Vortex Recall"
|
||||
desc = "Recall yourself, and anyone nearby, to an attuned hierophant beacon at any time.<br>If the beacon is still attached, will detach it."
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
//title_image = ntitle_image
|
||||
|
||||
/datum/browser/proc/add_stylesheet(name, file)
|
||||
if (istype(name, /datum/asset/spritesheet))
|
||||
if(istype(name, /datum/asset/spritesheet))
|
||||
var/datum/asset/spritesheet/sheet = name
|
||||
stylesheets["spritesheet_[sheet.name].css"] = "data/spritesheets/[sheet.name]"
|
||||
else
|
||||
|
||||
+212
-57
@@ -14,26 +14,32 @@
|
||||
name = "Glass working tools"
|
||||
desc = "A lovely belt of most the tools you will need to shape, mold, and refine glass into more advanced shapes."
|
||||
icon_state = "glass_tools"
|
||||
tool_behaviour = TOOL_GLASS_CUT
|
||||
tool_behaviour = TOOL_GLASS_CUT //Cutting takes 20 ticks
|
||||
|
||||
/obj/item/glasswork/blowing_rod
|
||||
name = "Glass working blow rod"
|
||||
desc = "A hollow metal stick made for glass blowing."
|
||||
icon_state = "blowing_rods_unused"
|
||||
tool_behaviour = TOOL_BLOW
|
||||
tool_behaviour = TOOL_BLOW //Rods take 5 ticks
|
||||
|
||||
/obj/item/glasswork/glass_base
|
||||
/obj/item/glasswork/glass_base //Welding takes 30 ticks
|
||||
name = "Glass fodder sheet"
|
||||
desc = "A sheet of glass set aside for glass working"
|
||||
icon_state = "glass_base"
|
||||
var/next_step = null
|
||||
var/rod = /obj/item/glasswork/blowing_rod
|
||||
|
||||
/obj/item/lens
|
||||
name = "Optical lens"
|
||||
desc = "Good for selling or crafting, by itself its useless"
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "glass_optics"
|
||||
/obj/item/tea_plate
|
||||
name = "Tea Plate"
|
||||
desc = "A polished plate for a tea cup. How fancy!"
|
||||
icon = 'icons/obj/glass_ware.dmi'
|
||||
icon_state = "tea_plate"
|
||||
|
||||
/obj/item/tea_cup
|
||||
name = "Tea Cup"
|
||||
desc = "A glass cup made for fake tea!"
|
||||
icon = 'icons/obj/glass_ware.dmi'
|
||||
icon_state = "tea_plate"
|
||||
|
||||
//////////////////////Chem Disk/////////////////////
|
||||
//Two Steps //
|
||||
@@ -49,8 +55,9 @@
|
||||
/obj/item/glasswork/glass_base/dish/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_GLASS_CUT)
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
if(do_after(user,20, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/dish_part1
|
||||
name = "Half chem dish sheet"
|
||||
@@ -61,8 +68,9 @@
|
||||
/obj/item/glasswork/glass_base/dish_part1/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_GLASS_CUT)
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
if(do_after(user,20, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
//////////////////////Lens//////////////////////////
|
||||
//Six Steps //
|
||||
@@ -78,8 +86,9 @@
|
||||
/obj/item/glasswork/glass_base/glass_lens/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_GLASS_CUT)
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
if(do_after(user,20, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/glass_lens_part1
|
||||
name = "Glass fodder sheet"
|
||||
@@ -90,8 +99,9 @@
|
||||
/obj/item/glasswork/glass_base/glass_lens_part1/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_WELDER)
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
if(do_after(user,30, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/glass_lens_part2
|
||||
name = "Glass fodder sheet"
|
||||
@@ -102,8 +112,9 @@
|
||||
/obj/item/glasswork/glass_base/glass_lens_part2/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_WELDER)
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
if(do_after(user,30, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/glass_lens_part3
|
||||
name = "Glass fodder sheet"
|
||||
@@ -114,9 +125,10 @@
|
||||
/obj/item/glasswork/glass_base/glass_lens_part3/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_BLOW)
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
qdel(I)
|
||||
if(do_after(user,5, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
qdel(I)
|
||||
|
||||
/obj/item/glasswork/glass_base/glass_lens_part4
|
||||
name = "Glass fodder sheet"
|
||||
@@ -127,29 +139,31 @@
|
||||
/obj/item/glasswork/glass_base/glass_lens_part4/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_GLASS_CUT)
|
||||
new next_step(user.loc, 1)
|
||||
new rod(user.loc, 1)
|
||||
qdel(src)
|
||||
if(do_after(user,20, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
new rod(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/glass_lens_part5
|
||||
name = "Unpolished glass lens"
|
||||
desc = "A small unpolished glass lens. Could be polished with some cloth."
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
desc = "A small unpolished glass lens. Could be polished with some silk."
|
||||
icon = 'icons/obj/glass_ware.dmi'
|
||||
icon_state = "glass_optics"
|
||||
next_step = /obj/item/glasswork/glass_base/glass_lens_part6
|
||||
|
||||
/obj/item/glasswork/glass_base/glass_lens_part5/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(istype(I, /obj/item/stack/sheet/cloth))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
if(istype(I, /obj/item/stack/sheet/silk))
|
||||
if(do_after(user,10, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/glass_lens_part6
|
||||
name = "Unrefined glass lens"
|
||||
desc = "A small polished glass lens. Just needs to be refined with some sandstone."
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon = 'icons/obj/glass_ware.dmi'
|
||||
icon_state = "glass_optics"
|
||||
next_step = /obj/item/lens
|
||||
next_step = /obj/item/glasswork/glass_base/lens
|
||||
|
||||
/obj/item/glasswork/glass_base/glass_lens_part6/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
@@ -171,8 +185,9 @@
|
||||
/obj/item/glasswork/glass_base/spouty/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_GLASS_CUT)
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
if(do_after(user,20, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/spouty_part2
|
||||
name = "Glass fodder sheet"
|
||||
@@ -183,8 +198,9 @@
|
||||
/obj/item/glasswork/glass_base/spouty_part2/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_WELDER)
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
if(do_after(user,30, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/spouty_part3
|
||||
name = "Glass fodder sheet"
|
||||
@@ -195,9 +211,10 @@
|
||||
/obj/item/glasswork/glass_base/spouty_part3/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_BLOW)
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
qdel(I)
|
||||
if(do_after(user,5, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
qdel(I)
|
||||
|
||||
/obj/item/glasswork/glass_base/spouty_part4
|
||||
name = "Glass fodder sheet"
|
||||
@@ -208,9 +225,10 @@
|
||||
/obj/item/glasswork/glass_base/spouty_part4/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_GLASS_CUT)
|
||||
new next_step(user.loc, 1)
|
||||
new rod(user.loc, 1)
|
||||
qdel(src)
|
||||
if(do_after(user,20, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
new rod(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
//////////////////////Small Bulb Flask//////////////
|
||||
//Two Steps //
|
||||
@@ -226,8 +244,9 @@
|
||||
/obj/item/glasswork/glass_base/flask_small/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_WELDER)
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
if(do_after(user,30, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/flask_small_part1
|
||||
name = "Metled glass"
|
||||
@@ -238,9 +257,10 @@
|
||||
/obj/item/glasswork/glass_base/flask_small_part1/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_BLOW)
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
qdel(I)
|
||||
if(do_after(user,5, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
qdel(I)
|
||||
|
||||
/obj/item/glasswork/glass_base/flask_small_part2
|
||||
name = "Metled glass"
|
||||
@@ -251,9 +271,10 @@
|
||||
/obj/item/glasswork/glass_base/flask_small_part2/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_GLASS_CUT)
|
||||
new next_step(user.loc, 1)
|
||||
new rod(user.loc, 1)
|
||||
qdel(src)
|
||||
if(do_after(user,20, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
new rod(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
//////////////////////Large Bulb Flask//////////////
|
||||
//Two Steps //
|
||||
@@ -269,8 +290,9 @@
|
||||
/obj/item/glasswork/glass_base/flask_large/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_WELDER)
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
if(do_after(user,30, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/flask_large_part1
|
||||
name = "Metled glass"
|
||||
@@ -281,9 +303,10 @@
|
||||
/obj/item/glasswork/glass_base/flask_large_part1/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_BLOW)
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
qdel(I)
|
||||
if(do_after(user,5, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
qdel(I)
|
||||
|
||||
/obj/item/glasswork/glass_base/flask_large_part2
|
||||
name = "Metled glass"
|
||||
@@ -294,6 +317,138 @@
|
||||
/obj/item/glasswork/glass_base/flask_large_part2/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_GLASS_CUT)
|
||||
new next_step(user.loc, 1)
|
||||
new rod(user.loc, 1)
|
||||
qdel(src)
|
||||
if(do_after(user,20, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
new rod(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
//////////////////////Tea Plates////////////////////
|
||||
//Three Steps //
|
||||
//Sells for 1200 cr, takes 5 glass shets //
|
||||
//Usefull for selling and chemical things //
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_plate
|
||||
name = "Glass fodder sheet"
|
||||
desc = "A set of glass sheets set aside for glass working, this one is ideal for a tea plate, how fancy! Needs to be heated with some tools."
|
||||
next_step = /obj/item/glasswork/glass_base/tea_plate1
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_plate/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_WELDER)
|
||||
if(do_after(user,30, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_plate1
|
||||
name = "Metled glass"
|
||||
desc = "A blob of metled glass, this one is ideal for a tea plate. Needs to be blown with some tools."
|
||||
icon_state = "glass_base_molding"
|
||||
next_step = /obj/item/glasswork/glass_base/tea_plate2
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_plate1/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_BLOW)
|
||||
if(do_after(user,5, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
qdel(I)
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_plate2
|
||||
name = "Metled glass"
|
||||
desc = "A blob of metled glass on the end of a blowing rod. Needs to be cut off with some tools."
|
||||
icon_state = "blowing_rods_inuse"
|
||||
next_step = /obj/item/glasswork/glass_base/tea_plate3
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_plate2/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_GLASS_CUT)
|
||||
if(do_after(user,20, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
new rod(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_plate3
|
||||
name = "Disk of glass"
|
||||
desc = "A disk of glass that can be cant be used for much. Needs to be polished with some silk."
|
||||
icon_state = "glass_base_half"
|
||||
next_step = /obj/item/tea_plate
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_plate3/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(istype(I, /obj/item/stack/sheet/silk))
|
||||
if(do_after(user,10, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
//////////////////////Tea Cup///////////////////////
|
||||
//Four Steps //
|
||||
//Sells for 1800 cr, takes 6 glass shets //
|
||||
//Usefull for selling and chemical things //
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_cup
|
||||
name = "Glass fodder sheet"
|
||||
desc = "A set of glass sheets set aside for glass working, this one is ideal for a tea cup, how fancy! Needs to be heated with some tools."
|
||||
next_step = /obj/item/glasswork/glass_base/tea_cup1
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_cup/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_WELDER)
|
||||
if(do_after(user,30, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_cup1
|
||||
name = "Metled glass"
|
||||
desc = "A blob of metled glass, this one is ideal for a tea cup. Needs to be blown with some tools."
|
||||
icon_state = "glass_base_molding"
|
||||
next_step = /obj/item/glasswork/glass_base/tea_cup2
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_cup1/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_BLOW)
|
||||
if(do_after(user,5, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
qdel(I)
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_cupe2
|
||||
name = "Metled glass"
|
||||
desc = "A blob of metled glass on the end of a blowing rod. Needs to be cut off with some tools."
|
||||
icon_state = "blowing_rods_inuse"
|
||||
next_step = /obj/item/glasswork/glass_base/tea_cup3
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_cup2/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_GLASS_CUT)
|
||||
if(do_after(user,20, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
new rod(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_cup3
|
||||
name = "Disk of glass"
|
||||
desc = "A bowl of glass that can be cant be used for much. Needs to be polished with some silk."
|
||||
icon_state = "glass_base_half"
|
||||
next_step = /obj/item/glasswork/glass_base/tea_cup4
|
||||
|
||||
/obj/item/glasswork/glass_base/cup3/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(istype(I, /obj/item/stack/sheet/silk))
|
||||
if(do_after(user,10, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/tea_cup4
|
||||
name = "Disk of glass"
|
||||
desc = "A bowl of polished glass that can be cant be used for much. Needs some more glass to make a handle."
|
||||
icon_state = "glass_base_half"
|
||||
next_step = /obj/item/tea_cup
|
||||
|
||||
/obj/item/glasswork/glass_base/cup4/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(istype(I, /obj/item/stack/sheet/glass))
|
||||
if(do_after(user,10, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
@@ -0,0 +1,98 @@
|
||||
//This file is for crafting using a lens!
|
||||
|
||||
/obj/item/glasswork/glass_base/lens
|
||||
name = "Optical lens"
|
||||
desc = "Good for selling or crafting, by itself its useless"
|
||||
icon = 'icons/obj/glass_ware.dmi'
|
||||
icon_state = "glass_optics"
|
||||
|
||||
//Laser pointers - 2600
|
||||
/obj/item/glasswork/glass_base/laserpointer_shell
|
||||
name = "Laser pointer assembly"
|
||||
desc = "Good for selling or crafting, by itself its useless. Needs a power capactor."
|
||||
icon_state = "laser_case"
|
||||
icon = 'icons/obj/glass_ware.dmi'
|
||||
next_step = /obj/item/glasswork/glass_base/laserpointer_shell_1
|
||||
|
||||
/obj/item/glasswork/glass_base/laserpointer_shell/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(istype(I, /obj/item/stock_parts/capacitor))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/laserpointer_shell_1
|
||||
name = "Laser pointer assembly"
|
||||
desc = "Good for selling or crafting, by itself its useless. Needs a glass lens."
|
||||
icon_state = "laser_wire"
|
||||
icon_state = "laser_case"
|
||||
next_step = /obj/item/glasswork/glass_base/laserpointer_shell_2
|
||||
|
||||
/obj/item/glasswork/glass_base/laserpointer_shell_1/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(istype(I, /obj/item/glasswork/glass_base/lens))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/laserpointer_shell_2
|
||||
name = "Laser pointer assembly"
|
||||
desc = "Good for selling or crafting, by itself its useless. Needs to be screwed together."
|
||||
icon_state = "laser_wire"
|
||||
icon_state = "laser_case"
|
||||
next_step = /obj/item/laser_pointer/blue/handmade
|
||||
|
||||
/obj/item/glasswork/glass_base/laserpointer_shell_2/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
if(do_after(user,260, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
//NERD SHIT - 5000
|
||||
|
||||
/obj/item/glasswork/glass_base/glasses_frame
|
||||
name = "Glasses Frame"
|
||||
desc = "Good for crafting a pare of glasses, by itself its useless. Just add a pare of lens."
|
||||
icon = 'icons/obj/glass_ware.dmi'
|
||||
icon_state = "frames"
|
||||
next_step = /obj/item/glasswork/glass_base/glasses_frame_1
|
||||
|
||||
/obj/item/glasswork/glass_base/glasses_frame/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(istype(I, /obj/item/glasswork/glass_base/lens))
|
||||
if(do_after(user,60, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/glasses_frame_1
|
||||
name = "Glasses Frame"
|
||||
desc = "Good for crafting a pare of glasses, by itself its useless. Just add a the other lens."
|
||||
icon = 'icons/obj/glass_ware.dmi'
|
||||
icon_state = "frames_1"
|
||||
next_step = /obj/item/glasswork/glass_base/glasses_frame_2
|
||||
|
||||
/obj/item/glasswork/glass_base/glasses_frame_1/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(istype(I, /obj/item/glasswork/glass_base/lens))
|
||||
if(do_after(user,60, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glass_base/glasses_frame_2
|
||||
name = "Glasses Frame"
|
||||
desc = "Good for crafting a pare of glasses, by itself its useless. Just adjust the pices into the frame with a screwdriver."
|
||||
icon = 'icons/obj/glass_ware.dmi'
|
||||
icon_state = "frames_2"
|
||||
next_step = /obj/item/glasswork/glasses
|
||||
|
||||
/obj/item/glasswork/glass_base/glasses_frame_2/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(I.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
if(do_after(user,180, target = src))
|
||||
new next_step(user.loc, 1)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/glasswork/glasses
|
||||
name = "Hand Made Glasses"
|
||||
desc = "Hande made glasses that have not been polished at all making them useless. Selling them could still be worth a bit of credits."
|
||||
icon = 'icons/obj/glass_ware.dmi'
|
||||
icon_state = "frames_2"
|
||||
@@ -27,6 +27,8 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
var/datum/ui_state/checkstate
|
||||
var/compact_mode = FALSE
|
||||
var/debug = FALSE
|
||||
var/saved_player_population = 0
|
||||
var/list/filters = list()
|
||||
|
||||
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/ui_state/_checkstate, datum/traitor_class/traitor_class)
|
||||
if(!isitem(parent))
|
||||
@@ -47,7 +49,6 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
RegisterSignal(parent, COMSIG_PEN_ROTATED, .proc/pen_rotation)
|
||||
|
||||
GLOB.uplinks += src
|
||||
var/list/filters = list()
|
||||
if(istype(traitor_class))
|
||||
filters = traitor_class.uplink_filters
|
||||
starting_tc = traitor_class.TC
|
||||
@@ -68,6 +69,7 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
if(!lockable)
|
||||
active = TRUE
|
||||
locked = FALSE
|
||||
saved_player_population = GLOB.joined_player_list.len
|
||||
|
||||
/datum/component/uplink/InheritComponent(datum/component/uplink/U)
|
||||
lockable |= U.lockable
|
||||
@@ -117,7 +119,18 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
return
|
||||
active = TRUE
|
||||
if(user)
|
||||
//update the saved population
|
||||
var/previous_player_population = saved_player_population
|
||||
saved_player_population = GLOB.joined_player_list.len
|
||||
//if population has changed, update uplink items
|
||||
if(saved_player_population != previous_player_population)
|
||||
//make sure discounts are not rerolled
|
||||
var/old_discounts = uplink_items["Discounted Gear"]
|
||||
uplink_items = get_uplink_items(gamemode, FALSE, allow_restricted, filters)
|
||||
if(old_discounts)
|
||||
uplink_items["Discounted Gear"] = old_discounts
|
||||
ui_interact(user)
|
||||
|
||||
// an unlocked uplink blocks also opening the PDA or headset menu
|
||||
return COMPONENT_NO_INTERACT
|
||||
|
||||
@@ -190,7 +203,9 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
|
||||
if(item in buyable_items)
|
||||
var/datum/uplink_item/I = buyable_items[item]
|
||||
MakePurchase(usr, I)
|
||||
//check to make sure people cannot buy items when the player pop is below the requirement
|
||||
if(GLOB.joined_player_list.len >= I.player_minimum)
|
||||
MakePurchase(usr, I)
|
||||
. = TRUE
|
||||
if("lock")
|
||||
active = FALSE
|
||||
|
||||
@@ -19,4 +19,4 @@
|
||||
UnregisterSignal(equipper, signals)
|
||||
|
||||
/datum/component/wearertargeting/proc/on_drop(datum/source, mob/user)
|
||||
UnregisterSignal(user, signals)
|
||||
UnregisterSignal(user, signals)
|
||||
|
||||
@@ -109,6 +109,8 @@
|
||||
UnregisterSignal(target, signal_procs[target])
|
||||
//END: ECS SHIT
|
||||
|
||||
SSsounds.free_datum_channels(src)
|
||||
|
||||
return QDEL_HINT_QUEUE
|
||||
|
||||
#ifdef DATUMVAR_DEBUGGING_MODE
|
||||
|
||||
@@ -1,67 +1,48 @@
|
||||
GLOBAL_LIST_EMPTY(ghost_eligible_mobs)
|
||||
|
||||
GLOBAL_LIST_EMPTY(client_ghost_timeouts)
|
||||
|
||||
/datum/element/ghost_role_eligibility
|
||||
element_flags = ELEMENT_DETACH | ELEMENT_BESPOKE
|
||||
id_arg_index = 3
|
||||
var/list/timeouts = list()
|
||||
var/list/mob/eligible_mobs = list()
|
||||
id_arg_index = 2
|
||||
var/penalizing = FALSE
|
||||
var/free_ghost = FALSE
|
||||
|
||||
/datum/element/ghost_role_eligibility/Attach(datum/target,penalize = FALSE,free_ghosting = FALSE, penalize_on_ghost = FALSE)
|
||||
/datum/element/ghost_role_eligibility/Attach(datum/target,free_ghosting = FALSE, penalize_on_ghost = FALSE)
|
||||
. = ..()
|
||||
if(!ismob(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
penalizing = penalize_on_ghost
|
||||
free_ghost = free_ghosting
|
||||
var/mob/M = target
|
||||
if(!(M in eligible_mobs))
|
||||
eligible_mobs += M
|
||||
if(!(M in GLOB.ghost_eligible_mobs))
|
||||
GLOB.ghost_eligible_mobs += M
|
||||
RegisterSignal(M, COMSIG_MOB_GHOSTIZE, .proc/get_ghost_flags)
|
||||
if(penalize) //penalizing them from making a ghost role / midround antag comeback right away.
|
||||
var/penalty = CONFIG_GET(number/suicide_reenter_round_timer) MINUTES
|
||||
var/roundstart_quit_limit = CONFIG_GET(number/roundstart_suicide_time_limit) MINUTES
|
||||
if(world.time < roundstart_quit_limit) //add up the time difference to their antag rolling penalty if they quit before half a (ingame) hour even passed.
|
||||
penalty += roundstart_quit_limit - world.time
|
||||
if(penalty)
|
||||
penalty += world.realtime
|
||||
if(SSautotransfer.can_fire && SSautotransfer.maxvotes)
|
||||
var/maximumRoundEnd = SSautotransfer.starttime + SSautotransfer.voteinterval * SSautotransfer.maxvotes
|
||||
if(penalty - SSshuttle.realtimeofstart > maximumRoundEnd + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime)
|
||||
penalty = CANT_REENTER_ROUND
|
||||
if(!(M.ckey in timeouts))
|
||||
timeouts += M.ckey
|
||||
timeouts[M.ckey] = 0
|
||||
else if(timeouts[M.ckey] == CANT_REENTER_ROUND)
|
||||
return
|
||||
timeouts[M.ckey] = max(timeouts[M.ckey],penalty)
|
||||
|
||||
/datum/element/ghost_role_eligibility/Detach(mob/M)
|
||||
. = ..()
|
||||
if(M in eligible_mobs)
|
||||
eligible_mobs -= M
|
||||
if(M in GLOB.ghost_eligible_mobs)
|
||||
GLOB.ghost_eligible_mobs -= M
|
||||
UnregisterSignal(M, COMSIG_MOB_GHOSTIZE)
|
||||
|
||||
/datum/element/ghost_role_eligibility/proc/get_all_ghost_role_eligible(silent = FALSE)
|
||||
/proc/get_all_ghost_role_eligible(silent = FALSE)
|
||||
var/list/candidates = list()
|
||||
for(var/m in eligible_mobs)
|
||||
for(var/m in GLOB.ghost_eligible_mobs)
|
||||
var/mob/M = m
|
||||
if(M.can_reenter_round(TRUE))
|
||||
candidates += M
|
||||
return candidates
|
||||
|
||||
/mob/proc/can_reenter_round(silent = FALSE)
|
||||
var/datum/element/ghost_role_eligibility/eli = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility))
|
||||
return eli.can_reenter_round(src,silent)
|
||||
|
||||
/datum/element/ghost_role_eligibility/proc/can_reenter_round(var/mob/M,silent = FALSE)
|
||||
if(!(M in eligible_mobs))
|
||||
if(!(src in GLOB.ghost_eligible_mobs))
|
||||
return FALSE
|
||||
if(!(M.ckey in timeouts))
|
||||
if(!(ckey in GLOB.client_ghost_timeouts))
|
||||
return TRUE
|
||||
var/timeout = timeouts[M.ckey]
|
||||
var/timeout = GLOB.client_ghost_timeouts[ckey]
|
||||
if(timeout != CANT_REENTER_ROUND && timeout <= world.realtime)
|
||||
return TRUE
|
||||
if(!silent && M.client)
|
||||
to_chat(M, "<span class='warning'>You are unable to reenter the round[timeout != CANT_REENTER_ROUND ? " yet. Your ghost role blacklist will expire in [DisplayTimeText(timeout - world.realtime)]" : ""].</span>")
|
||||
if(!silent && client)
|
||||
to_chat(src, "<span class='warning'>You are unable to reenter the round[timeout != CANT_REENTER_ROUND ? " yet. Your ghost role blacklist will expire in [DisplayTimeText(timeout - world.realtime)]" : ""].</span>")
|
||||
return FALSE
|
||||
|
||||
/datum/element/ghost_role_eligibility/proc/get_ghost_flags()
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
var/cast_flags
|
||||
var/cast_slots
|
||||
var/list/users_by_item = list()
|
||||
var/list/stacked_spellcasting_by_user = list()
|
||||
|
||||
/datum/element/spellcasting/Attach(datum/target, _flags, _slots)
|
||||
. = ..()
|
||||
@@ -12,6 +13,7 @@
|
||||
RegisterSignal(target, COMSIG_ITEM_DROPPED, .proc/on_drop)
|
||||
else if(ismob(target))
|
||||
RegisterSignal(target, COMSIG_MOB_SPELL_CAST_CHECK, .proc/on_cast)
|
||||
stacked_spellcasting_by_user[target]++
|
||||
else
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
cast_flags = _flags
|
||||
@@ -22,16 +24,31 @@
|
||||
UnregisterSignal(target, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, COMSIG_MOB_SPELL_CAST_CHECK))
|
||||
if(users_by_item[target])
|
||||
var/mob/user = users_by_item[target]
|
||||
UnregisterSignal(user, COMSIG_MOB_SPELL_CAST_CHECK)
|
||||
stacked_spellcasting_by_user[user]--
|
||||
if(!stacked_spellcasting_by_user[user])
|
||||
stacked_spellcasting_by_user -= user
|
||||
UnregisterSignal(user, COMSIG_MOB_SPELL_CAST_CHECK)
|
||||
else if(ismob(target))
|
||||
stacked_spellcasting_by_user[target]--
|
||||
if(!stacked_spellcasting_by_user[target])
|
||||
stacked_spellcasting_by_user -= target
|
||||
|
||||
/datum/element/spellcasting/proc/on_equip(datum/source, mob/equipper, slot)
|
||||
if(slot in cast_slots)
|
||||
if(!(slot in cast_slots))
|
||||
return
|
||||
users_by_item[source] = equipper
|
||||
if(!stacked_spellcasting_by_user[equipper])
|
||||
RegisterSignal(equipper, COMSIG_MOB_SPELL_CAST_CHECK, .proc/on_cast)
|
||||
users_by_item[source] = equipper
|
||||
stacked_spellcasting_by_user[equipper]++
|
||||
|
||||
/datum/element/spellcasting/proc/on_drop(datum/source, mob/user)
|
||||
UnregisterSignal(user, COMSIG_MOB_SPELL_CAST_CHECK)
|
||||
if(!users_by_item[source])
|
||||
return
|
||||
users_by_item -= source
|
||||
stacked_spellcasting_by_user[user]--
|
||||
if(!stacked_spellcasting_by_user[user])
|
||||
stacked_spellcasting_by_user -= user
|
||||
UnregisterSignal(user, COMSIG_MOB_SPELL_CAST_CHECK)
|
||||
|
||||
/datum/element/spellcasting/proc/on_cast(mob/caster, obj/effect/proc_holder/spell)
|
||||
return cast_flags
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
var/list/atoms_cache = output_atoms
|
||||
var/sound/S = sound(soundfile)
|
||||
if(direct)
|
||||
S.channel = open_sound_channel()
|
||||
S.channel = SSsounds.random_available_channel()
|
||||
S.volume = volume
|
||||
for(var/i in 1 to atoms_cache.len)
|
||||
var/atom/thing = atoms_cache[i]
|
||||
|
||||
@@ -35,6 +35,17 @@
|
||||
current_target = new_target
|
||||
streak = ""
|
||||
|
||||
/datum/martial_art/proc/damage_roll(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
//Here we roll for our damage to be added into the damage var in the various attack procs. This is changed depending on whether we are in combat mode, lying down, or if our target is in combat mode.
|
||||
var/damage = rand(A.dna.species.punchdamagelow, A.dna.species.punchdamagehigh)
|
||||
if(!(D.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
|
||||
damage *= 1.5
|
||||
if(!CHECK_MOBILITY(A, MOBILITY_STAND))
|
||||
damage *= 0.5
|
||||
if(!(A.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
|
||||
damage *= 0.25
|
||||
return damage
|
||||
|
||||
/datum/martial_art/proc/teach(mob/living/carbon/human/H, make_temporary = FALSE)
|
||||
if(!istype(H) || !H.mind)
|
||||
return FALSE
|
||||
@@ -50,6 +61,7 @@
|
||||
if(help_verb)
|
||||
H.verbs += help_verb
|
||||
H.mind.martial_art = src
|
||||
ADD_TRAIT(H, TRAIT_PUGILIST, MARTIAL_ARTIST_TRAIT)
|
||||
return TRUE
|
||||
|
||||
/datum/martial_art/proc/store(datum/martial_art/M,mob/living/carbon/human/H)
|
||||
@@ -68,7 +80,8 @@
|
||||
else
|
||||
var/datum/martial_art/X = H.mind.default_martial_art
|
||||
X.teach(H)
|
||||
|
||||
REMOVE_TRAIT(H, TRAIT_PUGILIST, MARTIAL_ARTIST_TRAIT)
|
||||
|
||||
/datum/martial_art/proc/on_remove(mob/living/carbon/human/H)
|
||||
if(help_verb)
|
||||
H.verbs -= help_verb
|
||||
|
||||
@@ -16,16 +16,13 @@
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
|
||||
|
||||
var/atk_verb = pick("left hook","right hook","straight punch")
|
||||
|
||||
var/damage = rand(10, 13)
|
||||
var/extra_damage = rand(A.dna.species.punchdamagelow, A.dna.species.punchdamagehigh)
|
||||
var/extra_damage = damage_roll(A,D)
|
||||
if(extra_damage == A.dna.species.punchdamagelow)
|
||||
playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1)
|
||||
D.visible_message("<span class='warning'>[A] has attempted to [atk_verb] [D]!</span>", \
|
||||
"<span class='userdanger'>[A] has attempted to [atk_verb] [D]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
log_combat(A, D, "attempted to hit", atk_verb)
|
||||
return TRUE
|
||||
damage += extra_damage
|
||||
|
||||
var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected))
|
||||
var/armor_block = D.run_armor_check(affecting, "melee")
|
||||
@@ -35,7 +32,7 @@
|
||||
D.visible_message("<span class='danger'>[A] has [atk_verb]ed [D]!</span>", \
|
||||
"<span class='userdanger'>[A] has [atk_verb]ed [D]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
D.apply_damage(damage, STAMINA, affecting, armor_block)
|
||||
D.apply_damage(rand(10,13) + extra_damage, STAMINA, affecting, armor_block)
|
||||
log_combat(A, D, "punched (boxing) ")
|
||||
if(D.getStaminaLoss() > 100 && istype(D.mind?.martial_art, /datum/martial_art/boxing))
|
||||
var/knockout_prob = (D.getStaminaLoss() + rand(-15,15))*0.75
|
||||
|
||||
+25
-17
@@ -42,11 +42,12 @@
|
||||
/datum/martial_art/cqc/proc/Slam(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(!can_use(A))
|
||||
return FALSE
|
||||
var/damage = (damage_roll(A,D) + 5)
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
D.visible_message("<span class='warning'>[A] slams [D] into the ground!</span>", \
|
||||
"<span class='userdanger'>[A] slams you into the ground!</span>")
|
||||
playsound(get_turf(A), 'sound/weapons/slam.ogg', 50, 1, -1)
|
||||
D.apply_damage(10, BRUTE)
|
||||
D.apply_damage(damage, BRUTE)
|
||||
D.DefaultCombatKnockdown(120)
|
||||
log_combat(A, D, "slammed (CQC)")
|
||||
return TRUE
|
||||
@@ -54,29 +55,33 @@
|
||||
/datum/martial_art/cqc/proc/Kick(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(!can_use(A))
|
||||
return FALSE
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
D.visible_message("<span class='warning'>[A] kicks [D] back!</span>", \
|
||||
"<span class='userdanger'>[A] kicks you back!</span>")
|
||||
playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
|
||||
var/atom/throw_target = get_edge_target_turf(D, A.dir)
|
||||
D.throw_at(throw_target, 1, 14, A)
|
||||
D.apply_damage(10, BRUTE)
|
||||
log_combat(A, D, "kicked (CQC)")
|
||||
var/damage = damage_roll(A,D)
|
||||
if(!CHECK_MOBILITY(D, MOBILITY_STAND) && CHECK_MOBILITY(D, MOBILITY_USE))
|
||||
log_combat(A, D, "knocked out (Head kick)(CQC)")
|
||||
D.visible_message("<span class='warning'>[A] kicks [D]'s head, knocking [D.p_them()] out!</span>", \
|
||||
"<span class='userdanger'>[A] kicks your head, knocking you out!</span>")
|
||||
playsound(get_turf(A), 'sound/weapons/genhit1.ogg', 50, 1, -1)
|
||||
D.SetSleeping(300)
|
||||
D.adjustOrganLoss(ORGAN_SLOT_BRAIN, 15, 150)
|
||||
D.apply_damage(damage + 5, BRUTE)
|
||||
var/atom/throw_target = get_edge_target_turf(D, A.dir)
|
||||
D.throw_at(throw_target, 1, 14, A)
|
||||
D.adjustOrganLoss(ORGAN_SLOT_BRAIN, damage + 10, 150)
|
||||
else
|
||||
D.visible_message("<span class='warning'>[A] kicks [D]!</span>", \
|
||||
"<span class='userdanger'>[A] kicks you!</span>")
|
||||
playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
|
||||
D.Dizzy(damage)
|
||||
D.apply_damage(damage + 15, BRUTE)
|
||||
log_combat(A, D, "kicked (CQC)")
|
||||
return TRUE
|
||||
|
||||
/datum/martial_art/cqc/proc/Pressure(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(!can_use(A))
|
||||
return FALSE
|
||||
var/damage = (damage_roll(A,D) + 55)
|
||||
log_combat(A, D, "pressured (CQC)")
|
||||
D.visible_message("<span class='warning'>[A] punches [D]'s neck!</span>")
|
||||
D.adjustStaminaLoss(60)
|
||||
D.apply_damage(damage, STAMINA)
|
||||
playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
|
||||
return TRUE
|
||||
|
||||
@@ -85,11 +90,12 @@
|
||||
return
|
||||
if(!can_use(A))
|
||||
return FALSE
|
||||
var/damage = (damage_roll(A,D) + 15)
|
||||
if(!D.stat)
|
||||
log_combat(A, D, "restrained (CQC)")
|
||||
D.visible_message("<span class='warning'>[A] locks [D] into a restraining position!</span>", \
|
||||
"<span class='userdanger'>[A] locks you into a restraining position!</span>")
|
||||
D.adjustStaminaLoss(20)
|
||||
D.apply_damage(damage, STAMINA)
|
||||
D.Stun(100)
|
||||
restraining = TRUE
|
||||
addtimer(VARSET_CALLBACK(src, restraining, FALSE), 50, TIMER_UNIQUE)
|
||||
@@ -98,6 +104,7 @@
|
||||
/datum/martial_art/cqc/proc/Consecutive(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(!can_use(A))
|
||||
return FALSE
|
||||
var/damage = damage_roll(A,D)
|
||||
if(!D.stat)
|
||||
log_combat(A, D, "consecutive CQC'd (CQC)")
|
||||
D.visible_message("<span class='warning'>[A] strikes [D]'s abdomen, neck and back consecutively</span>", \
|
||||
@@ -106,8 +113,8 @@
|
||||
var/obj/item/I = D.get_active_held_item()
|
||||
if(I && D.temporarilyRemoveItemFromInventory(I))
|
||||
A.put_in_hands(I)
|
||||
D.adjustStaminaLoss(50)
|
||||
D.apply_damage(25, BRUTE)
|
||||
D.apply_damage(damage + 45, STAMINA)
|
||||
D.apply_damage(damage + 20, BRUTE)
|
||||
return TRUE
|
||||
|
||||
/datum/martial_art/cqc/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
@@ -135,7 +142,7 @@
|
||||
log_combat(A, D, "attacked (CQC)")
|
||||
A.do_attack_animation(D)
|
||||
var/picked_hit_type = pick("CQC'd", "Big Bossed")
|
||||
var/bonus_damage = 13
|
||||
var/bonus_damage = (damage_roll(A,D) + 7)
|
||||
if(!CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
bonus_damage += 5
|
||||
picked_hit_type = "stomps on"
|
||||
@@ -151,7 +158,7 @@
|
||||
D.visible_message("<span class='warning'>[A] leg sweeps [D]!", \
|
||||
"<span class='userdanger'>[A] leg sweeps you!</span>")
|
||||
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1)
|
||||
D.apply_damage(10, BRUTE)
|
||||
D.apply_damage(bonus_damage, BRUTE)
|
||||
D.DefaultCombatKnockdown(60)
|
||||
log_combat(A, D, "sweeped (CQC)")
|
||||
return TRUE
|
||||
@@ -161,6 +168,7 @@
|
||||
return FALSE
|
||||
add_to_streak("D",D)
|
||||
var/obj/item/I = null
|
||||
var/damage = (damage_roll(A,D)*0.5)
|
||||
if(check_streak(A,D))
|
||||
return TRUE
|
||||
if(prob(65))
|
||||
@@ -172,7 +180,7 @@
|
||||
if(I && D.temporarilyRemoveItemFromInventory(I))
|
||||
A.put_in_hands(I)
|
||||
D.Jitter(2)
|
||||
D.apply_damage(5, BRUTE)
|
||||
D.apply_damage(damage, BRUTE)
|
||||
else
|
||||
D.visible_message("<span class='danger'>[A] attempted to disarm [D]!</span>", \
|
||||
"<span class='userdanger'>[A] attempted to disarm [D]!</span>")
|
||||
|
||||
@@ -84,64 +84,71 @@
|
||||
if("neck_chop")
|
||||
streak = ""
|
||||
neck_chop(A,D)
|
||||
return 1
|
||||
return TRUE
|
||||
if("leg_sweep")
|
||||
streak = ""
|
||||
leg_sweep(A,D)
|
||||
return 1
|
||||
return TRUE
|
||||
if("quick_choke")//is actually lung punch
|
||||
streak = ""
|
||||
quick_choke(A,D)
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/martial_art/krav_maga/proc/leg_sweep(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
var/obj/item/bodypart/affecting = D.get_bodypart(BODY_ZONE_CHEST)
|
||||
var/armor_block = D.run_armor_check(affecting, "melee")
|
||||
var/damage = damage_roll(A,D)
|
||||
if(!CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
return 0
|
||||
return FALSE
|
||||
D.visible_message("<span class='warning'>[A] leg sweeps [D]!</span>", \
|
||||
"<span class='userdanger'>[A] leg sweeps you!</span>")
|
||||
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1)
|
||||
D.apply_damage(5, BRUTE)
|
||||
D.DefaultCombatKnockdown(40, override_hardstun = 0.01, override_stamdmg = 25)
|
||||
D.apply_damage(damage + 25, STAMINA, affecting, armor_block)
|
||||
D.DefaultCombatKnockdown(80, override_hardstun = 1, override_stamdmg = 0)
|
||||
log_combat(A, D, "leg sweeped")
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/datum/martial_art/krav_maga/proc/quick_choke(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)//is actually lung punch
|
||||
var/damage = damage_roll(A,D)
|
||||
D.visible_message("<span class='warning'>[A] pounds [D] on the chest!</span>", \
|
||||
"<span class='userdanger'>[A] slams your chest! You can't breathe!</span>")
|
||||
playsound(get_turf(A), 'sound/effects/hit_punch.ogg', 50, 1, -1)
|
||||
if(D.losebreath <= 10)
|
||||
D.losebreath = CLAMP(D.losebreath + 5, 0, 10)
|
||||
D.adjustOxyLoss(10)
|
||||
D.adjustOxyLoss(damage + 5)
|
||||
log_combat(A, D, "quickchoked")
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/datum/martial_art/krav_maga/proc/neck_chop(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
|
||||
var/damage = (damage_roll(A,D)*0.5)
|
||||
D.visible_message("<span class='warning'>[A] karate chops [D]'s neck!</span>", \
|
||||
"<span class='userdanger'>[A] karate chops your neck, rendering you unable to speak!</span>")
|
||||
playsound(get_turf(A), 'sound/effects/hit_punch.ogg', 50, 1, -1)
|
||||
D.apply_damage(5, BRUTE)
|
||||
D.apply_damage(damage, BRUTE)
|
||||
if(D.silent <= 10)
|
||||
D.silent = CLAMP(D.silent + 10, 0, 10)
|
||||
log_combat(A, D, "neck chopped")
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/datum/martial_art/krav_maga/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
|
||||
if(check_streak(A,D))
|
||||
return 1
|
||||
return TRUE
|
||||
log_combat(A, D, "grabbed (Krav Maga)")
|
||||
..()
|
||||
|
||||
/datum/martial_art/krav_maga/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
|
||||
var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected))
|
||||
var/armor_block = D.run_armor_check(affecting, "melee")
|
||||
if(check_streak(A,D))
|
||||
return 1
|
||||
return TRUE
|
||||
log_combat(A, D, "punched")
|
||||
var/picked_hit_type = pick("punches", "kicks")
|
||||
var/bonus_damage = 10
|
||||
var/bonus_damage = damage_roll(A,D)
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
bonus_damage += 5
|
||||
bonus_damage += 10
|
||||
picked_hit_type = "stomps on"
|
||||
D.apply_damage(bonus_damage, BRUTE)
|
||||
D.apply_damage(bonus_damage, BRUTE, affecting, armor_block)
|
||||
if(picked_hit_type == "kicks" || picked_hit_type == "stomps on")
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
|
||||
playsound(get_turf(D), 'sound/effects/hit_kick.ogg', 50, 1, -1)
|
||||
@@ -151,24 +158,34 @@
|
||||
D.visible_message("<span class='danger'>[A] [picked_hit_type] [D]!</span>", \
|
||||
"<span class='userdanger'>[A] [picked_hit_type] you!</span>")
|
||||
log_combat(A, D, "[picked_hit_type] with [name]")
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/datum/martial_art/krav_maga/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
|
||||
var/obj/item/I = null
|
||||
if(prob(60))
|
||||
I = D.get_active_held_item()
|
||||
if(I)
|
||||
if(D.temporarilyRemoveItemFromInventory(I))
|
||||
A.put_in_hands(I)
|
||||
D.visible_message("<span class='danger'>[A] has disarmed [D]!</span>", \
|
||||
"<span class='userdanger'>[A] has disarmed [D]!</span>")
|
||||
playsound(D, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
/datum/martial_art/krav_maga/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(check_streak(A,D))
|
||||
return TRUE
|
||||
var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected))
|
||||
var/armor_block = D.run_armor_check(affecting, "melee")
|
||||
var/damage = damage_roll(A,D)
|
||||
if(D.mobility_flags & MOBILITY_STAND)
|
||||
D.visible_message("<span class='danger'>[A] reprimands [D]!</span>", \
|
||||
"<span class='userdanger'>You're slapped by [A]!</span>", "<span class='hear'>You hear a sickening sound of flesh hitting flesh!</span>", COMBAT_MESSAGE_RANGE, A)
|
||||
to_chat(A, "<span class='danger'>You jab [D]!</span>")
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
|
||||
playsound(D, 'sound/effects/hit_punch.ogg', 50, TRUE, -1)
|
||||
D.apply_damage(damage + 5, STAMINA, affecting, armor_block)
|
||||
log_combat(A, D, "punched nonlethally")
|
||||
else
|
||||
D.visible_message("<span class='danger'>[A] attempted to disarm [D]!</span>", \
|
||||
"<span class='userdanger'>[A] attempted to disarm [D]!</span>")
|
||||
playsound(D, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||
log_combat(A, D, "disarmed (Krav Maga)", "[I ? " removing \the [I]" : ""]")
|
||||
return 1
|
||||
D.visible_message("<span class='danger'>[A] reprimands [D]!</span>", \
|
||||
"<span class='userdanger'>You're manhandled by [A]!</span>", "<span class='hear'>You hear a sickening sound of flesh hitting flesh!</span>", COMBAT_MESSAGE_RANGE, A)
|
||||
to_chat(A, "<span class='danger'>You stomp [D]!</span>")
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
|
||||
playsound(D, 'sound/effects/hit_punch.ogg', 50, TRUE, -1)
|
||||
D.apply_damage(damage + 10, STAMINA, affecting, armor_block)
|
||||
log_combat(A, D, "stomped nonlethally")
|
||||
if(prob(D.getStaminaLoss()))
|
||||
D.visible_message("<span class='warning'>[D] sputters and recoils in pain!</span>", "<span class='userdanger'>You recoil in pain as you are jabbed in a nerve!</span>")
|
||||
D.drop_all_held_items()
|
||||
return TRUE
|
||||
|
||||
//Krav Maga Gloves
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
/datum/martial_art/mushpunch/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
var/atk_verb
|
||||
var/damage = (damage_roll(A,D)*3)
|
||||
to_chat(A, "<span class='spider'>You begin to wind up an attack...</span>")
|
||||
if(!do_after(A, 25, target = D))
|
||||
to_chat(A, "<span class='spider'><b>Your attack was interrupted!</b></span>")
|
||||
@@ -12,7 +13,7 @@
|
||||
atk_verb = pick("punches", "smashes", "ruptures", "cracks")
|
||||
D.visible_message("<span class='danger'>[A] [atk_verb] [D] with inhuman strength, sending [D.p_them()] flying backwards!</span>", \
|
||||
"<span class='userdanger'>[A] [atk_verb] you with inhuman strength, sending you flying backwards!</span>")
|
||||
D.apply_damage(rand(15,30), BRUTE)
|
||||
D.apply_damage(damage, BRUTE) //KAPOW
|
||||
playsound(D, 'sound/effects/meteorimpact.ogg', 25, 1, -1)
|
||||
var/throwtarget = get_edge_target_turf(A, get_dir(A, get_step_away(D, A)))
|
||||
D.throw_at(throwtarget, 4, 2, A)//So stuff gets tossed around at the same time.
|
||||
|
||||
@@ -44,11 +44,13 @@
|
||||
return
|
||||
|
||||
/datum/martial_art/plasma_fist/proc/Throwback(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
var/damage = (damage_roll(A,D)*3)
|
||||
D.visible_message("<span class='danger'>[A] has hit [D] with Plasma Punch!</span>", \
|
||||
"<span class='userdanger'>[A] has hit [D] with Plasma Punch!</span>")
|
||||
playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1)
|
||||
var/atom/throw_target = get_edge_target_turf(D, get_dir(D, get_step_away(D, A)))
|
||||
D.throw_at(throw_target, 200, 4,A)
|
||||
D.apply_damage(damage, BRUTE)
|
||||
A.say("HYAH!", forced="plasma fist")
|
||||
log_combat(A, D, "threw back (Plasma Fist)")
|
||||
return
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
/datum/martial_art/psychotic_brawling/proc/psycho_attack(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
var/atk_verb
|
||||
var/damage = damage_roll(A,D)
|
||||
switch(rand(1,8))
|
||||
if(1)
|
||||
D.help_shake_act(A)
|
||||
@@ -44,10 +45,10 @@
|
||||
D.visible_message("<span class='danger'>[A] [atk_verb] [D]!</span>", \
|
||||
"<span class='userdanger'>[A] [atk_verb] you!</span>")
|
||||
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 40, 1, -1)
|
||||
D.apply_damage(rand(5,10), BRUTE, BODY_ZONE_HEAD)
|
||||
A.apply_damage(rand(5,10), BRUTE, BODY_ZONE_HEAD)
|
||||
D.apply_damage(damage*1.5, BRUTE, BODY_ZONE_HEAD)
|
||||
A.apply_damage(damage, BRUTE, BODY_ZONE_HEAD)
|
||||
if(!istype(D.head,/obj/item/clothing/head/helmet/) && !istype(D.head,/obj/item/clothing/head/hardhat))
|
||||
D.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5)
|
||||
D.adjustOrganLoss(ORGAN_SLOT_BRAIN, damage)
|
||||
A.Stun(rand(10,45))
|
||||
D.DefaultCombatKnockdown(rand(5,30))//CIT CHANGE - makes stuns from martial arts always use Knockdown instead of Stun for the sake of consistency
|
||||
if(5,6)
|
||||
@@ -55,7 +56,7 @@
|
||||
atk_verb = pick("punches", "kicks", "hits", "slams into")
|
||||
D.visible_message("<span class='danger'>[A] [atk_verb] [D] with inhuman strength, sending [D.p_them()] flying backwards!</span>", \
|
||||
"<span class='userdanger'>[A] [atk_verb] you with inhuman strength, sending you flying backwards!</span>")
|
||||
D.apply_damage(rand(15,30), BRUTE)
|
||||
D.apply_damage(damage*2, BRUTE)
|
||||
playsound(get_turf(D), 'sound/effects/meteorimpact.ogg', 25, 1, -1)
|
||||
var/throwtarget = get_edge_target_turf(A, get_dir(A, get_step_away(D, A)))
|
||||
D.throw_at(throwtarget, 4, 2, A)//So stuff gets tossed around at the same time.
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
return TRUE
|
||||
|
||||
/datum/martial_art/the_rising_bass/proc/sideKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
var/damage = (damage_roll(A,D)*0.5)
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
var/dir = A.dir & (NORTH | SOUTH) ? pick(EAST, WEST) : pick(NORTH, SOUTH)
|
||||
var/oppdir = dir == NORTH ? SOUTH : dir == SOUTH ? NORTH : dir == EAST ? WEST : EAST
|
||||
@@ -87,7 +88,7 @@
|
||||
D.visible_message("<span class='warning'>[A] kicks [D] in the side, sliding them over!</span>", \
|
||||
"<span class='userdanger'>[A] kicks you in the side, forcing you to step away!</span>")
|
||||
playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
D.apply_damage(5, BRUTE, BODY_ZONE_CHEST)
|
||||
D.apply_damage(damage, BRUTE, BODY_ZONE_CHEST)
|
||||
D.DefaultCombatKnockdown(60)
|
||||
var/L = !checkfordensity(H,D) ? (!checkfordensity(K,D) ? D.loc : K) : H
|
||||
D.forceMove(L)
|
||||
@@ -96,6 +97,7 @@
|
||||
return TRUE
|
||||
|
||||
/datum/martial_art/the_rising_bass/proc/shoulderFlip(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
var/damage = (damage_roll(A,D) + 25)
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
var/turf/H = get_step(A, get_dir(D,A))
|
||||
var/L = checkfordensity(H,D) ? H : A.loc
|
||||
@@ -104,8 +106,8 @@
|
||||
"<span class='userdanger'>[A] flips you over their shoulder, slamming you into the ground!</span>")
|
||||
playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
D.emote("scream")
|
||||
D.apply_damage(10, BRUTE, BODY_ZONE_CHEST)
|
||||
D.apply_damage(30, BRUTE, BODY_ZONE_HEAD)
|
||||
D.apply_damage(damage, BRUTE, BODY_ZONE_CHEST)
|
||||
D.apply_damage(damage, BRUTE, BODY_ZONE_HEAD)
|
||||
D.Sleeping(60)
|
||||
D.DefaultCombatKnockdown(300)
|
||||
D.forceMove(L)
|
||||
@@ -114,6 +116,7 @@
|
||||
return FALSE
|
||||
|
||||
/datum/martial_art/the_rising_bass/proc/repulsePunch(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
var/damage = damage_roll(A,D)
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND) && repulsecool < world.time)
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
|
||||
D.visible_message("<span class='warning'>[A] smashes [D] in the chest, throwing them away!</span>", \
|
||||
@@ -121,7 +124,7 @@
|
||||
playsound(get_turf(A), 'sound/weapons/punch1.ogg', 50, 1, -1)
|
||||
var/atom/F = get_edge_target_turf(D, get_dir(A, get_step_away(D, A)))
|
||||
D.throw_at(F, 10, 1)
|
||||
D.apply_damage(10, BRUTE, BODY_ZONE_CHEST)
|
||||
D.apply_damage(damage, BRUTE, BODY_ZONE_CHEST)
|
||||
D.DefaultCombatKnockdown(90)
|
||||
log_combat(A, D, "repulse punched (Rising Bass)")
|
||||
repulsecool = world.time + 3 SECONDS
|
||||
@@ -129,12 +132,13 @@
|
||||
return FALSE
|
||||
|
||||
/datum/martial_art/the_rising_bass/proc/footSmash(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
var/damage = (damage_roll(A,D)*0.5)
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND))
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
|
||||
D.visible_message("<span class='warning'>[A] smashes their foot down on [D]'s foot!</span>", \
|
||||
"<span class='userdanger'>[A] smashes your foot!</span>")
|
||||
playsound(get_turf(A), 'sound/weapons/punch1.ogg', 50, 1, -1)
|
||||
D.apply_damage(5, BRUTE, pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
|
||||
D.apply_damage(damage, BRUTE, pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
|
||||
D.dropItemToGround(D.get_active_held_item())
|
||||
log_combat(A, D, "foot smashed (Rising Bass)")
|
||||
return TRUE
|
||||
@@ -181,7 +185,7 @@
|
||||
. = ..()
|
||||
if(A.incapacitated(FALSE, TRUE)) //NO STUN
|
||||
return BULLET_ACT_HIT
|
||||
if(!(A.mobility_flags & MOBILITY_USE)) //NO UNABLE TO USE
|
||||
if(CHECK_ALL_MOBILITY(A, MOBILITY_USE|MOBILITY_STAND)) //NO UNABLE TO USE, NO DODGING ON THE FLOOR
|
||||
return BULLET_ACT_HIT
|
||||
if(A.dna && A.dna.check_mutation(HULK)) //NO HULK
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
@@ -31,45 +31,48 @@
|
||||
var/atk_verb = pick("precisely kick", "brutally chop", "cleanly hit", "viciously slam")
|
||||
///this is the critical hit damage added to the attack if it rolls, it starts at 0 because it'll be changed when rolled
|
||||
var/crit_damage = 0
|
||||
var/damage = damage_roll(A,D)
|
||||
D.visible_message("<span class='danger'>[A] [atk_verb]s [D]!</span>", \
|
||||
"<span class='userdanger'>[A] [atk_verb]s you!</span>", null, null, A)
|
||||
to_chat(A, "<span class='danger'>You [atk_verb] [D]!</span>")
|
||||
if(prob(10))
|
||||
crit_damage += 20
|
||||
crit_damage += (damage*2 + 15)
|
||||
playsound(get_turf(D), 'sound/weapons/bite.ogg', 50, TRUE, -1)
|
||||
D.visible_message("<span class='warning'>[D] sputters blood as the blow strikes them with inhuman force!</span>", "<span class='userdanger'>You are struck with incredible precision by [A]!</span>")
|
||||
D.visible_message("<span class='warning'>[D] staggers as the blow strikes them with inhuman force!</span>", "<span class='userdanger'>You are struck with incredible precision by [A]!</span>")
|
||||
log_combat(A, D, "critcal strong punched (Sleeping Carp)")//log it here because a critical can swing for 40 force and it's important for the sake of how hard they hit
|
||||
else
|
||||
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, TRUE, -1)
|
||||
log_combat(A, D, "strong punched (Sleeping Carp)")//so as to not double up on logging
|
||||
D.apply_damage(20 + crit_damage, BRUTE, affecting)
|
||||
D.apply_damage((damage + 15) + crit_damage, BRUTE, affecting)
|
||||
return
|
||||
|
||||
///Crashing Wave Kick: Harm Disarm combo, throws people seven tiles backwards
|
||||
/datum/martial_art/the_sleeping_carp/proc/launchKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
var/damage = (damage_roll(A,D) + 15)
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
|
||||
D.visible_message("<span class='warning'>[A] kicks [D] square in the chest, sending them flying!</span>", \
|
||||
"<span class='userdanger'>You are kicked square in the chest by [A], sending you flying!</span>", "<span class='hear'>You hear a sickening sound of flesh hitting flesh!</span>", COMBAT_MESSAGE_RANGE, A)
|
||||
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, TRUE, -1)
|
||||
var/atom/throw_target = get_edge_target_turf(D, A.dir)
|
||||
D.throw_at(throw_target, 7, 14, A)
|
||||
D.apply_damage(15, BRUTE, BODY_ZONE_CHEST)
|
||||
D.apply_damage(damage, BRUTE, BODY_ZONE_CHEST)
|
||||
log_combat(A, D, "launchkicked (Sleeping Carp)")
|
||||
return
|
||||
|
||||
///Keelhaul: Harm Grab combo, knocks people down, deals stamina damage while they're on the floor
|
||||
/datum/martial_art/the_sleeping_carp/proc/dropKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
var/damage = damage_roll(A,D)
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
|
||||
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, TRUE, -1)
|
||||
if((D.mobility_flags & MOBILITY_STAND))
|
||||
D.apply_damage(10, BRUTE, BODY_ZONE_HEAD)
|
||||
D.apply_damage(damage, BRUTE, BODY_ZONE_HEAD)
|
||||
D.DefaultCombatKnockdown(50, override_hardstun = 0.01, override_stamdmg = 0)
|
||||
D.adjustStaminaLoss(40) //A cit specific change form the tg port to really punish anyone who tries to stand up
|
||||
D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD) //A cit specific change form the tg port to really punish anyone who tries to stand up
|
||||
D.visible_message("<span class='warning'>[A] kicks [D] in the head, sending them face first into the floor!</span>", \
|
||||
"<span class='userdanger'>You are kicked in the head by [A], sending you crashing to the floor!</span>", "<span class='hear'>You hear a sickening sound of flesh hitting flesh!</span>", COMBAT_MESSAGE_RANGE, A)
|
||||
else if(!(D.mobility_flags & MOBILITY_STAND))
|
||||
D.apply_damage(5, BRUTE, BODY_ZONE_HEAD)
|
||||
D.adjustStaminaLoss(40)
|
||||
else
|
||||
D.apply_damage(damage*0.5, BRUTE, BODY_ZONE_HEAD)
|
||||
D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD)
|
||||
D.drop_all_held_items()
|
||||
D.visible_message("<span class='warning'>[A] kicks [D] in the head!</span>", \
|
||||
"<span class='userdanger'>You are kicked in the head by [A]!</span>", "<span class='hear'>You hear a sickening sound of flesh hitting flesh!</span>", COMBAT_MESSAGE_RANGE, A)
|
||||
@@ -85,6 +88,7 @@
|
||||
|
||||
/datum/martial_art/the_sleeping_carp/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
add_to_streak("H",D)
|
||||
var/damage = (damage_roll(A,D) + 5)
|
||||
if(check_streak(A,D))
|
||||
return TRUE
|
||||
var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected))
|
||||
@@ -93,7 +97,7 @@
|
||||
D.visible_message("<span class='danger'>[A] [atk_verb]s [D]!</span>", \
|
||||
"<span class='userdanger'>[A] [atk_verb]s you!</span>", null, null, A)
|
||||
to_chat(A, "<span class='danger'>You [atk_verb] [D]!</span>")
|
||||
D.apply_damage(rand(10,15), BRUTE, affecting)
|
||||
D.apply_damage(damage, BRUTE, affecting)
|
||||
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, TRUE, -1)
|
||||
log_combat(A, D, "punched (Sleeping Carp)")
|
||||
return TRUE
|
||||
@@ -110,7 +114,7 @@
|
||||
. = ..()
|
||||
if(A.incapacitated(FALSE, TRUE)) //NO STUN
|
||||
return BULLET_ACT_HIT
|
||||
if(!(A.mobility_flags & MOBILITY_USE)) //NO UNABLE TO USE
|
||||
if(CHECK_ALL_MOBILITY(A, MOBILITY_USE|MOBILITY_STAND)) //NO UNABLE TO USE, NO DEFLECTION ON THE FLOOR
|
||||
return BULLET_ACT_HIT
|
||||
if(A.dna && A.dna.check_mutation(HULK)) //NO HULK
|
||||
return BULLET_ACT_HIT
|
||||
@@ -121,6 +125,7 @@
|
||||
playsound(get_turf(A), pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, TRUE)
|
||||
P.firer = A
|
||||
P.setAngle(rand(0, 360))//SHING
|
||||
A.adjustStaminaLossBuffered (3) //Citadel change to stop infinite bullet sponging as you run away, but it is buffered!
|
||||
return BULLET_ACT_FORCE_PIERCE
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
@@ -133,7 +138,6 @@
|
||||
ADD_TRAIT(H, TRAIT_NODISMEMBER, SLEEPING_CARP_TRAIT)
|
||||
H.physiology.brute_mod *= 0.4 //brute is really not gonna cut it
|
||||
H.physiology.burn_mod *= 0.7 //burn is distinctly more useful against them than brute but they're still resistant
|
||||
H.physiology.stamina_mod *= 0.5 //stun batons prove to be one of the few ways to fight them. They have stun resistance already, so I think doubling down too hard on this resistance is a bit much.
|
||||
H.physiology.stun_mod *= 0.3 //for those rare stuns
|
||||
H.physiology.pressure_mod *= 0.3 //go hang out with carp
|
||||
H.physiology.cold_mod *= 0.3 //cold mods are different to burn mods, they do stack however
|
||||
@@ -148,7 +152,6 @@
|
||||
REMOVE_TRAIT(H, TRAIT_NODISMEMBER, SLEEPING_CARP_TRAIT)
|
||||
H.physiology.brute_mod = initial(H.physiology.brute_mod)
|
||||
H.physiology.burn_mod = initial(H.physiology.burn_mod)
|
||||
H.physiology.stamina_mod = initial(H.physiology.stamina_mod)
|
||||
H.physiology.stun_mod = initial(H.physiology.stun_mod)
|
||||
H.physiology.pressure_mod = initial(H.physiology.pressure_mod) //no more carpies
|
||||
H.physiology.cold_mod = initial(H.physiology.cold_mod)
|
||||
@@ -237,7 +240,7 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/twohanded/bostaff/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(wielded)
|
||||
return ..()
|
||||
return FALSE
|
||||
/obj/item/twohanded/bostaff/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(!wielded)
|
||||
return BLOCK_NONE
|
||||
return ..()
|
||||
|
||||
@@ -19,29 +19,29 @@
|
||||
|
||||
/datum/martial_art/wrestling/proc/check_streak(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
|
||||
if(!can_use(A, D))
|
||||
return 0
|
||||
return FALSE
|
||||
switch(streak)
|
||||
if("drop")
|
||||
streak = ""
|
||||
drop(A,D)
|
||||
return 1
|
||||
return TRUE
|
||||
if("strike")
|
||||
streak = ""
|
||||
strike(A,D)
|
||||
return 1
|
||||
return TRUE
|
||||
if("kick")
|
||||
streak = ""
|
||||
kick(A,D)
|
||||
return 1
|
||||
return TRUE
|
||||
if("throw")
|
||||
streak = ""
|
||||
throw_wrassle(A,D)
|
||||
return 1
|
||||
return TRUE
|
||||
if("slam")
|
||||
streak = ""
|
||||
slam(A,D)
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/action/slam
|
||||
name = "Slam (Cinch) - Slam a grappled opponent into the floor."
|
||||
@@ -138,7 +138,7 @@
|
||||
|
||||
/datum/martial_art/wrestling/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(check_streak(A,D))
|
||||
return 1
|
||||
return TRUE
|
||||
log_combat(A, D, "punched with wrestling")
|
||||
..()
|
||||
|
||||
@@ -173,11 +173,11 @@
|
||||
|
||||
if (get_dist(A, D) > 1)
|
||||
to_chat(A, "[D] is too far away!")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if (!isturf(A.loc) || !isturf(D.loc))
|
||||
to_chat(A, "You can't throw [D] from here!")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
A.setDir(turn(A.dir, 90))
|
||||
var/turf/T = get_step(A, A.dir)
|
||||
@@ -186,7 +186,7 @@
|
||||
D.forceMove(T)
|
||||
D.setDir(get_dir(D, A))
|
||||
else
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
sleep(delay)
|
||||
|
||||
@@ -195,11 +195,11 @@
|
||||
|
||||
if (get_dist(A, D) > 1)
|
||||
to_chat(A, "[D] is too far away!")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if (!isturf(A.loc) || !isturf(D.loc))
|
||||
to_chat(A, "You can't throw [D] from here!")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
D.forceMove(A.loc) // Maybe this will help with the wallthrowing bug.
|
||||
|
||||
@@ -211,7 +211,7 @@
|
||||
D.emote("scream")
|
||||
D.throw_at(T, 10, 4, A, TRUE, TRUE, callback = CALLBACK(D, /mob/living/carbon/human.proc/DefaultCombatKnockdown, 20))
|
||||
log_combat(A, D, "has thrown with wrestling")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/datum/martial_art/wrestling/proc/FlipAnimation(mob/living/carbon/human/D)
|
||||
set waitfor = FALSE
|
||||
@@ -227,6 +227,7 @@
|
||||
if(!A.pulling || A.pulling != D)
|
||||
to_chat(A, "You need to have [D] in a cinch!")
|
||||
return
|
||||
var/damage = damage_roll(A,D)
|
||||
D.forceMove(A.loc)
|
||||
A.setDir(get_dir(A, D))
|
||||
D.setDir(get_dir(D, A))
|
||||
@@ -258,7 +259,7 @@
|
||||
A.pixel_y = 0
|
||||
D.pixel_x = 0
|
||||
D.pixel_y = 0
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if (!isturf(A.loc) || !isturf(D.loc))
|
||||
to_chat(A, "You can't slam [D] here!")
|
||||
@@ -266,7 +267,7 @@
|
||||
A.pixel_y = 0
|
||||
D.pixel_x = 0
|
||||
D.pixel_y = 0
|
||||
return 0
|
||||
return FALSE
|
||||
else
|
||||
if (A)
|
||||
A.pixel_x = 0
|
||||
@@ -274,7 +275,7 @@
|
||||
if (D)
|
||||
D.pixel_x = 0
|
||||
D.pixel_y = 0
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
sleep(1)
|
||||
|
||||
@@ -286,11 +287,11 @@
|
||||
|
||||
if (get_dist(A, D) > 1)
|
||||
to_chat(A, "[D] is too far away!")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if (!isturf(A.loc) || !isturf(D.loc))
|
||||
to_chat(A, "You can't slam [D] here!")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
D.forceMove(A.loc)
|
||||
|
||||
@@ -309,11 +310,11 @@
|
||||
|
||||
switch(rand(1,3))
|
||||
if (2)
|
||||
D.adjustBruteLoss(rand(20,30))
|
||||
D.apply_damage(damage + 25, BRUTE)
|
||||
if (3)
|
||||
D.ex_act(EXPLODE_LIGHT)
|
||||
else
|
||||
D.adjustBruteLoss(rand(10,20))
|
||||
D.apply_damage(damage + 15, BRUTE)
|
||||
else
|
||||
D.ex_act(EXPLODE_LIGHT)
|
||||
|
||||
@@ -327,7 +328,7 @@
|
||||
|
||||
|
||||
log_combat(A, D, "body-slammed")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/datum/martial_art/wrestling/proc/CheckStrikeTurf(mob/living/carbon/human/A, turf/T)
|
||||
if (A && (T && isturf(T) && get_dist(A, T) <= 1))
|
||||
@@ -337,6 +338,7 @@
|
||||
if(!D)
|
||||
return
|
||||
var/turf/T = get_turf(A)
|
||||
var/damage = damage_roll(A,D)
|
||||
if (T && isturf(T) && D && isturf(D.loc))
|
||||
for (var/i = 0, i < 4, i++)
|
||||
A.setDir(turn(A.dir, 90))
|
||||
@@ -345,7 +347,7 @@
|
||||
addtimer(CALLBACK(src, .proc/CheckStrikeTurf, A, T), 4)
|
||||
|
||||
A.visible_message("<span class = 'danger'><b>[A] headbutts [D]!</b></span>")
|
||||
D.adjustBruteLoss(rand(10,20))
|
||||
D.apply_damage(damage + 15, BRUTE)
|
||||
playsound(A.loc, "swing_hit", 50, 1)
|
||||
D.Unconscious(20)
|
||||
log_combat(A, D, "headbutted")
|
||||
@@ -353,13 +355,14 @@
|
||||
/datum/martial_art/wrestling/proc/kick(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(!D)
|
||||
return
|
||||
var/damage = damage_roll(A,D)
|
||||
A.emote("scream")
|
||||
A.emote("flip")
|
||||
A.setDir(turn(A.dir, 90))
|
||||
|
||||
A.visible_message("<span class = 'danger'><B>[A] roundhouse-kicks [D]!</B></span>")
|
||||
playsound(A.loc, "swing_hit", 50, 1)
|
||||
D.adjustBruteLoss(rand(10,20))
|
||||
D.apply_damage(damage + 15, STAMINA)
|
||||
|
||||
var/turf/T = get_edge_target_turf(A, get_dir(A, get_step_away(D, A)))
|
||||
if (T && isturf(T))
|
||||
@@ -373,7 +376,8 @@
|
||||
var/obj/surface = null
|
||||
var/turf/ST = null
|
||||
var/falling = 0
|
||||
|
||||
var/damage = damage_roll(A,D)
|
||||
|
||||
for (var/obj/O in oview(1, A))
|
||||
if (O.density == 1)
|
||||
if (O == A)
|
||||
@@ -401,15 +405,15 @@
|
||||
A.pixel_y = 0
|
||||
if (falling == 1)
|
||||
A.visible_message("<span class = 'danger'><B>...and dives head-first into the ground, ouch!</b></span>")
|
||||
A.adjustBruteLoss(rand(10,20))
|
||||
A.apply_damage(damage + 15, BRUTE)
|
||||
A.DefaultCombatKnockdown(60)
|
||||
to_chat(A, "[D] is too far away!")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if (!isturf(A.loc) || !isturf(D.loc))
|
||||
A.pixel_y = 0
|
||||
to_chat(A, "You can't drop onto [D] from here!")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if(A)
|
||||
animate(A, transform = matrix(90, MATRIX_ROTATE), time = 1, loop = 0)
|
||||
@@ -427,9 +431,9 @@
|
||||
if (prob(33) || D.stat)
|
||||
D.ex_act(EXPLODE_LIGHT)
|
||||
else
|
||||
D.adjustBruteLoss(rand(20,30))
|
||||
D.apply_damage(damage + 25, BRUTE)
|
||||
else
|
||||
D.adjustBruteLoss(rand(20,30))
|
||||
D.apply_damage(damage + 25, BRUTE)
|
||||
|
||||
D.DefaultCombatKnockdown(40)
|
||||
|
||||
@@ -442,14 +446,16 @@
|
||||
return
|
||||
|
||||
/datum/martial_art/wrestling/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
damage_roll(A,D)
|
||||
if(check_streak(A,D))
|
||||
return 1
|
||||
return TRUE
|
||||
log_combat(A, D, "wrestling-disarmed")
|
||||
..()
|
||||
|
||||
/datum/martial_art/wrestling/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
damage_roll(A,D)
|
||||
if(check_streak(A,D))
|
||||
return 1
|
||||
return TRUE
|
||||
if(!can_use(A,D))
|
||||
return ..()
|
||||
if(A.pulling == D || A == D) // don't stun grab yoursel
|
||||
@@ -459,7 +465,7 @@
|
||||
"<span class='userdanger'>[A] gets [D] in a cinch!</span>")
|
||||
D.Stun(rand(60,100))
|
||||
log_combat(A, D, "cinched")
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/obj/item/storage/belt/champion/wrestling
|
||||
name = "Wrestling Belt"
|
||||
@@ -492,7 +498,7 @@
|
||||
//Make sure that moves can only be used on people wearing the holodeck belt
|
||||
/datum/martial_art/wrestling/holodeck/can_use(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
|
||||
if(!(istype(D.mind?.martial_art, /datum/martial_art/wrestling/holodeck)))
|
||||
return 0
|
||||
return FALSE
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -113,20 +113,25 @@
|
||||
duration = set_duration
|
||||
. = ..()
|
||||
|
||||
/datum/status_effect/no_combat_mode/mesmerize
|
||||
/datum/status_effect/mesmerize
|
||||
id = "Mesmerize"
|
||||
alert_type = /obj/screen/alert/status_effect/mesmerized
|
||||
|
||||
/datum/status_effect/no_combat_mode/mesmerize/on_creation(mob/living/new_owner, set_duration)
|
||||
/datum/status_effect/mesmerize/on_creation(mob/living/new_owner, set_duration)
|
||||
. = ..()
|
||||
ADD_TRAIT(owner, TRAIT_MUTE, "mesmerize")
|
||||
owner.add_movespeed_modifier("[STATUS_EFFECT_MESMERIZE]_[id]", TRUE, priority = 64, override = TRUE, multiplicative_slowdown = 5, blacklisted_movetypes = FALSE? NONE : CRAWLING)
|
||||
|
||||
/datum/status_effect/no_combat_mode/mesmerize/on_remove()
|
||||
/datum/status_effect/mesmerize/on_remove()
|
||||
. = ..()
|
||||
REMOVE_TRAIT(owner, TRAIT_MUTE, "mesmerize")
|
||||
owner.remove_movespeed_modifier("[STATUS_EFFECT_MESMERIZE]_[id]")
|
||||
|
||||
/datum/status_effect/mesmerize/on_creation(mob/living/new_owner, set_duration)
|
||||
if(isnum(set_duration))
|
||||
duration = set_duration
|
||||
. = ..()
|
||||
|
||||
/obj/screen/alert/status_effect/mesmerized
|
||||
name = "Mesmerized"
|
||||
desc = "You cant tear your sight from who is in front of you... their gaze is simply too enthralling.."
|
||||
|
||||
@@ -54,12 +54,18 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
// Current storyteller
|
||||
var/datum/dynamic_storyteller/storyteller = null
|
||||
// Threat logging vars
|
||||
/// Starting threat level, for things that increase it but can bring it back down.
|
||||
var/initial_threat_level = 0
|
||||
/// Target threat level right now. Events and antags will try to keep the round at this level.
|
||||
var/threat_level = 0
|
||||
/// The current antag threat. Recalculated every time a ruletype starts or ends.
|
||||
var/threat = 0
|
||||
/// Starting threat level, for things that increase it but can bring it back down.
|
||||
var/initial_threat_level = 0
|
||||
/// Threat average over the course of the round, for endgame logs.
|
||||
var/threat_average = 0
|
||||
/// Number of times threat average has been calculated, for calculating above.
|
||||
var/threat_average_weight = 0
|
||||
/// Last time a threat average sample was taken. Used for weighting the rolling average.
|
||||
var/last_threat_sample_time = 0
|
||||
/// Things that cause a rolling threat adjustment to be displayed at roundend.
|
||||
var/list/threat_tallies = list()
|
||||
/// Running information about the threat. Can store text or datum entries.
|
||||
@@ -717,6 +723,16 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
continue
|
||||
current_players[CURRENT_DEAD_PLAYERS].Add(M) // Players who actually died (and admins who ghosted, would be nice to avoid counting them somehow)
|
||||
threat = storyteller.calculate_threat() + added_threat
|
||||
if(threat_average_weight)
|
||||
var/cur_sample_weight = world.time - last_threat_sample_time
|
||||
threat_average = ((threat_average * threat_average_weight) + threat) / (threat_average_weight + cur_sample_weight)
|
||||
threat_average_weight += cur_sample_weight
|
||||
last_threat_sample_time = world.time
|
||||
else
|
||||
threat_average = threat
|
||||
threat_average_weight++
|
||||
last_threat_sample_time = world.time
|
||||
|
||||
/// Removes type from the list
|
||||
/datum/game_mode/dynamic/proc/remove_from_list(list/type_list, type)
|
||||
for(var/I in type_list)
|
||||
|
||||
@@ -34,8 +34,7 @@
|
||||
living_players = trim_list(mode.current_players[CURRENT_LIVING_PLAYERS])
|
||||
living_antags = trim_list(mode.current_players[CURRENT_LIVING_ANTAGS])
|
||||
list_observers = trim_list(mode.current_players[CURRENT_OBSERVERS])
|
||||
var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility))
|
||||
ghost_eligible = trim_list(eligibility.get_all_ghost_role_eligible())
|
||||
ghost_eligible = trim_list(get_all_ghost_role_eligible())
|
||||
|
||||
/datum/dynamic_ruleset/midround/proc/trim_list(list/L = list())
|
||||
var/list/trimmed_list = L.Copy()
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
WAROPS_ALWAYS_ALLOWED: Can always do warops, regardless of threat level.
|
||||
USE_PREF_WEIGHTS: Will use peoples' preferences to change the threat centre.
|
||||
FORCE_IF_WON: If this mode won the vote, forces it
|
||||
USE_PREV_ROUND_WEIGHTS: Changes its threat centre based on the average chaos of previous rounds.
|
||||
*/
|
||||
var/flags = 0
|
||||
var/dead_player_weight = 1 // How much dead players matter for threat calculation
|
||||
@@ -92,6 +93,8 @@ Property weights are:
|
||||
mean += 5
|
||||
if(voters)
|
||||
GLOB.dynamic_curve_centre += (mean/voters)
|
||||
if(flags & USE_PREV_ROUND_WEIGHTS)
|
||||
GLOB.dynamic_curve_centre += (50 - SSpersistence.average_dynamic_threat) / 10
|
||||
GLOB.dynamic_forced_threat_level = forced_threat_level
|
||||
|
||||
/datum/dynamic_storyteller/proc/get_midround_cooldown()
|
||||
@@ -230,7 +233,7 @@ Property weights are:
|
||||
curve_width = 1.5
|
||||
weight = 2
|
||||
min_players = 30
|
||||
flags = WAROPS_ALWAYS_ALLOWED
|
||||
flags = WAROPS_ALWAYS_ALLOWED | USE_PREV_ROUND_WEIGHTS
|
||||
property_weights = list("valid" = 3, "trust" = 5)
|
||||
|
||||
/datum/dynamic_storyteller/team/get_injection_chance(dry_run = FALSE)
|
||||
@@ -268,9 +271,6 @@ Property weights are:
|
||||
/datum/dynamic_storyteller/random/get_injection_chance()
|
||||
return 50 // i would do rand(0,100) but it's actually the same thing when you do the math
|
||||
|
||||
/datum/dynamic_storyteller/random/calculate_threat()
|
||||
return 0 // what IS threat
|
||||
|
||||
/datum/dynamic_storyteller/random/roundstart_draft()
|
||||
var/list/drafted_rules = list()
|
||||
for (var/datum/dynamic_ruleset/roundstart/rule in mode.roundstart_rules)
|
||||
@@ -324,6 +324,7 @@ Property weights are:
|
||||
desc = "Antags with options for loadouts and gimmicks. Traitor, wizard, nukies. Has a buildup-climax-falling action threat curve."
|
||||
weight = 2
|
||||
curve_width = 2
|
||||
flags = USE_PREV_ROUND_WEIGHTS
|
||||
property_weights = list("story_potential" = 2)
|
||||
|
||||
|
||||
@@ -336,7 +337,7 @@ Property weights are:
|
||||
name = "Classic"
|
||||
config_tag = "classic"
|
||||
desc = "No special antagonist weights. Good variety, but not like random. Uses your chaos preference to weight."
|
||||
flags = USE_PREF_WEIGHTS
|
||||
flags = USE_PREF_WEIGHTS | USE_PREV_ROUND_WEIGHTS
|
||||
|
||||
/datum/dynamic_storyteller/suspicion
|
||||
name = "Intrigue"
|
||||
@@ -345,6 +346,7 @@ Property weights are:
|
||||
weight = 2
|
||||
curve_width = 2
|
||||
dead_player_weight = 2
|
||||
flags = USE_PREV_ROUND_WEIGHTS
|
||||
property_weights = list("trust" = -3)
|
||||
|
||||
/datum/dynamic_storyteller/liteextended
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
/obj/item/stack/tile/fakespace/loaded = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/stack/tile/fakepit/loaded = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/restraints/handcuffs/fake = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/clothing/gloves/rapid/hug = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/clothing/gloves/fingerless/pugilist/rapid/hug = ARCADE_WEIGHT_TRICK,
|
||||
|
||||
/obj/item/grenade/chem_grenade/glitter/pink = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/grenade/chem_grenade/glitter/blue = ARCADE_WEIGHT_TRICK,
|
||||
|
||||
@@ -382,18 +382,26 @@
|
||||
explosion(loc, 1, 3, rand(1,5), rand(1,10))
|
||||
var/list/targets = list()
|
||||
var/cur_y = y - round(row_limit * 0.5, 1)
|
||||
var/starting_row = 1
|
||||
if(cur_y < 1)
|
||||
starting_row -= cur_y - 1
|
||||
cur_y = 1
|
||||
var/start_x = x - round(column_limit * 0.5, 1)
|
||||
for(var/row in table) //translate the mines locations into actual turf coordinates.
|
||||
var/starting_column = 1
|
||||
if(start_x < 1)
|
||||
starting_column -= start_x - 1
|
||||
start_x = 1
|
||||
for(var/row in starting_row to length(table)) //translate the mines locations into actual turf coordinates.
|
||||
if(!locate(cur_y, start_x, z))
|
||||
continue
|
||||
break
|
||||
var/cur_x = start_x
|
||||
for(var/column in row)
|
||||
for(var/column in starting_column to length(table[row]))
|
||||
var/coord_value = table[row][column]
|
||||
if(coord_value == 10 || coord_value == 0) //there is a mine in here.
|
||||
var/turf/target = locate(cur_y, cur_x, z)
|
||||
if(!target)
|
||||
continue
|
||||
targets += target
|
||||
var/turf/T = locate(cur_y, cur_x, z)
|
||||
if(!T)
|
||||
break
|
||||
targets += T
|
||||
cur_x++
|
||||
cur_y++
|
||||
var/num_explosions = 0
|
||||
@@ -406,4 +414,4 @@
|
||||
#undef MINESWEEPER_GAME_MAIN_MENU
|
||||
#undef MINESWEEPER_GAME_PLAYING
|
||||
#undef MINESWEEPER_GAME_LOST
|
||||
#undef MINESWEEPER_GAME_WON
|
||||
#undef MINESWEEPER_GAME_WON
|
||||
|
||||
@@ -17,6 +17,11 @@ GLOBAL_VAR_INIT(message_delay, 0) // To make sure restarting the recentmessages
|
||||
idle_power_usage = 25
|
||||
circuit = /obj/item/circuitboard/machine/telecomms/broadcaster
|
||||
|
||||
/obj/machinery/telecomms/broadcaster/RefreshParts()
|
||||
idle_power_usage = 25
|
||||
for(var/obj/item/stock_parts/manipulator/P in component_parts)
|
||||
idle_power_usage -= (P.rating * 1.5) //Has 2 manipulators
|
||||
|
||||
/obj/machinery/telecomms/broadcaster/receive_information(datum/signal/subspace/signal, obj/machinery/telecomms/machine_from)
|
||||
// Don't broadcast rejected signals
|
||||
if(!istype(signal))
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
circuit = /obj/item/circuitboard/machine/telecomms/bus
|
||||
var/change_frequency = 0
|
||||
|
||||
/obj/machinery/telecomms/bus/RefreshParts()
|
||||
idle_power_usage = 50
|
||||
for(var/obj/item/stock_parts/manipulator/P in component_parts)
|
||||
idle_power_usage -= (P.rating * 2) //Has 2 manipulators
|
||||
|
||||
/obj/machinery/telecomms/bus/receive_information(datum/signal/subspace/signal, obj/machinery/telecomms/machine_from)
|
||||
if(!istype(signal) || !is_freq_listening(signal))
|
||||
return
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
netspeed = 40
|
||||
circuit = /obj/item/circuitboard/machine/telecomms/hub
|
||||
|
||||
/obj/machinery/telecomms/hub/RefreshParts()
|
||||
idle_power_usage = 80
|
||||
for(var/obj/item/stock_parts/manipulator/P in component_parts)
|
||||
idle_power_usage -= (P.rating * 5) //Has 2 manipulators
|
||||
|
||||
/obj/machinery/telecomms/hub/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
|
||||
if(!is_freq_listening(signal))
|
||||
return
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
circuit = /obj/item/circuitboard/machine/telecomms/processor
|
||||
var/process_mode = 1 // 1 = Uncompress Signals, 0 = Compress Signals
|
||||
|
||||
/obj/machinery/telecomms/processor/RefreshParts()
|
||||
idle_power_usage = 30
|
||||
for(var/obj/item/stock_parts/manipulator/P in component_parts)
|
||||
idle_power_usage -= (P.rating * 1.5) //Has 2 manipulators
|
||||
|
||||
/obj/machinery/telecomms/processor/receive_information(datum/signal/subspace/signal, obj/machinery/telecomms/machine_from)
|
||||
if(!is_freq_listening(signal))
|
||||
return
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
idle_power_usage = 30
|
||||
circuit = /obj/item/circuitboard/machine/telecomms/receiver
|
||||
|
||||
/obj/machinery/telecomms/receiver/RefreshParts()
|
||||
idle_power_usage = 30
|
||||
for(var/obj/item/stock_parts/manipulator/P in component_parts)
|
||||
idle_power_usage -= (P.rating * 1.5) //Has 2 manipulators
|
||||
|
||||
/obj/machinery/telecomms/receiver/receive_signal(datum/signal/subspace/signal)
|
||||
if(!on || !istype(signal) || !check_receive_level(signal) || signal.transmission_method != TRANSMISSION_SUBSPACE)
|
||||
return
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
var/broadcasting = 1
|
||||
var/receiving = 1
|
||||
|
||||
/obj/machinery/telecomms/relay/RefreshParts()
|
||||
idle_power_usage = 30
|
||||
for(var/obj/item/stock_parts/manipulator/P in component_parts)
|
||||
idle_power_usage -= (P.rating * 1.5) //Has 2 manipulators
|
||||
|
||||
/obj/machinery/telecomms/relay/receive_information(datum/signal/subspace/signal, obj/machinery/telecomms/machine_from)
|
||||
// Add our level and send it back
|
||||
var/turf/T = get_turf(src)
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
/obj/machinery/telecomms/server/Initialize()
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/telecomms/server/RefreshParts()
|
||||
idle_power_usage = 15
|
||||
for(var/obj/item/stock_parts/manipulator/P in component_parts)
|
||||
idle_power_usage -= (P.rating) //has 2 manipulators
|
||||
|
||||
/obj/machinery/telecomms/server/receive_information(datum/signal/subspace/vocal/signal, obj/machinery/telecomms/machine_from)
|
||||
// can't log non-vocal signals
|
||||
if(!istype(signal) || !signal.data["message"] || !is_freq_listening(signal))
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
// Full credit goes to VG station for these assets. https://github.com/vgstation-coders/vgstation13
|
||||
// All items in this .dm and the associated .dmi were made by VG station and all credit should go to them.
|
||||
|
||||
// -<| IMPORTANT MAPPER NOTE |>-
|
||||
// Change the 'color' variable on any white sprite to simply recolour it!
|
||||
|
||||
/obj/effect/turf_decal/vg_decals
|
||||
icon = 'icons/turf/vgstation_decals.dmi'
|
||||
icon_state = "no"
|
||||
|
||||
// NUMBERS START
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/numbers
|
||||
icon_state = "no"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/numbers/one
|
||||
icon_state = "1"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/numbers/two
|
||||
icon_state = "2"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/numbers/three
|
||||
icon_state = "3"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/numbers/four
|
||||
icon_state = "4"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/numbers/five
|
||||
icon_state = "5"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/numbers/six
|
||||
icon_state = "6"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/numbers/seven
|
||||
icon_state = "7"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/numbers/eight
|
||||
icon_state = "8"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/numbers/nine
|
||||
icon_state = "9"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/numbers/zero
|
||||
icon_state = "0"
|
||||
|
||||
// NUMBERS END
|
||||
|
||||
// ATMOS START
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/atmos
|
||||
icon_state = "no"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/atmos/oxygen
|
||||
icon_state = "oxygen"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/atmos/carbon_dioxide
|
||||
icon_state = "carbon_dioxide"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/atmos/nitrogen
|
||||
icon_state = "nitrogen"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/atmos/air
|
||||
icon_state = "air"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/atmos/nitrous_oxide
|
||||
icon_state = "nitrous_oxide"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/atmos/plasma
|
||||
icon_state = "plasma"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/atmos/mix
|
||||
icon_state = "mix"
|
||||
|
||||
// ATMOS END
|
||||
|
||||
// DEPARTMENT START
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/department/hop
|
||||
icon_state = "hop"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/department/bar
|
||||
icon_state = "bar"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/department/cargo
|
||||
icon_state = "cargo"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/department/med
|
||||
icon_state = "med"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/department/sci
|
||||
icon_state = "sci"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/department/sec
|
||||
icon_state = "sec"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/department/mining
|
||||
icon_state = "mine"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/department/zoo
|
||||
icon_state = "zoo"
|
||||
|
||||
// DEPARTMENT END
|
||||
|
||||
// MISC START
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/no
|
||||
icon = 'icons/turf/vgstation_decals.dmi'
|
||||
icon_state = "no"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/radiation_huge
|
||||
icon_state = "radiation_huge"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/radiation
|
||||
icon_state = "radiation"
|
||||
|
||||
/obj/effect/turf_decal/vg_decals/radiation_custom
|
||||
icon_state = "radiation-w"
|
||||
|
||||
// MISC END
|
||||
@@ -45,7 +45,6 @@
|
||||
/obj/effect/spawner/lootdrop/armory_contraband
|
||||
name = "armory contraband gun spawner"
|
||||
lootdoubles = FALSE
|
||||
|
||||
loot = list(
|
||||
/obj/item/gun/ballistic/automatic/pistol = 8,
|
||||
/obj/item/gun/ballistic/shotgun/automatic/combat = 5,
|
||||
@@ -129,7 +128,6 @@
|
||||
loot = typesof(/obj/item/flashlight/glowstick)
|
||||
. = ..()
|
||||
|
||||
|
||||
/obj/effect/spawner/lootdrop/gloves
|
||||
name = "random gloves"
|
||||
desc = "These gloves are supposed to be a random color..."
|
||||
@@ -150,7 +148,6 @@
|
||||
/obj/effect/spawner/lootdrop/crate_spawner
|
||||
name = "lootcrate spawner" //USE PROMO CODE "SELLOUT" FOR 20% OFF!
|
||||
lootdoubles = FALSE
|
||||
|
||||
loot = list(
|
||||
/obj/structure/closet/crate/secure/loot = 20,
|
||||
"" = 80
|
||||
@@ -386,3 +383,141 @@
|
||||
/obj/structure/reagent_dispensers/keg/aphro = 2,
|
||||
/obj/structure/reagent_dispensers/keg/aphro/strong = 2,
|
||||
/obj/structure/reagent_dispensers/keg/gargle = 1)
|
||||
|
||||
/obj/effect/spawner/lootdrop/coin
|
||||
lootcount = 1
|
||||
loot = list(
|
||||
/obj/item/coin/silver = 30,
|
||||
/obj/item/coin/iron = 30,
|
||||
/obj/item/coin/gold = 10,
|
||||
/obj/item/coin/diamond = 10,
|
||||
/obj/item/coin/plasma = 10,
|
||||
/obj/item/coin/uranium = 10,
|
||||
)
|
||||
|
||||
/obj/effect/spawner/lootdrop/cig_packs
|
||||
lootcount = 1
|
||||
loot = list(
|
||||
/obj/item/storage/fancy/cigarettes = 20,
|
||||
/obj/item/storage/fancy/cigarettes/dromedaryco = 10,
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_robust = 5,
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_robustgold = 5,
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_carp = 15,
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_syndicate = 2,
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_midori = 10,
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_shadyjims = 5,
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_xeno = 3,
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_cannabis = 10,
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_mindbreaker = 10,
|
||||
/obj/item/storage/fancy/rollingpapers = 10
|
||||
)
|
||||
|
||||
/obj/effect/spawner/lootdrop/cigars_cases
|
||||
lootcount = 1
|
||||
loot = list(
|
||||
/obj/item/storage/fancy/cigarettes/cigars = 50,
|
||||
/obj/item/storage/fancy/cigarettes/cigars/cohiba = 25,
|
||||
/obj/item/storage/fancy/cigarettes/cigars/havana = 25,
|
||||
)
|
||||
|
||||
/obj/effect/spawner/lootdrop/space_cash
|
||||
lootcount = 1
|
||||
loot = list(
|
||||
/obj/item/stack/spacecash/c1 = 1,
|
||||
/obj/item/stack/spacecash/c10 = 9,
|
||||
/obj/item/stack/spacecash/c20 = 10,
|
||||
/obj/item/stack/spacecash/c50 = 15,
|
||||
/obj/item/stack/spacecash/c100 = 25,
|
||||
/obj/item/stack/spacecash/c200 = 20,
|
||||
/obj/item/stack/spacecash/c500 = 19,
|
||||
/obj/item/stack/spacecash/c1000 = 1,
|
||||
)
|
||||
|
||||
/obj/effect/spawner/lootdrop/druggie_pill
|
||||
lootcount = 1
|
||||
loot = list(
|
||||
/obj/item/reagent_containers/pill/stimulant = 1,
|
||||
/obj/item/reagent_containers/pill/zoom = 9,
|
||||
/obj/item/reagent_containers/pill/happy = 10,
|
||||
/obj/item/reagent_containers/pill/lsd = 15,
|
||||
/obj/item/reagent_containers/pill/aranesp = 25,
|
||||
/obj/item/reagent_containers/pill/psicodine = 20,
|
||||
/obj/item/reagent_containers/pill/mannitol = 19,
|
||||
/obj/item/reagent_containers/pill/happiness = 1,
|
||||
)
|
||||
|
||||
/obj/effect/spawner/lootdrop/low_loot_toilet
|
||||
name = "random low toilet spawner"
|
||||
lootcount = 1
|
||||
//Note this is out of a 100 - Meaning the number you see is also the percent its going to pick that
|
||||
//This is ment for "low" loot that anyone could fine in a toilet, for better gear use high loot toilet
|
||||
loot = list("" = 30,
|
||||
/obj/item/lighter = 2,
|
||||
/obj/item/tape/random = 1,
|
||||
/obj/item/poster/random_contraband = 1,
|
||||
/obj/item/clothing/glasses/sunglasses/blindfold = 4,
|
||||
/obj/item/clothing/glasses/sunglasses = 1,
|
||||
/obj/item/toy/plush/random = 5,
|
||||
/obj/effect/spawner/lootdrop/gloves = 5,
|
||||
/obj/effect/spawner/lootdrop/glowstick = 5,
|
||||
/obj/effect/spawner/lootdrop/coin = 3,
|
||||
/obj/effect/spawner/lootdrop/cig_packs = 10,
|
||||
/obj/effect/spawner/lootdrop/cigars_cases = 2,
|
||||
/obj/effect/spawner/lootdrop/space_cash = 5,
|
||||
/obj/item/reagent_containers/food/snacks/grown/cannabis = 5,
|
||||
/obj/item/storage/pill_bottle/dice = 5,
|
||||
/obj/item/toy/cards/deck = 5,
|
||||
/obj/effect/spawner/lootdrop/druggie_pill = 5
|
||||
)
|
||||
|
||||
/obj/effect/spawner/lootdrop/prison_loot_toilet
|
||||
name = "random prison toilet spawner"
|
||||
lootcount = 1
|
||||
//Note this is out of a 100 - Meaning the number you see is also the percent its going to pick that
|
||||
//This is ment for "prison" loot that is rather rare and ment for "prisoners if they get a crowbar to fine, or sec.
|
||||
loot = list("" = 10,
|
||||
/obj/item/lighter = 5,
|
||||
/obj/item/poster/random_contraband = 5,
|
||||
/obj/item/clothing/glasses/sunglasses = 5,
|
||||
/obj/effect/spawner/lootdrop/coin = 5,
|
||||
/obj/effect/spawner/lootdrop/cig_packs = 10,
|
||||
/obj/effect/spawner/lootdrop/cigars_cases = 5,
|
||||
/obj/item/reagent_containers/food/snacks/grown/cannabis = 5,
|
||||
/obj/item/storage/pill_bottle/dice = 5,
|
||||
/obj/item/toy/cards/deck = 5,
|
||||
/obj/effect/spawner/lootdrop/druggie_pill = 5,
|
||||
/obj/item/kitchen/knife = 5,
|
||||
/obj/item/screwdriver = 5,
|
||||
/obj/item/crowbar/red = 0.5, //Dont you need a crowbar to open this?
|
||||
/obj/item/stack/medical/bruise_pack = 3,
|
||||
/obj/item/reagent_containers/food/drinks/bottle/vodka = 2,
|
||||
/obj/item/radio = 5,
|
||||
/obj/item/flashlight = 4.5,
|
||||
/obj/item/clothing/mask/breath = 2,
|
||||
/obj/item/tank/internals/emergency_oxygen = 3,
|
||||
/obj/item/storage/box/mre/menu4/safe = 3,
|
||||
/obj/item/grenade/smokebomb = 2
|
||||
)
|
||||
|
||||
/obj/effect/spawner/lootdrop/high_loot_toilet
|
||||
name = "random high toilet spawner"
|
||||
lootcount = 1
|
||||
//Note this is out of a 100 - Meaning the number you see is also the percent its going to pick that
|
||||
//The items inside are always going to be something usefull, illegal and likely traitorous.
|
||||
loot = list(
|
||||
/obj/item/clothing/glasses/sunglasses = 5,
|
||||
/obj/effect/spawner/lootdrop/coin = 5,
|
||||
/obj/effect/spawner/lootdrop/space_cash = 5,
|
||||
/obj/effect/spawner/lootdrop/druggie_pill = 5,
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_syndicate = 5,
|
||||
/obj/item/suppressor = 5,
|
||||
/obj/item/toy/cards/deck/syndicate = 5,
|
||||
/obj/item/clothing/under/syndicate = 5,
|
||||
/obj/item/clothing/mask/gas/syndicate = 5,
|
||||
/obj/item/grenade/smokebomb = 10,
|
||||
/obj/item/gun/ballistic/automatic/toy/pistol = 5,
|
||||
/obj/item/firing_pin = 5,
|
||||
/obj/item/grenade/empgrenade = 15,
|
||||
/obj/item/clothing/gloves/combat = 10,
|
||||
/obj/item/clothing/shoes/sneakers/noslip = 10
|
||||
)
|
||||
|
||||
@@ -93,8 +93,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
var/tool_behaviour = NONE
|
||||
var/toolspeed = 1
|
||||
|
||||
var/block_chance = 0
|
||||
var/hit_reaction_chance = 0 //If you want to have something unrelated to blocking/armour piercing etc. Maybe not needed, but trying to think ahead/allow more freedom
|
||||
var/reach = 1 //In tiles, how far this weapon can reach; 1 for adjacent, which is default
|
||||
|
||||
//The list of slots by priority. equip_to_appropriate_slot() uses this list. Doesn't matter if a mob type doesn't have a slot.
|
||||
@@ -365,13 +363,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
|
||||
// afterattack() and attack() prototypes moved to _onclick/item_attack.dm for consistency
|
||||
|
||||
/obj/item/proc/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
SEND_SIGNAL(src, COMSIG_ITEM_HIT_REACT, args)
|
||||
if(prob(final_block_chance))
|
||||
owner.visible_message("<span class='danger'>[owner] blocks [attack_text] with [src]!</span>")
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/proc/talk_into(mob/M, input, channel, spans, datum/language/language)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
|
||||
@@ -464,9 +455,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
/obj/item/proc/ui_action_click(mob/user, actiontype)
|
||||
attack_self(user)
|
||||
|
||||
/obj/item/proc/IsReflect(var/def_zone) //This proc determines if and at what% an object will reflect energy projectiles if it's in l_hand,r_hand or wear_suit
|
||||
return 0
|
||||
|
||||
/obj/item/proc/eyestab(mob/living/carbon/M, mob/living/carbon/user)
|
||||
if(HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
to_chat(user, "<span class='warning'>You don't want to harm [M]!</span>")
|
||||
|
||||
@@ -706,11 +706,11 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
name = "\improper E-Cigarette"
|
||||
desc = "A classy and highly sophisticated electronic cigarette, for classy and dignified gentlemen. A warning label reads \"Warning: Do not fill with flammable materials.\""//<<< i'd vape to that.
|
||||
icon = 'icons/obj/clothing/masks.dmi'
|
||||
icon_state = null
|
||||
item_state = null
|
||||
icon_state = "black_vape"
|
||||
item_state = "black_vape"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
var/chem_volume = 100
|
||||
var/vapetime = FALSE //this so it won't puff out clouds every tick
|
||||
var/vapetime = FALSE //this so it won't puff out clouds every tick
|
||||
var/screw = FALSE // kinky
|
||||
var/super = FALSE //for the fattest vapes dude.
|
||||
|
||||
@@ -723,11 +723,10 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
. = ..()
|
||||
create_reagents(chem_volume, NO_REACT, NO_REAGENTS_VALUE) // so it doesn't react until you light it
|
||||
reagents.add_reagent(/datum/reagent/drug/nicotine, 50)
|
||||
if(!icon_state)
|
||||
if(!param_color)
|
||||
param_color = pick("red","blue","black","white","green","purple","yellow","orange")
|
||||
icon_state = "[param_color]_vape"
|
||||
item_state = "[param_color]_vape"
|
||||
if(!param_color)
|
||||
param_color = pick("red","blue","black","white","green","purple","yellow","orange")
|
||||
icon_state = "[param_color]_vape"
|
||||
item_state = "[param_color]_vape"
|
||||
|
||||
/obj/item/clothing/mask/vape/attackby(obj/item/O, mob/user, params)
|
||||
if(O.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
@@ -1067,4 +1066,4 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
name = "coconut bong"
|
||||
icon_off = "coconut_bong"
|
||||
icon_on = "coconut_bong_lit"
|
||||
desc = "A water bong used for smoking dried plants. This one's made out of a coconut and some bamboo."
|
||||
desc = "A water bong used for smoking dried plants. This one's made out of a coconut and some bamboo."
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
var/recharge_locked = FALSE
|
||||
var/obj/item/stock_parts/micro_laser/diode //used for upgrading!
|
||||
|
||||
|
||||
/obj/item/laser_pointer/red
|
||||
pointer_icon_state = "red_laser"
|
||||
/obj/item/laser_pointer/green
|
||||
@@ -28,6 +27,9 @@
|
||||
/obj/item/laser_pointer/purple
|
||||
pointer_icon_state = "purple_laser"
|
||||
|
||||
/obj/item/laser_pointer/blue/handmade
|
||||
diode = null
|
||||
|
||||
/obj/item/laser_pointer/New()
|
||||
..()
|
||||
diode = new(src)
|
||||
|
||||
@@ -310,11 +310,11 @@ SLIME SCANNER
|
||||
//GENERAL HANDLER
|
||||
if(!damage_message)
|
||||
if(O.organ_flags & ORGAN_FAILING)
|
||||
damage_message += " <span class='alert'><b>End Stage [O.name] failure detected.</b></span>"
|
||||
damage_message += " <span class='alert'><b>Chronic [O.name] failure detected.</b></span>"
|
||||
else if(O.damage > O.high_threshold)
|
||||
damage_message += " <span class='alert'>Chronic [O.name] failure detected.</span>"
|
||||
damage_message += " <span class='alert'>Acute [O.name] failure detected.</span>"
|
||||
else if(O.damage > O.low_threshold && advanced)
|
||||
damage_message += " <font color='red'>Acute [O.name] failure detected.</span>"
|
||||
damage_message += " <font color='red'>Minor [O.name] failure detected.</span>"
|
||||
|
||||
if(temp_message || damage_message)
|
||||
msg += "\t<b><span class='info'>[uppertext(O.name)]:</b></span> [damage_message] [temp_message]\n"
|
||||
|
||||
@@ -234,15 +234,16 @@
|
||||
/obj/item/flamethrower/full/tank
|
||||
create_with_tank = TRUE
|
||||
|
||||
/obj/item/flamethrower/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
var/obj/item/projectile/P = hitby
|
||||
if(damage && attack_type == PROJECTILE_ATTACK && P.damage_type != STAMINA && prob(15))
|
||||
owner.visible_message("<span class='danger'>\The [attack_text] hits the fueltank on [owner]'s [name], rupturing it! What a shot!</span>")
|
||||
var/target_turf = get_turf(owner)
|
||||
igniter.ignite_turf(src,target_turf, release_amount = 100)
|
||||
qdel(ptank)
|
||||
return 1 //It hit the flamethrower, not them
|
||||
|
||||
/obj/item/flamethrower/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(attack_type & ATTACK_TYPE_PROJECTILE)
|
||||
var/obj/item/projectile/P = object
|
||||
if(istype(P) && (P.damage_type != STAMINA) && damage && !P.nodamage && prob(15))
|
||||
owner.visible_message("<span class='danger'>\The [attack_text] hits the fueltank on [owner]'s [name], rupturing it! What a shot!</span>")
|
||||
var/target_turf = get_turf(owner)
|
||||
igniter.ignite_turf(src,target_turf, release_amount = 100)
|
||||
qdel(ptank)
|
||||
return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/igniter/proc/flamethrower_process(turf/open/location)
|
||||
location.hotspot_expose(700,2)
|
||||
|
||||
@@ -115,12 +115,14 @@
|
||||
/obj/item/grenade/attack_paw(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/item/grenade/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
var/obj/item/projectile/P = hitby
|
||||
if(damage && attack_type == PROJECTILE_ATTACK && P.damage_type != STAMINA && prob(15))
|
||||
owner.visible_message("<span class='danger'>[attack_text] hits [owner]'s [src], setting it off! What a shot!</span>")
|
||||
prime()
|
||||
return TRUE //It hit the grenade, not them
|
||||
/obj/item/grenade/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(attack_type & ATTACK_TYPE_PROJECTILE)
|
||||
var/obj/item/projectile/P = object
|
||||
if(damage && !P.nodamage && (P.damage_type != STAMINA) && prob(15))
|
||||
owner.visible_message("<span class='danger'>[attack_text] hits [owner]'s [src], setting it off! What a shot!</span>")
|
||||
prime()
|
||||
return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
|
||||
return ..()
|
||||
|
||||
/obj/item/proc/grenade_prime_react(obj/item/grenade/nade)
|
||||
return
|
||||
|
||||
@@ -328,9 +328,9 @@
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
|
||||
|
||||
/obj/item/nullrod/claymore/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(attack_type == PROJECTILE_ATTACK)
|
||||
final_block_chance = 0 //Don't bring a sword to a gunfight
|
||||
/obj/item/nullrod/claymore/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(attack_type & ATTACK_TYPE_PROJECTILE) // Don't bring a sword to a gunfight
|
||||
return NONE
|
||||
return ..()
|
||||
|
||||
/obj/item/nullrod/claymore/darkblade
|
||||
|
||||
@@ -142,6 +142,7 @@
|
||||
name = "plastic knife"
|
||||
desc = "A plastic knife. Rather harmless to anything."
|
||||
force = 1
|
||||
throwforce = 1
|
||||
bayonet = FALSE
|
||||
|
||||
/obj/item/kitchen/knife/combat/cyborg
|
||||
|
||||
@@ -113,10 +113,10 @@
|
||||
else
|
||||
RemoveElement(/datum/element/sword_point)
|
||||
|
||||
/obj/item/melee/transforming/energy/sword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(active)
|
||||
return ..()
|
||||
return 0
|
||||
/obj/item/melee/transforming/energy/sword/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(!active)
|
||||
return NONE
|
||||
return ..()
|
||||
|
||||
/obj/item/melee/transforming/energy/sword/cyborg
|
||||
item_color = "red"
|
||||
@@ -148,8 +148,8 @@
|
||||
tool_behaviour = TOOL_SAW
|
||||
toolspeed = 0.7
|
||||
|
||||
/obj/item/melee/transforming/energy/sword/cyborg/saw/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
return 0
|
||||
/obj/item/melee/transforming/energy/sword/cyborg/saw/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
return NONE
|
||||
|
||||
/obj/item/melee/transforming/energy/sword/saber
|
||||
var/list/possible_colors = list("red" = LIGHT_COLOR_RED, "blue" = LIGHT_COLOR_LIGHT_CYAN, "green" = LIGHT_COLOR_GREEN, "purple" = LIGHT_COLOR_LAVENDER)
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
item_flags = NEEDS_PERMIT
|
||||
|
||||
/obj/item/melee/proc/check_martial_counter(mob/living/carbon/human/target, mob/living/carbon/human/user)
|
||||
if(target.check_block())
|
||||
if(target.check_martial_melee_block())
|
||||
target.visible_message("<span class='danger'>[target.name] blocks [src] and twists [user]'s arm behind [user.p_their()] back!</span>",
|
||||
"<span class='userdanger'>You block the attack!</span>")
|
||||
user.Stun(40)
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/melee/chainofcommand
|
||||
name = "chain of command"
|
||||
desc = "A tool used by great men to placate the frothing masses."
|
||||
@@ -75,9 +74,9 @@
|
||||
AddComponent(/datum/component/butchering, 30, 95, 5) //fast and effective, but as a sword, it might damage the results.
|
||||
AddElement(/datum/element/sword_point)
|
||||
|
||||
/obj/item/melee/sabre/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(attack_type == PROJECTILE_ATTACK)
|
||||
final_block_chance = 0 //Don't bring a sword to a gunfight
|
||||
/obj/item/melee/sabre/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(attack_type & ATTACK_TYPE_PROJECTILE) // Don't bring a sword to a gunfight.
|
||||
return BLOCK_NONE
|
||||
return ..()
|
||||
|
||||
/obj/item/melee/sabre/on_exit_storage(datum/component/storage/S)
|
||||
@@ -165,8 +164,8 @@
|
||||
. = ..()
|
||||
AddComponent(/datum/component/butchering, 20, 65, 0)
|
||||
|
||||
/obj/item/melee/rapier/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(attack_type == PROJECTILE_ATTACK)
|
||||
/obj/item/melee/rapier/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(attack_type == ATTACK_TYPE_PROJECTILE)
|
||||
final_block_chance = 0
|
||||
return ..()
|
||||
|
||||
@@ -305,7 +304,7 @@
|
||||
return
|
||||
else
|
||||
if(cooldown_check < world.time)
|
||||
if(target.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
|
||||
if(target.run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user) & BLOCK_SUCCESS)
|
||||
playsound(target, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
return
|
||||
if(ishuman(target))
|
||||
|
||||
@@ -434,7 +434,15 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths())
|
||||
can_random_spawn = FALSE
|
||||
|
||||
/obj/item/toy/plush/random/Initialize()
|
||||
var/newtype = prob(CONFIG_GET(number/snowflake_plushie_prob))? /obj/item/toy/plush/random_snowflake : pick(GLOB.valid_plushie_paths)
|
||||
var/newtype
|
||||
var/list/snowflake_list = CONFIG_GET(keyed_list/snowflake_plushies)
|
||||
|
||||
/// If there are no snowflake plushies we'll default to base plush, so we grab from the valid list
|
||||
if (snowflake_list.len)
|
||||
newtype = prob(CONFIG_GET(number/snowflake_plushie_prob)) ? /obj/item/toy/plush/random_snowflake : pick(GLOB.valid_plushie_paths)
|
||||
else
|
||||
newtype = pick(GLOB.valid_plushie_paths)
|
||||
|
||||
new newtype(loc)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
var/charge_cost = 30
|
||||
|
||||
/obj/item/borg/stun/attack(mob/living/M, mob/living/user)
|
||||
if(M.check_shields(src, 0, "[M]'s [name]", MELEE_ATTACK))
|
||||
if(M.run_block(src, 0, "[M]'s [name]", ATTACK_TYPE_MELEE, 0, user, ran_zone(user.zone_selected)) & BLOCK_SUCCESS)
|
||||
playsound(M, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
return FALSE
|
||||
if(iscyborg(user))
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 70)
|
||||
var/transparent = FALSE // makes beam projectiles pass through the shield
|
||||
|
||||
/obj/item/shield/proc/on_shield_block(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0, attack_type = MELEE_ATTACK)
|
||||
/obj/item/shield/proc/on_shield_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance)
|
||||
return TRUE
|
||||
|
||||
/obj/item/shield/riot
|
||||
@@ -26,16 +26,18 @@
|
||||
transparent = TRUE
|
||||
max_integrity = 75
|
||||
|
||||
/obj/item/shield/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(transparent && (hitby.pass_flags & PASSGLASS))
|
||||
return FALSE
|
||||
if(attack_type == THROWN_PROJECTILE_ATTACK)
|
||||
/obj/item/shield/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(ismovableatom(object))
|
||||
var/atom/movable/AM = object
|
||||
if(transparent && (AM.pass_flags & PASSGLASS))
|
||||
return BLOCK_NONE
|
||||
if(attack_type & ATTACK_TYPE_THROWN)
|
||||
final_block_chance += 30
|
||||
if(attack_type == LEAP_ATTACK)
|
||||
if(attack_type & ATTACK_TYPE_TACKLE)
|
||||
final_block_chance = 100
|
||||
. = ..()
|
||||
if(.)
|
||||
on_shield_block(owner, hitby, attack_text, damage, attack_type)
|
||||
if(. & BLOCK_SUCCESS)
|
||||
on_shield_block(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
|
||||
|
||||
/obj/item/shield/riot/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/melee/baton))
|
||||
@@ -69,10 +71,10 @@
|
||||
playsound(owner, 'sound/effects/glassbr3.ogg', 100)
|
||||
new /obj/item/shard((get_turf(src)))
|
||||
|
||||
/obj/item/shield/riot/on_shield_block(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0, attack_type = MELEE_ATTACK)
|
||||
/obj/item/shield/riot/on_shield_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(obj_integrity <= damage)
|
||||
var/turf/T = get_turf(owner)
|
||||
T.visible_message("<span class='warning'>[hitby] destroys [src]!</span>")
|
||||
T.visible_message("<span class='warning'>[attack_text] destroys [src]!</span>")
|
||||
shatter(owner)
|
||||
qdel(src)
|
||||
return FALSE
|
||||
@@ -139,11 +141,11 @@
|
||||
. = ..()
|
||||
icon_state = "[base_icon_state]0"
|
||||
|
||||
/obj/item/shield/energy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
return 0
|
||||
|
||||
/obj/item/shield/energy/IsReflect()
|
||||
return (active)
|
||||
/obj/item/shield/energy/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if((attack_type & ATTACK_TYPE_PROJECTILE) && is_energy_reflectable_projectile(object))
|
||||
block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_DEFLECT
|
||||
return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT
|
||||
return ..()
|
||||
|
||||
/obj/item/shield/energy/attack_self(mob/living/carbon/human/user)
|
||||
if(clumsy_check && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
|
||||
@@ -182,10 +184,10 @@
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
var/active = 0
|
||||
|
||||
/obj/item/shield/riot/tele/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(active)
|
||||
return ..()
|
||||
return 0
|
||||
/obj/item/shield/riot/tele/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(!active)
|
||||
return BLOCK_NONE
|
||||
return ..()
|
||||
|
||||
/obj/item/shield/riot/tele/attack_self(mob/living/user)
|
||||
active = !active
|
||||
@@ -249,7 +251,7 @@
|
||||
transparent = FALSE
|
||||
item_flags = SLOWS_WHILE_IN_HAND
|
||||
|
||||
/obj/item/shield/riot/implant/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(attack_type == PROJECTILE_ATTACK)
|
||||
/obj/item/shield/riot/implant/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(attack_type & ATTACK_TYPE_PROJECTILE)
|
||||
final_block_chance = 60 //Massive shield
|
||||
return ..()
|
||||
|
||||
@@ -22,6 +22,8 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
|
||||
new/datum/stack_recipe("spout flask", /obj/item/glasswork/glass_base/spouty, 20), \
|
||||
new/datum/stack_recipe("small bulb flask", /obj/item/glasswork/glass_base/flask_small, 5), \
|
||||
new/datum/stack_recipe("large bottle flask", /obj/item/glasswork/glass_base/flask_large, 15), \
|
||||
new/datum/stack_recipe("tea cup", /obj/item/glasswork/glass_base/tea_plate, 5), \
|
||||
new/datum/stack_recipe("tea plate", /obj/item/glasswork/glass_base/tea_cup, 5), \
|
||||
)), \
|
||||
))
|
||||
|
||||
@@ -137,7 +139,7 @@ GLOBAL_LIST_INIT(pglass_recipes, list ( \
|
||||
return ..()
|
||||
|
||||
/obj/item/stack/sheet/plasmaglass/on_solar_construction(obj/machinery/power/solar/S)
|
||||
S.obj_integrity *= 1.2
|
||||
S.max_integrity *= 1.2
|
||||
S.efficiency *= 1.2
|
||||
|
||||
/*
|
||||
@@ -170,7 +172,7 @@ GLOBAL_LIST_INIT(reinforced_glass_recipes, list ( \
|
||||
..()
|
||||
|
||||
/obj/item/stack/sheet/rglass/on_solar_construction(obj/machinery/power/solar/S)
|
||||
S.obj_integrity *= 2
|
||||
S.max_integrity *= 2
|
||||
|
||||
/obj/item/stack/sheet/rglass/cyborg
|
||||
custom_materials = null
|
||||
@@ -218,7 +220,7 @@ GLOBAL_LIST_INIT(prglass_recipes, list ( \
|
||||
. += GLOB.prglass_recipes
|
||||
|
||||
/obj/item/stack/sheet/plasmarglass/on_solar_construction(obj/machinery/power/solar/S)
|
||||
S.obj_integrity *= 2.2
|
||||
S.max_integrity *= 2.2
|
||||
S.efficiency *= 1.2
|
||||
|
||||
GLOBAL_LIST_INIT(titaniumglass_recipes, list(
|
||||
@@ -242,7 +244,7 @@ GLOBAL_LIST_INIT(titaniumglass_recipes, list(
|
||||
. += GLOB.titaniumglass_recipes
|
||||
|
||||
/obj/item/stack/sheet/titaniumglass/on_solar_construction(obj/machinery/power/solar/S)
|
||||
S.obj_integrity *= 2.5
|
||||
S.max_integrity *= 2.5
|
||||
S.efficiency *= 1.5
|
||||
|
||||
GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
|
||||
@@ -270,7 +272,7 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
|
||||
. += GLOB.plastitaniumglass_recipes
|
||||
|
||||
/obj/item/stack/sheet/titaniumglass/on_solar_construction(obj/machinery/power/solar/S)
|
||||
S.obj_integrity *= 2
|
||||
S.max_integrity *= 2
|
||||
S.efficiency *= 2
|
||||
|
||||
/obj/item/shard
|
||||
|
||||
@@ -368,6 +368,7 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
|
||||
new/datum/stack_recipe("towel", /obj/item/reagent_containers/rag/towel, 3), \
|
||||
new/datum/stack_recipe("bedsheet", /obj/item/bedsheet, 3), \
|
||||
new/datum/stack_recipe("empty sandbag", /obj/item/emptysandbag, 4), \
|
||||
new/datum/stack_recipe("padded floor tile", /obj/item/stack/tile/padded, 1, 4, 20), \
|
||||
null, \
|
||||
new/datum/stack_recipe("fingerless gloves", /obj/item/clothing/gloves/fingerless, 1),\
|
||||
new/datum/stack_recipe("white gloves", /obj/item/clothing/gloves/color/white, 1),\
|
||||
@@ -768,6 +769,7 @@ GLOBAL_LIST_INIT(plastic_recipes, list(
|
||||
new /datum/stack_recipe("water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/empty), \
|
||||
new /datum/stack_recipe("large water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/large/empty,3), \
|
||||
new /datum/stack_recipe("shower curtain", /obj/structure/curtain, 10, time = 10, one_per_turf = 1, on_floor = 1), \
|
||||
new /datum/stack_recipe("laser pointer case", /obj/item/glasswork/glass_base/laserpointer_shell, 30), \
|
||||
new /datum/stack_recipe("wet floor sign", /obj/item/caution, 2)))
|
||||
|
||||
/obj/item/stack/sheet/plastic
|
||||
|
||||
@@ -142,6 +142,14 @@
|
||||
turf_type = /turf/open/floor/wood
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
//Cloth Floors
|
||||
|
||||
/obj/item/stack/tile/padded
|
||||
name = "padded floor tile"
|
||||
desc = "These are soft and cushy, they'd make good pillows. They look very comfortable, although what they're used for is discomforting."
|
||||
icon_state = "tile_padded"
|
||||
turf_type = /turf/open/floor/padded
|
||||
|
||||
//Basalt
|
||||
/obj/item/stack/tile/basalt
|
||||
name = "basalt tile"
|
||||
|
||||
@@ -804,3 +804,4 @@
|
||||
attack_verb = list("bashed", "slashes", "prods", "pokes")
|
||||
fitting_swords = list(/obj/item/melee/rapier)
|
||||
starting_sword = /obj/item/melee/rapier
|
||||
|
||||
|
||||
@@ -404,6 +404,12 @@
|
||||
new /obj/item/gun/ballistic/revolver(src)
|
||||
new /obj/item/ammo_box/a357(src)
|
||||
|
||||
/obj/item/storage/box/syndie_kit/pistol
|
||||
|
||||
/obj/item/storage/box/syndie_kit/pistol/PopulateContents()
|
||||
new /obj/item/gun/ballistic/automatic/pistol(src)
|
||||
new /obj/item/ammo_box/magazine/m10mm(src)
|
||||
|
||||
/obj/item/storage/box/syndie_kit/contract_kit
|
||||
name = "contractor kit"
|
||||
desc = "Supplied to Syndicate contractors in active mission areas."
|
||||
@@ -494,4 +500,4 @@
|
||||
new item1(src) // Create three, non repeat items from the list.
|
||||
new item2(src)
|
||||
new item3(src)
|
||||
new /obj/item/paper/contractor_guide(src) //Paper guide
|
||||
new /obj/item/paper/contractor_guide(src) //Paper guide
|
||||
|
||||
@@ -170,7 +170,7 @@
|
||||
return disarming || (user.a_intent != INTENT_HARM)
|
||||
|
||||
/obj/item/melee/baton/proc/baton_stun(mob/living/L, mob/user, disarming = FALSE)
|
||||
if(L.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that
|
||||
if(L.run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user) & BLOCK_SUCCESS) //No message; check_shields() handles that
|
||||
playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
return FALSE
|
||||
var/stunpwr = stamforce
|
||||
|
||||
@@ -454,11 +454,8 @@
|
||||
total_mass_on = TOTAL_MASS_TOY_SWORD
|
||||
sharpness = IS_BLUNT
|
||||
|
||||
/obj/item/twohanded/dualsaber/toy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
return FALSE
|
||||
|
||||
/obj/item/twohanded/dualsaber/toy/IsReflect()//Stops Toy Dualsabers from reflecting energy projectiles
|
||||
return FALSE
|
||||
/obj/item/twohanded/dualsaber/toy/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
return BLOCK_NONE
|
||||
|
||||
/obj/item/twohanded/dualsaber/hypereutactic/toy
|
||||
name = "\improper DX Hyper-Euplastic LightSword"
|
||||
@@ -474,11 +471,8 @@
|
||||
slowdown_wielded = 0
|
||||
sharpness = IS_BLUNT
|
||||
|
||||
/obj/item/twohanded/dualsaber/hypereutactic/toy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
return FALSE
|
||||
|
||||
/obj/item/twohanded/dualsaber/hypereutactic/toy/IsReflect()//Stops it from reflecting energy projectiles
|
||||
return FALSE
|
||||
/obj/item/twohanded/dualsaber/hypereutactic/toy/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
return BLOCK_NONE
|
||||
|
||||
/obj/item/twohanded/dualsaber/hypereutactic/toy/rainbow
|
||||
name = "\improper Hyper-Euclidean Reciprocating Trigonometric Zweihander"
|
||||
|
||||
@@ -289,6 +289,8 @@
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 70)
|
||||
resistance_flags = FIRE_PROOF
|
||||
var/hacked = FALSE
|
||||
/// Can this reflect all energy projectiles?
|
||||
var/can_reflect = TRUE
|
||||
var/brightness_on = 6 //TWICE AS BRIGHT AS A REGULAR ESWORD
|
||||
var/list/possible_colors = list("red", "blue", "green", "purple")
|
||||
var/list/rainbow_colors = list(LIGHT_COLOR_RED, LIGHT_COLOR_GREEN, LIGHT_COLOR_LIGHT_CYAN, LIGHT_COLOR_LAVENDER)
|
||||
@@ -373,10 +375,13 @@
|
||||
else
|
||||
user.adjustStaminaLoss(25)
|
||||
|
||||
/obj/item/twohanded/dualsaber/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(wielded)
|
||||
return ..()
|
||||
return 0
|
||||
/obj/item/twohanded/dualsaber/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(!wielded)
|
||||
return NONE
|
||||
if(can_reflect && is_energy_reflectable_projectile(object) && (attack_type & ATTACK_TYPE_PROJECTILE))
|
||||
block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_RETURN_TO_SENDER //no you
|
||||
return BLOCK_SHOULD_REDIRECT | BLOCK_SUCCESS | BLOCK_REDIRECTED
|
||||
return ..()
|
||||
|
||||
/obj/item/twohanded/dualsaber/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0) //In case thats just so happens that it is still activated on the groud, prevents hulk from picking it up
|
||||
if(wielded)
|
||||
@@ -419,10 +424,6 @@
|
||||
/obj/item/twohanded/dualsaber/proc/rainbow_process()
|
||||
light_color = pick(rainbow_colors)
|
||||
|
||||
/obj/item/twohanded/dualsaber/IsReflect()
|
||||
if(wielded)
|
||||
return 1
|
||||
|
||||
/obj/item/twohanded/dualsaber/ignition_effect(atom/A, mob/user)
|
||||
// same as /obj/item/melee/transforming/energy, mostly
|
||||
if(!wielded)
|
||||
@@ -560,15 +561,13 @@
|
||||
block_chance = 50
|
||||
armour_penetration = 0
|
||||
var/chaplain_spawnable = TRUE
|
||||
can_reflect = FALSE
|
||||
obj_flags = UNIQUE_RENAME
|
||||
|
||||
/obj/item/twohanded/dualsaber/hypereutactic/chaplain/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE)
|
||||
|
||||
/obj/item/twohanded/dualsaber/hypereutactic/chaplain/IsReflect()
|
||||
return FALSE
|
||||
|
||||
//spears
|
||||
/obj/item/twohanded/spear
|
||||
icon_state = "spearglass0"
|
||||
@@ -752,12 +751,16 @@
|
||||
armour_penetration = 100
|
||||
force_on = 30
|
||||
|
||||
/obj/item/twohanded/required/chainsaw/doomslayer/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(attack_type == PROJECTILE_ATTACK)
|
||||
/obj/item/twohanded/required/chainsaw/doomslayer/check_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
block_return[BLOCK_RETURN_REFLECT_PROJECTILE_CHANCE] = 100
|
||||
return ..()
|
||||
|
||||
/obj/item/twohanded/required/chainsaw/doomslayer/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(attack_type & ATTACK_TYPE_PROJECTILE)
|
||||
owner.visible_message("<span class='danger'>Ranged attacks just make [owner] angrier!</span>")
|
||||
playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1)
|
||||
return 1
|
||||
return 0
|
||||
return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
|
||||
return ..()
|
||||
|
||||
//GREY TIDE
|
||||
/obj/item/twohanded/spear/grey_tide
|
||||
@@ -897,19 +900,20 @@
|
||||
AddComponent(/datum/component/butchering, 20, 105)
|
||||
AddElement(/datum/element/sword_point)
|
||||
|
||||
/obj/item/twohanded/vibro_weapon/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
/obj/item/twohanded/vibro_weapon/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(wielded)
|
||||
final_block_chance *= 2
|
||||
if(wielded || attack_type != PROJECTILE_ATTACK)
|
||||
if(wielded || !(attack_type & ATTACK_TYPE_PROJECTILE))
|
||||
if(prob(final_block_chance))
|
||||
if(attack_type == PROJECTILE_ATTACK)
|
||||
if(attack_type & ATTACK_TYPE_PROJECTILE)
|
||||
owner.visible_message("<span class='danger'>[owner] deflects [attack_text] with [src]!</span>")
|
||||
playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1)
|
||||
return 1
|
||||
block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_DEFLECT
|
||||
return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_EXTERNAL
|
||||
else
|
||||
owner.visible_message("<span class='danger'>[owner] parries [attack_text] with [src]!</span>")
|
||||
return 1
|
||||
return 0
|
||||
return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
|
||||
return NONE
|
||||
|
||||
/obj/item/twohanded/vibro_weapon/update_icon_state()
|
||||
icon_state = "hfrequency[wielded]"
|
||||
@@ -1055,11 +1059,9 @@
|
||||
var/mob/living/silicon/robot/R = loc
|
||||
. = R.get_cell()
|
||||
|
||||
/obj/item/twohanded/electrostaff/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(!on)
|
||||
return FALSE
|
||||
if((attack_type == PROJECTILE_ATTACK) && !can_block_projectiles)
|
||||
return FALSE
|
||||
/obj/item/twohanded/electrostaff/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(!on || (!can_block_projectiles && (attack_type & ATTACK_TYPE_PROJECTILE)))
|
||||
return BLOCK_NONE
|
||||
return ..()
|
||||
|
||||
/obj/item/twohanded/electrostaff/proc/min_hitcost()
|
||||
@@ -1180,7 +1182,7 @@
|
||||
if(iscyborg(target))
|
||||
..()
|
||||
return
|
||||
if(target.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that
|
||||
if(target.run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user) & BLOCK_SUCCESS) //No message; run_block() handles that
|
||||
playsound(target, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
return FALSE
|
||||
if(user.a_intent != INTENT_HARM)
|
||||
|
||||
@@ -84,6 +84,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
name = "purified longsword"
|
||||
desc = "A hastily-purified longsword. While not as holy as it could be, it's still a formidable weapon against those who would rather see you dead."
|
||||
force = 25
|
||||
block_chance = 0
|
||||
|
||||
/obj/item/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS
|
||||
desc = "<b><i>THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!</i></b>\nActivate it in your hand to point to the nearest victim."
|
||||
@@ -155,8 +156,10 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
return
|
||||
to_chat(user, "<span class='danger'>[src] thrums and points to the [dir2text(get_dir(user, closest_victim))].</span>")
|
||||
|
||||
/obj/item/claymore/highlander/IsReflect()
|
||||
return 1 //YOU THINK YOUR PUNY LASERS CAN STOP ME?
|
||||
/obj/item/claymore/highlander/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if((attack_type & ATTACK_TYPE_PROJECTILE) && is_energy_reflectable_projectile(object))
|
||||
return BLOCK_SUCCESS | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_EXTERNAL | BLOCK_REDIRECTED
|
||||
return ..()
|
||||
|
||||
/obj/item/claymore/highlander/proc/add_notch(mob/living/user) //DYNAMIC CLAYMORE PROGRESSION SYSTEM - THIS IS THE FUTURE
|
||||
notches++
|
||||
@@ -607,14 +610,13 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
force = 12
|
||||
throwforce = 15
|
||||
|
||||
/obj/item/melee/baseball_bat/ablative/IsReflect()//some day this will reflect thrown items instead of lasers
|
||||
var/picksound = rand(1,2)
|
||||
var/turf = get_turf(src)
|
||||
if(picksound == 1)
|
||||
playsound(turf, 'sound/weapons/effects/batreflect1.ogg', 50, 1)
|
||||
if(picksound == 2)
|
||||
playsound(turf, 'sound/weapons/effects/batreflect2.ogg', 50, 1)
|
||||
return 1
|
||||
/obj/item/melee/baseball_bat/ablative/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
//some day this will reflect thrown items instead of lasers
|
||||
if(is_energy_reflectable_projectile(object) && (attack_type == ATTACK_TYPE_PROJECTILE))
|
||||
var/turf = get_turf(src)
|
||||
playsound(turf, pick('sound/weapons/effects/batreflect1.ogg', 'sound/weapons/effects/batreflect2.ogg'), 50, 1)
|
||||
return BLOCK_SUCCESS | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_EXTERNAL | BLOCK_REDIRECTED
|
||||
return ..()
|
||||
|
||||
/obj/item/melee/baseball_bat/ablative/syndi
|
||||
name = "syndicate major league bat"
|
||||
|
||||
@@ -317,7 +317,7 @@
|
||||
throwforce = 10
|
||||
throw_range = 3
|
||||
hitsound = 'sound/items/trayhit1.ogg'
|
||||
hit_reaction_chance = 50
|
||||
block_chance = 50
|
||||
custom_materials = list(/datum/material/iron = 2000)
|
||||
var/break_chance = 5 //Likely hood of smashing the chair.
|
||||
var/obj/structure/chair/origin_type = /obj/structure/chair
|
||||
@@ -362,18 +362,17 @@
|
||||
new stack_type(get_turf(loc))
|
||||
qdel(src)
|
||||
|
||||
/obj/item/chair/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(attack_type == UNARMED_ATTACK && prob(hit_reaction_chance))
|
||||
owner.visible_message("<span class='danger'>[owner] fends off [attack_text] with [src]!</span>")
|
||||
return 1
|
||||
return 0
|
||||
/obj/item/chair/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(!(attack_type & ATTACK_TYPE_UNARMED))
|
||||
return NONE
|
||||
return ..()
|
||||
|
||||
/obj/item/chair/afterattack(atom/target, mob/living/carbon/user, proximity)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
if(prob(break_chance))
|
||||
user.visible_message("<span class='danger'>[user] smashes \the [src] to pieces against \the [target]</span>")
|
||||
user.visible_message("<span class='danger'>[user] smashes [src] to pieces against [target]</span>")
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/C = target
|
||||
if(C.health < C.maxHealth*0.5)
|
||||
|
||||
@@ -1,383 +0,0 @@
|
||||
|
||||
#define MUSICIAN_HEARCHECK_MINDELAY 4
|
||||
#define MUSIC_MAXLINES 600
|
||||
#define MUSIC_MAXLINECHARS 150
|
||||
|
||||
/datum/song
|
||||
var/name = "Untitled"
|
||||
var/list/lines = new()
|
||||
var/tempo = 5 // delay between notes
|
||||
|
||||
var/playing = 0 // if we're playing
|
||||
var/help = 0 // if help is open
|
||||
var/edit = 1 // if we're in editing mode
|
||||
var/repeat = 0 // number of times remaining to repeat
|
||||
var/max_repeats = 10 // maximum times we can repeat
|
||||
|
||||
var/instrumentDir = "piano" // the folder with the sounds
|
||||
var/instrumentExt = "ogg" // the file extension
|
||||
var/obj/instrumentObj = null // the associated obj playing the sound
|
||||
var/last_hearcheck = 0
|
||||
var/list/hearing_mobs
|
||||
|
||||
/datum/song/New(dir, obj, ext = "ogg")
|
||||
tempo = sanitize_tempo(tempo)
|
||||
instrumentDir = dir
|
||||
instrumentObj = obj
|
||||
instrumentExt = ext
|
||||
|
||||
/datum/song/Destroy()
|
||||
instrumentObj = null
|
||||
return ..()
|
||||
|
||||
// note is a number from 1-7 for A-G
|
||||
// acc is either "b", "n", or "#"
|
||||
// oct is 1-8 (or 9 for C)
|
||||
/datum/song/proc/playnote(note, acc as text, oct)
|
||||
// handle accidental -> B<>C of E<>F
|
||||
if(acc == "b" && (note == 3 || note == 6)) // C or F
|
||||
if(note == 3)
|
||||
oct--
|
||||
note--
|
||||
acc = "n"
|
||||
else if(acc == "#" && (note == 2 || note == 5)) // B or E
|
||||
if(note == 2)
|
||||
oct++
|
||||
note++
|
||||
acc = "n"
|
||||
else if(acc == "#" && (note == 7)) //G#
|
||||
note = 1
|
||||
acc = "b"
|
||||
else if(acc == "#") // mass convert all sharps to flats, octave jump already handled
|
||||
acc = "b"
|
||||
note++
|
||||
|
||||
// check octave, C is allowed to go to 9
|
||||
if(oct < 1 || (note == 3 ? oct > 9 : oct > 8))
|
||||
return
|
||||
|
||||
// now generate name
|
||||
var/soundfile = "sound/instruments/[instrumentDir]/[ascii2text(note+64)][acc][oct].[instrumentExt]"
|
||||
soundfile = file(soundfile)
|
||||
// make sure the note exists
|
||||
if(!fexists(soundfile))
|
||||
return
|
||||
// and play
|
||||
var/turf/source = get_turf(instrumentObj)
|
||||
if((world.time - MUSICIAN_HEARCHECK_MINDELAY) > last_hearcheck)
|
||||
LAZYCLEARLIST(hearing_mobs)
|
||||
for(var/mob/M in get_hearers_in_view(15, source))
|
||||
if(!M.client || !(M.client.prefs.toggles & SOUND_INSTRUMENTS))
|
||||
continue
|
||||
LAZYADD(hearing_mobs, M)
|
||||
last_hearcheck = world.time
|
||||
|
||||
var/sound/music_played = sound(soundfile)
|
||||
for(var/i in hearing_mobs)
|
||||
var/mob/M = i
|
||||
M.playsound_local(source, null, 100, falloff = 5, S = music_played)
|
||||
|
||||
/datum/song/proc/updateDialog(mob/user)
|
||||
instrumentObj.updateDialog() // assumes it's an object in world, override if otherwise
|
||||
|
||||
/datum/song/proc/shouldStopPlaying(mob/user)
|
||||
if(instrumentObj)
|
||||
if(!user.canUseTopic(instrumentObj, TRUE, FALSE, FALSE, FALSE))
|
||||
return TRUE
|
||||
return !instrumentObj.anchored // add special cases to stop in subclasses
|
||||
else
|
||||
return TRUE
|
||||
|
||||
/datum/song/proc/playsong(mob/user)
|
||||
while(repeat >= 0)
|
||||
var/cur_oct[7]
|
||||
var/cur_acc[7]
|
||||
for(var/i = 1 to 7)
|
||||
cur_oct[i] = 3
|
||||
cur_acc[i] = "n"
|
||||
|
||||
for(var/line in lines)
|
||||
for(var/beat in splittext(lowertext(line), ","))
|
||||
var/list/notes = splittext(beat, "/")
|
||||
for(var/note in splittext(notes[1], "-"))
|
||||
if(!playing || shouldStopPlaying(user))//If the instrument is playing, or special case
|
||||
playing = FALSE
|
||||
hearing_mobs = null
|
||||
return
|
||||
if(!length(note))
|
||||
continue
|
||||
var/cur_note = text2ascii(note) - 96
|
||||
if(cur_note < 1 || cur_note > 7)
|
||||
continue
|
||||
var/notelen = length(note)
|
||||
var/ni = ""
|
||||
for(var/i = length(note[1]) + 1, i <= notelen, i += length(ni))
|
||||
ni = note[i]
|
||||
if(!text2num(ni))
|
||||
if(ni == "#" || ni == "b" || ni == "n")
|
||||
cur_acc[cur_note] = ni
|
||||
else if(ni == "s")
|
||||
cur_acc[cur_note] = "#" // so shift is never required
|
||||
else
|
||||
cur_oct[cur_note] = text2num(ni)
|
||||
if(user.dizziness > 0 && prob(user.dizziness / 2))
|
||||
cur_note = CLAMP(cur_note + rand(round(-user.dizziness / 10), round(user.dizziness / 10)), 1, 7)
|
||||
if(user.dizziness > 0 && prob(user.dizziness / 5))
|
||||
if(prob(30))
|
||||
cur_acc[cur_note] = "#"
|
||||
else if(prob(42))
|
||||
cur_acc[cur_note] = "b"
|
||||
else if(prob(75))
|
||||
cur_acc[cur_note] = "n"
|
||||
playnote(cur_note, cur_acc[cur_note], cur_oct[cur_note])
|
||||
if(notes.len >= 2 && text2num(notes[2]))
|
||||
sleep(sanitize_tempo(tempo / text2num(notes[2])))
|
||||
else
|
||||
sleep(tempo)
|
||||
repeat--
|
||||
hearing_mobs = null
|
||||
playing = FALSE
|
||||
repeat = 0
|
||||
updateDialog(user)
|
||||
|
||||
/datum/song/proc/interact(mob/user)
|
||||
var/dat = ""
|
||||
|
||||
if(lines.len > 0)
|
||||
dat += "<H3>Playback</H3>"
|
||||
if(!playing)
|
||||
dat += "<A href='?src=[REF(src)];play=1'>Play</A> <SPAN CLASS='linkOn'>Stop</SPAN><BR><BR>"
|
||||
dat += "Repeat Song: "
|
||||
dat += repeat > 0 ? "<A href='?src=[REF(src)];repeat=-10'>-</A><A href='?src=[REF(src)];repeat=-1'>-</A>" : "<SPAN CLASS='linkOff'>-</SPAN><SPAN CLASS='linkOff'>-</SPAN>"
|
||||
dat += " [repeat] times "
|
||||
dat += repeat < max_repeats ? "<A href='?src=[REF(src)];repeat=1'>+</A><A href='?src=[REF(src)];repeat=10'>+</A>" : "<SPAN CLASS='linkOff'>+</SPAN><SPAN CLASS='linkOff'>+</SPAN>"
|
||||
dat += "<BR>"
|
||||
else
|
||||
dat += "<SPAN CLASS='linkOn'>Play</SPAN> <A href='?src=[REF(src)];stop=1'>Stop</A><BR>"
|
||||
dat += "Repeats left: <B>[repeat]</B><BR>"
|
||||
if(!edit)
|
||||
dat += "<BR><B><A href='?src=[REF(src)];edit=2'>Show Editor</A></B><BR>"
|
||||
else
|
||||
dat += "<H3>Editing</H3>"
|
||||
dat += "<B><A href='?src=[REF(src)];edit=1'>Hide Editor</A></B>"
|
||||
dat += " <A href='?src=[REF(src)];newsong=1'>Start a New Song</A>"
|
||||
dat += " <A href='?src=[REF(src)];import=1'>Import a Song</A><BR><BR>"
|
||||
var/bpm = round(600 / tempo)
|
||||
dat += "Tempo: <A href='?src=[REF(src)];tempo=[world.tick_lag]'>-</A> [bpm] BPM <A href='?src=[REF(src)];tempo=-[world.tick_lag]'>+</A><BR><BR>"
|
||||
var/linecount = 0
|
||||
for(var/line in lines)
|
||||
linecount += 1
|
||||
dat += "Line [linecount]: <A href='?src=[REF(src)];modifyline=[linecount]'>Edit</A> <A href='?src=[REF(src)];deleteline=[linecount]'>X</A> [line]<BR>"
|
||||
dat += "<A href='?src=[REF(src)];newline=1'>Add Line</A><BR><BR>"
|
||||
if(help)
|
||||
dat += "<B><A href='?src=[REF(src)];help=1'>Hide Help</A></B><BR>"
|
||||
dat += {"
|
||||
Lines are a series of chords, separated by commas (,), each with notes separated by hyphens (-).<br>
|
||||
Every note in a chord will play together, with chord timed by the tempo.<br>
|
||||
<br>
|
||||
Notes are played by the names of the note, and optionally, the accidental, and/or the octave number.<br>
|
||||
By default, every note is natural and in octave 3. Defining otherwise is remembered for each note.<br>
|
||||
Example: <i>C,D,E,F,G,A,B</i> will play a C major scale.<br>
|
||||
After a note has an accidental placed, it will be remembered: <i>C,C4,C,C3</i> is <i>C3,C4,C4,C3</i><br>
|
||||
Chords can be played simply by seperating each note with a hyphon: <i>A-C#,Cn-E,E-G#,Gn-B</i><br>
|
||||
A pause may be denoted by an empty chord: <i>C,E,,C,G</i><br>
|
||||
To make a chord be a different time, end it with /x, where the chord length will be length<br>
|
||||
defined by tempo / x: <i>C,G/2,E/4</i><br>
|
||||
Combined, an example is: <i>E-E4/4,F#/2,G#/8,B/8,E3-E4/4</i>
|
||||
<br>
|
||||
Lines may be up to [MUSIC_MAXLINECHARS] characters.<br>
|
||||
A song may only contain up to [MUSIC_MAXLINES] lines.<br>
|
||||
"}
|
||||
else
|
||||
dat += "<B><A href='?src=[REF(src)];help=2'>Show Help</A></B><BR>"
|
||||
|
||||
var/datum/browser/popup = new(user, "instrument", instrumentObj.name, 700, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(instrumentObj.icon, instrumentObj.icon_state))
|
||||
popup.open()
|
||||
|
||||
/datum/song/proc/ParseSong(text)
|
||||
set waitfor = FALSE
|
||||
//split into lines
|
||||
lines = splittext(text, "\n")
|
||||
if(lines.len)
|
||||
var/bpm_string = "BPM: "
|
||||
if(findtext(lines[1], bpm_string, 1, length(bpm_string) + 1))
|
||||
var/divisor = text2num(copytext(lines[1], length(bpm_string) + 1)) || 120 // default
|
||||
tempo = sanitize_tempo(600 / round(divisor, 1))
|
||||
lines.Cut(1, 2)
|
||||
else
|
||||
tempo = sanitize_tempo(5) // default 120 BPM
|
||||
if(lines.len > MUSIC_MAXLINES)
|
||||
to_chat(usr, "Too many lines!")
|
||||
lines.Cut(MUSIC_MAXLINES + 1)
|
||||
var/linenum = 1
|
||||
for(var/l in lines)
|
||||
if(length_char(l) > MUSIC_MAXLINECHARS)
|
||||
to_chat(usr, "Line [linenum] too long!")
|
||||
lines.Remove(l)
|
||||
else
|
||||
linenum++
|
||||
updateDialog(usr) // make sure updates when complete
|
||||
|
||||
/datum/song/Topic(href, href_list)
|
||||
if(!usr.canUseTopic(instrumentObj, TRUE, FALSE, FALSE, FALSE))
|
||||
usr << browse(null, "window=instrument")
|
||||
usr.unset_machine()
|
||||
return
|
||||
|
||||
instrumentObj.add_fingerprint(usr)
|
||||
|
||||
if(href_list["newsong"])
|
||||
lines = new()
|
||||
tempo = sanitize_tempo(5) // default 120 BPM
|
||||
name = ""
|
||||
|
||||
else if(href_list["import"])
|
||||
var/t = ""
|
||||
do
|
||||
t = html_encode(input(usr, "Please paste the entire song, formatted:", text("[]", name), t) as message)
|
||||
if(!in_range(instrumentObj, usr))
|
||||
return
|
||||
|
||||
if(length_char(t) >= MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
|
||||
var/cont = input(usr, "Your message is too long! Would you like to continue editing it?", "", "yes") in list("yes", "no")
|
||||
if(cont == "no")
|
||||
break
|
||||
while(length_char(t) > MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
|
||||
ParseSong(t)
|
||||
|
||||
else if(href_list["help"])
|
||||
help = text2num(href_list["help"]) - 1
|
||||
|
||||
else if(href_list["edit"])
|
||||
edit = text2num(href_list["edit"]) - 1
|
||||
|
||||
if(href_list["repeat"]) //Changing this from a toggle to a number of repeats to avoid infinite loops.
|
||||
if(playing)
|
||||
return //So that people cant keep adding to repeat. If the do it intentionally, it could result in the server crashing.
|
||||
repeat += round(text2num(href_list["repeat"]))
|
||||
if(repeat < 0)
|
||||
repeat = 0
|
||||
if(repeat > max_repeats)
|
||||
repeat = max_repeats
|
||||
|
||||
else if(href_list["tempo"])
|
||||
tempo = sanitize_tempo(tempo + text2num(href_list["tempo"]))
|
||||
|
||||
else if(href_list["play"])
|
||||
playing = TRUE
|
||||
spawn()
|
||||
playsong(usr)
|
||||
|
||||
else if(href_list["newline"])
|
||||
var/newline = html_encode(input("Enter your line: ", instrumentObj.name) as text|null)
|
||||
if(!newline || !in_range(instrumentObj, usr))
|
||||
return
|
||||
if(lines.len > MUSIC_MAXLINES)
|
||||
return
|
||||
if(length(newline) > MUSIC_MAXLINECHARS)
|
||||
newline = copytext(newline, 1, MUSIC_MAXLINECHARS)
|
||||
lines.Add(newline)
|
||||
|
||||
else if(href_list["deleteline"])
|
||||
var/num = round(text2num(href_list["deleteline"]))
|
||||
if(num > lines.len || num < 1)
|
||||
return
|
||||
lines.Cut(num, num+1)
|
||||
|
||||
else if(href_list["modifyline"])
|
||||
var/num = round(text2num(href_list["modifyline"]),1)
|
||||
var/content = stripped_input(usr, "Enter your line: ", instrumentObj.name, lines[num], MUSIC_MAXLINECHARS)
|
||||
if(!content || !in_range(instrumentObj, usr))
|
||||
return
|
||||
if(num > lines.len || num < 1)
|
||||
return
|
||||
lines[num] = content
|
||||
|
||||
else if(href_list["stop"])
|
||||
playing = FALSE
|
||||
hearing_mobs = null
|
||||
|
||||
updateDialog(usr)
|
||||
return
|
||||
|
||||
/datum/song/proc/sanitize_tempo(new_tempo)
|
||||
new_tempo = abs(new_tempo)
|
||||
return max(round(new_tempo, world.tick_lag), world.tick_lag)
|
||||
|
||||
// subclass for handheld instruments, like violin
|
||||
/datum/song/handheld
|
||||
|
||||
/datum/song/handheld/updateDialog(mob/user)
|
||||
instrumentObj.interact(user)
|
||||
|
||||
/datum/song/handheld/shouldStopPlaying()
|
||||
if(instrumentObj)
|
||||
return !isliving(instrumentObj.loc)
|
||||
else
|
||||
return TRUE
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/obj/structure/piano
|
||||
name = "space minimoog"
|
||||
icon = 'icons/obj/musician.dmi'
|
||||
icon_state = "minimoog"
|
||||
anchored = TRUE
|
||||
density = TRUE
|
||||
var/datum/song/song
|
||||
|
||||
/obj/structure/piano/unanchored
|
||||
anchored = FALSE
|
||||
|
||||
/obj/structure/piano/New()
|
||||
..()
|
||||
song = new("piano", src)
|
||||
|
||||
if(prob(50) && icon_state == initial(icon_state))
|
||||
name = "space minimoog"
|
||||
desc = "This is a minimoog, like a space piano, but more spacey!"
|
||||
icon_state = "minimoog"
|
||||
else
|
||||
name = "space piano"
|
||||
desc = "This is a space piano, like a regular piano, but always in tune! Even if the musician isn't."
|
||||
icon_state = "piano"
|
||||
|
||||
/obj/structure/piano/Destroy()
|
||||
qdel(song)
|
||||
song = null
|
||||
return ..()
|
||||
|
||||
/obj/structure/piano/Initialize(mapload)
|
||||
. = ..()
|
||||
if(mapload)
|
||||
song.tempo = song.sanitize_tempo(song.tempo) // tick_lag isn't set when the map is loaded
|
||||
|
||||
/obj/structure/piano/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
interact(user)
|
||||
|
||||
/obj/structure/piano/attack_paw(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/structure/piano/interact(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/structure/piano/ui_interact(mob/user)
|
||||
if(!user || !anchored)
|
||||
return
|
||||
|
||||
if(!user.IsAdvancedToolUser())
|
||||
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
|
||||
return 1
|
||||
user.set_machine(src)
|
||||
song.interact(user)
|
||||
|
||||
/obj/structure/piano/wrench_act(mob/living/user, obj/item/I)
|
||||
default_unfasten_wrench(user, I, 40)
|
||||
return TRUE
|
||||
@@ -60,6 +60,11 @@
|
||||
desc = "A sign labelling a restroom."
|
||||
icon_state = "restroom"
|
||||
|
||||
/obj/structure/sign/departments/showers
|
||||
name ="\improper SHOWER"
|
||||
desc = "A sign labelling showers."
|
||||
icon_state = "showerroom"
|
||||
|
||||
/obj/structure/sign/departments/medbay
|
||||
name = "\improper MEDBAY"
|
||||
desc = "The Intergalactic symbol of Medical institutions. You'll probably get help here."
|
||||
|
||||
@@ -55,3 +55,18 @@
|
||||
name = "cafe"
|
||||
desc = "A direction sign, pointing out which way the Cafe is."
|
||||
icon_state = "direction_cafe"
|
||||
|
||||
obj/structure/sign/directions/rooms
|
||||
name = "room"
|
||||
desc = "Room numbers, helps others find you!"
|
||||
icon_state = "roomnum"
|
||||
|
||||
obj/structure/sign/directions/dorms
|
||||
name = "dorm"
|
||||
desc = "Dorm numbers, help others find you, or you find others."
|
||||
icon_state = "dormnum"
|
||||
|
||||
obj/structure/sign/directions/cells
|
||||
name = "room"
|
||||
desc = "So the less fortunate amongst us know where they'll be staying."
|
||||
icon_state = "cellnum"
|
||||
|
||||
@@ -12,13 +12,11 @@
|
||||
var/w_items = 0 //the combined w_class of all the items in the cistern
|
||||
var/mob/living/swirlie = null //the mob being given a swirlie
|
||||
|
||||
|
||||
/obj/structure/toilet/Initialize()
|
||||
. = ..()
|
||||
open = round(rand(0, 1))
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/structure/toilet/attack_hand(mob/living/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
@@ -71,11 +69,9 @@
|
||||
open = !open
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/structure/toilet/update_icon_state()
|
||||
icon_state = "toilet[open][cistern]"
|
||||
|
||||
|
||||
/obj/structure/toilet/attackby(obj/item/I, mob/living/user, params)
|
||||
if(istype(I, /obj/item/crowbar))
|
||||
to_chat(user, "<span class='notice'>You start to [cistern ? "replace the lid on the cistern" : "lift the lid off the cistern"]...</span>")
|
||||
@@ -116,12 +112,17 @@
|
||||
. = ..()
|
||||
if (secret_type)
|
||||
secret = new secret_type(src)
|
||||
secret.desc += " It's a secret!"
|
||||
w_items += secret.w_class
|
||||
secret.desc += "" //In case you want to add something to the item that spawns
|
||||
contents += secret
|
||||
|
||||
/obj/structure/toilet/secret/low_loot
|
||||
secret_type = /obj/effect/spawner/lootdrop/low_loot_toilet
|
||||
|
||||
/obj/structure/toilet/secret/high_loot
|
||||
secret_type = /obj/effect/spawner/lootdrop/high_loot_toilet
|
||||
|
||||
/obj/structure/toilet/secret/prison
|
||||
secret_type = /obj/effect/spawner/lootdrop/prison_loot_toilet
|
||||
|
||||
/obj/structure/urinal
|
||||
name = "urinal"
|
||||
@@ -194,7 +195,6 @@
|
||||
exposed = !exposed
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/reagent_containers/food/urinalcake
|
||||
name = "urinal cake"
|
||||
desc = "The noble urinal cake, protecting the station's pipes from the station's pee. Do not eat."
|
||||
@@ -278,7 +278,6 @@
|
||||
add_hiddenprint(user)
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/machinery/shower/update_overlays()
|
||||
. = ..()
|
||||
if(on)
|
||||
@@ -315,7 +314,6 @@
|
||||
else if(isobj(AM))
|
||||
wash_obj(AM)
|
||||
|
||||
|
||||
/obj/machinery/shower/proc/wash_obj(obj/O)
|
||||
. = SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
|
||||
. = O.clean_blood()
|
||||
@@ -325,7 +323,6 @@
|
||||
I.acid_level = 0
|
||||
I.extinguish()
|
||||
|
||||
|
||||
/obj/machinery/shower/proc/wash_turf()
|
||||
if(isturf(loc))
|
||||
var/turf/tile = loc
|
||||
@@ -336,7 +333,6 @@
|
||||
if(is_cleanable(E))
|
||||
qdel(E)
|
||||
|
||||
|
||||
/obj/machinery/shower/proc/wash_mob(mob/living/L)
|
||||
SEND_SIGNAL(L, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
|
||||
L.wash_cream()
|
||||
@@ -667,11 +663,9 @@
|
||||
/obj/structure/sink/puddle/deconstruct(disassembled = TRUE)
|
||||
qdel(src)
|
||||
|
||||
|
||||
//Shower Curtains//
|
||||
//Defines used are pre-existing in layers.dm//
|
||||
|
||||
|
||||
/obj/structure/curtain
|
||||
name = "curtain"
|
||||
desc = "Contains less than 1% mercury."
|
||||
@@ -727,7 +721,6 @@
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/structure/curtain/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
|
||||
+13
-12
@@ -8,7 +8,7 @@
|
||||
return
|
||||
|
||||
//allocate a channel if necessary now so its the same for everyone
|
||||
channel = channel || open_sound_channel()
|
||||
channel = channel || SSsounds.random_available_channel()
|
||||
|
||||
// Looping through the player list has the added bonus of working for mobs inside containers
|
||||
var/sound/S = sound(get_sfx(soundin))
|
||||
@@ -26,10 +26,10 @@
|
||||
if(get_dist(M, turf_source) <= maxdistance)
|
||||
M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S, soundenvwet, soundenvdry)
|
||||
|
||||
/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff, channel = 0, pressure_affected = TRUE, sound/S, envwet = -10000, envdry = 0, manual_x, manual_y)
|
||||
/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff, channel = 0, pressure_affected = TRUE, sound/S, envwet = -10000, envdry = 0, manual_x, manual_y, distance_multiplier = 1)
|
||||
if(audiovisual_redirect)
|
||||
var/turf/T = get_turf(src)
|
||||
audiovisual_redirect.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S, 0, -1000, turf_source.x - T.x, turf_source.y - T.y)
|
||||
audiovisual_redirect.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S, 0, -1000, turf_source.x - T.x, turf_source.y - T.y, distance_multiplier)
|
||||
if(!client || !can_hear())
|
||||
return
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
S = sound(get_sfx(soundin))
|
||||
|
||||
S.wait = 0 //No queue
|
||||
S.channel = channel || open_sound_channel()
|
||||
S.channel = channel || SSsounds.random_available_channel()
|
||||
S.volume = vol
|
||||
S.environment = 7
|
||||
|
||||
@@ -55,6 +55,8 @@
|
||||
if(!manual_x && !manual_y)
|
||||
distance = get_dist(T, turf_source)
|
||||
|
||||
distance *= distance_multiplier
|
||||
|
||||
S.volume -= max(distance - world.view, 0) * 2 //multiplicative falloff to add on top of natural audio falloff.
|
||||
|
||||
if(pressure_affected)
|
||||
@@ -86,13 +88,13 @@
|
||||
dx = turf_source.x - T.x
|
||||
else
|
||||
dx = manual_x
|
||||
S.x = dx
|
||||
S.x = dx * distance_multiplier
|
||||
var/dz = 0 // Hearing from infront/behind
|
||||
if(!manual_x)
|
||||
dz = turf_source.y - T.y
|
||||
else
|
||||
dz = manual_y
|
||||
S.z = dz
|
||||
S.z = dz * distance_multiplier
|
||||
// The y value is for above your head, but there is no ceiling in 2d spessmens.
|
||||
S.y = 1
|
||||
S.falloff = (falloff ? falloff : FALLOFF_SOUNDS)
|
||||
@@ -107,15 +109,14 @@
|
||||
var/mob/M = m
|
||||
M.playsound_local(M, null, volume, vary, frequency, falloff, channel, pressure_affected, S)
|
||||
|
||||
/proc/open_sound_channel()
|
||||
var/static/next_channel = 1 //loop through the available 1024 - (the ones we reserve) channels and pray that its not still being used
|
||||
. = ++next_channel
|
||||
if(next_channel > CHANNEL_HIGHEST_AVAILABLE)
|
||||
next_channel = 1
|
||||
|
||||
/mob/proc/stop_sound_channel(chan)
|
||||
SEND_SOUND(src, sound(null, repeat = 0, wait = 0, channel = chan))
|
||||
|
||||
/mob/proc/set_sound_channel_volume(channel, volume)
|
||||
var/sound/S = sound(null, FALSE, FALSE, channel, volume)
|
||||
S.status = SOUND_UPDATE
|
||||
SEND_SOUND(src, S)
|
||||
|
||||
/client/proc/playtitlemusic(vol = 85)
|
||||
set waitfor = FALSE
|
||||
UNTIL(SSticker.login_music) //wait for SSticker init to set the login music
|
||||
|
||||
@@ -260,3 +260,10 @@
|
||||
icon = 'icons/obj/clockwork_objects.dmi'
|
||||
icon_state = "clockwork_floor"
|
||||
floor_tile = /obj/item/stack/tile/bronze
|
||||
|
||||
/turf/open/floor/padded
|
||||
name = "padded floor"
|
||||
desc = "Keeps crazy people from hurting themselves. It's soft, plush, and very nice to get shoved agaisnt."
|
||||
icon = 'icons/turf/floors.dmi'
|
||||
icon_state = "floor_padded"
|
||||
floor_tile = /obj/item/stack/tile/padded
|
||||
|
||||
@@ -68,6 +68,9 @@
|
||||
/turf/open/floor/plasteel/chapel
|
||||
icon_state = "chapel"
|
||||
|
||||
/turf/open/floor/plasteel/chapel_floor
|
||||
icon_state = "chapel_alt"
|
||||
|
||||
/turf/open/floor/plasteel/showroomfloor
|
||||
icon_state = "showroomfloor"
|
||||
|
||||
|
||||
@@ -1732,9 +1732,8 @@
|
||||
var/mob/M = locate(href_list["makeeligible"])
|
||||
if(!ismob(M))
|
||||
to_chat(usr, "this can only be used on instances of type /mob.")
|
||||
var/datum/element/ghost_role_eligibility/eli = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility))
|
||||
if(M.ckey in eli.timeouts)
|
||||
eli.timeouts -= M.ckey
|
||||
if(M.ckey in GLOB.client_ghost_timeouts)
|
||||
GLOB.client_ghost_timeouts -= M.ckey
|
||||
|
||||
else if(href_list["sendtoprison"])
|
||||
if(!check_rights(R_ADMIN))
|
||||
|
||||
@@ -92,10 +92,8 @@
|
||||
M.cut_overlays()
|
||||
M.regenerate_icons()
|
||||
|
||||
/obj/item/clothing/suit/armor/abductor/vest/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
DeactivateStealth()
|
||||
|
||||
/obj/item/clothing/suit/armor/abductor/vest/IsReflect()
|
||||
/obj/item/clothing/suit/armor/abductor/vest/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
. = ..()
|
||||
DeactivateStealth()
|
||||
|
||||
/obj/item/clothing/suit/armor/abductor/vest/ui_action_click()
|
||||
@@ -493,7 +491,7 @@
|
||||
|
||||
user.do_attack_animation(L)
|
||||
|
||||
if(L.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
|
||||
if(L.run_block(src, 0, "[user]'s [src]", ATTACK_TYPE_MELEE, 0, user, check_zone(user.zone_selected)) & BLOCK_SUCCESS)
|
||||
playsound(L, 'sound/weapons/genhit.ogg', 50, TRUE)
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
to_chat(owner, "<span class='warning'>Your victim's eyes are glazed over. They cannot perceive you.</span>")
|
||||
return FALSE
|
||||
// Check: Target See Me? (behind wall)
|
||||
if(!(target in view(target_range, get_turf(owner))))
|
||||
if(!(target in viewers(target_range, get_turf(owner))))
|
||||
// Sub-Check: GET CLOSER
|
||||
//if (!(owner in range(target_range, get_turf(target)))
|
||||
// if (display_error)
|
||||
@@ -90,48 +90,56 @@
|
||||
|
||||
/datum/action/bloodsucker/targeted/mesmerize/proc/ContinueTarget(atom/A)
|
||||
var/mob/living/carbon/target = A
|
||||
var/mob/living/user = owner
|
||||
var/mob/living/L = owner
|
||||
|
||||
var/cancontinue=CheckCanTarget(target)
|
||||
var/cancontinue = CheckCanTarget(target)
|
||||
if(!cancontinue)
|
||||
success = FALSE
|
||||
target.remove_status_effect(STATUS_EFFECT_MESMERIZE)
|
||||
user.remove_status_effect(STATUS_EFFECT_MESMERIZE)
|
||||
L.remove_status_effect(STATUS_EFFECT_MESMERIZE)
|
||||
DeactivatePower()
|
||||
DeactivateRangedAbility()
|
||||
StartCooldown()
|
||||
to_chat(user, "<span class='warning'>[target] has escaped your gaze!</span>")
|
||||
to_chat(L, "<span class='warning'>[target] has escaped your gaze!</span>")
|
||||
UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
|
||||
|
||||
/datum/action/bloodsucker/targeted/mesmerize/FireTargetedPower(atom/A)
|
||||
// set waitfor = FALSE <---- DONT DO THIS!We WANT this power to hold up ClickWithPower(), so that we can unlock the power when it's done.
|
||||
var/mob/living/carbon/target = A
|
||||
var/mob/living/user = owner
|
||||
var/mob/living/L = owner
|
||||
L.face_atom(A)
|
||||
if(!istype(target))
|
||||
return
|
||||
success = TRUE
|
||||
var/power_time = 138 + level_current * 12
|
||||
target.apply_status_effect(STATUS_EFFECT_MESMERIZE, 30)
|
||||
L.apply_status_effect(STATUS_EFFECT_MESMERIZE, 30)
|
||||
RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/ContinueTarget)
|
||||
// 5 second windup
|
||||
addtimer(CALLBACK(src, .proc/apply_effects, L, target, power_time), 6 SECONDS)
|
||||
ADD_TRAIT(target, TRAIT_COMBAT_MODE_LOCKED, src)
|
||||
ADD_TRAIT(L, TRAIT_COMBAT_MODE_LOCKED, src)
|
||||
|
||||
if(istype(target))
|
||||
success = TRUE
|
||||
var/power_time = 138 + level_current * 12
|
||||
target.apply_status_effect(STATUS_EFFECT_MESMERIZE, 30)
|
||||
user.apply_status_effect(STATUS_EFFECT_MESMERIZE, 30)
|
||||
|
||||
RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/ContinueTarget)
|
||||
/datum/action/bloodsucker/targeted/mesmerize/proc/apply_effects(aggressor, victim, power_time)
|
||||
var/mob/living/carbon/target = victim
|
||||
var/mob/living/L = aggressor
|
||||
if(!success)
|
||||
return
|
||||
PowerActivatedSuccessfully() // blood & cooldown only altered if power activated successfully - less "fuck you"-y
|
||||
target.apply_status_effect(STATUS_EFFECT_MESMERIZE, power_time)
|
||||
REMOVE_TRAIT(L, TRAIT_COMBAT_MODE_LOCKED, src)
|
||||
target.face_atom(L)
|
||||
target.Stun(power_time)
|
||||
to_chat(L, "<span class='notice'>[target] is fixed in place by your hypnotic gaze.</span>")
|
||||
target.next_move = world.time + power_time // <--- Use direct change instead. We want an unmodified delay to their next move // target.changeNext_move(power_time) // check click.dm
|
||||
target.notransform = TRUE // <--- Fuck it. We tried using next_move, but they could STILL resist. We're just doing a hard freeze.
|
||||
spawn(power_time)
|
||||
if(istype(target) && success)
|
||||
target.notransform = FALSE
|
||||
REMOVE_TRAIT(target, TRAIT_COMBAT_MODE_LOCKED, src)
|
||||
if(istype(L) && target.stat == CONSCIOUS && (target in view(10, get_turf(L)))) // They Woke Up! (Notice if within view)
|
||||
to_chat(L, "<span class='warning'>[target] has snapped out of their trance.</span>")
|
||||
|
||||
// 3 second windup
|
||||
sleep(30)
|
||||
if(success)
|
||||
PowerActivatedSuccessfully() // blood & cooldown only altered if power activated successfully - less "fuck you"-y
|
||||
target.face_atom(user)
|
||||
target.apply_status_effect(STATUS_EFFECT_MESMERIZE, power_time) // pretty much purely cosmetic
|
||||
target.Stun(power_time)
|
||||
to_chat(user, "<span class='notice'>[target] is fixed in place by your hypnotic gaze.</span>")
|
||||
target.next_move = world.time + power_time // <--- Use direct change instead. We want an unmodified delay to their next move // target.changeNext_move(power_time) // check click.dm
|
||||
target.notransform = TRUE // <--- Fuck it. We tried using next_move, but they could STILL resist. We're just doing a hard freeze.
|
||||
spawn(power_time)
|
||||
if(istype(target) && success)
|
||||
target.notransform = FALSE
|
||||
// They Woke Up! (Notice if within view)
|
||||
if(istype(user) && target.stat == CONSCIOUS && (target in view(10, get_turf(user))) )
|
||||
to_chat(user, "<span class='warning'>[target] has snapped out of their trance.</span>")
|
||||
|
||||
/datum/action/bloodsucker/targeted/mesmerize/ContinueActive(mob/living/user, mob/living/target)
|
||||
return ..() && CheckCanUse() && CheckCanTarget(target)
|
||||
|
||||
@@ -441,23 +441,23 @@
|
||||
|
||||
var/remaining_uses //Set by the changeling ability.
|
||||
|
||||
/obj/item/shield/changeling/Initialize()
|
||||
/obj/item/shield/changeling/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
|
||||
if(ismob(loc))
|
||||
loc.visible_message("<span class='warning'>The end of [loc.name]\'s hand inflates rapidly, forming a huge shield-like mass!</span>", "<span class='warning'>We inflate our hand into a strong shield.</span>", "<span class='italics'>You hear organic matter ripping and tearing!</span>")
|
||||
|
||||
/obj/item/shield/changeling/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(remaining_uses < 1)
|
||||
/obj/item/shield/changeling/check_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
block_return[BLOCK_RETURN_BLOCK_CAPACITY] = (block_return[BLOCK_RETURN_BLOCK_CAPACITY] || 0) + remaining_uses
|
||||
return ..()
|
||||
|
||||
/obj/item/shield/changeling/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
. = ..()
|
||||
if(--remaining_uses < 1)
|
||||
if(ishuman(loc))
|
||||
var/mob/living/carbon/human/H = loc
|
||||
H.visible_message("<span class='warning'>With a sickening crunch, [H] reforms [H.p_their()] shield into an arm!</span>", "<span class='notice'>We assimilate our shield into our body</span>", "<span class='italics>You hear organic matter ripping and tearing!</span>")
|
||||
qdel(src)
|
||||
return 0
|
||||
else
|
||||
remaining_uses--
|
||||
return ..()
|
||||
|
||||
|
||||
/***************************************\
|
||||
|*********SPACE SUIT + HELMET***********|
|
||||
|
||||
@@ -656,6 +656,7 @@
|
||||
C.equip_to_slot_or_del(new /obj/item/clothing/suit/cultrobes/alt(user), SLOT_WEAR_SUIT)
|
||||
C.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult/alt(user), SLOT_SHOES)
|
||||
C.equip_to_slot_or_del(new /obj/item/storage/backpack/cultpack(user), SLOT_BACK)
|
||||
C.equip_to_slot_or_del(new /obj/item/clothing/gloves/fingerless/pugilist/hungryghost(user), SLOT_GLOVES)
|
||||
if(C == user)
|
||||
qdel(src) //Clears the hands
|
||||
C.put_in_hands(new /obj/item/melee/cultblade(user))
|
||||
|
||||
@@ -162,24 +162,20 @@
|
||||
jaunt.Remove(user)
|
||||
user.update_icons()
|
||||
|
||||
/obj/item/twohanded/required/cult_bastard/IsReflect()
|
||||
if(spinning)
|
||||
/obj/item/twohanded/required/cult_bastard/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(spinning && is_energy_reflectable_projectile(object) && (attack_type & ATTACK_TYPE_PROJECTILE))
|
||||
playsound(src, pick('sound/weapons/effects/ric1.ogg', 'sound/weapons/effects/ric2.ogg', 'sound/weapons/effects/ric3.ogg', 'sound/weapons/effects/ric4.ogg', 'sound/weapons/effects/ric5.ogg'), 100, 1)
|
||||
return TRUE
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/twohanded/required/cult_bastard/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT
|
||||
if(prob(final_block_chance))
|
||||
if(attack_type == PROJECTILE_ATTACK)
|
||||
if(attack_type & ATTACK_TYPE_PROJECTILE)
|
||||
owner.visible_message("<span class='danger'>[owner] deflects [attack_text] with [src]!</span>")
|
||||
playsound(src, pick('sound/weapons/effects/ric1.ogg', 'sound/weapons/effects/ric2.ogg', 'sound/weapons/effects/ric3.ogg', 'sound/weapons/effects/ric4.ogg', 'sound/weapons/effects/ric5.ogg'), 100, 1)
|
||||
return TRUE
|
||||
return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT
|
||||
else
|
||||
playsound(src, 'sound/weapons/parry.ogg', 75, 1)
|
||||
owner.visible_message("<span class='danger'>[owner] parries [attack_text] with [src]!</span>")
|
||||
return TRUE
|
||||
return FALSE
|
||||
return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
|
||||
return BLOCK_NONE
|
||||
|
||||
/obj/item/twohanded/required/cult_bastard/afterattack(atom/target, mob/user, proximity, click_parameters)
|
||||
. = ..()
|
||||
@@ -423,7 +419,13 @@
|
||||
user.adjustBruteLoss(25)
|
||||
user.dropItemToGround(src, TRUE)
|
||||
|
||||
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/check_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(current_charges)
|
||||
block_return[BLOCK_RETURN_NORMAL_BLOCK_CHANCE] = 100
|
||||
block_return[BLOCK_RETURN_BLOCK_CAPACITY] = (block_return[BLOCK_RETURN_BLOCK_CAPACITY] || 0) + current_charges
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(current_charges)
|
||||
owner.visible_message("<span class='danger'>\The [attack_text] is deflected in a burst of blood-red sparks!</span>")
|
||||
current_charges--
|
||||
@@ -431,8 +433,8 @@
|
||||
if(!current_charges)
|
||||
owner.visible_message("<span class='danger'>The runed shield around [owner] suddenly disappears!</span>")
|
||||
owner.update_inv_wear_suit()
|
||||
return 1
|
||||
return 0
|
||||
return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
|
||||
return BLOCK_NONE
|
||||
|
||||
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/worn_overlays(isinhands, icon_file, style_flags = NONE)
|
||||
. = list()
|
||||
@@ -734,19 +736,19 @@
|
||||
playsound(T, 'sound/effects/glassbr3.ogg', 100)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/twohanded/cult_spear/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
/obj/item/twohanded/cult_spear/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(wielded)
|
||||
final_block_chance *= 2
|
||||
if(prob(final_block_chance))
|
||||
if(attack_type == PROJECTILE_ATTACK)
|
||||
if(attack_type & ATTACK_TYPE_PROJECTILE)
|
||||
owner.visible_message("<span class='danger'>[owner] deflects [attack_text] with [src]!</span>")
|
||||
playsound(src, pick('sound/weapons/effects/ric1.ogg', 'sound/weapons/effects/ric2.ogg', 'sound/weapons/effects/ric3.ogg', 'sound/weapons/effects/ric4.ogg', 'sound/weapons/effects/ric5.ogg'), 100, 1)
|
||||
return TRUE
|
||||
return BLOCK_SUCCESS | BLOCK_SHOULD_REDIRECT | BLOCK_REDIRECTED | BLOCK_PHYSICAL_EXTERNAL
|
||||
else
|
||||
playsound(src, 'sound/weapons/parry.ogg', 100, 1)
|
||||
owner.visible_message("<span class='danger'>[owner] parries [attack_text] with [src]!</span>")
|
||||
return TRUE
|
||||
return FALSE
|
||||
return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL
|
||||
return BLOCK_NONE
|
||||
|
||||
/datum/action/innate/cult/spear
|
||||
name = "Bloody Bond"
|
||||
@@ -945,10 +947,18 @@
|
||||
hitsound = 'sound/weapons/smash.ogg'
|
||||
var/illusions = 2
|
||||
|
||||
/obj/item/shield/mirror/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
/obj/item/shield/mirror/check_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
block_return[BLOCK_RETURN_REFLECT_PROJECTILE_CHANCE] = max(block_return[BLOCK_RETURN_REFLECT_PROJECTILE_CHANCE] || null, final_block_chance)
|
||||
return ..()
|
||||
|
||||
/obj/item/shield/mirror/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if(iscultist(owner))
|
||||
if(istype(hitby, /obj/item/projectile))
|
||||
var/obj/item/projectile/P = hitby
|
||||
if(istype(object, /obj/item/projectile) && (attack_type == ATTACK_TYPE_PROJECTILE))
|
||||
if(is_energy_reflectable_projectile(object))
|
||||
if(prob(final_block_chance))
|
||||
return BLOCK_SUCCESS | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_EXTERNAL | BLOCK_REDIRECTED
|
||||
return BLOCK_NONE //To avoid reflection chance double-dipping with block chance
|
||||
var/obj/item/projectile/P = object
|
||||
if(P.damage >= 30)
|
||||
var/turf/T = get_turf(owner)
|
||||
T.visible_message("<span class='warning'>The sheer force from [P] shatters the mirror shield!</span>")
|
||||
@@ -956,11 +966,9 @@
|
||||
playsound(T, 'sound/effects/glassbr3.ogg', 100)
|
||||
owner.DefaultCombatKnockdown(25)
|
||||
qdel(src)
|
||||
return FALSE
|
||||
if(P.is_reflectable)
|
||||
return FALSE //To avoid reflection chance double-dipping with block chance
|
||||
return BLOCK_NONE
|
||||
. = ..()
|
||||
if(.)
|
||||
if(. & BLOCK_SUCCESS)
|
||||
playsound(src, 'sound/weapons/parry.ogg', 100, 1)
|
||||
if(illusions > 0)
|
||||
illusions--
|
||||
@@ -975,7 +983,7 @@
|
||||
E.Copy_Parent(owner, 70, 10)
|
||||
E.GiveTarget(owner)
|
||||
E.Goto(owner, owner.movement_delay(), E.minimum_distance)
|
||||
return TRUE
|
||||
return
|
||||
else
|
||||
if(prob(50))
|
||||
var/mob/living/simple_animal/hostile/illusion/H = new(owner.loc)
|
||||
@@ -984,7 +992,7 @@
|
||||
H.GiveTarget(owner)
|
||||
H.move_to_delay = owner.movement_delay()
|
||||
to_chat(owner, "<span class='danger'><b>[src] betrays you!</b></span>")
|
||||
return FALSE
|
||||
return BLOCK_NONE
|
||||
|
||||
/obj/item/shield/mirror/proc/readd()
|
||||
illusions++
|
||||
@@ -992,11 +1000,6 @@
|
||||
var/mob/living/holder = loc
|
||||
to_chat(holder, "<span class='cult italic'>The shield's illusions are back at full strength!</span>")
|
||||
|
||||
/obj/item/shield/mirror/IsReflect()
|
||||
if(prob(block_chance))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/shield/mirror/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
var/turf/T = get_turf(hit_atom)
|
||||
var/datum/thrownthing/D = throwingdatum
|
||||
|
||||
@@ -414,11 +414,11 @@
|
||||
if(safety)
|
||||
to_chat(usr, "<span class='danger'>The safety is still on.</span>")
|
||||
return
|
||||
if(!timing && nuclear_cooldown > world.time)
|
||||
to_chat(usr, "<span class='danger'>[src]'s timer protocols are currently on cooldown, please stand by.</span>")
|
||||
return
|
||||
timing = !timing
|
||||
if(timing)
|
||||
if(nuclear_cooldown > world.time)
|
||||
to_chat(usr, "<span class='danger'>[src]'s timer protocols are currently on cooldown, please stand by.</span>")
|
||||
return
|
||||
previous_level = get_security_level()
|
||||
detonation_timer = world.time + (timer_set * 10)
|
||||
for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list)
|
||||
|
||||
@@ -38,8 +38,8 @@
|
||||
weights[C] = weight
|
||||
var/choice = pickweightAllowZero(weights)
|
||||
if(!choice)
|
||||
choice = GLOB.traitor_classes[TRAITOR_HUMAN]
|
||||
set_traitor_kind(pickweightAllowZero(weights))
|
||||
choice = GLOB.traitor_classes[TRAITOR_HUMAN] // it's an "easter egg"
|
||||
set_traitor_kind(choice)
|
||||
traitor_kind.weight *= 0.8 // less likely this round
|
||||
SSticker.mode.traitors += owner
|
||||
owner.special_role = special_role
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
/datum/syndicate_contract/proc/handleVictimExperience(var/mob/living/M) // They're off to holding - handle the return timer and give some text about what's going on.
|
||||
addtimer(CALLBACK(src, .proc/returnVictim, M), 4 MINUTES) // Ship 'em back - dead or alive... 4 minutes wait.
|
||||
if(M.stat != DEAD) //Even if they weren't the target, we're still treating them the same.
|
||||
M.reagents.add_reagent(/datum/reagent/medicine/omnizine, 20) // Heal them up - gets them out of crit/soft crit.
|
||||
M.reagents.add_reagent(/datum/reagent/medicine/regen_jelly, 20) // Heal them up - gets them out of crit/soft crit. -- now 100% toxinlover friendly!!
|
||||
M.flash_act()
|
||||
M.confused += 10
|
||||
M.blur_eyes(5)
|
||||
|
||||
@@ -312,7 +312,7 @@
|
||||
if(holder)
|
||||
holder.update_icon()
|
||||
|
||||
/obj/item/assembly/flash/shield/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
/obj/item/assembly/flash/shield/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
activate()
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(/datum/gas/oxygen, /datum/g
|
||||
|
||||
/datum/gas/miasma
|
||||
id = "miasma"
|
||||
specific_heat = 0.00001
|
||||
specific_heat = 20
|
||||
fusion_power = 50
|
||||
name = "Miasma"
|
||||
gas_overlay = "miasma"
|
||||
|
||||
@@ -309,7 +309,7 @@
|
||||
/datum/export/gear/combatgloves
|
||||
cost = 80
|
||||
unit_name = "combat gloves"
|
||||
export_types = list(/obj/item/clothing/gloves/combat, /obj/item/clothing/gloves/rapid, /obj/item/clothing/gloves/krav_maga)
|
||||
export_types = list(/obj/item/clothing/gloves/combat, /obj/item/clothing/gloves/fingerless/pugilist/rapid, /obj/item/clothing/gloves/krav_maga)
|
||||
include_subtypes = TRUE
|
||||
|
||||
/datum/export/gear/bonegloves
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
/datum/export/glasswork_lens
|
||||
cost = 1800
|
||||
unit_name = "small glass lens"
|
||||
export_types = list(/obj/item/lens)
|
||||
export_types = list(/obj/item/glasswork/glass_base/lens)
|
||||
|
||||
/datum/export/glasswork_spouty
|
||||
cost = 1200
|
||||
@@ -131,3 +131,27 @@
|
||||
unit_name = "large flask"
|
||||
export_types = list(/obj/item/reagent_containers/glass/beaker/flask/large)
|
||||
include_subtypes = FALSE
|
||||
|
||||
/datum/export/glasswork_teaplate
|
||||
cost = 1200
|
||||
unit_name = "tea gear"
|
||||
export_types = list(/obj/item/tea_plate)
|
||||
include_subtypes = FALSE
|
||||
|
||||
/datum/export/glasswork_teacup
|
||||
cost = 1800
|
||||
unit_name = "tea gear"
|
||||
export_types = list(/obj/item/tea_cup)
|
||||
include_subtypes = FALSE
|
||||
|
||||
/datum/export/glasswork_laserpointer
|
||||
cost = 2600
|
||||
unit_name = "hand made laserpointer"
|
||||
export_types = list(/obj/item/laser_pointer/blue/handmade)
|
||||
include_subtypes = FALSE
|
||||
|
||||
/datum/export/glasswork_glasses
|
||||
cost = 5000
|
||||
unit_name = "hand made glasses"
|
||||
export_types = list(/obj/item/glasswork/glasses)
|
||||
include_subtypes = FALSE
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user