mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
[MIRROR] Unlucky trait (#11775)
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
This commit is contained in:
committed by
GitHub
parent
6eab8c8408
commit
b8fe8fa68d
@@ -163,6 +163,11 @@
|
|||||||
///from base of atom/attack_paw(): (mob/user)
|
///from base of atom/attack_paw(): (mob/user)
|
||||||
//This signal return value bitflags can be found in __DEFINES/misc.dm
|
//This signal return value bitflags can be found in __DEFINES/misc.dm
|
||||||
|
|
||||||
|
///from base of /obj/structure/stairs/top/use_stairs(var/atom/movable/AM, var/atom/oldloc)
|
||||||
|
#define COMSIG_MOVED_DOWN_STAIRS "atom_moved_down_stairs"
|
||||||
|
///from base of /obj/structure/stairs/bottom/use_stairs(var/atom/movable/AM, var/atom/oldloc)
|
||||||
|
#define COMSIG_MOVED_UP_STAIRS "atom_moved_up_stairs"
|
||||||
|
|
||||||
///called for each movable in a turf contents on /turf/zImpact(): (atom/movable/A, levels)
|
///called for each movable in a turf contents on /turf/zImpact(): (atom/movable/A, levels)
|
||||||
#define COMSIG_ATOM_INTERCEPT_Z_FALL "movable_intercept_z_impact"
|
#define COMSIG_ATOM_INTERCEPT_Z_FALL "movable_intercept_z_impact"
|
||||||
///called on a movable (NOT living) when someone starts pulling it (atom/movable/puller, state, force)
|
///called on a movable (NOT living) when someone starts pulling it (atom/movable/puller, state, force)
|
||||||
@@ -240,6 +245,8 @@
|
|||||||
#define COMPONENT_MOVABLE_IMPACT_NEVERMIND (1<<1) //return true if you destroyed whatever it was you're impacting and there won't be anything for hitby() to run on
|
#define COMPONENT_MOVABLE_IMPACT_NEVERMIND (1<<1) //return true if you destroyed whatever it was you're impacting and there won't be anything for hitby() to run on
|
||||||
///from base of mob/living/hitby(): (mob/living/target, hit_zone)
|
///from base of mob/living/hitby(): (mob/living/target, hit_zone)
|
||||||
#define COMSIG_MOVABLE_IMPACT_ZONE "item_impact_zone"
|
#define COMSIG_MOVABLE_IMPACT_ZONE "item_impact_zone"
|
||||||
|
///from the base of mob/living/carbon/human/hitby(): (atom/movable/source, speed)
|
||||||
|
#define COMSIG_HUMAN_ON_CATCH_THROW "human_on_catch_throw"
|
||||||
///from base of atom/movable/buckle_mob(): (mob, force)
|
///from base of atom/movable/buckle_mob(): (mob, force)
|
||||||
#define COMSIG_MOVABLE_BUCKLE "buckle"
|
#define COMSIG_MOVABLE_BUCKLE "buckle"
|
||||||
///from base of atom/movable/unbuckle_mob(): (mob, force)
|
///from base of atom/movable/unbuckle_mob(): (mob, force)
|
||||||
@@ -290,6 +297,9 @@
|
|||||||
#define COMSIG_MOB_ALTCLICKON "mob_altclickon"
|
#define COMSIG_MOB_ALTCLICKON "mob_altclickon"
|
||||||
#define COMSIG_MOB_CANCEL_CLICKON (1<<0)
|
#define COMSIG_MOB_CANCEL_CLICKON (1<<0)
|
||||||
|
|
||||||
|
///from base of /obj/item/dice/proc/rollDice(mob/user as mob, var/silent = 0). Has the arguments of 'src, silent, result'
|
||||||
|
#define COMSIG_MOB_ROLLED_DICE "mob_rolled_dice" //can give a return value if we want it to make the dice roll a specific number!
|
||||||
|
|
||||||
///from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj
|
///from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj
|
||||||
#define COMSIG_MOB_ALLOWED "mob_allowed"
|
#define COMSIG_MOB_ALLOWED "mob_allowed"
|
||||||
///from base of mob/anti_magic_check(): (mob/user, magic, holy, tinfoil, chargecost, self, protection_sources)
|
///from base of mob/anti_magic_check(): (mob/user, magic, holy, tinfoil, chargecost, self, protection_sources)
|
||||||
@@ -406,6 +416,8 @@
|
|||||||
#define COMSIG_TAKING_APPLY_EFFECT "applying_effect"
|
#define COMSIG_TAKING_APPLY_EFFECT "applying_effect"
|
||||||
///Return this in response if you don't want the effect to be applied
|
///Return this in response if you don't want the effect to be applied
|
||||||
#define COMSIG_CANCEL_EFFECT (1<<0)
|
#define COMSIG_CANCEL_EFFECT (1<<0)
|
||||||
|
///from /mob/living/proc/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone, var/used_weapon=null, var/electric = FALSE)
|
||||||
|
#define COMSIG_STUN_EFFECT_ACT "stun_effect_act"
|
||||||
|
|
||||||
///Misc signal for checking for godmode. Used by /datum/element/godmode
|
///Misc signal for checking for godmode. Used by /datum/element/godmode
|
||||||
#define COMSIG_CHECK_FOR_GODMODE "check_for_godmode"
|
#define COMSIG_CHECK_FOR_GODMODE "check_for_godmode"
|
||||||
@@ -450,7 +462,8 @@
|
|||||||
///called when being electrocuted, from /mob/living/carbon/electrocute_act(shock_damage, source, siemens_coeff, def_zone, stun)
|
///called when being electrocuted, from /mob/living/carbon/electrocute_act(shock_damage, source, siemens_coeff, def_zone, stun)
|
||||||
#define COMSIG_BEING_ELECTROCUTED "being_electrocuted"
|
#define COMSIG_BEING_ELECTROCUTED "being_electrocuted"
|
||||||
#define COMPONENT_CARBON_CANCEL_ELECTROCUTE (1<<0) //If this is set, the carbon will be not be electrocuted.
|
#define COMPONENT_CARBON_CANCEL_ELECTROCUTE (1<<0) //If this is set, the carbon will be not be electrocuted.
|
||||||
|
///called when a carbon slipps, from /mob/living/carbon/slip(var/slipped_on,stun_duration=8)
|
||||||
|
#define COMSIG_ON_CARBON_SLIP "carbon_slip"
|
||||||
|
|
||||||
// /mob/living/silicon signals
|
// /mob/living/silicon signals
|
||||||
///called when a silicon is emp'd. from /mob/living/silicon/emp_act(severity)
|
///called when a silicon is emp'd. from /mob/living/silicon/emp_act(severity)
|
||||||
@@ -536,6 +549,8 @@
|
|||||||
#define COMSIG_MOB_UNEQUIPPED_ITEM "mob_unequipped_item"
|
#define COMSIG_MOB_UNEQUIPPED_ITEM "mob_unequipped_item"
|
||||||
///from base of obj/item/pickup(): (/mob/taker)
|
///from base of obj/item/pickup(): (/mob/taker)
|
||||||
#define COMSIG_ITEM_PICKUP "item_pickup"
|
#define COMSIG_ITEM_PICKUP "item_pickup"
|
||||||
|
///from base of obj/item/pickup(): (/obj/item)
|
||||||
|
#define COMSIG_PICKED_UP_ITEM "piked_up_item"
|
||||||
///from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone)
|
///from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone)
|
||||||
#define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone"
|
#define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone"
|
||||||
///return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/targeted/lichdom/cast(): (mob/user)
|
///return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/targeted/lichdom/cast(): (mob/user)
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
|||||||
/// Prevents the affected object from opening a loot window via alt click. See atom/AltClick()
|
/// Prevents the affected object from opening a loot window via alt click. See atom/AltClick()
|
||||||
#define TRAIT_ALT_CLICK_BLOCKER "no_alt_click"
|
#define TRAIT_ALT_CLICK_BLOCKER "no_alt_click"
|
||||||
|
|
||||||
|
/// Unlucky trait. Given by the 'unlucky' trait in character select. Checked by various things to cause unlucky interactions.
|
||||||
|
#define TRAIT_UNLUCKY "trait_unlucky"
|
||||||
|
|
||||||
#define TRAIT_INCAPACITATED "incapacitated"
|
#define TRAIT_INCAPACITATED "incapacitated"
|
||||||
|
|
||||||
#define TRAIT_NOFIRE "nonflammable"
|
#define TRAIT_NOFIRE "nonflammable"
|
||||||
|
|||||||
@@ -370,6 +370,7 @@
|
|||||||
old_component.InheritComponent(arglist(arguments))
|
old_component.InheritComponent(arglist(arguments))
|
||||||
else
|
else
|
||||||
old_component.InheritComponent(new_component, TRUE)
|
old_component.InheritComponent(new_component, TRUE)
|
||||||
|
QDEL_NULL(new_component)
|
||||||
|
|
||||||
if(COMPONENT_DUPE_SOURCES)
|
if(COMPONENT_DUPE_SOURCES)
|
||||||
if(source in old_component.sources)
|
if(source in old_component.sources)
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
if(G.affecting)
|
if(G.affecting)
|
||||||
G.affecting.electrocute_act(10 * siemens, src, 1.0, BP_TORSO, 0)
|
G.affecting.electrocute_act(10 * siemens, src, 1.0, BP_TORSO, 0)
|
||||||
var/agony = 80 * siemens //Does more than if hit with an electric hand, since grabbing is slower.
|
var/agony = 80 * siemens //Does more than if hit with an electric hand, since grabbing is slower.
|
||||||
G.affecting.stun_effect_act(0, agony, BP_TORSO, src)
|
G.affecting.stun_effect_act(0, agony, BP_TORSO, src, electric = TRUE)
|
||||||
|
|
||||||
add_attack_logs(src,G.affecting,"Changeling shocked")
|
add_attack_logs(src,G.affecting,"Changeling shocked")
|
||||||
|
|
||||||
|
|||||||
544
code/datums/components/traits/unlucky.dm
Normal file
544
code/datums/components/traits/unlucky.dm
Normal file
@@ -0,0 +1,544 @@
|
|||||||
|
/**
|
||||||
|
* Ripped from /tg/ with modifications.
|
||||||
|
* unlucky.dm: For when you want someone to have a really bad day
|
||||||
|
*
|
||||||
|
* When you attach an omen component to someone, they start running the risk of all sorts of bad environmental injuries, like nearby vending machines randomly falling on you (TBI),
|
||||||
|
* or hitting your head really hard when you slip and fall, or you get shocked by the tram rails at an unfortunate moment.
|
||||||
|
*
|
||||||
|
* Omens are removed once the victim is either maimed by one of the possible injuries, or if they receive a blessing (read: bashing with a bible) from the chaplain. (TBI)
|
||||||
|
*/
|
||||||
|
/datum/component/omen
|
||||||
|
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
|
||||||
|
/// How many incidents are left. If 0 exactly, it will get deleted.
|
||||||
|
var/incidents_left = INFINITY
|
||||||
|
/// Base probability of negative events. Cursed are half as unlucky.
|
||||||
|
var/luck_mod = 1
|
||||||
|
/// Base damage from negative events. Cursed take 25% of this damage.
|
||||||
|
var/damage_mod = 1
|
||||||
|
/// If we want to do more evil events, such as spontaneous combustion
|
||||||
|
var/evil = TRUE
|
||||||
|
/// If our codebase has safe disposals or not
|
||||||
|
var/safe_disposals = FALSE
|
||||||
|
/// If we have vore interactions or not
|
||||||
|
var/vorish = TRUE
|
||||||
|
|
||||||
|
/datum/component/omen/Initialize(incidents_left, luck_mod, damage_mod, evil, safe_disposals, vorish)
|
||||||
|
if(!isliving(parent))
|
||||||
|
return COMPONENT_INCOMPATIBLE
|
||||||
|
|
||||||
|
if(!isnull(incidents_left))
|
||||||
|
src.incidents_left = incidents_left
|
||||||
|
if(!isnull(luck_mod))
|
||||||
|
src.luck_mod = luck_mod
|
||||||
|
if(!isnull(damage_mod))
|
||||||
|
src.damage_mod = damage_mod
|
||||||
|
if(!isnull(evil))
|
||||||
|
src.evil = evil
|
||||||
|
if(!isnull(safe_disposals))
|
||||||
|
src.safe_disposals = safe_disposals
|
||||||
|
if(!isnull(vorish))
|
||||||
|
src.vorish = vorish
|
||||||
|
|
||||||
|
ADD_TRAIT(parent, TRAIT_UNLUCKY, src)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a omen eat omen world! The stronger omen survives.
|
||||||
|
*/
|
||||||
|
/datum/component/omen/InheritComponent(
|
||||||
|
datum/component/omen/new_comp,
|
||||||
|
i_am_original,
|
||||||
|
incidents_left,
|
||||||
|
luck_mod,
|
||||||
|
damage_mod,
|
||||||
|
evil,
|
||||||
|
safe_disposals,
|
||||||
|
vorish,
|
||||||
|
)
|
||||||
|
// If we have more incidents left the new one gets deleted.
|
||||||
|
if(src.incidents_left > incidents_left)
|
||||||
|
return
|
||||||
|
src.incidents_left = incidents_left
|
||||||
|
|
||||||
|
// The new omen is weaker than our current omen? Let's split the difference.
|
||||||
|
if(src.luck_mod > luck_mod)
|
||||||
|
src.luck_mod += luck_mod * 0.5
|
||||||
|
if(src.damage_mod > damage_mod)
|
||||||
|
src.damage_mod += damage_mod * 0.5
|
||||||
|
|
||||||
|
// If the new omen has special modifiers, we take them on forever!
|
||||||
|
if(evil)
|
||||||
|
src.evil = TRUE
|
||||||
|
if(safe_disposals)
|
||||||
|
src.safe_disposals = TRUE
|
||||||
|
if(vorish)
|
||||||
|
src.vorish = TRUE
|
||||||
|
//This means weaker, longing lasting omens will take priority, but have some of the strength of the original.
|
||||||
|
|
||||||
|
/datum/component/omen/Destroy(force)
|
||||||
|
var/mob/living/person = parent
|
||||||
|
REMOVE_TRAIT(person, TRAIT_UNLUCKY, src)
|
||||||
|
to_chat(person, span_warning(span_green("You feel a horrible omen lifted off your shoulders!")))
|
||||||
|
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/datum/component/omen/RegisterWithParent()
|
||||||
|
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(check_accident))
|
||||||
|
RegisterSignal(parent, COMSIG_ON_CARBON_SLIP, PROC_REF(check_slip))
|
||||||
|
RegisterSignal(parent, COMSIG_MOVED_DOWN_STAIRS, PROC_REF(check_stairs))
|
||||||
|
RegisterSignal(parent, COMSIG_STUN_EFFECT_ACT, PROC_REF(check_taser))
|
||||||
|
RegisterSignal(parent, COMSIG_MOB_ROLLED_DICE, PROC_REF(check_roll))
|
||||||
|
RegisterSignal(parent, COMSIG_HUMAN_ON_CATCH_THROW, PROC_REF(check_throw))
|
||||||
|
RegisterSignal(parent, COMSIG_PICKED_UP_ITEM, PROC_REF(check_pickup))
|
||||||
|
|
||||||
|
/datum/component/omen/UnregisterFromParent()
|
||||||
|
UnregisterSignal(parent, list(COMSIG_ON_CARBON_SLIP, COMSIG_MOVABLE_MOVED, COMSIG_STUN_EFFECT_ACT, COMSIG_MOVED_DOWN_STAIRS, COMSIG_MOB_ROLLED_DICE, COMSIG_HUMAN_ON_CATCH_THROW, COMSIG_PICKED_UP_ITEM))
|
||||||
|
|
||||||
|
/datum/component/omen/proc/consume_omen()
|
||||||
|
incidents_left--
|
||||||
|
if(incidents_left < 1)
|
||||||
|
qdel(src)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check_accident() is called each step we take
|
||||||
|
*
|
||||||
|
* While we're walking around, roll to see if there's any environmental hazards on one of the adjacent tiles we can trigger.
|
||||||
|
* We do the prob() at the beginning to A. add some tension for /when/ it will strike, and B. (more importantly) ameliorate the fact that we're checking up to 5 turfs's contents each time
|
||||||
|
*/
|
||||||
|
/datum/component/omen/proc/check_accident(atom/movable/our_guy)
|
||||||
|
SIGNAL_HANDLER
|
||||||
|
|
||||||
|
if(!isliving(our_guy) || isbelly(our_guy.loc))
|
||||||
|
return
|
||||||
|
|
||||||
|
var/mob/living/living_guy = our_guy
|
||||||
|
if(living_guy.is_incorporeal()) //no being unlucky if you don't even exist on the same plane.
|
||||||
|
return
|
||||||
|
|
||||||
|
if(evil && prob(0.0001) && (living_guy.stat != DEAD)) // 1 in a million
|
||||||
|
living_guy.visible_message(span_danger("[living_guy] suddenly bursts into flames!"), span_danger("You suddenly burst into flames!"))
|
||||||
|
living_guy.emote("scream")
|
||||||
|
living_guy.adjust_fire_stacks(20)
|
||||||
|
living_guy.ignite_mob()
|
||||||
|
consume_omen()
|
||||||
|
return
|
||||||
|
|
||||||
|
var/effective_luck = luck_mod
|
||||||
|
|
||||||
|
// If there's nobody to witness the misfortune, make it less likely.
|
||||||
|
// This way, we allow for people to be able to get into hilarious situations without making the game nigh unplayable most of the time.
|
||||||
|
|
||||||
|
var/has_watchers = FALSE
|
||||||
|
for(var/mob/viewer in viewers(our_guy, world.view))
|
||||||
|
if(viewer.client && !viewer.client.is_afk())
|
||||||
|
has_watchers = TRUE
|
||||||
|
break
|
||||||
|
if(!has_watchers)
|
||||||
|
effective_luck *= 0.5
|
||||||
|
|
||||||
|
if(!prob(2 * effective_luck))
|
||||||
|
return
|
||||||
|
|
||||||
|
var/turf/our_guy_pos = get_turf(our_guy)
|
||||||
|
if(!our_guy_pos)
|
||||||
|
return
|
||||||
|
if(evil)
|
||||||
|
for(var/obj/machinery/door/airlock/darth_airlock in our_guy_pos)
|
||||||
|
if(darth_airlock.locked || !darth_airlock.arePowerSystemsOn())
|
||||||
|
continue
|
||||||
|
to_chat(living_guy, span_warning("The airlock suddenly closes on you!"))
|
||||||
|
living_guy.Paralyse(1 SECONDS)
|
||||||
|
slam_airlock(darth_airlock)
|
||||||
|
consume_omen()
|
||||||
|
return
|
||||||
|
|
||||||
|
for(var/turf/the_turf as anything in our_guy_pos.AdjacentTurfs(check_blockage = FALSE)) //need false so we can check disposal units
|
||||||
|
if(the_turf.CanZPass(our_guy, DOWN))
|
||||||
|
to_chat(living_guy, span_warning("You lose your balance and slip towards the edge!"))
|
||||||
|
living_guy.Weaken(5)
|
||||||
|
living_guy.throw_at(the_turf, 1, 20)
|
||||||
|
consume_omen()
|
||||||
|
return
|
||||||
|
|
||||||
|
if(vorish)
|
||||||
|
for(var/mob/living/living_mob in the_turf)
|
||||||
|
if(living_mob == our_guy)
|
||||||
|
continue //Don't do anything to ourselves.
|
||||||
|
if(living_mob.stat)
|
||||||
|
continue
|
||||||
|
if(!living_mob.CanStumbleVore(living_guy) && !living_guy.CanStumbleVore(living_mob)) //Works both ways! Either way, someone's getting eaten!
|
||||||
|
continue
|
||||||
|
living_mob.stumble_into(living_guy) //logic reversed here because the game is DUMB. This means that living_guy is stumbling into the target!
|
||||||
|
living_guy.visible_message(span_danger("[living_guy] loses their balance and slips into [living_mob]!"), span_boldwarning("You lose your balance, slipping into [living_mob]!"))
|
||||||
|
consume_omen()
|
||||||
|
return
|
||||||
|
|
||||||
|
for(var/obj/machinery/washing_machine/evil_washer in the_turf)
|
||||||
|
if(evil_washer.state == 1) //Empty and open door
|
||||||
|
our_guy.visible_message(span_danger("[our_guy] slips near the [evil_washer] and falls in, the door shutting!"), span_boldwarning("You slip on a wet spot near the [evil_washer] and fall in, the door shutting! You're stuck!"))
|
||||||
|
our_guy.forceMove(evil_washer)
|
||||||
|
evil_washer.washing += our_guy
|
||||||
|
evil_washer.state = 4
|
||||||
|
evil_washer.visible_message(span_danger("[evil_washer] begins its spin cycle!"))
|
||||||
|
evil_washer.start(TRUE, damage_mod)
|
||||||
|
consume_omen()
|
||||||
|
return
|
||||||
|
|
||||||
|
if(evil || safe_disposals) //On servers without safe disposals, this is a death sentence. With servers with safe disposals, it's just funny.
|
||||||
|
for(var/obj/machinery/disposal/evil_disposal in the_turf)
|
||||||
|
if(evil_disposal.stat & (BROKEN|NOPOWER))
|
||||||
|
continue
|
||||||
|
if(evil_disposal.loc == living_guy.loc) //Let's not do a continual loop of them falling into it as soon as they climb out, as funny as that is.
|
||||||
|
continue
|
||||||
|
our_guy.visible_message(span_danger("[our_guy] slips on a spill near the [evil_disposal] and falls in!"), span_boldwarning("You slip on a spill near the [evil_disposal] and fall in!"))
|
||||||
|
living_guy.forceMove(evil_disposal)
|
||||||
|
evil_disposal.flush = TRUE
|
||||||
|
evil_disposal.update()
|
||||||
|
living_guy.Weaken(5)
|
||||||
|
consume_omen()
|
||||||
|
return
|
||||||
|
|
||||||
|
if(evil && prob(33)) //This has an additional 2 in 3 chance to not happen as there's a LOT of lights on stations. This should be rarer.
|
||||||
|
for(var/obj/machinery/light/evil_light in the_turf)
|
||||||
|
if((evil_light.status == LIGHT_BURNED || evil_light.status == LIGHT_BROKEN) || (living_guy.get_shock_protection() == 1)) // we can't do anything :(
|
||||||
|
to_chat(living_guy, span_warning("[evil_light] sparks weakly for a second."))
|
||||||
|
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread //this shit is copy pasted all over the code...this needs to just be made into a proc at this point jesus christ
|
||||||
|
s.set_up(4, FALSE, evil_light)
|
||||||
|
s.start()
|
||||||
|
//We don't clear the omen as nothing really happened.
|
||||||
|
break
|
||||||
|
|
||||||
|
to_chat(living_guy, span_warning("[evil_light] glows ominously...")) // ominously
|
||||||
|
evil_light.visible_message(span_boldwarning("[evil_light] suddenly flares brightly and sparks!"))
|
||||||
|
//evil_light.broken(skip_sound_and_sparks = FALSE) //Let's not break it actually.
|
||||||
|
evil_light.Beam(living_guy, icon_state = "lightning[rand(1,12)]", time = 0.5 SECONDS)
|
||||||
|
living_guy.electrocute_act(35 * (damage_mod * 0.5), evil_light, stun = TRUE) //Stun is binary and scales on damage..Lame.
|
||||||
|
living_guy.emote("scream")
|
||||||
|
consume_omen()
|
||||||
|
return
|
||||||
|
|
||||||
|
for(var/obj/machinery/vending/darth_vendor in the_turf)
|
||||||
|
if(darth_vendor.stat & (BROKEN|NOPOWER))
|
||||||
|
continue
|
||||||
|
to_chat(living_guy, span_warning("The delivery chute of [darth_vendor] raises up..."))
|
||||||
|
darth_vendor.throw_item(living_guy)
|
||||||
|
consume_omen()
|
||||||
|
return
|
||||||
|
|
||||||
|
for(var/obj/structure/mirror/evil_mirror in the_turf)
|
||||||
|
to_chat(living_guy, span_warning("You pass by the mirror and glance at it..."))
|
||||||
|
if(evil_mirror.shattered)
|
||||||
|
to_chat(living_guy, span_notice("You feel lucky, somehow."))
|
||||||
|
return
|
||||||
|
var/mirror_rand
|
||||||
|
if(evil)
|
||||||
|
mirror_rand = rand(1,5)
|
||||||
|
else
|
||||||
|
mirror_rand = rand(1,3)
|
||||||
|
switch(mirror_rand)
|
||||||
|
if(1)
|
||||||
|
to_chat(living_guy, span_boldwarning("You see your reflection, but it is grinning malevolently and staring directly at you!"))
|
||||||
|
living_guy.emote("scream")
|
||||||
|
if(2 to 3)
|
||||||
|
to_chat(living_guy, span_large(span_cult("Oh god, you can't see your reflection!!")))
|
||||||
|
living_guy.emote("scream")
|
||||||
|
if(4 to 5)
|
||||||
|
to_chat(living_guy, span_warning("The mirror explodes into a million pieces! Wait, does that mean you're even more unlucky?"))
|
||||||
|
evil_mirror.shatter()
|
||||||
|
if(prob(50 * effective_luck)) // sometimes
|
||||||
|
luck_mod += 0.25
|
||||||
|
damage_mod += 0.25
|
||||||
|
var/max_health_coefficient = (living_guy.maxHealth * 0.06)
|
||||||
|
for(var/obj/item/organ/external/limb in living_guy.organs)
|
||||||
|
living_guy.apply_damage(max_health_coefficient * damage_mod, BRUTE, limb.organ_tag, used_weapon = "glass shrapnel")
|
||||||
|
|
||||||
|
living_guy.make_jittery(250)
|
||||||
|
if(evil && prob(7 * effective_luck))
|
||||||
|
to_chat(living_guy, span_warning("You are completely shocked by this turn of events!"))
|
||||||
|
if(ishuman(living_guy))
|
||||||
|
var/mob/living/carbon/human/human_guy = living_guy
|
||||||
|
if(human_guy.should_have_organ(O_HEART))
|
||||||
|
for(var/obj/item/organ/internal/heart/heart in human_guy.internal_organs)
|
||||||
|
heart.bruise() //Closest thing we have to a heart attack.
|
||||||
|
to_chat(living_guy, span_boldwarning("You clutch at your heart!"))
|
||||||
|
|
||||||
|
consume_omen()
|
||||||
|
return
|
||||||
|
if(evil)
|
||||||
|
for(var/obj/item/reagent_containers/glass/beaker/evil_beaker in the_turf)
|
||||||
|
if(!evil_beaker.is_open_container() && (evil_beaker.reagents.total_volume > 0)) //A closed beaker is a safe beaker!
|
||||||
|
continue
|
||||||
|
living_guy.visible_message(span_danger("[evil_beaker] tilts, spilling its contents on [living_guy]!"), span_bolddanger("[evil_beaker] spills all over you!"))
|
||||||
|
evil_beaker.balloon_alert_visible("[evil_beaker]'s contents splashes onto [living_guy]!")
|
||||||
|
evil_beaker.reagents.splash(living_guy, evil_beaker.reagents.total_volume)
|
||||||
|
consume_omen()
|
||||||
|
return
|
||||||
|
|
||||||
|
for(var/obj/structure/table/evil_table in the_turf)
|
||||||
|
if(!evil_table.material) //We only want tables, not just table frames.
|
||||||
|
continue
|
||||||
|
var/datum/gender/gender = GLOB.gender_datums[living_guy.get_visible_gender()]
|
||||||
|
living_guy.visible_message(span_danger("[living_guy] stubs [gender.his] toe on [evil_table]!"), span_bolddanger("You stub your toe on [evil_table]!"))
|
||||||
|
living_guy.apply_damage(2 * damage_mod, BRUTE, pick(BP_L_FOOT, BP_R_FOOT), used_weapon = "blunt force trauma")
|
||||||
|
living_guy.adjustHalLoss(25) //It REALLY hurts.
|
||||||
|
living_guy.Weaken(3)
|
||||||
|
consume_omen()
|
||||||
|
return
|
||||||
|
//Ran out of turf options. Let's do more generic options.
|
||||||
|
|
||||||
|
if(prob(luck_mod * 5))
|
||||||
|
// In complete darkness
|
||||||
|
if(our_guy_pos.get_lumcount() <= LIGHTING_SOFT_THRESHOLD)
|
||||||
|
living_guy.Blind(5) //10 seconds of 'OH GOD WHAT'S HAPPENING'
|
||||||
|
living_guy.silent = 5
|
||||||
|
living_guy.Paralyse(5)
|
||||||
|
to_chat(living_guy, span_bolddanger("You feel the ground buckle underneath you, falling down, your vision going dark as you feel paralyzed in place!"))
|
||||||
|
consume_omen()
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
/datum/component/omen/proc/slam_airlock(obj/machinery/door/airlock/darth_airlock)
|
||||||
|
SIGNAL_HANDLER
|
||||||
|
. = darth_airlock.close(forced = TRUE, ignore_safties = TRUE, crush_damage = 15) //Not enough to cause any IB or massively injured organs.
|
||||||
|
if(.)
|
||||||
|
consume_omen()
|
||||||
|
|
||||||
|
/// If we get knocked down, see if we have a really bad slip and bash our head hard
|
||||||
|
/datum/component/omen/proc/check_slip(mob/living/our_guy, amount)
|
||||||
|
SIGNAL_HANDLER
|
||||||
|
|
||||||
|
if(prob(30)) // AAAA
|
||||||
|
our_guy.emote("scream")
|
||||||
|
to_chat(our_guy, span_cult("What a horrible night... To have a curse!"))
|
||||||
|
|
||||||
|
if(prob(30 * luck_mod) && our_guy.get_bodypart_name(BP_HEAD)) /// Bonk!
|
||||||
|
playsound(our_guy, 'sound/effects/tableheadsmash.ogg', 90, TRUE)
|
||||||
|
var/datum/gender/gender = GLOB.gender_datums[our_guy.get_visible_gender()]
|
||||||
|
our_guy.visible_message(span_danger("[our_guy] hits [gender.his] head really badly falling down!"), span_bolddanger("You hit your head really badly falling down!"))
|
||||||
|
var/max_health_coefficient = (our_guy.maxHealth * 0.5)
|
||||||
|
our_guy.apply_damage(max_health_coefficient * damage_mod, BRUTE, BP_HEAD, used_weapon = "slipping")
|
||||||
|
if(ishuman(our_guy))
|
||||||
|
var/mob/living/carbon/human/human_guy = our_guy
|
||||||
|
if(human_guy.should_have_organ(O_BRAIN))
|
||||||
|
for(var/obj/item/organ/internal/brain/brain in human_guy.internal_organs)
|
||||||
|
brain.take_damage(30 * damage_mod) //60 damage kills.
|
||||||
|
if(human_guy.glasses && human_guy.canUnEquip(human_guy.glasses))
|
||||||
|
var/turf/T = get_turf(human_guy)
|
||||||
|
if(T)
|
||||||
|
var/obj/item/our_glasses = human_guy.glasses
|
||||||
|
human_guy.unEquip(human_guy.glasses, target = T)
|
||||||
|
to_chat(human_guy, span_warning("Your glasses fly off as you hit the ground!"))
|
||||||
|
our_glasses.throw_at_random(FALSE, 3, 2)
|
||||||
|
consume_omen()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
/datum/component/omen/proc/check_roll(mob/living/unlucky_soul, var/obj/item/dice/the_dice, silent, result)
|
||||||
|
SIGNAL_HANDLER
|
||||||
|
if(prob(20 * luck_mod))
|
||||||
|
//unlucky_soul.visible_message(span_danger("[unlucky_soul] rolls [the_dice] with it landing on the edge of [result] before tilting over!"), span_boldwarning("You feel dreadfully unlucky as you roll the dice!"))
|
||||||
|
//I had thought about making this have a notice that it happened.
|
||||||
|
//However, gaslighting the user by providing no visible notice is MUCH funnier.
|
||||||
|
return 1 // We override the roll to a 1.
|
||||||
|
|
||||||
|
///Returns TRUE and stops us from catching
|
||||||
|
/datum/component/omen/proc/check_throw(mob/living/unlucky_soul, source, speed)
|
||||||
|
SIGNAL_HANDLER
|
||||||
|
if(prob(30 * luck_mod)) //~9% chance
|
||||||
|
if(istype(source, /obj/item/grenade))
|
||||||
|
var/obj/item/grenade/bad_grenade = source
|
||||||
|
if(bad_grenade.active)
|
||||||
|
unlucky_soul.put_in_active_hand(bad_grenade)
|
||||||
|
unlucky_soul.visible_message(span_warning("[src] catches [source] as it goes off in their hand!"), span_bolddanger("You catch [source] and it goes off in your hand!"))
|
||||||
|
unlucky_soul.throw_mode_off()
|
||||||
|
bad_grenade.detonate()
|
||||||
|
return TRUE
|
||||||
|
else
|
||||||
|
unlucky_soul.visible_message(span_attack("[unlucky_soul] tries to catch [source] and fumbles it, getting thrown back!"))
|
||||||
|
unlucky_soul.Weaken(5)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dynamic injury system for when you pick up objects!
|
||||||
|
* Some objects might cut, burn, or otherwise injure you if you pick them up!
|
||||||
|
* Genenerally more of an annoyance than anything.
|
||||||
|
* Variables that can be changed:
|
||||||
|
* injury_type, damage_to_inflict, damage_type, injury_verb, is_sharp, is_edge.
|
||||||
|
*/
|
||||||
|
/datum/component/omen/proc/check_pickup(mob/living/unlucky_soul, obj/item/item)
|
||||||
|
SIGNAL_HANDLER
|
||||||
|
if(prob(3 * luck_mod) && ishuman(unlucky_soul)) // ~3% chance
|
||||||
|
var/mob/living/carbon/human/unlucky_human = unlucky_soul
|
||||||
|
|
||||||
|
///What the injury will show up as on an autopsy.
|
||||||
|
var/injury_type = "injury"
|
||||||
|
|
||||||
|
///How much damage we'll inflect.
|
||||||
|
var/damage_to_inflict = 0
|
||||||
|
|
||||||
|
///What type of damage we'll inflict
|
||||||
|
var/damage_type = BRUTE
|
||||||
|
|
||||||
|
///If the item we get injured on has is sharp.
|
||||||
|
var/is_sharp = FALSE
|
||||||
|
|
||||||
|
///If the item we get injured on has an edge.
|
||||||
|
var/has_edge = FALSE
|
||||||
|
|
||||||
|
///What verb we use to describe the injury.
|
||||||
|
var/injury_verb = "cuts"
|
||||||
|
|
||||||
|
///What hand we are currently using, so we injure the correct one.
|
||||||
|
var/current_hand = BP_R_HAND
|
||||||
|
if(unlucky_human.hand)
|
||||||
|
current_hand = BP_L_HAND
|
||||||
|
|
||||||
|
if(istype(item, /obj/item/paper))
|
||||||
|
injury_verb = "cuts"
|
||||||
|
injury_type = "paper cut"
|
||||||
|
damage_to_inflict = 2
|
||||||
|
|
||||||
|
else if(istype(item, /obj/item/material/knife))
|
||||||
|
var/obj/item/material/knife = item
|
||||||
|
|
||||||
|
injury_verb = "cuts"
|
||||||
|
injury_type = "knife"
|
||||||
|
is_sharp = knife.sharp
|
||||||
|
has_edge = knife.edge
|
||||||
|
damage_to_inflict = knife.force
|
||||||
|
|
||||||
|
else if(istype(item, /obj/item/material/shard))
|
||||||
|
var/obj/item/material/shard/shard = item
|
||||||
|
|
||||||
|
injury_verb = "cuts"
|
||||||
|
injury_type = "shard"
|
||||||
|
is_sharp = shard.sharp
|
||||||
|
has_edge = shard.edge
|
||||||
|
damage_to_inflict = shard.force
|
||||||
|
|
||||||
|
else if(istype(item, /obj/item/flame/lighter))
|
||||||
|
var/obj/item/flame/lighter/lighter = item
|
||||||
|
if(!lighter.lit)
|
||||||
|
return
|
||||||
|
|
||||||
|
injury_verb = "burns"
|
||||||
|
injury_type = "lighter"
|
||||||
|
damage_type = BURN
|
||||||
|
damage_to_inflict = 5
|
||||||
|
|
||||||
|
else if(istype(item, /obj/item/tool/transforming/jawsoflife))
|
||||||
|
var/obj/item/tool/transforming/jawsoflife/jaws = item
|
||||||
|
|
||||||
|
injury_verb = "clamps"
|
||||||
|
injury_type = "industrial tool"
|
||||||
|
is_sharp = jaws.sharp
|
||||||
|
has_edge = jaws.edge
|
||||||
|
damage_to_inflict = jaws.force
|
||||||
|
|
||||||
|
else if(istype(item, /obj/item/tool/screwdriver))
|
||||||
|
var/obj/item/tool/screwdriver/screwdriver = item
|
||||||
|
|
||||||
|
injury_verb = "stabs"
|
||||||
|
injury_type = "industrial tool"
|
||||||
|
is_sharp = screwdriver.sharp
|
||||||
|
has_edge = screwdriver.edge
|
||||||
|
damage_to_inflict = screwdriver.force
|
||||||
|
|
||||||
|
else if(istype(item, /obj/item/tool/wirecutters))
|
||||||
|
var/obj/item/tool/wirecutters/wirecutters = item
|
||||||
|
|
||||||
|
injury_verb = "nips"
|
||||||
|
injury_type = "industrial tool"
|
||||||
|
is_sharp = wirecutters.sharp
|
||||||
|
has_edge = wirecutters.edge
|
||||||
|
damage_to_inflict = wirecutters.force
|
||||||
|
|
||||||
|
if(!damage_to_inflict)
|
||||||
|
return
|
||||||
|
|
||||||
|
var/datum/gender/gender = GLOB.gender_datums[unlucky_human.get_visible_gender()]
|
||||||
|
unlucky_human.visible_message(span_danger("[unlucky_human] accidentally [injury_verb] [gender.his] hand on [item]!"))
|
||||||
|
unlucky_human.apply_damage(damage_to_inflict * damage_mod, damage_type, current_hand, sharp = is_sharp, edge = has_edge, used_weapon = injury_type)
|
||||||
|
|
||||||
|
/datum/component/omen/proc/check_stairs(mob/living/unlucky_soul)
|
||||||
|
SIGNAL_HANDLER
|
||||||
|
if(prob(3 * luck_mod)) /// Bonk!
|
||||||
|
playsound(unlucky_soul, 'sound/effects/tableheadsmash.ogg', 90, TRUE)
|
||||||
|
unlucky_soul.visible_message(span_danger("One of the stairs give way as [unlucky_soul] steps onto it, tumbling them down to the bottom!"), span_bolddanger("A stair gives way and you trip to the bottom!"))
|
||||||
|
var/max_health_coefficient = (unlucky_soul.maxHealth * 0.09)
|
||||||
|
for(var/obj/item/organ/external/limb in unlucky_soul.organs) //In total, you should have 11 limbs (generally, unless you have an amputation). The full omen variant we want to leave you at 1 hp, the trait version less. As of writing, the trait version is 25% of the damage, so you take 24.75 across all limbs.
|
||||||
|
unlucky_soul.apply_damage(max_health_coefficient * damage_mod, BRUTE, limb.organ_tag, used_weapon = "slipping")
|
||||||
|
unlucky_soul.Weaken(5)
|
||||||
|
consume_omen()
|
||||||
|
|
||||||
|
/datum/component/omen/proc/check_taser(mob/living/unlucky_soul, stun_amount, agony_amount, def_zone, used_weapon, electric)
|
||||||
|
SIGNAL_HANDLER
|
||||||
|
if(!electric || !evil) //If it's not electric we don't care! Likewise, if we don't have the evil variant, don't care!
|
||||||
|
return
|
||||||
|
if(!ishuman(unlucky_soul))
|
||||||
|
return
|
||||||
|
if(prob(3 * luck_mod))
|
||||||
|
var/mob/living/carbon/human/human_guy = unlucky_soul
|
||||||
|
if(human_guy.should_have_organ(O_HEART))
|
||||||
|
for(var/obj/item/organ/internal/heart/heart in human_guy.internal_organs)
|
||||||
|
if(heart.robotic)
|
||||||
|
continue //Robotic hearts are immune to this.
|
||||||
|
heart.take_damage(10 * stun_amount * damage_mod)
|
||||||
|
heart.take_damage(0.25 * agony_amount * damage_mod)
|
||||||
|
playsound(src, 'sound/effects/singlebeat.ogg', 50, FALSE)
|
||||||
|
to_chat(unlucky_soul, span_bolddanger("You feel as though your heart stopped"))
|
||||||
|
human_guy.Stun(5)
|
||||||
|
consume_omen()
|
||||||
|
return
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The trait omen. Permanent.
|
||||||
|
* Has only a 30% chance of bad things happening, and takes only 25% of normal damage.
|
||||||
|
* Evil is false, so you get less dramatic things happening.
|
||||||
|
*/
|
||||||
|
/datum/component/omen/trait
|
||||||
|
incidents_left = INFINITY
|
||||||
|
dupe_type = /datum/component/omen/trait
|
||||||
|
luck_mod = 0.3 // 30% chance of bad things happening
|
||||||
|
damage_mod = 0.25 // 25% of normal damage
|
||||||
|
evil = FALSE
|
||||||
|
safe_disposals = FALSE
|
||||||
|
|
||||||
|
///Major variant of the trait.
|
||||||
|
/datum/component/omen/trait/major
|
||||||
|
evil = TRUE
|
||||||
|
damage_mod = 0.75 //75% of normal damage
|
||||||
|
|
||||||
|
///Variant trait for downstreams that have safe disposals.
|
||||||
|
/datum/component/omen/trait/safe_disposals
|
||||||
|
safe_disposals = TRUE
|
||||||
|
|
||||||
|
/datum/component/omen/trait/safe_disposals/major
|
||||||
|
evil = TRUE
|
||||||
|
damage_mod = 0.75 //75% of normal damage
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The bible omen.
|
||||||
|
* While it lasts, parent gets a cursed aura filter.
|
||||||
|
*/
|
||||||
|
/datum/component/omen/bible
|
||||||
|
incidents_left = 1
|
||||||
|
|
||||||
|
/datum/component/omen/bible/RegisterWithParent()
|
||||||
|
. = ..()
|
||||||
|
var/mob/living/living_parent = parent
|
||||||
|
living_parent.add_filter("omen", 2, list("type" = "drop_shadow", "color" = "#A50824", "alpha" = 0, "size" = 2))
|
||||||
|
var/filter = living_parent.get_filter("omen")
|
||||||
|
animate(filter, alpha = 255, time = 2 SECONDS, loop = -1)
|
||||||
|
animate(alpha = 0, time = 2 SECONDS)
|
||||||
|
|
||||||
|
/datum/component/omen/bible/UnregisterFromParent()
|
||||||
|
. = ..()
|
||||||
|
var/mob/living/living_parent = parent
|
||||||
|
living_parent.remove_filter("omen")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The dice omen.
|
||||||
|
* Single use omen from rolling a nat 1 on a cursed d20.
|
||||||
|
*/
|
||||||
|
/datum/component/omen/dice
|
||||||
|
incidents_left = 1
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
var/loot_left = 0 // When this reaches zero, and loot_depleted is true, you can't obtain anymore loot.
|
var/loot_left = 0 // When this reaches zero, and loot_depleted is true, you can't obtain anymore loot.
|
||||||
var/delete_on_depletion = FALSE // If true, and if the loot gets depleted as above, the pile is deleted.
|
var/delete_on_depletion = FALSE // If true, and if the loot gets depleted as above, the pile is deleted.
|
||||||
|
|
||||||
|
var/list/unlucky_loot = list() // Unlucky is the worst tier. Only people with the unlucky trait can get this stuff. Primed grenades, dangerous syringes, etc.
|
||||||
var/list/common_loot = list() // Common is generally less-than-useful junk and filler, at least for maint loot piles.
|
var/list/common_loot = list() // Common is generally less-than-useful junk and filler, at least for maint loot piles.
|
||||||
var/list/uncommon_loot = list() // Uncommon is actually maybe some useful items, usually the reason someone bothers looking inside.
|
var/list/uncommon_loot = list() // Uncommon is actually maybe some useful items, usually the reason someone bothers looking inside.
|
||||||
var/list/rare_loot = list() // Rare is really powerful, or at least unique items.
|
var/list/rare_loot = list() // Rare is really powerful, or at least unique items.
|
||||||
@@ -47,7 +48,17 @@
|
|||||||
var/obj/item/loot = null
|
var/obj/item/loot = null
|
||||||
var/span = "notice" // Blue
|
var/span = "notice" // Blue
|
||||||
|
|
||||||
if(prob(chance_uncommon) && uncommon_loot.len) // You might still get something good.
|
if(HAS_TRAIT(L, TRAIT_UNLUCKY) && unlucky_loot.len) // If you're unlucky, you will always find bad stuff.
|
||||||
|
loot = produce_unlucky_item(source)
|
||||||
|
span = "cult" // Purple and bold.
|
||||||
|
if(prob(1))
|
||||||
|
to_chat(L, span_danger("You cut your hand on something in the trash!"))
|
||||||
|
L.apply_damage(2, BRUTE, pick(BP_L_HAND, BP_R_HAND), used_weapon = "sharp object")
|
||||||
|
var/datum/disease/advance/random/random_disease = new /datum/disease/advance/random()
|
||||||
|
random_disease.spread_flags |= DISEASE_SPREAD_NON_CONTAGIOUS
|
||||||
|
L.ForceContractDisease(random_disease)
|
||||||
|
|
||||||
|
else if(prob(chance_uncommon) && uncommon_loot.len) // You might still get something good.
|
||||||
loot = produce_uncommon_item(source)
|
loot = produce_uncommon_item(source)
|
||||||
span = "alium" // Green
|
span = "alium" // Green
|
||||||
|
|
||||||
@@ -96,6 +107,9 @@
|
|||||||
if(delete_on_depletion)
|
if(delete_on_depletion)
|
||||||
qdel(source)
|
qdel(source)
|
||||||
|
|
||||||
|
/datum/element/lootable/proc/produce_unlucky_item(atom/source)
|
||||||
|
var/path = pick(unlucky_loot)
|
||||||
|
return new path(source)
|
||||||
|
|
||||||
/datum/element/lootable/proc/produce_common_item(atom/source)
|
/datum/element/lootable/proc/produce_common_item(atom/source)
|
||||||
var/path = pick(common_loot)
|
var/path = pick(common_loot)
|
||||||
|
|||||||
@@ -1,6 +1,44 @@
|
|||||||
// Contains loads of different types of boxes, which may have items inside!
|
// Contains loads of different types of boxes, which may have items inside!
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/datum/element/lootable/boxes
|
/datum/element/lootable/boxes
|
||||||
|
|
||||||
|
unlucky_loot = list(
|
||||||
|
/obj/item/grenade/flashbang/clusterbang/primed,
|
||||||
|
/obj/item/storage/box/old_syringes,
|
||||||
|
/obj/item/storage/box/donut/empty,
|
||||||
|
/obj/item/grenade/smokebomb/primed,
|
||||||
|
/obj/item/storage/box,
|
||||||
|
/obj/item/storage/box/cups,
|
||||||
|
/obj/item/trash/candle,
|
||||||
|
/obj/item/trash/candy,
|
||||||
|
/obj/item/trash/candy/proteinbar,
|
||||||
|
/obj/item/trash/candy/gums,
|
||||||
|
/obj/item/trash/cheesie,
|
||||||
|
/obj/item/trash/chips,
|
||||||
|
/obj/item/trash/chips/bbq,
|
||||||
|
/obj/item/trash/liquidfood,
|
||||||
|
/obj/item/trash/pistachios,
|
||||||
|
/obj/item/trash/plate,
|
||||||
|
/obj/item/trash/popcorn,
|
||||||
|
/obj/item/trash/raisins,
|
||||||
|
/obj/item/trash/semki,
|
||||||
|
/obj/item/trash/snack_bowl,
|
||||||
|
/obj/item/trash/sosjerky,
|
||||||
|
/obj/item/trash/syndi_cakes,
|
||||||
|
/obj/item/trash/tastybread,
|
||||||
|
/obj/item/trash/coffee,
|
||||||
|
/obj/item/trash/tray,
|
||||||
|
/obj/item/trash/unajerky,
|
||||||
|
/obj/item/trash/waffles,
|
||||||
|
/obj/item/spacecash/c1,
|
||||||
|
/obj/item/card/emag_broken,
|
||||||
|
/obj/effect/decal/remains/lizard,
|
||||||
|
/obj/effect/decal/remains/mouse,
|
||||||
|
/obj/effect/decal/remains/robot,
|
||||||
|
/obj/item/pizzabox/old,
|
||||||
|
/obj/item/paper/crumpled
|
||||||
|
)
|
||||||
|
|
||||||
common_loot = list(
|
common_loot = list(
|
||||||
/obj/item/storage/box,
|
/obj/item/storage/box,
|
||||||
/obj/item/storage/box/beakers,
|
/obj/item/storage/box/beakers,
|
||||||
|
|||||||
@@ -1,6 +1,43 @@
|
|||||||
// Has large amounts of possible items, most of which may or may not be useful.
|
// Has large amounts of possible items, most of which may or may not be useful.
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/datum/element/lootable/maint/junk
|
/datum/element/lootable/maint/junk
|
||||||
|
unlucky_loot = list(
|
||||||
|
/obj/item/grenade/flashbang/clusterbang/primed,
|
||||||
|
/obj/item/storage/box/old_syringes,
|
||||||
|
/obj/item/storage/box/donut/empty,
|
||||||
|
/obj/item/grenade/smokebomb/primed,
|
||||||
|
/obj/item/storage/box,
|
||||||
|
/obj/item/storage/box/cups,
|
||||||
|
/obj/item/trash/candle,
|
||||||
|
/obj/item/trash/candy,
|
||||||
|
/obj/item/trash/candy/proteinbar,
|
||||||
|
/obj/item/trash/candy/gums,
|
||||||
|
/obj/item/trash/cheesie,
|
||||||
|
/obj/item/trash/chips,
|
||||||
|
/obj/item/trash/chips/bbq,
|
||||||
|
/obj/item/trash/liquidfood,
|
||||||
|
/obj/item/trash/pistachios,
|
||||||
|
/obj/item/trash/plate,
|
||||||
|
/obj/item/trash/popcorn,
|
||||||
|
/obj/item/trash/raisins,
|
||||||
|
/obj/item/trash/semki,
|
||||||
|
/obj/item/trash/snack_bowl,
|
||||||
|
/obj/item/trash/sosjerky,
|
||||||
|
/obj/item/trash/syndi_cakes,
|
||||||
|
/obj/item/trash/tastybread,
|
||||||
|
/obj/item/trash/coffee,
|
||||||
|
/obj/item/trash/tray,
|
||||||
|
/obj/item/trash/unajerky,
|
||||||
|
/obj/item/trash/waffles,
|
||||||
|
/obj/item/spacecash/c1,
|
||||||
|
/obj/item/card/emag_broken,
|
||||||
|
/obj/effect/decal/remains/lizard,
|
||||||
|
/obj/effect/decal/remains/mouse,
|
||||||
|
/obj/effect/decal/remains/robot,
|
||||||
|
/obj/item/pizzabox/old,
|
||||||
|
/obj/item/paper/crumpled
|
||||||
|
)
|
||||||
|
|
||||||
common_loot = list(
|
common_loot = list(
|
||||||
/obj/item/flashlight/flare,
|
/obj/item/flashlight/flare,
|
||||||
/obj/item/flashlight/glowstick,
|
/obj/item/flashlight/glowstick,
|
||||||
@@ -95,6 +132,43 @@
|
|||||||
// Contains mostly useless garbage.
|
// Contains mostly useless garbage.
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/datum/element/lootable/maint/trash
|
/datum/element/lootable/maint/trash
|
||||||
|
unlucky_loot = list(
|
||||||
|
/obj/item/grenade/flashbang/clusterbang/primed,
|
||||||
|
/obj/item/storage/box/old_syringes,
|
||||||
|
/obj/item/storage/box/donut/empty,
|
||||||
|
/obj/item/grenade/smokebomb/primed,
|
||||||
|
/obj/item/storage/box,
|
||||||
|
/obj/item/storage/box/cups,
|
||||||
|
/obj/item/trash/candle,
|
||||||
|
/obj/item/trash/candy,
|
||||||
|
/obj/item/trash/candy/proteinbar,
|
||||||
|
/obj/item/trash/candy/gums,
|
||||||
|
/obj/item/trash/cheesie,
|
||||||
|
/obj/item/trash/chips,
|
||||||
|
/obj/item/trash/chips/bbq,
|
||||||
|
/obj/item/trash/liquidfood,
|
||||||
|
/obj/item/trash/pistachios,
|
||||||
|
/obj/item/trash/plate,
|
||||||
|
/obj/item/trash/popcorn,
|
||||||
|
/obj/item/trash/raisins,
|
||||||
|
/obj/item/trash/semki,
|
||||||
|
/obj/item/trash/snack_bowl,
|
||||||
|
/obj/item/trash/sosjerky,
|
||||||
|
/obj/item/trash/syndi_cakes,
|
||||||
|
/obj/item/trash/tastybread,
|
||||||
|
/obj/item/trash/coffee,
|
||||||
|
/obj/item/trash/tray,
|
||||||
|
/obj/item/trash/unajerky,
|
||||||
|
/obj/item/trash/waffles,
|
||||||
|
/obj/item/spacecash/c1,
|
||||||
|
/obj/item/card/emag_broken,
|
||||||
|
/obj/effect/decal/remains/lizard,
|
||||||
|
/obj/effect/decal/remains/mouse,
|
||||||
|
/obj/effect/decal/remains/robot,
|
||||||
|
/obj/item/pizzabox/old,
|
||||||
|
/obj/item/paper/crumpled
|
||||||
|
)
|
||||||
|
|
||||||
common_loot = list(
|
common_loot = list(
|
||||||
/obj/item/trash/candle,
|
/obj/item/trash/candle,
|
||||||
/obj/item/trash/candy,
|
/obj/item/trash/candy,
|
||||||
|
|||||||
@@ -5,6 +5,43 @@
|
|||||||
chance_rare = 2
|
chance_rare = 2
|
||||||
chance_gamma = 1 // Special single drop table
|
chance_gamma = 1 // Special single drop table
|
||||||
|
|
||||||
|
unlucky_loot = list(
|
||||||
|
/obj/item/grenade/flashbang/clusterbang/primed,
|
||||||
|
/obj/item/storage/box/old_syringes,
|
||||||
|
/obj/item/storage/box/donut/empty,
|
||||||
|
/obj/item/grenade/smokebomb/primed,
|
||||||
|
/obj/item/storage/box,
|
||||||
|
/obj/item/storage/box/cups,
|
||||||
|
/obj/item/trash/candle,
|
||||||
|
/obj/item/trash/candy,
|
||||||
|
/obj/item/trash/candy/proteinbar,
|
||||||
|
/obj/item/trash/candy/gums,
|
||||||
|
/obj/item/trash/cheesie,
|
||||||
|
/obj/item/trash/chips,
|
||||||
|
/obj/item/trash/chips/bbq,
|
||||||
|
/obj/item/trash/liquidfood,
|
||||||
|
/obj/item/trash/pistachios,
|
||||||
|
/obj/item/trash/plate,
|
||||||
|
/obj/item/trash/popcorn,
|
||||||
|
/obj/item/trash/raisins,
|
||||||
|
/obj/item/trash/semki,
|
||||||
|
/obj/item/trash/snack_bowl,
|
||||||
|
/obj/item/trash/sosjerky,
|
||||||
|
/obj/item/trash/syndi_cakes,
|
||||||
|
/obj/item/trash/tastybread,
|
||||||
|
/obj/item/trash/coffee,
|
||||||
|
/obj/item/trash/tray,
|
||||||
|
/obj/item/trash/unajerky,
|
||||||
|
/obj/item/trash/waffles,
|
||||||
|
/obj/item/spacecash/c1,
|
||||||
|
/obj/item/card/emag_broken,
|
||||||
|
/obj/effect/decal/remains/lizard,
|
||||||
|
/obj/effect/decal/remains/mouse,
|
||||||
|
/obj/effect/decal/remains/robot,
|
||||||
|
/obj/item/pizzabox/old,
|
||||||
|
/obj/item/paper/crumpled
|
||||||
|
)
|
||||||
|
|
||||||
common_loot = list(
|
common_loot = list(
|
||||||
/obj/item/clothing/gloves/rainbow,
|
/obj/item/clothing/gloves/rainbow,
|
||||||
/obj/item/clothing/gloves/white,
|
/obj/item/clothing/gloves/white,
|
||||||
|
|||||||
@@ -442,7 +442,7 @@ var/list/mob/living/forced_ambiance_list = list()
|
|||||||
if(istype(get_turf(mob), /turf/space)) // Can't fall onto nothing.
|
if(istype(get_turf(mob), /turf/space)) // Can't fall onto nothing.
|
||||||
return
|
return
|
||||||
|
|
||||||
if(istype(mob,/mob/living/carbon/human/))
|
if(ishuman(mob))
|
||||||
var/mob/living/carbon/human/H = mob
|
var/mob/living/carbon/human/H = mob
|
||||||
if(H.buckled)
|
if(H.buckled)
|
||||||
return // Being buckled to something solid keeps you in place.
|
return // Being buckled to something solid keeps you in place.
|
||||||
@@ -460,6 +460,11 @@ var/list/mob/living/forced_ambiance_list = list()
|
|||||||
H.AdjustStunned(1) // CHOMPedit: No longer a supermassive long stun.
|
H.AdjustStunned(1) // CHOMPedit: No longer a supermassive long stun.
|
||||||
// H.AdjustWeakened(3) // CHOMPedit: No longer weakens.
|
// H.AdjustWeakened(3) // CHOMPedit: No longer weakens.
|
||||||
to_chat(mob, span_notice("The sudden appearance of gravity makes you fall to the floor!"))
|
to_chat(mob, span_notice("The sudden appearance of gravity makes you fall to the floor!"))
|
||||||
|
if(HAS_TRAIT(H, TRAIT_UNLUCKY) && prob(50) && H.get_bodypart_name(BP_HEAD))
|
||||||
|
var/datum/gender/gender = GLOB.gender_datums[H.get_visible_gender()]
|
||||||
|
H.visible_message(span_warning("[H] falls to the ground from the sudden appearance of gravity, smashing [gender.his] head against the ground!"),span_warning("You smash your head into the ground as gravity appears!"))
|
||||||
|
H.apply_damage(14, BRUTE, BP_HEAD, used_weapon = "blunt force")
|
||||||
|
playsound(H, 'sound/effects/tableheadsmash.ogg', 90, TRUE)
|
||||||
playsound(mob, "bodyfall", 50, 1)
|
playsound(mob, "bodyfall", 50, 1)
|
||||||
|
|
||||||
/area/proc/prison_break(break_lights = TRUE, open_doors = TRUE, open_blast_doors = FALSE) //CHOMP Edit set blast doors to FALSE
|
/area/proc/prison_break(break_lights = TRUE, open_doors = TRUE, open_blast_doors = FALSE) //CHOMP Edit set blast doors to FALSE
|
||||||
|
|||||||
@@ -75,6 +75,7 @@
|
|||||||
anchored = TRUE
|
anchored = TRUE
|
||||||
movement_type = UNSTOPPABLE
|
movement_type = UNSTOPPABLE
|
||||||
var/turf/despawn_loc = null
|
var/turf/despawn_loc = null
|
||||||
|
var/has_hunted_unlucky = FALSE
|
||||||
|
|
||||||
/obj/effect/immovablerod/proc/TakeFlight(var/turf/end)
|
/obj/effect/immovablerod/proc/TakeFlight(var/turf/end)
|
||||||
despawn_loc = end
|
despawn_loc = end
|
||||||
@@ -112,8 +113,8 @@
|
|||||||
if(despawn_loc != null && (src.x == despawn_loc.x && src.y == despawn_loc.y))
|
if(despawn_loc != null && (src.x == despawn_loc.x && src.y == despawn_loc.y))
|
||||||
qdel(src)
|
qdel(src)
|
||||||
return
|
return
|
||||||
/* //Used in conjunction with the Unlucky/Cursed trait. NYI.
|
|
||||||
if(prob(10))
|
if(prob(10) && !has_hunted_unlucky)
|
||||||
hunt_unlucky()
|
hunt_unlucky()
|
||||||
|
|
||||||
/obj/effect/immovablerod/proc/hunt_unlucky()
|
/obj/effect/immovablerod/proc/hunt_unlucky()
|
||||||
@@ -132,7 +133,7 @@
|
|||||||
/obj/effect/immovablerod/proc/resume_path()
|
/obj/effect/immovablerod/proc/resume_path()
|
||||||
walk(src, 0)
|
walk(src, 0)
|
||||||
walk_towards(src, despawn_loc, 1)
|
walk_towards(src, despawn_loc, 1)
|
||||||
*/
|
|
||||||
/obj/effect/immovablerod/Destroy()
|
/obj/effect/immovablerod/Destroy()
|
||||||
walk(src, 0) // Because we might have called walk_towards, we must stop the walk loop or BYOND keeps an internal reference to us forever.
|
walk(src, 0) // Because we might have called walk_towards, we must stop the walk loop or BYOND keeps an internal reference to us forever.
|
||||||
return ..()
|
return ..()
|
||||||
|
|||||||
@@ -911,13 +911,13 @@ About the new airlock wires panel:
|
|||||||
adjustBruteLoss(crush_damage)
|
adjustBruteLoss(crush_damage)
|
||||||
return FALSE
|
return FALSE
|
||||||
|
|
||||||
/obj/machinery/door/airlock/close(var/forced=0)
|
/obj/machinery/door/airlock/close(var/forced= FALSE, var/ignore_safties = FALSE, var/crush_damage = DOOR_CRUSH_DAMAGE)
|
||||||
if(!can_close(forced))
|
if(!can_close(forced))
|
||||||
return FALSE
|
return FALSE
|
||||||
|
|
||||||
hold_open = null //if it passes the can close check, always make sure to clear hold open
|
hold_open = null //if it passes the can close check, always make sure to clear hold open
|
||||||
|
|
||||||
if(safe)
|
if(safe && !ignore_safties)
|
||||||
for(var/turf/turf in locs)
|
for(var/turf/turf in locs)
|
||||||
for(var/atom/movable/AM in turf)
|
for(var/atom/movable/AM in turf)
|
||||||
if(AM.blocks_airlock())
|
if(AM.blocks_airlock())
|
||||||
@@ -929,8 +929,8 @@ About the new airlock wires panel:
|
|||||||
|
|
||||||
for(var/turf/turf in locs)
|
for(var/turf/turf in locs)
|
||||||
for(var/atom/movable/AM in turf)
|
for(var/atom/movable/AM in turf)
|
||||||
if(AM.airlock_crush(DOOR_CRUSH_DAMAGE))
|
if(AM.airlock_crush(crush_damage))
|
||||||
take_damage(DOOR_CRUSH_DAMAGE)
|
take_damage(crush_damage)
|
||||||
|
|
||||||
use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people
|
use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people
|
||||||
has_beeped = 0
|
has_beeped = 0
|
||||||
|
|||||||
@@ -128,9 +128,9 @@
|
|||||||
if(!surpress_send) send_status()
|
if(!surpress_send) send_status()
|
||||||
|
|
||||||
|
|
||||||
/obj/machinery/door/airlock/close(surpress_send)
|
/obj/machinery/door/airlock/close(var/forced= FALSE, var/ignore_safties = FALSE, var/crush_damage = DOOR_CRUSH_DAMAGE)
|
||||||
. = ..()
|
. = ..()
|
||||||
if(!surpress_send) send_status()
|
if(!forced) send_status()
|
||||||
|
|
||||||
|
|
||||||
/obj/machinery/door/airlock/Bumped(atom/AM)
|
/obj/machinery/door/airlock/Bumped(atom/AM)
|
||||||
|
|||||||
@@ -527,7 +527,7 @@
|
|||||||
open_speed = 15
|
open_speed = 15
|
||||||
return (normalspeed ? open_speed : 5)
|
return (normalspeed ? open_speed : 5)
|
||||||
|
|
||||||
/obj/machinery/door/proc/close(var/forced = 0)
|
/obj/machinery/door/proc/close(var/forced = 0, var/ignore_safties = FALSE, var/crush_damage = DOOR_CRUSH_DAMAGE)
|
||||||
if(!can_close(forced))
|
if(!can_close(forced))
|
||||||
return
|
return
|
||||||
operating = 1
|
operating = 1
|
||||||
|
|||||||
@@ -115,6 +115,50 @@
|
|||||||
return
|
return
|
||||||
//CHOMPEdit End
|
//CHOMPEdit End
|
||||||
|
|
||||||
|
// Checks to make sure he's not in space doing it, and that the area got proper power.
|
||||||
|
if(!powered())
|
||||||
|
to_chat(user, span_warning("\The [src] blinks red as you try to insert [G]!"))
|
||||||
|
return
|
||||||
|
if(istype(G, /obj/item/gun/energy))
|
||||||
|
var/obj/item/gun/energy/E = G
|
||||||
|
if(E.self_recharge)
|
||||||
|
to_chat(user, span_notice("\The [E] has no recharge port."))
|
||||||
|
return
|
||||||
|
if(istype(G, /obj/item/modular_computer))
|
||||||
|
var/obj/item/modular_computer/C = G
|
||||||
|
if(!C.battery_module)
|
||||||
|
to_chat(user, span_notice("\The [C] does not have a battery installed. "))
|
||||||
|
return
|
||||||
|
if(istype(G, /obj/item/flash))
|
||||||
|
var/obj/item/flash/F = G
|
||||||
|
if(F.use_external_power)
|
||||||
|
to_chat(user, span_notice("\The [F] has no recharge port."))
|
||||||
|
return
|
||||||
|
if(istype(G, /obj/item/weldingtool/electric))
|
||||||
|
var/obj/item/weldingtool/electric/EW = G
|
||||||
|
if(EW.use_external_power)
|
||||||
|
to_chat(user, span_notice("\The [EW] has no recharge port."))
|
||||||
|
return
|
||||||
|
if(!G.get_cell() && !istype(G, /obj/item/ammo_casing/microbattery) && !istype(G, /obj/item/paicard)) //VOREStation Edit: NSFW charging
|
||||||
|
to_chat(user, "\The [G] does not have a battery installed.")
|
||||||
|
return
|
||||||
|
if(istype(G, /obj/item/paicard))
|
||||||
|
var/obj/item/paicard/ourcard = G
|
||||||
|
if(ourcard.panel_open)
|
||||||
|
to_chat(user, span_warning("\The [ourcard] won't fit in the recharger with its panel open."))
|
||||||
|
return
|
||||||
|
if(ourcard.pai)
|
||||||
|
if(ourcard.pai.stat == CONSCIOUS)
|
||||||
|
to_chat(user, span_warning("\The [ourcard] boops... it doesn't need to be recharged!"))
|
||||||
|
return
|
||||||
|
else
|
||||||
|
to_chat(user, span_warning("\The [ourcard] doesn't have a personality!"))
|
||||||
|
return
|
||||||
|
if(HAS_TRAIT(user, TRAIT_UNLUCKY) && prob(10))
|
||||||
|
user.visible_message("[user] inserts [charging] into [src] backwards!", "You insert [charging] into [src] backwards!")
|
||||||
|
user.drop_item()
|
||||||
|
G.loc = get_turf(src)
|
||||||
|
return
|
||||||
user.drop_item()
|
user.drop_item()
|
||||||
G.loc = src
|
G.loc = src
|
||||||
charging = G
|
charging = G
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
#define EMPTY_OPEN 1
|
||||||
|
#define EMPTY_CLOSED 2
|
||||||
|
#define FULL_OPEN 3
|
||||||
|
#define FULL_CLOSED 4
|
||||||
|
#define RUNNING 5
|
||||||
|
#define BLOODY_OPEN 6 //Not actually used...
|
||||||
|
#define BLOODY_CLOSED 7
|
||||||
|
#define BLOODY_RUNNING 8
|
||||||
|
|
||||||
|
|
||||||
/obj/machinery/washing_machine
|
/obj/machinery/washing_machine
|
||||||
name = "Washing Machine"
|
name = "Washing Machine"
|
||||||
desc = "Not a hiding place. Unfit for pets."
|
desc = "Not a hiding place. Unfit for pets."
|
||||||
@@ -9,19 +19,9 @@
|
|||||||
clickvol = 40
|
clickvol = 40
|
||||||
|
|
||||||
circuit = /obj/item/circuitboard/washing
|
circuit = /obj/item/circuitboard/washing
|
||||||
var/state = 1
|
var/state = EMPTY_OPEN
|
||||||
//1 = empty, open door
|
var/hacked = TRUE //Bleh, screw hacking, let's have it hacked by default.
|
||||||
//2 = empty, closed door
|
var/gibs_ready = FALSE
|
||||||
//3 = full, open door
|
|
||||||
//4 = full, closed door
|
|
||||||
//5 = running
|
|
||||||
//6 = blood, open door
|
|
||||||
//7 = blood, closed door
|
|
||||||
//8 = blood, running
|
|
||||||
var/hacked = 1 //Bleh, screw hacking, let's have it hacked by default.
|
|
||||||
//0 = not hacked
|
|
||||||
//1 = hacked
|
|
||||||
var/gibs_ready = 0
|
|
||||||
var/obj/crayon
|
var/obj/crayon
|
||||||
var/list/washing = list()
|
var/list/washing = list()
|
||||||
var/list/disallowed_types = list(
|
var/list/disallowed_types = list(
|
||||||
@@ -34,6 +34,14 @@
|
|||||||
default_apply_parts()
|
default_apply_parts()
|
||||||
AddElement(/datum/element/climbable)
|
AddElement(/datum/element/climbable)
|
||||||
|
|
||||||
|
/obj/machinery/washing_machine/Destroy()
|
||||||
|
for(var/atom/movable/washed_items in contents)
|
||||||
|
washed_items.forceMove(get_turf(src))
|
||||||
|
washing.Cut()
|
||||||
|
crayon = null
|
||||||
|
. = ..()
|
||||||
|
|
||||||
|
|
||||||
/obj/machinery/washing_machine/AltClick()
|
/obj/machinery/washing_machine/AltClick()
|
||||||
start()
|
start()
|
||||||
|
|
||||||
@@ -43,26 +51,27 @@
|
|||||||
set src in oview(1)
|
set src in oview(1)
|
||||||
start()
|
start()
|
||||||
|
|
||||||
/obj/machinery/washing_machine/proc/start()
|
/obj/machinery/washing_machine/proc/start(force, damage_modifier)
|
||||||
|
|
||||||
if(!isliving(usr)) //ew ew ew usr, but it's the only way to check.
|
if(!isliving(usr) && !force) //ew ew ew usr, but it's the only way to check.
|
||||||
return
|
return
|
||||||
|
if(!damage_modifier)
|
||||||
if(state != 4)
|
damage_modifier = 0.5
|
||||||
to_chat(usr, "The washing machine cannot run in this state.")
|
if(state != FULL_CLOSED)
|
||||||
|
visible_message("The washing machine buzzes - it can not run in this state!")
|
||||||
return
|
return
|
||||||
|
|
||||||
if(locate(/mob,washing))
|
if(locate(/mob,washing))
|
||||||
state = 8
|
state = BLOODY_RUNNING
|
||||||
else
|
else
|
||||||
state = 5
|
state = RUNNING
|
||||||
update_icon()
|
update_icon()
|
||||||
to_chat(usr, "The washing machine starts a cycle.")
|
visible_message("The washing machine starts a cycle.")
|
||||||
playsound(src, 'sound/items/washingmachine.ogg', 50, 1, 1)
|
playsound(src, 'sound/items/washingmachine.ogg', 50, 1, 1)
|
||||||
|
|
||||||
addtimer(CALLBACK(src, PROC_REF(finish_wash)), 2 SECONDS)
|
addtimer(CALLBACK(src, PROC_REF(finish_wash), damage_modifier), 2 SECONDS)
|
||||||
|
|
||||||
/obj/machinery/washing_machine/proc/finish_wash()
|
/obj/machinery/washing_machine/proc/finish_wash(damage_modifier)
|
||||||
for(var/atom/A in washing)
|
for(var/atom/A in washing)
|
||||||
A.wash(CLEAN_ALL)
|
A.wash(CLEAN_ALL)
|
||||||
|
|
||||||
@@ -74,21 +83,49 @@
|
|||||||
HH.use(HH.get_amount())
|
HH.use(HH.get_amount())
|
||||||
|
|
||||||
washing += WL
|
washing += WL
|
||||||
|
var/has_mobs = FALSE
|
||||||
|
for(var/mob/living/mobs in washing)
|
||||||
|
has_mobs = TRUE
|
||||||
|
if(ishuman(mobs))
|
||||||
|
var/mob/living/carbon/human/our_human = mobs
|
||||||
|
var/max_health_coefficient = (our_human.maxHealth * 0.09) //9 for 100% hp human, 4.5 for 50% hp human (teshari), etc.
|
||||||
|
for(var/i=0,i<10,i++)
|
||||||
|
our_human.apply_damage(max_health_coefficient*damage_modifier, BRUTE, used_weapon = "spin cycle") //Let's randomly do damage across the body. One limb might get hurt more than the others. At 100% damge mod, does 90% of max hp in damage.
|
||||||
|
continue
|
||||||
|
mobs.stat = DEAD //Kill them so they can't interact anymore.
|
||||||
|
|
||||||
if(locate(/mob,washing))
|
if(has_mobs)
|
||||||
state = 7
|
state = BLOODY_CLOSED
|
||||||
gibs_ready = 1
|
gibs_ready = TRUE
|
||||||
else
|
else
|
||||||
state = 4
|
state = FULL_CLOSED
|
||||||
update_icon()
|
update_icon()
|
||||||
|
|
||||||
/obj/machinery/washing_machine/verb/climb_out()
|
/obj/machinery/washing_machine/verb/climb_out()
|
||||||
set name = "Climb out"
|
set name = "Climb out"
|
||||||
set category = "Object"
|
set category = "Object"
|
||||||
set src in usr.loc
|
set src in usr.loc
|
||||||
|
user_climb_out(usr)
|
||||||
|
|
||||||
if((state in list(1,3,6)) && do_after(usr, 2 SECONDS, target = src))
|
/obj/machinery/washing_machine/proc/user_climb_out(mob/user)
|
||||||
usr.loc = src.loc
|
if(user.loc != src) //Have to be in it to climb out of it.
|
||||||
|
return
|
||||||
|
if(state in list(EMPTY_OPEN, FULL_OPEN, BLOODY_OPEN)) //Door is open, we can climb out easily.
|
||||||
|
visible_message("[user] begins to climb out of the [src]!")
|
||||||
|
if(do_after(user, 2 SECONDS, target = src))
|
||||||
|
if(!(state in list(EMPTY_CLOSED, FULL_CLOSED, BLOODY_CLOSED))) //Someone shut the door while we were trying to climb out!
|
||||||
|
user.forceMove(get_turf(src))
|
||||||
|
visible_message("[user] climbs out of the [src]!")
|
||||||
|
else
|
||||||
|
to_chat(user, "Someone shut the door on you!")
|
||||||
|
else if(state in list(EMPTY_CLOSED, FULL_CLOSED, BLOODY_CLOSED)) //Door is shut.
|
||||||
|
visible_message("[src] begins to rattle and shake!")
|
||||||
|
if(do_after(user, 60 SECONDS, target = src))
|
||||||
|
visible_message("[user] climbs out of the [src]!")
|
||||||
|
attack_hand(user, force = TRUE)
|
||||||
|
|
||||||
|
/obj/machinery/washing_machine/container_resist(mob/living/escapee)
|
||||||
|
user_climb_out(escapee)
|
||||||
|
|
||||||
/obj/machinery/washing_machine/update_icon()
|
/obj/machinery/washing_machine/update_icon()
|
||||||
cut_overlays()
|
cut_overlays()
|
||||||
@@ -97,7 +134,7 @@
|
|||||||
add_overlay("panel")
|
add_overlay("panel")
|
||||||
|
|
||||||
/obj/machinery/washing_machine/attackby(obj/item/W as obj, mob/user as mob)
|
/obj/machinery/washing_machine/attackby(obj/item/W as obj, mob/user as mob)
|
||||||
if(state == 2 && washing.len < 1)
|
if(state == EMPTY_CLOSED && washing.len < 1)
|
||||||
if(default_deconstruction_screwdriver(user, W))
|
if(default_deconstruction_screwdriver(user, W))
|
||||||
return
|
return
|
||||||
if(default_deconstruction_crowbar(user, W))
|
if(default_deconstruction_crowbar(user, W))
|
||||||
@@ -108,22 +145,30 @@
|
|||||||
panel = !panel
|
panel = !panel
|
||||||
to_chat(user, span_notice("You [panel ? "open" : "close"] the [src]'s maintenance panel"))*/
|
to_chat(user, span_notice("You [panel ? "open" : "close"] the [src]'s maintenance panel"))*/
|
||||||
if(istype(W,/obj/item/pen/crayon) || istype(W,/obj/item/stamp))
|
if(istype(W,/obj/item/pen/crayon) || istype(W,/obj/item/stamp))
|
||||||
if(state in list( 1, 3, 6))
|
if(state in list (EMPTY_OPEN, FULL_OPEN, BLOODY_OPEN))
|
||||||
if(!crayon)
|
if(!crayon)
|
||||||
user.drop_item()
|
user.drop_item()
|
||||||
crayon = W
|
crayon = W
|
||||||
|
crayon.forceMove(src)
|
||||||
crayon.loc = src
|
crayon.loc = src
|
||||||
else
|
else
|
||||||
..()
|
..()
|
||||||
else
|
else
|
||||||
..()
|
..()
|
||||||
else if(istype(W,/obj/item/grab))
|
else if(istype(W,/obj/item/grab))
|
||||||
if((state == 1) && hacked)
|
if((state == EMPTY_OPEN) && hacked)
|
||||||
var/obj/item/grab/G = W
|
var/obj/item/grab/G = W
|
||||||
if(ishuman(G.assailant) && iscorgi(G.affecting))
|
if(ishuman(G.assailant) && (iscorgi(G.affecting) || ishuman(G.affecting)))
|
||||||
G.affecting.loc = src
|
user.visible_message("[user] begins stuffing [G.affecting] into the [src]!", "You begin stuffing [G.affecting] into the [src]!")
|
||||||
qdel(G)
|
if(do_after(user, 5 SECONDS, target = src))
|
||||||
state = 3
|
if(state == EMPTY_OPEN) //Checking to make sure nobody closed it before we shoved em in it.
|
||||||
|
user.visible_message("[user] stuffs [G.affecting] into the [src] and shuts the door!", "You stuff [G.affecting] into the [src] and shut the door!")
|
||||||
|
G.affecting.forceMove(src)
|
||||||
|
washing += G.affecting
|
||||||
|
qdel(G)
|
||||||
|
state = FULL_CLOSED
|
||||||
|
else
|
||||||
|
to_chat(user, "You can't shove [G.affecting] in unless the washer is empty and open!")
|
||||||
else
|
else
|
||||||
..()
|
..()
|
||||||
|
|
||||||
@@ -133,11 +178,11 @@
|
|||||||
|
|
||||||
else if(istype(W, /obj/item/clothing) || istype(W, /obj/item/bedsheet) || istype(W, /obj/item/stack/hairlesshide))
|
else if(istype(W, /obj/item/clothing) || istype(W, /obj/item/bedsheet) || istype(W, /obj/item/stack/hairlesshide))
|
||||||
if(washing.len < 5)
|
if(washing.len < 5)
|
||||||
if(state in list(1, 3))
|
if(state in list(EMPTY_OPEN, FULL_OPEN))
|
||||||
user.drop_item()
|
user.drop_item()
|
||||||
W.loc = src
|
W.forceMove(src)
|
||||||
washing += W
|
washing += W
|
||||||
state = 3
|
state = FULL_OPEN
|
||||||
else
|
else
|
||||||
to_chat(user, span_notice("You can't put the item in right now."))
|
to_chat(user, span_notice("You can't put the item in right now."))
|
||||||
else
|
else
|
||||||
@@ -146,38 +191,50 @@
|
|||||||
..()
|
..()
|
||||||
update_icon()
|
update_icon()
|
||||||
|
|
||||||
/obj/machinery/washing_machine/attack_hand(mob/user as mob)
|
/obj/machinery/washing_machine/attack_hand(mob/user, force)
|
||||||
|
if(user.loc == src && !force)
|
||||||
|
return //No interacting with it from the inside!
|
||||||
switch(state)
|
switch(state)
|
||||||
if(1)
|
if(EMPTY_OPEN)
|
||||||
state = 2
|
state = EMPTY_CLOSED
|
||||||
if(2)
|
if(EMPTY_CLOSED)
|
||||||
state = 1
|
state = EMPTY_OPEN
|
||||||
for(var/atom/movable/O in washing)
|
for(var/atom/movable/O in washing)
|
||||||
O.loc = src.loc
|
O.forceMove(get_turf(src))
|
||||||
washing.Cut()
|
washing.Cut()
|
||||||
if(3)
|
if(FULL_OPEN)
|
||||||
state = 4
|
state = FULL_CLOSED
|
||||||
if(4)
|
if(FULL_CLOSED)
|
||||||
state = 3
|
|
||||||
for(var/atom/movable/O in washing)
|
for(var/atom/movable/O in washing)
|
||||||
O.loc = src.loc
|
O.forceMove(get_turf(src))
|
||||||
crayon = null
|
crayon = null
|
||||||
washing.Cut()
|
washing.Cut()
|
||||||
state = 1
|
state = EMPTY_OPEN
|
||||||
if(5)
|
if(RUNNING)
|
||||||
to_chat(user, span_warning("The [src] is busy."))
|
if(user)
|
||||||
if(6)
|
to_chat(user, span_warning("The [src] is busy."))
|
||||||
state = 7
|
if(BLOODY_OPEN)
|
||||||
if(7)
|
state = BLOODY_CLOSED
|
||||||
|
if(BLOODY_CLOSED)
|
||||||
if(gibs_ready)
|
if(gibs_ready)
|
||||||
gibs_ready = 0
|
gibs_ready = FALSE
|
||||||
if(locate(/mob,washing))
|
for(var/mob/living/mobs in washing)
|
||||||
var/mob/M = locate(/mob,washing)
|
if(ishuman(mobs)) //Humans have special handling.
|
||||||
M.gib()
|
continue
|
||||||
|
mobs.gib()
|
||||||
for(var/atom/movable/O in washing)
|
for(var/atom/movable/O in washing)
|
||||||
O.loc = src.loc
|
O.forceMove(get_turf(src))
|
||||||
crayon = null
|
crayon = null
|
||||||
state = 1
|
state = EMPTY_OPEN
|
||||||
washing.Cut()
|
washing.Cut()
|
||||||
|
|
||||||
update_icon()
|
update_icon()
|
||||||
|
|
||||||
|
#undef EMPTY_OPEN
|
||||||
|
#undef EMPTY_CLOSED
|
||||||
|
#undef FULL_OPEN
|
||||||
|
#undef FULL_CLOSED
|
||||||
|
#undef RUNNING
|
||||||
|
#undef BLOODY_OPEN
|
||||||
|
#undef BLOODY_CLOSED
|
||||||
|
#undef BLOODY_RUNNING
|
||||||
|
|||||||
@@ -440,6 +440,7 @@
|
|||||||
// called just as an item is picked up (loc is not yet changed)
|
// called just as an item is picked up (loc is not yet changed)
|
||||||
/obj/item/proc/pickup(mob/user)
|
/obj/item/proc/pickup(mob/user)
|
||||||
SEND_SIGNAL(src, COMSIG_ITEM_PICKUP, user)
|
SEND_SIGNAL(src, COMSIG_ITEM_PICKUP, user)
|
||||||
|
SEND_SIGNAL(user, COMSIG_PICKED_UP_ITEM, src)
|
||||||
pixel_x = 0
|
pixel_x = 0
|
||||||
pixel_y = 0
|
pixel_y = 0
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -389,6 +389,10 @@
|
|||||||
return
|
return
|
||||||
|
|
||||||
H.apply_damage(burn_damage_amt, BURN, BP_TORSO)
|
H.apply_damage(burn_damage_amt, BURN, BP_TORSO)
|
||||||
|
if(HAS_TRAIT(H, TRAIT_UNLUCKY) && prob(5))
|
||||||
|
make_announcement("buzzes, \"Unknown error occurred. Please try again.\"", "warning")
|
||||||
|
playsound(src, 'sound/machines/defib_failed.ogg', 50, FALSE)
|
||||||
|
return
|
||||||
|
|
||||||
//set oxyloss so that the patient is just barely in crit, if possible
|
//set oxyloss so that the patient is just barely in crit, if possible
|
||||||
var/barely_in_crit = H.get_crit_point() - 1
|
var/barely_in_crit = H.get_crit_point() - 1
|
||||||
@@ -437,7 +441,7 @@
|
|||||||
playsound(src, 'sound/weapons/egloves.ogg', 100, 1, -1)
|
playsound(src, 'sound/weapons/egloves.ogg', 100, 1, -1)
|
||||||
set_cooldown(cooldowntime)
|
set_cooldown(cooldowntime)
|
||||||
|
|
||||||
H.stun_effect_act(2, 120, target_zone)
|
H.stun_effect_act(2, 120, target_zone, electric = TRUE)
|
||||||
var/burn_damage = H.electrocute_act(burn_damage_amt*2, src, def_zone = target_zone)
|
var/burn_damage = H.electrocute_act(burn_damage_amt*2, src, def_zone = target_zone)
|
||||||
if(burn_damage > 15 && H.can_feel_pain())
|
if(burn_damage > 15 && H.can_feel_pain())
|
||||||
H.emote("scream")
|
H.emote("scream")
|
||||||
|
|||||||
@@ -162,3 +162,10 @@
|
|||||||
walk_away(src,temploc,stepdist)
|
walk_away(src,temploc,stepdist)
|
||||||
|
|
||||||
addtimer(CALLBACK(src, PROC_REF(detonate)), rand(15, 60), TIMER_DELETE_ME)
|
addtimer(CALLBACK(src, PROC_REF(detonate)), rand(15, 60), TIMER_DELETE_ME)
|
||||||
|
|
||||||
|
/obj/item/grenade/flashbang/clusterbang/primed
|
||||||
|
desc = "This clusterbang seems to have already been activated. Uhoh."
|
||||||
|
|
||||||
|
/obj/item/grenade/flashbang/clusterbang/primed/Initialize(mapload)
|
||||||
|
. = ..()
|
||||||
|
activate()
|
||||||
|
|||||||
@@ -37,3 +37,10 @@
|
|||||||
var/new_smoke_color = tgui_color_picker(user, "Choose a color for the smoke:", "Smoke Color", smoke_color)
|
var/new_smoke_color = tgui_color_picker(user, "Choose a color for the smoke:", "Smoke Color", smoke_color)
|
||||||
if(new_smoke_color)
|
if(new_smoke_color)
|
||||||
smoke_color = new_smoke_color
|
smoke_color = new_smoke_color
|
||||||
|
|
||||||
|
/obj/item/grenade/smokebomb/primed
|
||||||
|
desc = "A smoke bomb. This one appears to be already activated!"
|
||||||
|
|
||||||
|
/obj/item/grenade/smokebomb/primed/Initialize(mapload)
|
||||||
|
. = ..()
|
||||||
|
activate()
|
||||||
|
|||||||
@@ -205,7 +205,7 @@
|
|||||||
|
|
||||||
//stun effects
|
//stun effects
|
||||||
if(status)
|
if(status)
|
||||||
target.stun_effect_act(stun, agony, hit_zone, src)
|
target.stun_effect_act(stun, agony, hit_zone, src, electric = TRUE)
|
||||||
msg_admin_attack("[key_name(user)] stunned [key_name(target)] with the [src].")
|
msg_admin_attack("[key_name(user)] stunned [key_name(target)] with the [src].")
|
||||||
|
|
||||||
if(ishuman(target))
|
if(ishuman(target))
|
||||||
|
|||||||
@@ -216,6 +216,13 @@
|
|||||||
user.put_in_hands(stuff)
|
user.put_in_hands(stuff)
|
||||||
else
|
else
|
||||||
stuff.forceMove(drop_location())
|
stuff.forceMove(drop_location())
|
||||||
|
//Now here's the kicker
|
||||||
|
if(HAS_TRAIT(user, TRAIT_UNLUCKY) && prob(5)) //1 in 20 chance for your mail to be rigged with a glitter bomb
|
||||||
|
to_chat(user, span_bolddanger("You open the mail and - OH SHIT IS THAT A BOMB!"))
|
||||||
|
var/obj/item/grenade/confetti/confetti_nade = new /obj/item/grenade/confetti()
|
||||||
|
confetti_nade.name = "Pipebomb"
|
||||||
|
confetti_nade.desc = span_bolddanger("What the hell are you looking at it for?! RUN!!")
|
||||||
|
confetti_nade.activate()
|
||||||
playsound(loc, 'sound/items/poster_ripped.ogg', 100, TRUE)
|
playsound(loc, 'sound/items/poster_ripped.ogg', 100, TRUE)
|
||||||
qdel(src)
|
qdel(src)
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
/datum/blob_type/energized_jelly/on_attack(obj/structure/blob/B, mob/living/victim, def_zone)
|
/datum/blob_type/energized_jelly/on_attack(obj/structure/blob/B, mob/living/victim, def_zone)
|
||||||
victim.electrocute_act(10, src, 1, def_zone)
|
victim.electrocute_act(10, src, 1, def_zone)
|
||||||
victim.stun_effect_act(0, 40, BP_TORSO, src)
|
victim.stun_effect_act(0, 40, BP_TORSO, src, electric = TRUE)
|
||||||
|
|
||||||
/datum/blob_type/energized_jelly/on_chunk_tick(obj/item/blobcore_chunk/B)
|
/datum/blob_type/energized_jelly/on_chunk_tick(obj/item/blobcore_chunk/B)
|
||||||
for(var/mob/living/L in oview(world.view, get_turf(B)))
|
for(var/mob/living/L in oview(world.view, get_turf(B)))
|
||||||
|
|||||||
@@ -590,6 +590,13 @@ GLOBAL_LIST_EMPTY(vending_products)
|
|||||||
addtimer(CALLBACK(src, PROC_REF(delayed_vend), R, user), vend_delay)
|
addtimer(CALLBACK(src, PROC_REF(delayed_vend), R, user), vend_delay)
|
||||||
|
|
||||||
/obj/machinery/vending/proc/delayed_vend(datum/stored_item/vending_product/R, mob/user)
|
/obj/machinery/vending/proc/delayed_vend(datum/stored_item/vending_product/R, mob/user)
|
||||||
|
if(HAS_TRAIT(user, TRAIT_UNLUCKY) && prob(10))
|
||||||
|
visible_message(span_infoplain(span_bold("\The [src]") + " clunks and fails to dispense any item."))
|
||||||
|
playsound(src, "sound/[vending_sound]", 100, TRUE, 1)
|
||||||
|
vend_ready = 1
|
||||||
|
currently_vending = null
|
||||||
|
SStgui.update_uis(src)
|
||||||
|
return
|
||||||
R.get_product(get_turf(src))
|
R.get_product(get_turf(src))
|
||||||
if(has_logs)
|
if(has_logs)
|
||||||
do_logging(R, user, 1)
|
do_logging(R, user, 1)
|
||||||
@@ -715,9 +722,11 @@ GLOBAL_LIST_EMPTY(vending_products)
|
|||||||
return
|
return
|
||||||
|
|
||||||
//Somebody cut an important wire and now we're following a new definition of "pitch."
|
//Somebody cut an important wire and now we're following a new definition of "pitch."
|
||||||
/obj/machinery/vending/proc/throw_item()
|
/obj/machinery/vending/proc/throw_item(forced_target)
|
||||||
var/obj/item/throw_item = null
|
var/obj/item/throw_item = null
|
||||||
var/mob/living/target = locate() in view(7,src)
|
var/mob/living/target = locate() in view(7,src)
|
||||||
|
if(forced_target && isliving(forced_target))
|
||||||
|
target = forced_target
|
||||||
if(!target)
|
if(!target)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|||||||
@@ -27,3 +27,16 @@
|
|||||||
to_chat(user, span_warning("You need at least one working hand to snap your fingers."))
|
to_chat(user, span_warning("You need at least one working hand to snap your fingers."))
|
||||||
return FALSE
|
return FALSE
|
||||||
. = ..()
|
. = ..()
|
||||||
|
|
||||||
|
/decl/emote/audible/snap/do_extra(mob/user)
|
||||||
|
. = ..()
|
||||||
|
if(HAS_TRAIT(user, TRAIT_UNLUCKY) && prob(0.1) && ishuman(user)) //1 in a thousand
|
||||||
|
var/mob/living/carbon/human/unlucky_human = user
|
||||||
|
var/datum/component/omen/bad_luck = unlucky_human.GetComponent(/datum/component/omen) //Also going to make sure they got the EVIL version.
|
||||||
|
if(bad_luck.evil)
|
||||||
|
unlucky_human.visible_message(span_danger("[unlucky_human] snaps, their hand fading to ash!"), span_danger(span_huge("OH GOD YOUR HAND")))
|
||||||
|
for(var/limb in list(BP_L_HAND, BP_R_HAND))
|
||||||
|
var/obj/item/organ/external/L = unlucky_human.get_organ(limb)
|
||||||
|
if(istype(L) && L.is_usable() && !L.splinted)
|
||||||
|
L.droplimb(TRUE, DROPLIMB_BURN)
|
||||||
|
break
|
||||||
|
|||||||
@@ -91,10 +91,10 @@
|
|||||||
sides = 10
|
sides = 10
|
||||||
result = 10
|
result = 10
|
||||||
|
|
||||||
/obj/item/dice/attack_self(mob/user as mob)
|
/obj/item/dice/attack_self(mob/user)
|
||||||
rollDice(user, 0)
|
rollDice(user, 0)
|
||||||
|
|
||||||
/obj/item/dice/proc/rollDice(mob/user as mob, var/silent = 0)
|
/obj/item/dice/proc/rollDice(mob/user, silent = FALSE)
|
||||||
result = rand(1, sides)
|
result = rand(1, sides)
|
||||||
if(loaded)
|
if(loaded)
|
||||||
if(cheater)
|
if(cheater)
|
||||||
@@ -103,6 +103,9 @@
|
|||||||
else if(prob(75)) //makeshift weighted dice don't always work
|
else if(prob(75)) //makeshift weighted dice don't always work
|
||||||
result = loaded
|
result = loaded
|
||||||
icon_state = "[name][result]"
|
icon_state = "[name][result]"
|
||||||
|
var/result_override = SEND_SIGNAL(user, COMSIG_MOB_ROLLED_DICE, src, silent, result) //We can override dice rolls!
|
||||||
|
if(result_override)
|
||||||
|
result = result_override
|
||||||
|
|
||||||
if(!silent)
|
if(!silent)
|
||||||
var/comment = ""
|
var/comment = ""
|
||||||
@@ -192,18 +195,18 @@
|
|||||||
/obj/item/dice,
|
/obj/item/dice,
|
||||||
)
|
)
|
||||||
|
|
||||||
/obj/item/storage/dicecup/attack_self(mob/user as mob)
|
/obj/item/storage/dicecup/attack_self(mob/user)
|
||||||
user.visible_message(span_notice("[user] shakes [src]."), \
|
user.visible_message(span_notice("[user] shakes [src]."), \
|
||||||
span_notice("You shake [src]."), \
|
span_notice("You shake [src]."), \
|
||||||
span_notice("You hear dice rolling."))
|
span_notice("You hear dice rolling."))
|
||||||
rollCup(user)
|
rollCup(user)
|
||||||
|
|
||||||
/obj/item/storage/dicecup/proc/rollCup(mob/user as mob)
|
/obj/item/storage/dicecup/proc/rollCup(mob/user)
|
||||||
for(var/obj/item/dice/I in src.contents)
|
for(var/obj/item/dice/I in src.contents)
|
||||||
var/obj/item/dice/D = I
|
var/obj/item/dice/D = I
|
||||||
D.rollDice(user, 1)
|
D.rollDice(user, 1)
|
||||||
|
|
||||||
/obj/item/storage/dicecup/proc/revealDice(var/mob/viewer)
|
/obj/item/storage/dicecup/proc/revealDice(mob/viewer)
|
||||||
for(var/obj/item/dice/I in src.contents)
|
for(var/obj/item/dice/I in src.contents)
|
||||||
var/obj/item/dice/D = I
|
var/obj/item/dice/D = I
|
||||||
to_chat(viewer, "The [D.name] shows a [D.result].")
|
to_chat(viewer, "The [D.name] shows a [D.result].")
|
||||||
@@ -230,3 +233,40 @@
|
|||||||
. = ..()
|
. = ..()
|
||||||
for(var/i = 1 to 5)
|
for(var/i = 1 to 5)
|
||||||
new /obj/item/dice(src)
|
new /obj/item/dice(src)
|
||||||
|
|
||||||
|
/obj/item/dice/d20/cursed
|
||||||
|
name = "d20"
|
||||||
|
desc = "A dice with twenty sides."
|
||||||
|
icon_state = "d2020"
|
||||||
|
sides = 20
|
||||||
|
result = 20
|
||||||
|
|
||||||
|
///If the dice will apply the major version of unlucky or not.
|
||||||
|
var/evil = TRUE
|
||||||
|
|
||||||
|
|
||||||
|
/obj/item/dice/d20/cursed/rollDice(mob/user, silent = FALSE)
|
||||||
|
..()
|
||||||
|
if(result == 1)
|
||||||
|
to_chat(user, span_cult("You feel extraordinarily unlucky..."))
|
||||||
|
if(evil)
|
||||||
|
user.AddComponent(
|
||||||
|
/datum/component/omen/dice,\
|
||||||
|
incidents_left = 1,\
|
||||||
|
luck_mod = 1,\
|
||||||
|
damage_mod = 1,\
|
||||||
|
evil = TRUE,\
|
||||||
|
safe_disposals = FALSE,\
|
||||||
|
vorish = TRUE,\
|
||||||
|
)
|
||||||
|
|
||||||
|
else
|
||||||
|
user.AddComponent(
|
||||||
|
/datum/component/omen/dice,\
|
||||||
|
incidents_left = 1,\
|
||||||
|
luck_mod = 0.3,\
|
||||||
|
damage_mod = 1,\
|
||||||
|
evil = FALSE,\
|
||||||
|
safe_disposals = FALSE,\
|
||||||
|
vorish = TRUE,\
|
||||||
|
)
|
||||||
|
|||||||
@@ -323,7 +323,7 @@
|
|||||||
if(!H.lying || H.handcuffed || arrest_type)
|
if(!H.lying || H.handcuffed || arrest_type)
|
||||||
cuff = FALSE
|
cuff = FALSE
|
||||||
if(!cuff)
|
if(!cuff)
|
||||||
H.stun_effect_act(0, stun_strength, null)
|
H.stun_effect_act(0, stun_strength, null, electric = TRUE)
|
||||||
playsound(src, 'sound/weapons/egloves.ogg', 50, 1, -1)
|
playsound(src, 'sound/weapons/egloves.ogg', 50, 1, -1)
|
||||||
do_attack_animation(H)
|
do_attack_animation(H)
|
||||||
busy = TRUE
|
busy = TRUE
|
||||||
|
|||||||
@@ -389,8 +389,9 @@
|
|||||||
return
|
return
|
||||||
|
|
||||||
/mob/living/carbon/slip(var/slipped_on,stun_duration=8)
|
/mob/living/carbon/slip(var/slipped_on,stun_duration=8)
|
||||||
|
SEND_SIGNAL(src, COMSIG_ON_CARBON_SLIP, slipped_on, stun_duration)
|
||||||
if(buckled)
|
if(buckled)
|
||||||
return 0
|
return FALSE
|
||||||
stop_pulling()
|
stop_pulling()
|
||||||
to_chat(src, span_warning("You slipped on [slipped_on]!"))
|
to_chat(src, span_warning("You slipped on [slipped_on]!"))
|
||||||
playsound(src, 'sound/misc/slip.ogg', 50, 1, -3)
|
playsound(src, 'sound/misc/slip.ogg', 50, 1, -3)
|
||||||
@@ -399,7 +400,7 @@
|
|||||||
src.emote("sflip")
|
src.emote("sflip")
|
||||||
return 1 //CHOMPEdit End
|
return 1 //CHOMPEdit End
|
||||||
Weaken(FLOOR(stun_duration/2, 1))
|
Weaken(FLOOR(stun_duration/2, 1))
|
||||||
return 1
|
return TRUE
|
||||||
|
|
||||||
/mob/living/carbon/proc/add_chemical_effect(var/effect, var/magnitude = 1)
|
/mob/living/carbon/proc/add_chemical_effect(var/effect, var/magnitude = 1)
|
||||||
if(effect in chem_effects)
|
if(effect in chem_effects)
|
||||||
|
|||||||
@@ -1506,12 +1506,12 @@
|
|||||||
if(lying)
|
if(lying)
|
||||||
playsound(src, 'sound/misc/slip.ogg', 25, 1, -1)
|
playsound(src, 'sound/misc/slip.ogg', 25, 1, -1)
|
||||||
drop_both_hands()
|
drop_both_hands()
|
||||||
return 0
|
return FALSE
|
||||||
if((species.flags & NO_SLIP && !footcoverage_check) || (shoes && (shoes.item_flags & NOSLIP))) //Footwear negates a species' natural traction.
|
if((species.flags & NO_SLIP && !footcoverage_check) || (shoes && (shoes.item_flags & NOSLIP))) //Footwear negates a species' natural traction.
|
||||||
return 0
|
return FALSE
|
||||||
if(..(slipped_on,stun_duration))
|
if(..(slipped_on,stun_duration))
|
||||||
drop_both_hands()
|
drop_both_hands()
|
||||||
return 1
|
return TRUE
|
||||||
|
|
||||||
/mob/living/carbon/human/proc/relocate()
|
/mob/living/carbon/human/proc/relocate()
|
||||||
set category = "Object"
|
set category = "Object"
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ emp_act
|
|||||||
|
|
||||||
return (..(P , def_zone))
|
return (..(P , def_zone))
|
||||||
|
|
||||||
/mob/living/carbon/human/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone)
|
/mob/living/carbon/human/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone, var/used_weapon=null, var/electric = FALSE)
|
||||||
var/obj/item/organ/external/affected = get_organ(check_zone(def_zone))
|
var/obj/item/organ/external/affected = get_organ(check_zone(def_zone))
|
||||||
var/siemens_coeff = get_siemens_coefficient_organ(affected)
|
var/siemens_coeff = get_siemens_coefficient_organ(affected)
|
||||||
if(fire_stacks < 0) // Water makes you more conductive.
|
if(fire_stacks < 0) // Water makes you more conductive.
|
||||||
@@ -87,7 +87,7 @@ emp_act
|
|||||||
var/emote_scream = pick("screams in pain and ", "lets out a sharp cry and ", "cries out and ")
|
var/emote_scream = pick("screams in pain and ", "lets out a sharp cry and ", "cries out and ")
|
||||||
automatic_custom_emote(VISIBLE_MESSAGE, "[affected.organ_can_feel_pain() ? "" : emote_scream] drops what they were holding in their [affected.name]!", check_stat = TRUE)
|
automatic_custom_emote(VISIBLE_MESSAGE, "[affected.organ_can_feel_pain() ? "" : emote_scream] drops what they were holding in their [affected.name]!", check_stat = TRUE)
|
||||||
|
|
||||||
..(stun_amount, agony_amount, def_zone)
|
..(stun_amount, agony_amount, def_zone, used_weapon, electric)
|
||||||
|
|
||||||
/mob/living/carbon/human/getarmor(var/def_zone, var/type)
|
/mob/living/carbon/human/getarmor(var/def_zone, var/type)
|
||||||
var/armorval = 0
|
var/armorval = 0
|
||||||
@@ -433,8 +433,8 @@ emp_act
|
|||||||
return
|
return
|
||||||
if(in_throw_mode && speed <= THROWFORCE_SPEED_DIVISOR) //empty active hand and we're in throw mode
|
if(in_throw_mode && speed <= THROWFORCE_SPEED_DIVISOR) //empty active hand and we're in throw mode
|
||||||
if(canmove && !restrained() && !src.is_incorporeal())
|
if(canmove && !restrained() && !src.is_incorporeal())
|
||||||
if(isturf(O.loc))
|
if(isturf(O.loc) && can_catch(O))
|
||||||
if(can_catch(O))
|
if(!SEND_SIGNAL(src, COMSIG_HUMAN_ON_CATCH_THROW, source, speed))
|
||||||
put_in_active_hand(O)
|
put_in_active_hand(O)
|
||||||
visible_message(span_warning("[src] catches [O]!"))
|
visible_message(span_warning("[src] catches [O]!"))
|
||||||
throw_mode_off()
|
throw_mode_off()
|
||||||
|
|||||||
@@ -830,3 +830,26 @@
|
|||||||
addiction = REAGENT_ID_ASUSTENANCE
|
addiction = REAGENT_ID_ASUSTENANCE
|
||||||
custom_only = FALSE
|
custom_only = FALSE
|
||||||
hidden = TRUE //Disabled on Virgo
|
hidden = TRUE //Disabled on Virgo
|
||||||
|
|
||||||
|
/datum/trait/negative/unlucky
|
||||||
|
name = "Unlucky"
|
||||||
|
desc = "You are naturally unlucky and ill-events often befall you."
|
||||||
|
cost = -2
|
||||||
|
is_genetrait = FALSE
|
||||||
|
hidden = FALSE
|
||||||
|
custom_only = FALSE
|
||||||
|
added_component_path = /datum/component/omen/trait
|
||||||
|
excludes = list(/datum/trait/negative/unlucky/major)
|
||||||
|
|
||||||
|
|
||||||
|
/datum/trait/negative/unlucky/major
|
||||||
|
name = "Unlucky, Major"
|
||||||
|
desc = "Your luck is extremely awful and potentially fatal."
|
||||||
|
cost = -5
|
||||||
|
tutorial = "You should avoid disposal bins."
|
||||||
|
is_genetrait = TRUE
|
||||||
|
hidden = FALSE
|
||||||
|
added_component_path = /datum/component/omen/trait/major
|
||||||
|
excludes = list(/datum/trait/negative/unlucky)
|
||||||
|
activation_message= span_cult(span_bold("What a terrible night to have a curse!"))
|
||||||
|
primitive_expression_messages=list("unluckily stubs their toe!")
|
||||||
|
|||||||
@@ -117,7 +117,7 @@
|
|||||||
// Getting hurt in VR doesn't damage the physical body, but you still got hurt.
|
// Getting hurt in VR doesn't damage the physical body, but you still got hurt.
|
||||||
if(ishuman(vr_holder) && total_damage)
|
if(ishuman(vr_holder) && total_damage)
|
||||||
var/mob/living/carbon/human/V = vr_holder
|
var/mob/living/carbon/human/V = vr_holder
|
||||||
V.stun_effect_act(0, total_damage*2/3, null) // 200 damage leaves the user in paincrit for several seconds, agony reaches 0 after around 2m.
|
V.stun_effect_act(0, total_damage*2/3, null, electric = FALSE) // 200 damage leaves the user in paincrit for several seconds, agony reaches 0 after around 2m.
|
||||||
to_chat(vr_holder, span_warning("Pain from your time in VR lingers.")) // 250 damage leaves the user unconscious for several seconds in addition to paincrit
|
to_chat(vr_holder, span_warning("Pain from your time in VR lingers.")) // 250 damage leaves the user unconscious for several seconds in addition to paincrit
|
||||||
|
|
||||||
// Maintain a link with the mob, but don't use teleop
|
// Maintain a link with the mob, but don't use teleop
|
||||||
|
|||||||
@@ -134,7 +134,7 @@
|
|||||||
|
|
||||||
//Stun Beams
|
//Stun Beams
|
||||||
if(P.taser_effect)
|
if(P.taser_effect)
|
||||||
stun_effect_act(0, P.agony, def_zone, P)
|
stun_effect_act(0, P.agony, def_zone, P, electric = TRUE)
|
||||||
if(!P.nodamage)
|
if(!P.nodamage)
|
||||||
apply_damage(P.damage, P.damage_type, def_zone, absorb, soaked, 0, sharp=proj_sharp, edge=proj_edge, used_weapon=P, projectile=TRUE)
|
apply_damage(P.damage, P.damage_type, def_zone, absorb, soaked, 0, sharp=proj_sharp, edge=proj_edge, used_weapon=P, projectile=TRUE)
|
||||||
qdel(P)
|
qdel(P)
|
||||||
@@ -154,8 +154,9 @@
|
|||||||
// return absorb
|
// return absorb
|
||||||
|
|
||||||
//Handles the effects of "stun" weapons
|
//Handles the effects of "stun" weapons
|
||||||
/mob/living/proc/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone, var/used_weapon=null)
|
/mob/living/proc/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone, var/used_weapon=null, var/electric = FALSE)
|
||||||
flash_pain()
|
flash_pain()
|
||||||
|
SEND_SIGNAL(src, COMSIG_STUN_EFFECT_ACT, stun_amount, agony_amount, def_zone, used_weapon, electric)
|
||||||
|
|
||||||
if (stun_amount)
|
if (stun_amount)
|
||||||
Stun(stun_amount)
|
Stun(stun_amount)
|
||||||
|
|||||||
@@ -91,7 +91,7 @@
|
|||||||
to_chat(src, span_danger("Warning: Electromagnetic pulse detected."))
|
to_chat(src, span_danger("Warning: Electromagnetic pulse detected."))
|
||||||
..()
|
..()
|
||||||
|
|
||||||
/mob/living/silicon/stun_effect_act(var/stun_amount, var/agony_amount)
|
/mob/living/silicon/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone, var/used_weapon=null, var/electric = FALSE)
|
||||||
return //immune
|
return //immune
|
||||||
|
|
||||||
/mob/living/silicon/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 0.0, var/def_zone = null, var/stun = 1)
|
/mob/living/silicon/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 0.0, var/def_zone = null, var/stun = 1)
|
||||||
|
|||||||
@@ -190,9 +190,8 @@
|
|||||||
. = min(., 1.0)
|
. = min(., 1.0)
|
||||||
|
|
||||||
// Electricity
|
// Electricity
|
||||||
/mob/living/simple_mob/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null)
|
/mob/living/simple_mob/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null, var/stun = 1)
|
||||||
var/zap = min((1-get_shock_protection()), siemens_coeff)
|
shock_damage *= siemens_coeff
|
||||||
shock_damage *= zap
|
|
||||||
if(shock_damage < 1)
|
if(shock_damage < 1)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@@ -217,7 +216,7 @@
|
|||||||
. = min(., 1.0)
|
. = min(., 1.0)
|
||||||
|
|
||||||
// Shot with taser/stunvolver
|
// Shot with taser/stunvolver
|
||||||
/mob/living/simple_mob/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone, var/used_weapon=null)
|
/mob/living/simple_mob/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone, var/used_weapon=null, var/electric = FALSE)
|
||||||
if(taser_kill)
|
if(taser_kill)
|
||||||
var/stunDam = 0
|
var/stunDam = 0
|
||||||
var/agonyDam = 0
|
var/agonyDam = 0
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
adjust_discipline(2) // Justified.
|
adjust_discipline(2) // Justified.
|
||||||
|
|
||||||
// Shocked grilles don't hurt slimes, and in fact give them charge.
|
// Shocked grilles don't hurt slimes, and in fact give them charge.
|
||||||
/mob/living/simple_mob/slime/xenobio/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0, def_zone = null)
|
/mob/living/simple_mob/slime/xenobio/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0, def_zone = null, stun = 1)
|
||||||
power_charge = between(0, power_charge + round(shock_damage / 10), 10)
|
power_charge = between(0, power_charge + round(shock_damage / 10), 10)
|
||||||
to_chat(src, span_notice("\The [source] shocks you, and it charges you."))
|
to_chat(src, span_notice("\The [source] shocks you, and it charges you."))
|
||||||
|
|
||||||
|
|||||||
@@ -116,8 +116,19 @@
|
|||||||
// On-click handling. Turns on the computer if it's off and opens the GUI.
|
// On-click handling. Turns on the computer if it's off and opens the GUI.
|
||||||
/obj/item/modular_computer/attack_self(var/mob/user)
|
/obj/item/modular_computer/attack_self(var/mob/user)
|
||||||
if(enabled && screen_on)
|
if(enabled && screen_on)
|
||||||
|
if(isliving(user) && HAS_TRAIT(user, TRAIT_UNLUCKY) && prob(5))
|
||||||
|
var/mob/living/unlucky_soul = user
|
||||||
|
to_chat(user, span_danger("You interact with \the [src] and are met with a sudden shock!"))
|
||||||
|
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||||
|
s.set_up(5, 1, src)
|
||||||
|
s.start()
|
||||||
|
unlucky_soul.electrocute_act(5, src, 1)
|
||||||
|
return
|
||||||
tgui_interact(user)
|
tgui_interact(user)
|
||||||
else if(!enabled && screen_on)
|
else if(!enabled && screen_on)
|
||||||
|
if(HAS_TRAIT(user, TRAIT_UNLUCKY) && prob(25))
|
||||||
|
to_chat(user, "You try to turn on \the [src] but it doesn't respond.")
|
||||||
|
return
|
||||||
turn_on(user)
|
turn_on(user)
|
||||||
|
|
||||||
/obj/item/modular_computer/attackby(var/obj/item/W, var/mob/user)
|
/obj/item/modular_computer/attackby(var/obj/item/W, var/mob/user)
|
||||||
|
|||||||
@@ -193,7 +193,7 @@
|
|||||||
var/mob/living/L = P
|
var/mob/living/L = P
|
||||||
if(L.client)
|
if(L.client)
|
||||||
L.client.Process_Grab() // Update any miscellanous grabs, possibly break grab-chains
|
L.client.Process_Grab() // Update any miscellanous grabs, possibly break grab-chains
|
||||||
|
SEND_SIGNAL(AM, COMSIG_MOVED_UP_STAIRS, AM, oldloc)
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
/obj/structure/stairs/bottom/use_stairs_instant(var/atom/movable/AM)
|
/obj/structure/stairs/bottom/use_stairs_instant(var/atom/movable/AM)
|
||||||
@@ -231,6 +231,7 @@
|
|||||||
L.client.Process_Grab()
|
L.client.Process_Grab()
|
||||||
else
|
else
|
||||||
AM.forceMove(get_turf(top))
|
AM.forceMove(get_turf(top))
|
||||||
|
SEND_SIGNAL(AM, COMSIG_MOVED_UP_STAIRS, AM)
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@@ -452,7 +453,7 @@
|
|||||||
var/mob/living/L = P
|
var/mob/living/L = P
|
||||||
if(L.client)
|
if(L.client)
|
||||||
L.client.Process_Grab() // Update any miscellanous grabs, possibly break grab-chains
|
L.client.Process_Grab() // Update any miscellanous grabs, possibly break grab-chains
|
||||||
|
SEND_SIGNAL(AM, COMSIG_MOVED_DOWN_STAIRS, AM, oldloc)
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
/obj/structure/stairs/top/use_stairs_instant(var/atom/movable/AM)
|
/obj/structure/stairs/top/use_stairs_instant(var/atom/movable/AM)
|
||||||
@@ -489,6 +490,7 @@
|
|||||||
L.client.Process_Grab()
|
L.client.Process_Grab()
|
||||||
else
|
else
|
||||||
AM.forceMove(get_turf(bottom))
|
AM.forceMove(get_turf(bottom))
|
||||||
|
SEND_SIGNAL(AM, COMSIG_MOVED_DOWN_STAIRS, AM)
|
||||||
|
|
||||||
// Mapping pieces, placed at the bottommost part of the stairs
|
// Mapping pieces, placed at the bottommost part of the stairs
|
||||||
/obj/structure/stairs/spawner
|
/obj/structure/stairs/spawner
|
||||||
|
|||||||
@@ -869,7 +869,7 @@ GLOBAL_LIST_EMPTY(light_type_cache)
|
|||||||
|
|
||||||
// break the light and make sparks if was on
|
// break the light and make sparks if was on
|
||||||
|
|
||||||
/obj/machinery/light/proc/broken(var/skip_sound_and_sparks = 0)
|
/obj/machinery/light/proc/broken(var/skip_sound_and_sparks = FALSE)
|
||||||
if(status == LIGHT_EMPTY)
|
if(status == LIGHT_EMPTY)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -150,7 +150,7 @@
|
|||||||
overlay_above_everything = TRUE
|
overlay_above_everything = TRUE
|
||||||
color = "#3e5064"
|
color = "#3e5064"
|
||||||
|
|
||||||
/obj/machinery/light/small/fairylights/broken()
|
/obj/machinery/light/small/fairylights/broken(var/skip_sound_and_sparks = FALSE)
|
||||||
return
|
return
|
||||||
|
|
||||||
/obj/machinery/light/small/fairylights/flicker
|
/obj/machinery/light/small/fairylights/flicker
|
||||||
|
|||||||
@@ -273,7 +273,7 @@
|
|||||||
target.visible_message(span_danger("[target] has been zapped with [src] by [user]!"))
|
target.visible_message(span_danger("[target] has been zapped with [src] by [user]!"))
|
||||||
|
|
||||||
playsound(src, 'sound/weapons/egloves.ogg', 50, 1, -1)
|
playsound(src, 'sound/weapons/egloves.ogg', 50, 1, -1)
|
||||||
target.stun_effect_act(0, agony, hit_zone, src)
|
target.stun_effect_act(0, agony, hit_zone, src, electric = TRUE)
|
||||||
msg_admin_attack("[key_name(user)] stunned [key_name(target)] with the [src].")
|
msg_admin_attack("[key_name(user)] stunned [key_name(target)] with the [src].")
|
||||||
if(ishuman(target))
|
if(ishuman(target))
|
||||||
var/mob/living/carbon/human/H = target
|
var/mob/living/carbon/human/H = target
|
||||||
@@ -495,7 +495,7 @@
|
|||||||
else
|
else
|
||||||
target.visible_message(span_danger("[target] has been prodded with [src] by [user]!"))
|
target.visible_message(span_danger("[target] has been prodded with [src] by [user]!"))
|
||||||
playsound(src, 'sound/weapons/egloves.ogg', 50, 1, -1)
|
playsound(src, 'sound/weapons/egloves.ogg', 50, 1, -1)
|
||||||
target.stun_effect_act(stun, agony, hit_zone, src)
|
target.stun_effect_act(stun, agony, hit_zone, src, electric = TRUE)
|
||||||
msg_admin_attack("[key_name(user)] stunned [key_name(target)] with the [src].")
|
msg_admin_attack("[key_name(user)] stunned [key_name(target)] with the [src].")
|
||||||
if(ishuman(target))
|
if(ishuman(target))
|
||||||
var/mob/living/carbon/human/H = target
|
var/mob/living/carbon/human/H = target
|
||||||
|
|||||||
@@ -2,6 +2,14 @@
|
|||||||
//The winner of the pull has an effect applied to them.
|
//The winner of the pull has an effect applied to them.
|
||||||
//Crackers do already exist, but these ones are a more memey scene item.
|
//Crackers do already exist, but these ones are a more memey scene item.
|
||||||
|
|
||||||
|
#define SHRINKING_CRACKER "shrinking"
|
||||||
|
#define GROWING_CRACKER "growing"
|
||||||
|
#define DRUGGED_CRACKER "drugged"
|
||||||
|
#define INVISIBLE_CRACKER "invisibility"
|
||||||
|
#define FALLING_CRACKER "knockdown"
|
||||||
|
#define TELEPORTING_CRACKER "teleport"
|
||||||
|
#define WEALTHY_CRACKER "wealth"
|
||||||
|
|
||||||
/obj/item/cracker
|
/obj/item/cracker
|
||||||
name = "bluespace cracker" //I have no idea why this was called shrink ray when this increased and decreased size.
|
name = "bluespace cracker" //I have no idea why this was called shrink ray when this increased and decreased size.
|
||||||
desc = "A celebratory little game with a bluespace twist! Pull it between two people until it snaps, and the person who recieves the larger end gets a prize!"
|
desc = "A celebratory little game with a bluespace twist! Pull it between two people until it snaps, and the person who recieves the larger end gets a prize!"
|
||||||
@@ -13,26 +21,35 @@
|
|||||||
)
|
)
|
||||||
item_state = "blue"
|
item_state = "blue"
|
||||||
var/rigged = 0 //So that they can be rigged by varedits to go one way or the other. positive values mean holder always wins, negative values mean target always wins.
|
var/rigged = 0 //So that they can be rigged by varedits to go one way or the other. positive values mean holder always wins, negative values mean target always wins.
|
||||||
var/list/prizes = list("shrinking","growing","drugged","invisibility","knocked over","teleport","wealth")
|
var/prize //What prize we have loaded
|
||||||
var/list/jokes = list(
|
var/joke //What joke we have loaded
|
||||||
"When is a boat just like snow? When it's adrift.",
|
|
||||||
"What happens to naughty elves? Santa gives them the sack.",
|
/obj/item/cracker/Initialize(mapload)
|
||||||
"What do you call an old snowman? Water.",
|
. = ..()
|
||||||
"Why has Santa been banned from sooty chimneys? Carbon footprints.",
|
var/style = pick("blue","green","yellow","red","heart","hazard")
|
||||||
"What goes down but doesn't come up? A yo.",
|
icon_state = style
|
||||||
"What's green and fuzzy, has four legs and would kill you if it fell from a tree? A pool table.",
|
item_state = style
|
||||||
"Why did the blind man fall into the well? Because he couldn't see that well.",
|
if(!prize)
|
||||||
"What did the pirate get on his report card? Seven Cs",
|
prize = pick(SHRINKING_CRACKER,GROWING_CRACKER,GROWING_CRACKER,INVISIBLE_CRACKER,FALLING_CRACKER,TELEPORTING_CRACKER,WEALTHY_CRACKER)
|
||||||
"What do you call a fish with no eyes? Fsh",
|
if(!joke)
|
||||||
"How do you make an egg roll? You push it.",
|
joke = pick("When is a boat just like snow? When it's adrift.",
|
||||||
"What do you call a deer with no eyes? NO EYED DEER!",
|
"What happens to naughty elves? Santa gives them the sack.",
|
||||||
"What's red, and smells like blue paint? Red paint.",
|
"What do you call an old snowman? Water.",
|
||||||
"Where do cows go to dance? A meat ball.",
|
"Why has Santa been banned from sooty chimneys? Carbon footprints.",
|
||||||
"What do you call a person who steals all your toenail clippings? A cliptoemaniac.",
|
"What goes down but doesn't come up? A yo.",
|
||||||
"What's brown and sticky? A stick.",
|
"What's green and fuzzy, has four legs and would kill you if it fell from a tree? A pool table.",
|
||||||
"What's the best way to kill a circus? Go for the juggler.",
|
"Why did the blind man fall into the well? Because he couldn't see that well.",
|
||||||
"What do you call a cow with no legs? Ground Beef.",
|
"What did the pirate get on his report card? Seven Cs",
|
||||||
"Why'd the scarecrow win the Nobel prize? He was outstanding in his field.")
|
"What do you call a fish with no eyes? Fsh",
|
||||||
|
"How do you make an egg roll? You push it.",
|
||||||
|
"What do you call a deer with no eyes? NO EYED DEER!",
|
||||||
|
"What's red, and smells like blue paint? Red paint.",
|
||||||
|
"Where do cows go to dance? A meat ball.",
|
||||||
|
"What do you call a person who steals all your toenail clippings? A cliptoemaniac.",
|
||||||
|
"What's brown and sticky? A stick.",
|
||||||
|
"What's the best way to kill a circus? Go for the juggler.",
|
||||||
|
"What do you call a cow with no legs? Ground Beef.",
|
||||||
|
"Why'd the scarecrow win the Nobel prize? He was outstanding in his field.")
|
||||||
|
|
||||||
/obj/item/cracker/attack(atom/A, mob/living/user, adjacent, params)
|
/obj/item/cracker/attack(atom/A, mob/living/user, adjacent, params)
|
||||||
var/mob/living/carbon/human/target = A
|
var/mob/living/carbon/human/target = A
|
||||||
@@ -56,8 +73,6 @@
|
|||||||
to_chat(user, span_notice("\The [src] is no longer in-hand!"))
|
to_chat(user, span_notice("\The [src] is no longer in-hand!"))
|
||||||
to_chat(target, span_notice("\The [src] is no longer in-hand!"))
|
to_chat(target, span_notice("\The [src] is no longer in-hand!"))
|
||||||
return
|
return
|
||||||
var/prize = pick(prizes)
|
|
||||||
var/joke = pick(jokes)
|
|
||||||
var/mob/living/carbon/human/winner
|
var/mob/living/carbon/human/winner
|
||||||
var/mob/living/carbon/human/loser
|
var/mob/living/carbon/human/loser
|
||||||
if(!rigged)
|
if(!rigged)
|
||||||
@@ -74,46 +89,52 @@
|
|||||||
else
|
else
|
||||||
winner = target
|
winner = target
|
||||||
loser = user
|
loser = user
|
||||||
|
if(HAS_TRAIT(loser, TRAIT_UNLUCKY) && prob(66))
|
||||||
|
if(prize == (SHRINKING_CRACKER || GROWING_CRACKER || FALLING_CRACKER || TELEPORTING_CRACKER)) //If we're unlucky and the prize is bad, chance for us to get it!
|
||||||
|
var/former_winner = winner
|
||||||
|
winner = loser
|
||||||
|
loser = former_winner
|
||||||
|
|
||||||
var/spawnloc = get_turf(winner)
|
var/spawnloc = get_turf(winner)
|
||||||
|
|
||||||
winner.visible_message(span_notice("\The [winner] wins the cracker prize!"),span_notice("You win the cracker prize!"))
|
winner.visible_message(span_notice("\The [winner] wins the cracker prize!"),span_notice("You win the cracker prize!"))
|
||||||
if(prize == "shrinking")
|
switch(prize)
|
||||||
winner.resize(0.25)
|
if(SHRINKING_CRACKER)
|
||||||
winner.visible_message(span_bold("\The [winner]") + " shrinks suddenly!")
|
winner.resize(0.25)
|
||||||
if(prize == "growing")
|
winner.visible_message(span_bold("\The [winner]") + " shrinks suddenly!")
|
||||||
winner.resize(2)
|
if(GROWING_CRACKER)
|
||||||
winner.visible_message(span_bold("\The [winner]") + " grows in height suddenly.")
|
winner.resize(2)
|
||||||
if(prize == "drugged")
|
winner.visible_message(span_bold("\The [winner]") + " grows in height suddenly.")
|
||||||
winner.druggy = max(winner.druggy, 50)
|
if(GROWING_CRACKER)
|
||||||
if(prize == "invisibility")
|
winner.druggy = max(winner.druggy, 50)
|
||||||
if(!winner.cloaked)
|
if(INVISIBLE_CRACKER)
|
||||||
winner.visible_message(span_bold("\The [winner]") + " vanishes from sight.")
|
if(!winner.cloaked)
|
||||||
winner.cloak()
|
winner.visible_message(span_bold("\The [winner]") + " vanishes from sight.")
|
||||||
spawn(600)
|
winner.cloak()
|
||||||
if(winner.cloaked)
|
spawn(600)
|
||||||
winner.uncloak()
|
if(winner.cloaked)
|
||||||
winner.visible_message(span_bold("\The [winner]") + " appears as if from thin air.")
|
winner.uncloak()
|
||||||
if(prize == "knocked over")
|
winner.visible_message(span_bold("\The [winner]") + " appears as if from thin air.")
|
||||||
winner.visible_message(span_bold("\The [winner]") + " is suddenly knocked to the ground.")
|
if(FALLING_CRACKER)
|
||||||
winner.weakened = max(winner.weakened,50)
|
winner.visible_message(span_bold("\The [winner]") + " is suddenly knocked to the ground.")
|
||||||
if(prize == "teleport")
|
winner.weakened = max(winner.weakened,50)
|
||||||
if(loser.can_be_drop_pred && loser.vore_selected)
|
if(TELEPORTING_CRACKER)
|
||||||
if(winner.devourable && winner.can_be_drop_prey)
|
if(loser.can_be_drop_pred && loser.vore_selected)
|
||||||
winner.visible_message(span_bold("\The [winner]") + " is teleported to somewhere nearby...")
|
if(winner.devourable && winner.can_be_drop_prey)
|
||||||
var/datum/effect/effect/system/spark_spread/spk
|
winner.visible_message(span_bold("\The [winner]") + " is teleported to somewhere nearby...")
|
||||||
spk = new(winner)
|
var/datum/effect/effect/system/spark_spread/spk
|
||||||
|
spk = new(winner)
|
||||||
|
|
||||||
var/T = get_turf(winner)
|
var/T = get_turf(winner)
|
||||||
spk.set_up(5, 0, winner)
|
spk.set_up(5, 0, winner)
|
||||||
spk.attach(winner)
|
spk.attach(winner)
|
||||||
playsound(T, "sparks", 50, 1)
|
playsound(T, "sparks", 50, 1)
|
||||||
anim(T,winner,'icons/mob/mob.dmi',,"phaseout",,winner.dir)
|
anim(T,winner,'icons/mob/mob.dmi',,"phaseout",,winner.dir)
|
||||||
winner.forceMove(loser.vore_selected)
|
winner.forceMove(loser.vore_selected)
|
||||||
if(prize == "wealth")
|
if(WEALTHY_CRACKER)
|
||||||
new /obj/random/cash/huge(spawnloc)
|
new /obj/random/cash/huge(spawnloc)
|
||||||
new /obj/random/cash/huge(spawnloc)
|
new /obj/random/cash/huge(spawnloc)
|
||||||
winner.visible_message(span_bold("\The [winner]") + " has a whole load of cash fall at their feet!")
|
winner.visible_message(span_bold("\The [winner]") + " has a whole load of cash fall at their feet!")
|
||||||
|
|
||||||
playsound(user, 'sound/effects/snap.ogg', 50, 1)
|
playsound(user, 'sound/effects/snap.ogg', 50, 1)
|
||||||
user.drop_item(src)
|
user.drop_item(src)
|
||||||
@@ -123,40 +144,33 @@
|
|||||||
J.info = joke
|
J.info = joke
|
||||||
qdel(src)
|
qdel(src)
|
||||||
|
|
||||||
/obj/item/cracker/Initialize(mapload)
|
|
||||||
var/list/styles = list("blue","green","yellow","red","heart","hazard")
|
|
||||||
var/style = pick(styles)
|
|
||||||
icon_state = style
|
|
||||||
item_state = style
|
|
||||||
. = ..()
|
|
||||||
|
|
||||||
/obj/item/cracker/shrinking
|
/obj/item/cracker/shrinking
|
||||||
name = "shrinking bluespace cracker"
|
name = "shrinking bluespace cracker"
|
||||||
prizes = list("shrinking")
|
prize = SHRINKING_CRACKER
|
||||||
|
|
||||||
/obj/item/cracker/growing
|
/obj/item/cracker/growing
|
||||||
name = "growing bluespace cracker"
|
name = "growing bluespace cracker"
|
||||||
prizes = list("growing")
|
prize = GROWING_CRACKER
|
||||||
|
|
||||||
/obj/item/cracker/invisibility
|
/obj/item/cracker/invisibility
|
||||||
name = "cloaking bluespace cracker"
|
name = "cloaking bluespace cracker"
|
||||||
prizes = list("invisibility")
|
prize = INVISIBLE_CRACKER
|
||||||
|
|
||||||
/obj/item/cracker/drugged
|
/obj/item/cracker/drugged
|
||||||
name = "psychedelic bluespace cracker"
|
name = "psychedelic bluespace cracker"
|
||||||
prizes = list("drugged")
|
prize = GROWING_CRACKER
|
||||||
|
|
||||||
/obj/item/cracker/knockover
|
/obj/item/cracker/knockover
|
||||||
name = "forceful bluespace cracker"
|
name = "forceful bluespace cracker"
|
||||||
prizes = list("knocked over")
|
prize = FALLING_CRACKER
|
||||||
|
|
||||||
/obj/item/cracker/vore
|
/obj/item/cracker/vore
|
||||||
name = "teleporting bluespace cracker"
|
name = "teleporting bluespace cracker"
|
||||||
prizes = list("teleport")
|
prize = TELEPORTING_CRACKER
|
||||||
|
|
||||||
/obj/item/cracker/money
|
/obj/item/cracker/money
|
||||||
name = "fortuitous bluespace cracker"
|
name = "fortuitous bluespace cracker"
|
||||||
prizes = list("wealth")
|
prize = WEALTHY_CRACKER
|
||||||
|
|
||||||
/obj/item/clothing/head/paper_crown
|
/obj/item/clothing/head/paper_crown
|
||||||
name = "paper crown"
|
name = "paper crown"
|
||||||
@@ -181,3 +195,11 @@
|
|||||||
|
|
||||||
/obj/item/paper/cracker_joke/update_icon()
|
/obj/item/paper/cracker_joke/update_icon()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
#undef SHRINKING_CRACKER
|
||||||
|
#undef GROWING_CRACKER
|
||||||
|
#undef DRUGGED_CRACKER
|
||||||
|
#undef INVISIBLE_CRACKER
|
||||||
|
#undef FALLING_CRACKER
|
||||||
|
#undef TELEPORTING_CRACKER
|
||||||
|
#undef WEALTHY_CRACKER
|
||||||
|
|||||||
BIN
sound/effects/tableheadsmash.ogg
Normal file
BIN
sound/effects/tableheadsmash.ogg
Normal file
Binary file not shown.
@@ -688,6 +688,7 @@
|
|||||||
#include "code\datums\components\traits\gargoyle.dm"
|
#include "code\datums\components\traits\gargoyle.dm"
|
||||||
#include "code\datums\components\traits\nutrition_size_change.dm"
|
#include "code\datums\components\traits\nutrition_size_change.dm"
|
||||||
#include "code\datums\components\traits\photosynth.dm"
|
#include "code\datums\components\traits\photosynth.dm"
|
||||||
|
#include "code\datums\components\traits\unlucky.dm"
|
||||||
#include "code\datums\components\traits\waddle.dm"
|
#include "code\datums\components\traits\waddle.dm"
|
||||||
#include "code\datums\components\traits\weaver.dm"
|
#include "code\datums\components\traits\weaver.dm"
|
||||||
#include "code\datums\diseases\_disease.dm"
|
#include "code\datums\diseases\_disease.dm"
|
||||||
|
|||||||
Reference in New Issue
Block a user