Files
68139d12a5 ERvent release (#16770)
* Winter event mobs (#16768)

Added christmas catslug variant.

Added a grey scaled drake variant of the dragon, specifically intended to be played by the creator of the art for the upcoming event (and future events), as it's not quite polished yet for every day use. Though they are fine with it being used in other ways here and downstream if desired. The creator is grayscaledrake.

* fix (#16767)

* Makes limbs able to be chopped off with reasonable limits (#16766)

Moves around limb code a bit to make cutting/destroying limbs ACTUALLY possible.

Previously, destroying a limb required you to:
1. Reach the person's max_damage to even let you start having a _chance_ to destroy the limb.
2. Have to have a REALLY strong weapon to destroy/cut limbs. We're talking about a weapon requiring 50 to 80 damage depending on the limb to destroy it.
3. Even IF you managed to get a weapon that could destroy a limb, you STILL had a random prob() based on the damage dealt in that blow.

This changes it so instead of requiring you to reach the limb's max_damage to start having chances to drop, it makes it so limbs have two factors: How damaged the limb currently is AND how strong the blow it.

This still has thresholds. You can't grab a 5 damage butterknife and chop people's limbs off. But if you step in a 30 damage beatrap, or have a 45 damage rock drop on your hand, it might actually get gibbed or knocked off!

* initial ghost spawn is important... (#16760)

* initia ghostl spawn is important...

* .

* On demand belly loading & multibelly (#16758)

* Moves simple mob belly loading to on demans

* style

* early

* multibelly

* even more human

* .

* bunch of update_fullness

* animals need an icon refresh

* the icon has the fullness part, optimize that

* one more

* Add launch eject option for vore panel (#16755)

* Small bugfixes / clarifications (#16763)

* Fixes mech cloak having the wrong path

From Outpost21 Commit a64c3ad.

* clarified player record console buttons

"Player had issue with button confusion, and reviewing the buttons they are WAY too similar. changed refuse update to DENY to ensure no at-a-glance confusion"

From Outpost 21 Commit 32bc6f7

* simple doors use their own bump timer and not the user's

simple material doors no longer use the USER'S last bump time, and isntead use their own for locking interaction. They now open promptly when bonked into and close after some time when clicked (they are meant to be slow after all)

The bug was casued by using the user's bump time. So if youtouched anything like a wall within the last 60 ticks (including the door itself) it wouldn't open

From Outpost21 Commit 783ef0a

* ears + horns (#16764)

* few more defines (#16765)

* Allows borg tasers to properly charge when in charging ports (#16753)

* taser

* Adds sanity check

* Turret & Sound Optimizations (#16754)

* Portable Turret Optimization

Optimizes portable turrets. Takes from Chomp PR here: https://github.com/CHOMPStation2/CHOMPStation2/pull/8088

Optimizes them further by changing mobs_in_xray_view to mobs_in_view.
Reason: mobs_in_xray_view was adding mobs that were out of sight (behind walls) to the target list and trying to do pathfinding to shoot them. If you had 20 mobs around a PoI with turrets, it'd use a LOT of CPU needlessly.

Also adds in Chomp's /mobs.dm helpers as they're helpful.

* Ports over Chompstation Sound Optimizations

- Replaces for( listeners) with a check that sees if a listener is ALSO a hearer

- Makes it so even if there is no vary, if someone has a frequency it uses the frequency for playsound_local

From https://github.com/CHOMPStation2/CHOMPStation2/pull/8088

---------

Co-authored-by: SatinIsle <98125273+SatinIsle@users.noreply.github.com>
Co-authored-by: Guti <32563288+TheCaramelion@users.noreply.github.com>
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
Co-authored-by: ShadowLarkens <shadowlarkens@gmail.com>
Co-authored-by: dan <75939194+PastelPrinceDan@users.noreply.github.com>
2024-12-28 09:44:41 +10:00

334 lines
12 KiB
Plaintext

/client/proc/smite(var/mob/living/carbon/human/target in player_list)
set name = "Smite"
set desc = "Abuse a player with various 'special treatments' from a list."
set category = "Fun.Do Not"
if(!check_rights(R_FUN))
return
if(!istype(target))
return
var/list/smite_types = list(SMITE_BREAKLEGS,SMITE_BLUESPACEARTILLERY,SMITE_SPONTANEOUSCOMBUSTION,SMITE_LIGHTNINGBOLT,SMITE_SHADEKIN_ATTACK,SMITE_SHADEKIN_NOMF,SMITE_AD_SPAM,SMITE_REDSPACE_ABDUCT,SMITE_AUTOSAVE,SMITE_AUTOSAVE_WIDE,SMITE_SPICEREQUEST,SMITE_PEPPERNADE,SMITE_TERROR)
var/smite_choice = tgui_input_list(usr, "Select the type of SMITE for [target]","SMITE Type Choice", smite_types)
if(!smite_choice)
return
log_and_message_admins("[key_name(src)] has used SMITE ([smite_choice]) on [key_name(target)].")
feedback_add_details("admin_verb","SMITE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
switch(smite_choice)
if(SMITE_BREAKLEGS)
var/broken_legs = 0
var/obj/item/organ/external/left_leg = target.get_organ(BP_L_LEG)
if(left_leg && left_leg.fracture())
broken_legs++
var/obj/item/organ/external/right_leg = target.get_organ(BP_R_LEG)
if(right_leg && right_leg.fracture())
broken_legs++
if(!broken_legs)
to_chat(src,"[target] didn't have any breakable legs, sorry.")
if(SMITE_BLUESPACEARTILLERY)
bluespace_artillery(target,src)
if(SMITE_SPONTANEOUSCOMBUSTION)
target.adjust_fire_stacks(10)
target.IgniteMob()
target.visible_message(span_danger("[target] bursts into flames!"))
if(SMITE_LIGHTNINGBOLT)
var/turf/T = get_step(get_step(target, NORTH), NORTH)
T.Beam(target, icon_state="lightning[rand(1,12)]", time = 5)
target.electrocute_act(75,def_zone = BP_HEAD)
target.visible_message(span_danger("[target] is struck by lightning!"))
if(SMITE_SHADEKIN_ATTACK)
var/turf/Tt = get_turf(target) //Turf for target
if(target.loc != Tt)
return //Too hard to attack someone in something
var/turf/Ts //Turf for shadekin
//Try to find nondense turf
for(var/direction in cardinal)
var/turf/T = get_step(target,direction)
if(T && !T.density)
Ts = T //Found shadekin spawn turf
if(!Ts)
return //Didn't find shadekin spawn turf
var/mob/living/simple_mob/shadekin/red/shadekin = new(Ts)
//Abuse of shadekin
shadekin.real_name = shadekin.name
shadekin.voremob_loaded = TRUE
shadekin.init_vore()
shadekin.ability_flags |= 0x1
shadekin.phase_shift()
shadekin.ai_holder.give_target(target)
shadekin.ai_holder.hostile = FALSE
shadekin.ai_holder.mauling = TRUE
shadekin.Life()
//Remove when done
spawn(10 SECONDS)
if(shadekin)
shadekin.death()
if(SMITE_SHADEKIN_NOMF)
var/static/list/kin_types = list(
"Red Eyes (Dark)" = /mob/living/simple_mob/shadekin/red/dark,
"Red Eyes (Light)" = /mob/living/simple_mob/shadekin/red/white,
"Red Eyes (Brown)" = /mob/living/simple_mob/shadekin/red/brown,
"Blue Eyes (Dark)" = /mob/living/simple_mob/shadekin/blue/dark,
"Blue Eyes (Light)" = /mob/living/simple_mob/shadekin/blue/white,
"Blue Eyes (Brown)" = /mob/living/simple_mob/shadekin/blue/brown,
"Purple Eyes (Dark)" = /mob/living/simple_mob/shadekin/purple/dark,
"Purple Eyes (Light)" = /mob/living/simple_mob/shadekin/purple/white,
"Purple Eyes (Brown)" = /mob/living/simple_mob/shadekin/purple/brown,
"Yellow Eyes (Dark)" = /mob/living/simple_mob/shadekin/yellow/dark,
"Yellow Eyes (Light)" = /mob/living/simple_mob/shadekin/yellow/white,
"Yellow Eyes (Brown)" = /mob/living/simple_mob/shadekin/yellow/brown,
"Green Eyes (Dark)" = /mob/living/simple_mob/shadekin/green/dark,
"Green Eyes (Light)" = /mob/living/simple_mob/shadekin/green/white,
"Green Eyes (Brown)" = /mob/living/simple_mob/shadekin/green/brown,
"Orange Eyes (Dark)" = /mob/living/simple_mob/shadekin/orange/dark,
"Orange Eyes (Light)" = /mob/living/simple_mob/shadekin/orange/white,
"Orange Eyes (Brown)" = /mob/living/simple_mob/shadekin/orange/brown,
"Rivyr (Unique)" = /mob/living/simple_mob/shadekin/blue/rivyr)
var/kin_type = tgui_input_list(usr, "Select the type of shadekin for [target] nomf","Shadekin Type Choice", kin_types)
if(!kin_type || !target)
return
kin_type = kin_types[kin_type]
var/myself = tgui_alert(usr, "Control the shadekin yourself or delete pred and prey after?","Control Shadekin?",list("Control","Cancel","Delete"))
if(!myself || myself == "Cancel" || !target)
return
var/turf/Tt = get_turf(target)
if(target.loc != Tt)
return //Can't nom when not exposed
//Begin abuse
target.transforming = TRUE //Cheap hack to stop them from moving
var/mob/living/simple_mob/shadekin/shadekin = new kin_type(Tt)
shadekin.real_name = shadekin.name
shadekin.voremob_loaded = TRUE
shadekin.init_vore()
shadekin.can_be_drop_pred = TRUE
shadekin.dir = SOUTH
shadekin.ability_flags |= 0x1
shadekin.phase_shift() //Homf
shadekin.energy = initial(shadekin.energy)
//For fun
sleep(1 SECOND)
shadekin.dir = WEST
sleep(1 SECOND)
shadekin.dir = EAST
sleep(1 SECOND)
shadekin.dir = SOUTH
sleep(1 SECOND)
shadekin.audible_message(span_vwarning(span_bold("[shadekin]") + " belches loudly!"), runemessage = "URRRRRP")
sleep(2 SECONDS)
shadekin.phase_shift()
target.transforming = FALSE //Undo cheap hack
if(myself == "Control") //Put admin in mob
shadekin.ckey = ckey
else //Permakin'd
to_chat(target,span_danger("You're carried off into The Dark by the [shadekin]. Who knows if you'll find your way back?"))
target.ghostize()
qdel(target)
qdel(shadekin)
if(SMITE_REDSPACE_ABDUCT)
redspace_abduction(target, src)
if(SMITE_AUTOSAVE)
fake_autosave(target, src)
if(SMITE_AUTOSAVE_WIDE)
fake_autosave(target, src, TRUE)
if(SMITE_AD_SPAM)
if(target.client)
target.client.create_fake_ad_popup_multiple(/obj/screen/popup/default, 15)
if(SMITE_PEPPERNADE)
var/obj/item/grenade/chem_grenade/teargas/grenade = new /obj/item/grenade/chem_grenade/teargas
grenade.loc = target.loc
to_chat(target,span_warning("GRENADE?!"))
grenade.detonate()
if(SMITE_SPICEREQUEST)
var/obj/item/reagent_containers/food/condiment/spacespice/spice = new /obj/item/reagent_containers/food/condiment/spacespice
spice.loc = target.loc
to_chat(target,"A bottle of spices appears at your feet... be careful what you wish for!")
if(SMITE_TERROR)
if(ishuman(target))
target.fear = 200
else
return //Injection? Don't print any messages.
/proc/bluespace_artillery(mob/living/target, user)
if(!istype(target))
return
to_chat(target,"You've been hit by bluespace artillery!")
log_and_message_admins("[key_name(target)] has been hit by Bluespace Artillery fired by [key_name(user ? user : usr)]")
target.setMoveCooldown(2 SECONDS)
var/turf/simulated/floor/T = get_turf(target)
if(istype(T))
if(prob(80)) T.break_tile_to_plating()
else T.break_tile()
playsound(T, get_sfx("explosion"), 100, 1, get_rand_frequency(), falloff = 5) // get_sfx() is so that everyone gets the same sound
if(target.health < 10)
target.gib()
else
target.adjustBruteLoss( max( 99 , (target.health - 1) ) )
target.Stun(20)
target.Weaken(20)
target.stuttering = 20
var/redspace_abduction_z
/area/redspace_abduction
name = "Another Time And Place"
requires_power = FALSE
dynamic_lighting = FALSE
/proc/redspace_abduction(mob/living/target, user)
if(redspace_abduction_z < 0)
to_chat(user,span_warning("The abduction z-level is already being created. Please wait."))
return
if(!redspace_abduction_z)
redspace_abduction_z = -1
to_chat(user,span_warning("This is the first use of the verb this shift, it will take a minute to configure the abduction z-level. It will be z[world.maxz+1]."))
var/z = ++world.maxz
world.max_z_changed()
for(var/x = 1 to world.maxx)
for(var/y = 1 to world.maxy)
var/turf/T = locate(x,y,z)
new /area/redspace_abduction(T)
T.ChangeTurf(/turf/unsimulated/fake_space)
T.plane = -100
CHECK_TICK
redspace_abduction_z = z
if(!target || !user)
return
var/size_of_square = 26
var/halfbox = round(size_of_square*0.5)
target.transforming = TRUE
to_chat(target,span_danger("You feel a strange tug, deep inside. You're frozen in momentarily..."))
to_chat(user,span_notice("Beginning vis_contents copy to abduction site, player mob is frozen."))
sleep(1 SECOND)
//Lower left corner of a working box
var/llc_x = max(0,halfbox-target.x) + min(target.x+halfbox, world.maxx) - size_of_square
var/llc_y = max(0,halfbox-target.y) + min(target.y+halfbox, world.maxy) - size_of_square
//Copy them all
for(var/x = llc_x to llc_x+size_of_square)
for(var/y = llc_y to llc_y+size_of_square)
var/turf/T_src = locate(x,y,target.z)
var/turf/T_dest = locate(x,y,redspace_abduction_z)
T_dest.vis_contents.Cut()
T_dest.vis_contents += T_src
T_dest.density = T_src.density
T_dest.opacity = T_src.opacity
CHECK_TICK
//Feather the edges
for(var/x = llc_x to llc_x+1) //Left
for(var/y = llc_y to llc_y+size_of_square)
if(prob(50))
var/turf/T = locate(x,y,redspace_abduction_z)
T.density = FALSE
T.opacity = FALSE
T.vis_contents.Cut()
for(var/x = llc_x+size_of_square-1 to llc_x+size_of_square) //Right
for(var/y = llc_y to llc_y+size_of_square)
if(prob(50))
var/turf/T = locate(x,y,redspace_abduction_z)
T.density = FALSE
T.opacity = FALSE
T.vis_contents.Cut()
for(var/x = llc_x to llc_x+size_of_square) //Top
for(var/y = llc_y+size_of_square-1 to llc_y+size_of_square)
if(prob(50))
var/turf/T = locate(x,y,redspace_abduction_z)
T.density = FALSE
T.opacity = FALSE
T.vis_contents.Cut()
for(var/x = llc_x to llc_x+size_of_square) //Bottom
for(var/y = llc_y to llc_y+1)
if(prob(50))
var/turf/T = locate(x,y,redspace_abduction_z)
T.density = FALSE
T.opacity = FALSE
T.vis_contents.Cut()
target.forceMove(locate(target.x,target.y,redspace_abduction_z))
to_chat(target,span_danger("The tug relaxes, but everything around you looks... slightly off."))
to_chat(user,span_notice("The mob has been moved. ([admin_jump_link(target,usr.client.holder)])"))
target.transforming = FALSE
/proc/fake_autosave(var/mob/living/target, var/client/user, var/wide)
if(!istype(target) || !target.client)
to_chat(user, span_warning("Skipping [target] because they are not a /mob/living or have no client."))
return
if(wide)
for(var/mob/living/L in orange(user.view, user.mob))
fake_autosave(L, user)
return
target.setMoveCooldown(10 SECONDS)
to_chat(target, "<span class='notice' style='font: small-caps bold large monospace!important'>Autosaving your progress, please wait...</span>")
target << 'sound/effects/ding.ogg'
var/static/list/bad_tips = list(
"Did you know that black shoes protect you from electrocution while hacking?",
"Did you know that airlocks always have a wire that disables ID checks?",
"You can always find at least 3 pairs of glowing purple gloves in maint!",
"Phoron is not toxic if you've had a soda within 30 seconds of exposure!",
"Space Mountain Wind makes you immune to damage from space for 30 seconds!",
"A mask and air tank are all you need to be safe in space!",
"When exploring maintenance, wearing no shoes makes you move faster!",
"Did you know that the bartender's shotgun is loaded with harmless ammo?",
"Did you know that the tesla and singulo only need containment for 5 minutes?")
var/tip = pick(bad_tips)
to_chat(target, "<span class='notice' style='font: small-caps bold large monospace!important'>Tip of the day:</span><br><span class='notice'>[tip]</span>")
var/obj/screen/loader = new(target)
loader.name = "Autosaving..."
loader.desc = "A disc icon that represents your game autosaving. Please wait."
loader.icon = 'icons/obj/discs_vr.dmi'
loader.icon_state = "quicksave"
loader.screen_loc = "NORTH-1, EAST-1"
target.client.screen += loader
spawn(10 SECONDS)
if(target)
to_chat(target, "<span class='notice' style='font: small-caps bold large monospace!important'>Autosave complete!</span>")
if(target.client)
target.client.screen -= loader