mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-10 09:54:52 +00:00
Merge branch 'Citadel-Station-13:master' into wingport
This commit is contained in:
@@ -7,5 +7,8 @@
|
||||
"ferry": "ferry_fancy",
|
||||
"whiteship": "whiteship_box",
|
||||
"emergency": "emergency_box"
|
||||
}
|
||||
},
|
||||
"traits": [
|
||||
{ "Weather_Icestorm":true }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -29637,6 +29637,7 @@
|
||||
/obj/effect/turf_decal/stripes/line{
|
||||
dir = 8
|
||||
},
|
||||
/obj/item/cautery,
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/science/robotics/lab)
|
||||
"btb" = (
|
||||
|
||||
@@ -7,5 +7,8 @@
|
||||
"whiteship": "whiteship_pubby",
|
||||
"ferry": "ferry_fancy",
|
||||
"cargo": "cargo_box"
|
||||
}
|
||||
},
|
||||
"traits": [
|
||||
{ "Weather_Longrain":true }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -43,6 +43,8 @@ require only minor tweaks.
|
||||
#define ZTRAIT_ASHSTORM "Weather_Ashstorm"
|
||||
#define ZTRAIT_ACIDRAIN "Weather_Acidrain"
|
||||
#define ZTRAIT_VOIDSTORM "Weather_Voidstorm"
|
||||
#define ZTRAIT_ICESTORM "Weather_Icestorm"
|
||||
#define ZTRAIT_LONGRAIN "Weather_Longrain"
|
||||
|
||||
// number - bombcap is multiplied by this before being applied to bombs
|
||||
#define ZTRAIT_BOMBCAP_MULTIPLIER "Bombcap Multiplier"
|
||||
|
||||
@@ -343,10 +343,15 @@ SUBSYSTEM_DEF(research)
|
||||
break //Just need one to work.
|
||||
if (!isnull(last_income))
|
||||
var/income_time_difference = world.time - last_income
|
||||
science_tech.last_bitcoins = bitcoins // Doesn't take tick drift into account
|
||||
for(var/i in bitcoins)
|
||||
bitcoins[i] *= income_time_difference / 10
|
||||
science_tech.add_point_list(bitcoins)
|
||||
if(!length(science_tech.last_bitcoins))
|
||||
science_tech.last_bitcoins = science_tech.research_points
|
||||
for(var/i in science_tech.last_bitcoins)
|
||||
var/old_weighted = science_tech.last_bitcoins[i] * (1 MINUTES - income_time_difference)
|
||||
var/new_weighted = science_tech.research_points[i] * income_time_difference
|
||||
science_tech.last_bitcoins[i] = round((old_weighted + new_weighted) / (1 MINUTES))
|
||||
last_income = world.time
|
||||
|
||||
/datum/controller/subsystem/research/proc/calculate_server_coefficient() //Diminishing returns.
|
||||
|
||||
@@ -178,7 +178,7 @@
|
||||
|
||||
var/mob/living/silicon/robot/R = target
|
||||
if(iscyborg(R))
|
||||
if(R.module.dogborg == TRUE || R.dogborg == TRUE) //I hate whoever that thought that putting two types of dogborg that don't even sync up properly was good
|
||||
if((R.module.dogborg == TRUE || R.dogborg == TRUE) && isturf(R.loc)) //I hate whoever that thought that putting two types of dogborg that don't even sync up properly was good
|
||||
message.pixel_x = 16
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
area_type = /area/edina
|
||||
protected_areas = list(/area/edina/protected)
|
||||
target_trait = ZTRAIT_STATION
|
||||
target_trait = ZTRAIT_ICESTORM
|
||||
|
||||
immunity_type = "rad"
|
||||
|
||||
|
||||
@@ -382,6 +382,70 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// Clock Cult (MID) //
|
||||
// //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
|
||||
//changes two people midround into clockwork cultists
|
||||
/datum/dynamic_ruleset/midround/ratvar_awakening
|
||||
name = "Ratvar Awakening"
|
||||
antag_datum = /datum/antagonist/clockcult
|
||||
antag_flag = "clock mid"
|
||||
antag_flag_override = ROLE_SERVANT_OF_RATVAR
|
||||
protected_roles = list("AI", "Cyborg", "Prisoner", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Chaplain", "Head of Personnel", "Quartermaster", "Chief Engineer", "Chief Medical Officer", "Research Director")
|
||||
restricted_roles = list("AI", "Cyborg", "Prisoner", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Chaplain", "Head of Personnel", "Quartermaster", "Chief Engineer", "Chief Medical Officer", "Research Director")
|
||||
enemy_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Chaplain", "Head of Personnel", "Quartermaster", "Chief Engineer", "Chief Medical Officer", "Research Director")
|
||||
required_enemies = list(1,1,1,1,1,1,0,0,0,0)
|
||||
required_candidates = 2
|
||||
weight = 3
|
||||
cost = 20
|
||||
requirements = list(101,101,101,101,50,40,30,20,10,10)
|
||||
var/list/clock_cap = list(1,1,1,1,2,3,4,5,5,5)
|
||||
flags = HIGH_IMPACT_RULESET
|
||||
|
||||
/datum/dynamic_ruleset/midround/ratvar_awakening/acceptable(population=0, threat=0)
|
||||
if (locate(/datum/dynamic_ruleset/roundstart/clockcult) in mode.executed_rules)
|
||||
return FALSE // Unavailable if clockies exist at round start
|
||||
indice_pop = min(clock_cap.len, round(living_players.len/5)+1)
|
||||
required_candidates = clock_cap[indice_pop]
|
||||
return ..()
|
||||
|
||||
/datum/dynamic_ruleset/midround/ratvar_awakening/trim_candidates()
|
||||
..()
|
||||
candidates = living_players
|
||||
for(var/mob/living/player as anything in candidates)
|
||||
var/turf/player_turf = get_turf(player)
|
||||
if(!player_turf || !is_station_level(player_turf.z))
|
||||
candidates -= player //no ghost roles
|
||||
continue
|
||||
|
||||
if(!is_eligible_servant(player))
|
||||
candidates -= player
|
||||
continue
|
||||
|
||||
if(player.mind && (player.mind.special_role || length(player.mind.antag_datums) > 0))
|
||||
candidates -= player //no double dipping
|
||||
|
||||
/datum/dynamic_ruleset/midround/ratvar_awakening/execute()
|
||||
if(!candidates || !candidates.len)
|
||||
return FALSE
|
||||
for(var/i = 0; i < required_candidates; i++)
|
||||
if(!candidates.len)
|
||||
break
|
||||
var/mob/living/clock_antag = pick_n_take(candidates)
|
||||
assigned += clock_antag.mind
|
||||
for(var/datum/mind/M in assigned) //add them to the clockwork team
|
||||
add_servant_of_ratvar(M.current)
|
||||
SSticker.mode.equip_servant(M.current)
|
||||
SSticker.mode.greet_servant(M.current)
|
||||
message_admins("[ADMIN_LOOKUPFLW(M.current)] was selected by the [name] ruleset and has been made into a midround clock cultist.")
|
||||
log_game("DYNAMIC: [key_name(M.current)] was selected by the [name] ruleset and has been made into a midround clock cultist.")
|
||||
load_reebe()
|
||||
return ..()
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// BLOB (GHOST) //
|
||||
|
||||
@@ -271,18 +271,7 @@
|
||||
if(resin_cooldown)
|
||||
to_chat(user, "<span class='warning'>Resin launcher is still recharging...</span>")
|
||||
return
|
||||
resin_cooldown = TRUE
|
||||
R.remove_any(100)
|
||||
var/obj/effect/resin_container/A = new (get_turf(src))
|
||||
log_game("[key_name(user)] used Resin Launcher at [AREACOORD(user)].")
|
||||
playsound(src,'sound/items/syringeproj.ogg',40,1)
|
||||
for(var/a=0, a<5, a++)
|
||||
step_towards(A, target)
|
||||
sleep(2)
|
||||
A.Smoke()
|
||||
spawn(100)
|
||||
if(src)
|
||||
resin_cooldown = FALSE
|
||||
launch_resin(target, user)
|
||||
return
|
||||
if(nozzle_mode == RESIN_FOAM)
|
||||
if(!Adj|| !isturf(target))
|
||||
@@ -301,6 +290,21 @@
|
||||
to_chat(user, "<span class='warning'>Resin foam mix is still being synthesized...</span>")
|
||||
return
|
||||
|
||||
/obj/item/extinguisher/mini/nozzle/proc/launch_resin(atom/target, mob/user)
|
||||
set waitfor = FALSE
|
||||
resin_cooldown = TRUE
|
||||
reagents.remove_any(100)
|
||||
var/obj/effect/resin_container/A = new (get_turf(src))
|
||||
log_game("[key_name(user)] used Resin Launcher at [AREACOORD(user)].")
|
||||
playsound(src,'sound/items/syringeproj.ogg',40,1)
|
||||
for(var/a=0, a<5, a++)
|
||||
step_towards(A, target)
|
||||
sleep(2)
|
||||
A.Smoke()
|
||||
spawn(100)
|
||||
if(src)
|
||||
resin_cooldown = FALSE
|
||||
|
||||
/obj/effect/resin_container
|
||||
name = "resin container"
|
||||
desc = "A compacted ball of expansive resin, used to repair the atmosphere in a room, or seal off breaches."
|
||||
|
||||
@@ -387,8 +387,7 @@
|
||||
log_combat(user, M, "used a cult spell on", source.name, "")
|
||||
M.set_last_attacker(user)
|
||||
|
||||
/obj/item/melee/blood_magic/afterattack(atom/target, mob/living/carbon/user, proximity)
|
||||
. = ..()
|
||||
/obj/item/melee/blood_magic/proc/post_cast(atom/target, mob/living/carbon/user, proximity)
|
||||
if(invocation)
|
||||
user.whisper(invocation, language = /datum/language/common)
|
||||
if(health_cost)
|
||||
@@ -467,6 +466,7 @@
|
||||
to_chat(user, "<span class='cultitalic'>In an brilliant flash of red, [L] [is_servant_of_ratvar(L) ? "writhes in pain!" : "falls to the ground!"]</span>")
|
||||
uses--
|
||||
..()
|
||||
post_cast(target, user, proximity)
|
||||
|
||||
//Teleportation
|
||||
/obj/item/melee/blood_magic/teleport
|
||||
@@ -480,40 +480,45 @@
|
||||
to_chat(user, "<span class='warning'>You can only teleport adjacent cultists with this spell!</span>")
|
||||
return
|
||||
if(iscultist(user))
|
||||
var/list/potential_runes = list()
|
||||
var/list/teleportnames = list()
|
||||
for(var/R in GLOB.teleport_runes)
|
||||
var/obj/effect/rune/teleport/T = R
|
||||
potential_runes[avoid_assoc_duplicate_keys(T.listkey, teleportnames)] = T
|
||||
|
||||
if(!potential_runes.len)
|
||||
to_chat(user, "<span class='warning'>There are no valid runes to teleport to!</span>")
|
||||
log_game("Teleport talisman failed - no other teleport runes")
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(is_away_level(T.z))
|
||||
to_chat(user, "<span class='cultitalic'>You are not in the right dimension!</span>")
|
||||
log_game("Teleport spell failed - user in away mission")
|
||||
return
|
||||
|
||||
var/input_rune_key = input(user, "Choose a rune to teleport to.", "Rune to Teleport to") as null|anything in potential_runes //we know what key they picked
|
||||
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
|
||||
if(QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated() || !actual_selected_rune || !proximity)
|
||||
return
|
||||
var/turf/dest = get_turf(actual_selected_rune)
|
||||
if(is_blocked_turf(dest, TRUE))
|
||||
to_chat(user, "<span class='warning'>The target rune is blocked. Attempting to teleport to it would be massively unwise.</span>")
|
||||
return
|
||||
uses--
|
||||
var/turf/origin = get_turf(user)
|
||||
var/mob/living/L = target
|
||||
if(do_teleport(L, dest, channel = TELEPORT_CHANNEL_CULT))
|
||||
origin.visible_message("<span class='warning'>Dust flows from [user]'s hand, and [user.p_they()] disappear[user.p_s()] with a sharp crack!</span>", \
|
||||
"<span class='cultitalic'>You speak the words of the talisman and find yourself somewhere else!</span>", "<i>You hear a sharp crack.</i>")
|
||||
dest.visible_message("<span class='warning'>There is a boom of outrushing air as something appears above the rune!</span>", null, "<i>You hear a boom.</i>")
|
||||
try_teleport(target, user, proximity)
|
||||
..()
|
||||
|
||||
/obj/item/melee/blood_magic/teleport/proc/try_teleport(atom/target, mob/living/carbon/user, proximity)
|
||||
set waitfor = FALSE
|
||||
var/list/potential_runes = list()
|
||||
var/list/teleportnames = list()
|
||||
for(var/R in GLOB.teleport_runes)
|
||||
var/obj/effect/rune/teleport/T = R
|
||||
potential_runes[avoid_assoc_duplicate_keys(T.listkey, teleportnames)] = T
|
||||
|
||||
if(!potential_runes.len)
|
||||
to_chat(user, "<span class='warning'>There are no valid runes to teleport to!</span>")
|
||||
log_game("Teleport talisman failed - no other teleport runes")
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(is_away_level(T.z))
|
||||
to_chat(user, "<span class='cultitalic'>You are not in the right dimension!</span>")
|
||||
log_game("Teleport spell failed - user in away mission")
|
||||
return
|
||||
|
||||
var/input_rune_key = input(user, "Choose a rune to teleport to.", "Rune to Teleport to") as null|anything in potential_runes //we know what key they picked
|
||||
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
|
||||
if(QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated() || !actual_selected_rune || !proximity)
|
||||
return
|
||||
var/turf/dest = get_turf(actual_selected_rune)
|
||||
if(is_blocked_turf(dest, TRUE))
|
||||
to_chat(user, "<span class='warning'>The target rune is blocked. Attempting to teleport to it would be massively unwise.</span>")
|
||||
return
|
||||
uses--
|
||||
var/turf/origin = get_turf(user)
|
||||
var/mob/living/L = target
|
||||
if(do_teleport(L, dest, channel = TELEPORT_CHANNEL_CULT))
|
||||
origin.visible_message("<span class='warning'>Dust flows from [user]'s hand, and [user.p_they()] disappear[user.p_s()] with a sharp crack!</span>", \
|
||||
"<span class='cultitalic'>You speak the words of the talisman and find yourself somewhere else!</span>", "<i>You hear a sharp crack.</i>")
|
||||
dest.visible_message("<span class='warning'>There is a boom of outrushing air as something appears above the rune!</span>", null, "<i>You hear a boom.</i>")
|
||||
post_cast(target, user, proximity)
|
||||
|
||||
//Shackles
|
||||
/obj/item/melee/blood_magic/shackles
|
||||
name = "Binding Aura"
|
||||
@@ -530,6 +535,7 @@
|
||||
user.visible_message("<span class='cultitalic'>This victim doesn't have enough arms to complete the restraint!</span>")
|
||||
return
|
||||
..()
|
||||
post_cast(target, user, proximity)
|
||||
|
||||
/obj/item/melee/blood_magic/shackles/proc/CuffAttack(mob/living/carbon/C, mob/living/user)
|
||||
if(!C.handcuffed)
|
||||
@@ -583,6 +589,7 @@
|
||||
to_chat(user, "<span class='warning'>A dark cloud emanates from your hand and swirls around the metal, twisting it into a construct shell!</span>")
|
||||
new /obj/structure/constructshell(T)
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
post_cast(target, proximity_flag, user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need 50 metal to produce a construct shell!</span>")
|
||||
else if(istype(target, /obj/item/stack/sheet/plasteel))
|
||||
@@ -593,56 +600,73 @@
|
||||
new /obj/item/stack/sheet/runed_metal(T,quantity)
|
||||
to_chat(user, "<span class='warning'>A dark cloud emanates from you hand and swirls around the plasteel, transforming it into runed metal!</span>")
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
post_cast(target, user, proximity_flag)
|
||||
if(istype(target, /obj/item/clothing/suit/hooded/wintercoat) && target.type != /obj/item/clothing/suit/hooded/wintercoat/narsie)
|
||||
if (do_after(user,30,target=target))
|
||||
new /obj/item/clothing/suit/hooded/wintercoat/narsie(T)
|
||||
qdel(target)
|
||||
to_chat(user, "<span class='warning'>A dark cloud emanates from you hand and swirls around [target], transforming it into a narsian winter coat!</span>")
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
convert_coat(target, user, proximity_flag, T)
|
||||
else if(istype(target,/mob/living/silicon/robot))
|
||||
var/mob/living/silicon/robot/candidate = target
|
||||
if(!iscultist(user, TRUE))
|
||||
to_chat(user, "<span class='warning'>You are not strongly connected enough to Nar'sie to use make constructs...</span>")
|
||||
else if(candidate.mmi)
|
||||
user.visible_message("<span class='danger'>A dark cloud emanates from [user]'s hand and swirls around [candidate]!</span>")
|
||||
playsound(T, 'sound/machines/airlock_alien_prying.ogg', 80, 1)
|
||||
var/prev_color = candidate.color
|
||||
candidate.color = "black"
|
||||
if(do_after(user, 90, target = candidate))
|
||||
candidate.emp_act(80)
|
||||
var/construct_class = alert(user, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer")
|
||||
user.visible_message("<span class='danger'>The dark cloud receedes from what was formerly [candidate], revealing a\n [construct_class]!</span>")
|
||||
switch(construct_class)
|
||||
if("Juggernaut")
|
||||
makeNewConstruct(/mob/living/simple_animal/hostile/construct/armored, candidate, user, 0, T)
|
||||
if("Wraith")
|
||||
makeNewConstruct(/mob/living/simple_animal/hostile/construct/wraith, candidate, user, 0, T)
|
||||
if("Artificer")
|
||||
makeNewConstruct(/mob/living/simple_animal/hostile/construct/builder, candidate, user, 0, T)
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
uses--
|
||||
candidate.mmi = null
|
||||
qdel(candidate)
|
||||
else
|
||||
candidate.color = prev_color
|
||||
else
|
||||
uses--
|
||||
to_chat(user, "<span class='warning'>A dark cloud emanates from you hand and swirls around [candidate] - twisting it into a construct shell!</span>")
|
||||
new /obj/structure/constructshell(T)
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
convert_borg(target, user, proximity_flag, T)
|
||||
else if(istype(target,/obj/machinery/door/airlock))
|
||||
playsound(T, 'sound/machines/airlockforced.ogg', 50, 1)
|
||||
do_sparks(5, TRUE, target)
|
||||
if(do_after(user, 50, target = user))
|
||||
target.narsie_act()
|
||||
uses--
|
||||
user.visible_message("<span class='warning'>Black ribbons suddenly emanate from [user]'s hand and cling to the airlock - twisting and corrupting it!</span>")
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
convert_door(target, user, proximity_flag, T)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The spell will not work on [target]!</span>")
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/melee/blood_magic/construction/proc/convert_coat(atom/target, mob/user, proximity_flag, turf/T)
|
||||
set waitfor = FALSE
|
||||
if(do_after(user,30,target=target))
|
||||
new /obj/item/clothing/suit/hooded/wintercoat/narsie(T)
|
||||
qdel(target)
|
||||
to_chat(user, "<span class='warning'>A dark cloud emanates from you hand and swirls around [target], transforming it into a narsian winter coat!</span>")
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
post_cast(target, user, proximity_flag)
|
||||
|
||||
/obj/item/melee/blood_magic/construction/proc/convert_door(atom/target, mob/user, proximity_flag, turf/T)
|
||||
set waitfor = FALSE
|
||||
playsound(T, 'sound/machines/airlockforced.ogg', 50, 1)
|
||||
do_sparks(5, TRUE, target)
|
||||
if(do_after(user, 50, target = user))
|
||||
target.narsie_act()
|
||||
uses--
|
||||
user.visible_message("<span class='warning'>Black ribbons suddenly emanate from [user]'s hand and cling to the airlock - twisting and corrupting it!</span>")
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
post_cast(target, user, proximity_flag)
|
||||
|
||||
/obj/item/melee/blood_magic/construction/proc/convert_borg(atom/target, mob/user, proximity_flag, turf/T)
|
||||
set waitfor = FALSE
|
||||
var/mob/living/silicon/robot/candidate = target
|
||||
if(!iscultist(user, TRUE))
|
||||
to_chat(user, "<span class='warning'>You are not strongly connected enough to Nar'sie to use make constructs...</span>")
|
||||
return
|
||||
else if(candidate.mmi)
|
||||
user.visible_message("<span class='danger'>A dark cloud emanates from [user]'s hand and swirls around [candidate]!</span>")
|
||||
playsound(T, 'sound/machines/airlock_alien_prying.ogg', 80, 1)
|
||||
var/prev_color = candidate.color
|
||||
candidate.color = "black"
|
||||
if(do_after(user, 90, target = candidate))
|
||||
candidate.emp_act(80)
|
||||
var/construct_class = alert(user, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer")
|
||||
user.visible_message("<span class='danger'>The dark cloud receedes from what was formerly [candidate], revealing a\n [construct_class]!</span>")
|
||||
switch(construct_class)
|
||||
if("Juggernaut")
|
||||
makeNewConstruct(/mob/living/simple_animal/hostile/construct/armored, candidate, user, 0, T)
|
||||
if("Wraith")
|
||||
makeNewConstruct(/mob/living/simple_animal/hostile/construct/wraith, candidate, user, 0, T)
|
||||
if("Artificer")
|
||||
makeNewConstruct(/mob/living/simple_animal/hostile/construct/builder, candidate, user, 0, T)
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
uses--
|
||||
candidate.mmi = null
|
||||
qdel(candidate)
|
||||
else
|
||||
candidate.color = prev_color
|
||||
else
|
||||
uses--
|
||||
to_chat(user, "<span class='warning'>A dark cloud emanates from you hand and swirls around [candidate] - twisting it into a construct shell!</span>")
|
||||
new /obj/structure/constructshell(T)
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
post_cast(target, user, proximity_flag)
|
||||
|
||||
//Armor: Gives the target a basic cultist combat loadout
|
||||
/obj/item/melee/blood_magic/armor
|
||||
name = "Bladed Aura"
|
||||
@@ -665,6 +689,7 @@
|
||||
C.put_in_hands(new /obj/item/melee/cultblade(user))
|
||||
C.put_in_hands(new /obj/item/restraints/legcuffs/bola/cult(user))
|
||||
..()
|
||||
post_cast(target, user, proximity)
|
||||
|
||||
/obj/item/melee/blood_magic/manipulator
|
||||
name = "Ritual Aura"
|
||||
@@ -693,7 +718,9 @@
|
||||
H.adjust_integration_blood(uses * 2)
|
||||
to_chat(user,"<span class='danger'>You use the last of your blood rites to restore what blood you could!</span>")
|
||||
uses = 0
|
||||
return ..()
|
||||
..()
|
||||
post_cast(target, user, proximity)
|
||||
return
|
||||
else
|
||||
H.blood_volume = (BLOOD_VOLUME_SAFE*H.blood_ratio)
|
||||
uses -= round(restore_blood/2)
|
||||
@@ -758,6 +785,7 @@
|
||||
if(istype(target, /obj/effect/decal/cleanable/blood))
|
||||
blood_draw(target, user)
|
||||
..()
|
||||
post_cast()
|
||||
|
||||
/obj/item/melee/blood_magic/manipulator/proc/blood_draw(atom/target, mob/living/carbon/human/user)
|
||||
var/temp = 0
|
||||
|
||||
@@ -660,40 +660,42 @@
|
||||
return
|
||||
|
||||
if(istype(A, /obj/item))
|
||||
|
||||
var/list/cultists = list()
|
||||
for(var/datum/mind/M in SSticker.mode.cult)
|
||||
if(M.current && M.current.stat != DEAD)
|
||||
cultists |= M.current
|
||||
var/mob/living/cultist_to_receive = input(user, "Who do you wish to call to [src]?", "Followers of the Geometer") as null|anything in (cultists - user)
|
||||
if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated())
|
||||
return
|
||||
if(!cultist_to_receive)
|
||||
to_chat(user, "<span class='cult italic'>You require a destination!</span>")
|
||||
log_game("Void torch failed - no target")
|
||||
return
|
||||
if(cultist_to_receive.stat == DEAD)
|
||||
to_chat(user, "<span class='cult italic'>[cultist_to_receive] has died!</span>")
|
||||
log_game("Void torch failed - target died")
|
||||
return
|
||||
if(!iscultist(cultist_to_receive))
|
||||
to_chat(user, "<span class='cult italic'>[cultist_to_receive] is not a follower of the Geometer!</span>")
|
||||
log_game("Void torch failed - target was deconverted")
|
||||
return
|
||||
if(A in user.GetAllContents())
|
||||
to_chat(user, "<span class='cult italic'>[A] must be on a surface in order to teleport it!</span>")
|
||||
return
|
||||
to_chat(user, "<span class='cult italic'>You ignite [A] with \the [src], turning it to ash, but through the torch's flames you see that [A] has reached [cultist_to_receive]!")
|
||||
cultist_to_receive.put_in_hands(A)
|
||||
charges--
|
||||
to_chat(user, "\The [src] now has [charges] charge\s.")
|
||||
if(charges == 0)
|
||||
qdel(src)
|
||||
transmit_item(A, user, proximity)
|
||||
|
||||
else
|
||||
..()
|
||||
to_chat(user, "<span class='warning'>\The [src] can only transport items!</span>")
|
||||
|
||||
/obj/item/flashlight/flare/culttorch/proc/transmit_item(atom/movable/A, mob/user, proximity)
|
||||
set waitfor = FALSE
|
||||
var/list/cultists = list()
|
||||
for(var/datum/mind/M in SSticker.mode.cult)
|
||||
if(M.current && M.current.stat != DEAD)
|
||||
cultists |= M.current
|
||||
var/mob/living/cultist_to_receive = input(user, "Who do you wish to call to [src]?", "Followers of the Geometer") as null|anything in (cultists - user)
|
||||
if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated())
|
||||
return
|
||||
if(!cultist_to_receive)
|
||||
to_chat(user, "<span class='cult italic'>You require a destination!</span>")
|
||||
log_game("Void torch failed - no target")
|
||||
return
|
||||
if(cultist_to_receive.stat == DEAD)
|
||||
to_chat(user, "<span class='cult italic'>[cultist_to_receive] has died!</span>")
|
||||
log_game("Void torch failed - target died")
|
||||
return
|
||||
if(!iscultist(cultist_to_receive))
|
||||
to_chat(user, "<span class='cult italic'>[cultist_to_receive] is not a follower of the Geometer!</span>")
|
||||
log_game("Void torch failed - target was deconverted")
|
||||
return
|
||||
if(A in user.GetAllContents())
|
||||
to_chat(user, "<span class='cult italic'>[A] must be on a surface in order to teleport it!</span>")
|
||||
return
|
||||
to_chat(user, "<span class='cult italic'>You ignite [A] with \the [src], turning it to ash, but through the torch's flames you see that [A] has reached [cultist_to_receive]!")
|
||||
cultist_to_receive.put_in_hands(A)
|
||||
charges--
|
||||
to_chat(user, "\The [src] now has [charges] charge\s.")
|
||||
if(charges == 0)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/cult_spear
|
||||
name = "blood halberd"
|
||||
|
||||
@@ -60,83 +60,86 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons)
|
||||
return
|
||||
if(A.anchored || (A.move_resist > max_force_fulton))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You start attaching the pack to [A]...</span>")
|
||||
if(do_after(user,50,target=A))
|
||||
to_chat(user, "<span class='notice'>You attach the pack to [A] and activate it.</span>")
|
||||
if(loc == user && istype(user.back, /obj/item/storage/backpack))
|
||||
var/obj/item/storage/backpack/B = user.back
|
||||
SEND_SIGNAL(B, COMSIG_TRY_STORAGE_INSERT, src, user, FALSE, FALSE)
|
||||
uses_left--
|
||||
if(uses_left <= 0)
|
||||
user.transferItemToLoc(src, A, TRUE)
|
||||
var/mutable_appearance/balloon
|
||||
var/mutable_appearance/balloon2
|
||||
var/mutable_appearance/balloon3
|
||||
if(isliving(A))
|
||||
var/mob/living/M = A
|
||||
M.DefaultCombatKnockdown(320) // Keep them from moving during the duration of the extraction
|
||||
M.buckled = 0 // Unbuckle them to prevent anchoring problems
|
||||
else
|
||||
A.anchored = TRUE
|
||||
A.density = FALSE
|
||||
var/obj/effect/extraction_holder/holder_obj = new(A.loc)
|
||||
holder_obj.appearance = A.appearance
|
||||
A.forceMove(holder_obj)
|
||||
balloon2 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_expand")
|
||||
balloon2.pixel_y = 10
|
||||
balloon2.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
|
||||
holder_obj.add_overlay(balloon2)
|
||||
sleep(4)
|
||||
balloon = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_balloon")
|
||||
balloon.pixel_y = 10
|
||||
balloon.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
|
||||
holder_obj.cut_overlay(balloon2)
|
||||
holder_obj.add_overlay(balloon)
|
||||
playsound(holder_obj.loc, 'sound/items/fulext_deploy.wav', 50, 1, -3)
|
||||
animate(holder_obj, pixel_z = 10, time = 20)
|
||||
sleep(20)
|
||||
animate(holder_obj, pixel_z = 15, time = 10)
|
||||
sleep(10)
|
||||
animate(holder_obj, pixel_z = 10, time = 10)
|
||||
sleep(10)
|
||||
animate(holder_obj, pixel_z = 15, time = 10)
|
||||
sleep(10)
|
||||
animate(holder_obj, pixel_z = 10, time = 10)
|
||||
sleep(10)
|
||||
playsound(holder_obj.loc, 'sound/items/fultext_launch.wav', 50, 1, -3)
|
||||
animate(holder_obj, pixel_z = 1000, time = 30)
|
||||
if(ishuman(A))
|
||||
var/mob/living/carbon/human/L = A
|
||||
L.SetUnconscious(0)
|
||||
L.drowsyness = 0
|
||||
L.SetSleeping(0)
|
||||
sleep(30)
|
||||
var/list/flooring_near_beacon = list()
|
||||
for(var/turf/open/floor in orange(1, beacon))
|
||||
flooring_near_beacon += floor
|
||||
holder_obj.forceMove(pick(flooring_near_beacon))
|
||||
animate(holder_obj, pixel_z = 10, time = 50)
|
||||
sleep(50)
|
||||
animate(holder_obj, pixel_z = 15, time = 10)
|
||||
sleep(10)
|
||||
animate(holder_obj, pixel_z = 10, time = 10)
|
||||
sleep(10)
|
||||
balloon3 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_retract")
|
||||
balloon3.pixel_y = 10
|
||||
balloon3.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
|
||||
holder_obj.cut_overlay(balloon)
|
||||
holder_obj.add_overlay(balloon3)
|
||||
sleep(4)
|
||||
holder_obj.cut_overlay(balloon3)
|
||||
A.anchored = FALSE // An item has to be unanchored to be extracted in the first place.
|
||||
A.density = initial(A.density)
|
||||
animate(holder_obj, pixel_z = 0, time = 5)
|
||||
sleep(5)
|
||||
A.forceMove(holder_obj.loc)
|
||||
qdel(holder_obj)
|
||||
if(uses_left <= 0)
|
||||
qdel(src)
|
||||
attach_fulton(A, user, flag, params)
|
||||
|
||||
/obj/item/extraction_pack/proc/attach_fulton(atom/movable/A, mob/living/carbon/human/user, flag, params)
|
||||
set waitfor = FALSE
|
||||
to_chat(user, "<span class='notice'>You start attaching the pack to [A]...</span>")
|
||||
if(do_after(user,50,target=A))
|
||||
to_chat(user, "<span class='notice'>You attach the pack to [A] and activate it.</span>")
|
||||
if(loc == user && istype(user.back, /obj/item/storage/backpack))
|
||||
var/obj/item/storage/backpack/B = user.back
|
||||
SEND_SIGNAL(B, COMSIG_TRY_STORAGE_INSERT, src, user, FALSE, FALSE)
|
||||
uses_left--
|
||||
if(uses_left <= 0)
|
||||
user.transferItemToLoc(src, A, TRUE)
|
||||
var/mutable_appearance/balloon
|
||||
var/mutable_appearance/balloon2
|
||||
var/mutable_appearance/balloon3
|
||||
if(isliving(A))
|
||||
var/mob/living/M = A
|
||||
M.DefaultCombatKnockdown(320) // Keep them from moving during the duration of the extraction
|
||||
M.buckled = 0 // Unbuckle them to prevent anchoring problems
|
||||
else
|
||||
A.anchored = TRUE
|
||||
A.density = FALSE
|
||||
var/obj/effect/extraction_holder/holder_obj = new(A.loc)
|
||||
holder_obj.appearance = A.appearance
|
||||
A.forceMove(holder_obj)
|
||||
balloon2 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_expand")
|
||||
balloon2.pixel_y = 10
|
||||
balloon2.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
|
||||
holder_obj.add_overlay(balloon2)
|
||||
sleep(4)
|
||||
balloon = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_balloon")
|
||||
balloon.pixel_y = 10
|
||||
balloon.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
|
||||
holder_obj.cut_overlay(balloon2)
|
||||
holder_obj.add_overlay(balloon)
|
||||
playsound(holder_obj.loc, 'sound/items/fulext_deploy.wav', 50, 1, -3)
|
||||
animate(holder_obj, pixel_z = 10, time = 20)
|
||||
sleep(20)
|
||||
animate(holder_obj, pixel_z = 15, time = 10)
|
||||
sleep(10)
|
||||
animate(holder_obj, pixel_z = 10, time = 10)
|
||||
sleep(10)
|
||||
animate(holder_obj, pixel_z = 15, time = 10)
|
||||
sleep(10)
|
||||
animate(holder_obj, pixel_z = 10, time = 10)
|
||||
sleep(10)
|
||||
playsound(holder_obj.loc, 'sound/items/fultext_launch.wav', 50, 1, -3)
|
||||
animate(holder_obj, pixel_z = 1000, time = 30)
|
||||
if(ishuman(A))
|
||||
var/mob/living/carbon/human/L = A
|
||||
L.SetUnconscious(0)
|
||||
L.drowsyness = 0
|
||||
L.SetSleeping(0)
|
||||
sleep(30)
|
||||
var/list/flooring_near_beacon = list()
|
||||
for(var/turf/open/floor in orange(1, beacon))
|
||||
flooring_near_beacon += floor
|
||||
holder_obj.forceMove(pick(flooring_near_beacon))
|
||||
animate(holder_obj, pixel_z = 10, time = 50)
|
||||
sleep(50)
|
||||
animate(holder_obj, pixel_z = 15, time = 10)
|
||||
sleep(10)
|
||||
animate(holder_obj, pixel_z = 10, time = 10)
|
||||
sleep(10)
|
||||
balloon3 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_retract")
|
||||
balloon3.pixel_y = 10
|
||||
balloon3.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
|
||||
holder_obj.cut_overlay(balloon)
|
||||
holder_obj.add_overlay(balloon3)
|
||||
sleep(4)
|
||||
holder_obj.cut_overlay(balloon3)
|
||||
A.anchored = FALSE // An item has to be unanchored to be extracted in the first place.
|
||||
A.density = initial(A.density)
|
||||
animate(holder_obj, pixel_z = 0, time = 5)
|
||||
sleep(5)
|
||||
A.forceMove(holder_obj.loc)
|
||||
qdel(holder_obj)
|
||||
if(uses_left <= 0)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/fulton_core
|
||||
name = "extraction beacon signaller"
|
||||
|
||||
@@ -2217,9 +2217,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
H.throw_alert("tempfeel", /atom/movable/screen/alert/cold, 2)
|
||||
if(-35 to -20)
|
||||
H.throw_alert("tempfeel", /atom/movable/screen/alert/cold, 1)
|
||||
if(-20 to 0) //This is the sweet spot where air is considered normal
|
||||
if(-20 to 1) //This is the sweet spot where air is considered normal
|
||||
H.clear_alert("tempfeel")
|
||||
if(0 to 15) //When the air around you matches your body's temperature, you'll start to feel warm.
|
||||
if(1 to 15) //When the air around you matches your body's temperature, you'll start to feel warm.
|
||||
H.throw_alert("tempfeel", /atom/movable/screen/alert/hot, 1)
|
||||
if(15 to 30)
|
||||
H.throw_alert("tempfeel", /atom/movable/screen/alert/hot, 2)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
/datum/movespeed_modifier/hunger
|
||||
variable = TRUE
|
||||
blacklisted_movetypes = FLOATING|FLYING
|
||||
|
||||
/datum/movespeed_modifier/slaughter
|
||||
multiplicative_slowdown = -1
|
||||
|
||||
@@ -148,6 +148,10 @@
|
||||
/obj/item/pen/afterattack(obj/O, mob/living/user, proximity)
|
||||
. = ..()
|
||||
//Changing name/description of items. Only works if they have the UNIQUE_RENAME object flag set
|
||||
try_modify_object(O, user, proximity)
|
||||
|
||||
/obj/item/pen/proc/try_modify_object(obj/O, mob/living/user, proximity)
|
||||
set waitfor = FALSE
|
||||
if(isobj(O) && proximity && (O.obj_flags & UNIQUE_RENAME))
|
||||
var/penchoice = input(user, "What would you like to edit?", "Rename, change description or reset both?") as null|anything in list("Rename","Change description","Reset")
|
||||
if(QDELETED(O) || !user.canUseTopic(O, BE_CLOSE))
|
||||
|
||||
@@ -235,10 +235,10 @@
|
||||
if(POOL_SCALDING) //Scalding
|
||||
M.adjust_bodytemperature(50,0,500)
|
||||
if(POOL_WARM) //Warm
|
||||
M.adjust_bodytemperature(20,0,360) //Heats up mobs till the thermometer shows up
|
||||
M.adjust_bodytemperature(20,0,323.15) //Heats up mobs till the thermometer shows up
|
||||
//Normal temp does nothing, because it's just room temperature water.
|
||||
if(POOL_COOL)
|
||||
M.adjust_bodytemperature(-20,250) //Cools mobs till the thermometer shows up
|
||||
M.adjust_bodytemperature(-20,274.15) //Cools mobs till the thermometer shows up
|
||||
if(POOL_FRIGID) //Freezing
|
||||
M.adjust_bodytemperature(-60) //cool mob at -35k per cycle, less would not affect the mob enough.
|
||||
if(M.bodytemperature <= 50 && !M.stat)
|
||||
|
||||
@@ -735,7 +735,10 @@
|
||||
if(jb)
|
||||
to_chat(user, "<span class='warning'>Your mind goes blank as you attempt to use the potion.</span>")
|
||||
return
|
||||
try_transfer_mind(SM, user)
|
||||
|
||||
/obj/item/slimepotion/transference/proc/try_transfer_mind(mob/living/simple_animal/SM, mob/user)
|
||||
set waitfor = FALSE
|
||||
prompted = 1
|
||||
if(alert("This will permanently transfer your consciousness to [SM]. Are you sure you want to do this?",,"Yes","No")=="No")
|
||||
prompted = 0
|
||||
|
||||
@@ -223,7 +223,6 @@
|
||||
var/alert_type = null
|
||||
if(ispath(breathing_class))
|
||||
breathing_class = breathing_classes[breathing_class]
|
||||
var/list/gases = breathing_class.gases
|
||||
alert_category = breathing_class.high_alert_category
|
||||
alert_type = breathing_class.high_alert_datum
|
||||
danger_reagent = breathing_class.danger_reagent
|
||||
|
||||
@@ -50,6 +50,40 @@
|
||||
-->
|
||||
<div class="commit sansserif">
|
||||
|
||||
<h2 class="date">11 December 2021</h2>
|
||||
<h3 class="author">SandPoot updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Borg speech is now centralized even inside lockers or something like that.</li>
|
||||
</ul>
|
||||
<h3 class="author">bunny232 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Cold blooded critters won't worry too much about the air around them being too hot even though their body temperature is the same as it.</li>
|
||||
<li class="balance">The warm pool is no longer nearly boiling and the cool pool no longer goes below 0C.</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">09 December 2021</h2>
|
||||
<h3 class="author">DeltaFire15 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Linters should no longer scream.</li>
|
||||
</ul>
|
||||
<h3 class="author">Linzolle updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">it now only snows on festivestation instead of every map</li>
|
||||
<li class="bugfix">rain now triggers properly on spookystation</li>
|
||||
</ul>
|
||||
<h3 class="author">TripleShades updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">(Pubby) Gives Robotic's Lab Surgery a cautery</li>
|
||||
</ul>
|
||||
<h3 class="author">keronshb updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Lets dynamic pick clock cultists midround</li>
|
||||
</ul>
|
||||
<h3 class="author">timothyteakettle updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">being fat no longer makes you slower when floating</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">05 December 2021</h2>
|
||||
<h3 class="author">Arturlang updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
|
||||
@@ -30372,3 +30372,23 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
|
||||
DeltaFire15:
|
||||
- bugfix: Fireman carry no longer drops the carried person if passing over a prone
|
||||
individual.
|
||||
2021-12-09:
|
||||
DeltaFire15:
|
||||
- bugfix: Linters should no longer scream.
|
||||
Linzolle:
|
||||
- bugfix: it now only snows on festivestation instead of every map
|
||||
- bugfix: rain now triggers properly on spookystation
|
||||
TripleShades:
|
||||
- rscadd: (Pubby) Gives Robotic's Lab Surgery a cautery
|
||||
keronshb:
|
||||
- rscadd: Lets dynamic pick clock cultists midround
|
||||
timothyteakettle:
|
||||
- bugfix: being fat no longer makes you slower when floating
|
||||
2021-12-11:
|
||||
SandPoot:
|
||||
- bugfix: Borg speech is now centralized even inside lockers or something like that.
|
||||
bunny232:
|
||||
- bugfix: Cold blooded critters won't worry too much about the air around them being
|
||||
too hot even though their body temperature is the same as it.
|
||||
- balance: The warm pool is no longer nearly boiling and the cool pool no longer
|
||||
goes below 0C.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "DeltaFire15"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Linters should no longer scream."
|
||||
4
html/changelogs/AutoChangeLog-pr-15421.yml
Normal file
4
html/changelogs/AutoChangeLog-pr-15421.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
author: "DeltaFire15"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Linters should no longer complain about afterattack sleeps."
|
||||
@@ -483,7 +483,8 @@
|
||||
end_message = "<span class='notice'>The downpour gradually slows until it stops.</span>"
|
||||
|
||||
area_type = /area/eventmap/outside
|
||||
target_trait = ZTRAIT_STATION
|
||||
target_trait = ZTRAIT_LONGRAIN
|
||||
probability = 90
|
||||
|
||||
barometer_predictable = TRUE
|
||||
|
||||
|
||||
Reference in New Issue
Block a user