Merge pull request #1 from Citadel-Station-13/master

d
This commit is contained in:
The-Sun-In-Splendour
2021-03-18 01:24:28 +01:00
committed by GitHub
54 changed files with 748 additions and 561 deletions
+7 -26
View File
@@ -80,10 +80,6 @@
},
/turf/open/floor/clockwork/reebe,
/area/reebe/city_of_cogs)
"az" = (
/obj/structure/destructible/clockwork/eminence_spire,
/turf/open/floor/clockwork/reebe,
/area/reebe/city_of_cogs)
"aA" = (
/obj/machinery/door/airlock/clockwork/brass{
name = "Infirmary"
@@ -168,21 +164,6 @@
/obj/effect/clockwork/sigil/transmission,
/turf/open/floor/clockwork/reebe,
/area/reebe/city_of_cogs)
"ew" = (
/obj/structure/table/reinforced/brass,
/obj/item/clockwork/construct_chassis/cogscarab{
pixel_y = 20
},
/obj/item/clockwork/construct_chassis/cogscarab{
pixel_x = -7;
pixel_y = 6
},
/obj/item/clockwork/construct_chassis/cogscarab{
pixel_x = 7;
pixel_y = 6
},
/turf/open/floor/clockwork/reebe,
/area/reebe/city_of_cogs)
"hY" = (
/obj/item/clockwork/alloy_shards/pinion_lock,
/turf/open/floor/clockwork/reebe,
@@ -208,10 +189,6 @@
/obj/item/storage/belt/utility/servant,
/turf/open/floor/clockwork/reebe,
/area/reebe/city_of_cogs)
"vx" = (
/obj/effect/clockwork/sigil/transmission,
/turf/open/floor/clockwork/reebe,
/area/reebe/city_of_cogs)
"wV" = (
/obj/item/clockwork/alloy_shards/large,
/turf/open/indestructible/reebe_void/spawning/lattices,
@@ -244,6 +221,10 @@
/obj/item/clockwork/alloy_shards/small,
/turf/open/indestructible/reebe_void/spawning/lattices,
/area/reebe)
"Ox" = (
/obj/structure/destructible/clockwork/eminence_spire,
/turf/open/floor/clockwork/reebe,
/area/reebe/city_of_cogs)
"OB" = (
/obj/item/clockwork/component/geis_capacitor/fallen_armor,
/turf/open/floor/clockwork/reebe,
@@ -32770,7 +32751,7 @@ ae
ae
ag
ah
ew
aL
aj
aj
aj
@@ -33284,8 +33265,8 @@ ab
ab
ae
ai
az
vx
Ox
aj
aj
aj
aE
+1
View File
@@ -59,6 +59,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
//Human sub-species
#define isabductor(A) (is_species(A, /datum/species/abductor))
#define isgolem(A) (is_species(A, /datum/species/golem))
#define isclockworkgolem(A) (is_species(A, /datum/species/golem/clockwork/no_scrap))
#define islizard(A) (is_species(A, /datum/species/lizard))
#define isplasmaman(A) (is_species(A, /datum/species/plasmaman))
#define ispodperson(A) (is_species(A, /datum/species/pod))
+11
View File
@@ -284,6 +284,17 @@ GLOBAL_LIST_INIT(wisdoms, world.file2list("strings/wisdoms.txt"))
GLOBAL_LIST_INIT(speech_verbs, list("default","says","gibbers", "states", "chitters", "chimpers", "declares", "bellows", "buzzes" ,"beeps", "chirps", "clicks", "hisses" ,"poofs" , "puffs", "rattles", "mewls" ,"barks", "blorbles", "squeaks", "squawks", "flutters", "warbles", "caws", "gekkers", "clucks"))
GLOBAL_LIST_INIT(roundstart_tongues, list("default","human tongue" = /obj/item/organ/tongue, "lizard tongue" = /obj/item/organ/tongue/lizard, "skeleton tongue" = /obj/item/organ/tongue/bone, "fly tongue" = /obj/item/organ/tongue/fly, "ipc tongue" = /obj/item/organ/tongue/robot/ipc, "xeno tongue" = /obj/item/organ/tongue/alien))
/proc/get_roundstart_languages()
var/list/languages = subtypesof(/datum/language)
var/list/roundstart_languages = list("None") //default option for the list
for(var/some_language in languages)
var/datum/language/language = some_language
if(initial(language.chooseable_roundstart))
roundstart_languages[initial(language.name)] = some_language
return roundstart_languages
GLOBAL_LIST_INIT(roundstart_languages, get_roundstart_languages())
//SPECIES BODYPART LISTS
//locked parts are those that your picked species requires to have
//unlocked parts are those that anyone can choose on customisation regardless
+4 -4
View File
@@ -3,7 +3,7 @@
var/obj/screen/blockchance
var/obj/screen/counterchance
/datum/hud/marauder/New(mob/living/simple_animal/hostile/clockwork/marauder/guardian/owner)
/datum/hud/marauder/New(mob/living/simple_animal/hostile/clockwork/guardian/owner)
..()
var/obj/screen/using
@@ -24,7 +24,7 @@
hosthealth = null
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/create_mob_hud()
/mob/living/simple_animal/hostile/clockwork/guardian/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/marauder(src, ui_style2icon(client.prefs.UI_style))
@@ -37,8 +37,8 @@
desc = "Emerge or Return."
/obj/screen/marauder/emerge/Click()
if(istype(usr, /mob/living/simple_animal/hostile/clockwork/marauder/guardian))
var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/G = usr
if(istype(usr, /mob/living/simple_animal/hostile/clockwork/guardian))
var/mob/living/simple_animal/hostile/clockwork/guardian/G = usr
if(G.is_in_host())
G.try_emerge()
else
+3
View File
@@ -34,3 +34,6 @@
/datum/skill_modifier/job/level/wiring/basic
level_mod = JOB_SKILL_BASIC
/datum/skill_modifier/job/level/dwarfy/blacksmithing
target_skills = /datum/skill/level/dwarfy/blacksmithing
-16
View File
@@ -219,19 +219,3 @@
/datum/quirk/night_vision/on_spawn()
var/mob/living/carbon/human/H = quirk_holder
H.update_sight()
/datum/quirk/multilingual
name = "Multi-Lingual"
desc = "You spent a portion of your life learning to understand an additional language. You may or may not be able to speak it based on your anatomy."
value = 1
mob_trait = TRAIT_MULTILINGUAL
gain_text = "You've learned an extra language!"
lose_text = "You've forgotten your extra language."
/datum/quirk/multilingual/post_add()
var/mob/living/carbon/human/H = quirk_holder
H.grant_language(H.client.prefs.language, TRUE, TRUE, LANGUAGE_MULTILINGUAL)
/datum/quirk/multilingual/remove()
var/mob/living/carbon/human/H = quirk_holder
H.remove_language(H.client.prefs.language, TRUE, TRUE, LANGUAGE_MULTILINGUAL)
+1 -1
View File
@@ -469,7 +469,7 @@
//hijacking the minature first aids for hypospray boxes. <3
/obj/item/storage/hypospraykit
name = "hypospray kit"
desc = "It's a kit containing a hypospray and specific treatment chemical-filled vials."
desc = "It's a kit designed for containing a hypospray and specific treatment chemical-filled vials."
icon_state = "firstaid-mini"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
@@ -144,7 +144,7 @@
to_chat(L, "<span class='heavy_brass'>\"You belong to me now.\"</span>")
if(!GLOB.application_scripture_unlocked)
GLOB.application_scripture_unlocked = TRUE
hierophant_message("<span class='large_brass bold'>With the conversion of a new servant the Ark's power grows. Application scriptures are now available.</span>")
hierophant_message("<span class='large_brass bold'>With the conversion of a new servant the Hierophant Network's power grows. Application scriptures are now available.</span>")
if(add_servant_of_ratvar(L))
L.log_message("conversion was done with a [sigil_name]", LOG_ATTACK, color="BE8700")
if(iscarbon(L))
@@ -196,4 +196,68 @@
CL.visible_message("<span class='warning'>[CL] materialises out of thin air!")
new /obj/effect/temp_visual/ratvar/sigil/transmission(T,2)
//summons a soul vessel, which is the clockwork cult version of a soul shard. It acts like a posibrain and, as long as the target has a brain, a soul shard.
/datum/clockwork_rite/soul_vessel
name = "Rite of the Vessel" //The name of the rite
desc = "This rite is used to summon a soul vessel, a special posibrain that makes whoever has their brain put into it loyal to the Justiciar.,\
When put into a cyborg shell, the created cyborg will automatically be a servant of Ratvar."
required_ingredients = list(/obj/item/stack/cable_coil, /obj/item/stock_parts/cell/, /obj/item/organ/cyberimp)
power_cost = 2500 //These things are pretty strong, I won't lie
requires_full_power = TRUE
cast_time = 50
limit = INFINITE
rite_cast_sound = 'sound/magic/summon_guns.ogg'
/datum/clockwork_rite/soul_vessel/cast(var/mob/living/invoker, var/turf/T, var/mob/living/carbon/human/target)
. = ..()
if(!.)
return FALSE
var/obj/item/mmi/posibrain/soul_vessel/SV = new /obj/item/mmi/posibrain/soul_vessel(T)
SV.visible_message("<span class='warning'>[SV] materalizes out of thin air!</span>")
new /obj/effect/temp_visual/ratvar/sigil/transmission(T,2)
/datum/clockwork_rite/cyborg_transform
name = "Rite of the Divine Form"
desc = "This rite is used to ascend into a cyborg, gaining unique scripture and a loadout that depends on which module is chosen. Consult the wiki for details on each cyborg module's loadout. Mutually exclusive to Enhanced Form."
required_ingredients = list(/obj/item/mmi/posibrain, /obj/item/stack/cable_coil, /obj/item/stock_parts/cell/super, /obj/item/bodypart/l_arm/robot, /obj/item/bodypart/r_arm/robot, /obj/item/bodypart/chest/robot, /obj/item/bodypart/head/robot, /obj/item/bodypart/r_leg/robot, /obj/item/bodypart/l_leg/robot)
power_cost = 20000
requires_human = TRUE
requires_full_power = FALSE
cast_time = 100
limit = INFINITE
rite_cast_sound = 'sound/magic/disable_tech.ogg'
/datum/clockwork_rite/cyborg_transform/cast(var/mob/living/invoker, var/turf/T, var/mob/living/carbon/human/target)
. = ..()
if(!.)
return FALSE
if(isclockworkgolem(target))
return FALSE
target.visible_message("<span class='warning'>The robotic parts magnetize to [target], the new frame's eyes glowing in a brilliant yellow!</span>")
var/mob/living/silicon/robot/R = target.Robotize()
R.cell = new /obj/item/stock_parts/cell/super(R)//takes one to use the rite to begin with
new /obj/effect/temp_visual/ratvar/sigil/transmission(T,2)
/datum/clockwork_rite/golem_transform
name = "Rite of the Enhanced Form"
desc = "This rite is used to shed one's flesh to become a clockwork automaton, becoming immune to many environmental hazards as well as being more resilient to incoming damage. Mutually exclusive to Divine Form."
required_ingredients = list(/obj/item/mmi/posibrain, /obj/item/stock_parts/cell/super, /obj/item/bodypart/l_arm/robot, /obj/item/bodypart/r_arm/robot, /obj/item/bodypart/chest/robot, /obj/item/bodypart/head/robot, /obj/item/bodypart/r_leg/robot, /obj/item/bodypart/l_leg/robot)
power_cost = 20000
requires_human = TRUE
requires_full_power = FALSE
cast_time = 100
limit = INFINITE
rite_cast_sound = 'sound/magic/disable_tech.ogg'
/datum/clockwork_rite/golem_transform/cast(var/mob/living/invoker, var/turf/T, var/mob/living/carbon/human/target)
. = ..()
if(!.)
return FALSE
target.visible_message("<span class='warning'>The robotic parts magnetize to [target], the humanoid shape's eye glowing with an inner flame!</span>")
to_chat(target, "<span class='bold alloy'>The rite's power warps your body into a clockwork form! You are now immune to many hazards, and your body is more robust against damage!</span>")
target.set_species(/datum/species/golem/clockwork/no_scrap)
new /obj/effect/temp_visual/ratvar/sigil/transmission(T,2)
#undef INFINITE
@@ -350,3 +350,22 @@
// Winter coat
/obj/item/clothing/suit/hooded/wintercoat/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //four sheets of metal
return list("operation_time" = 30, "new_obj_type" = /obj/item/clothing/suit/hooded/wintercoat/ratvar, "power_cost" = POWER_METAL * 4, "spawn_dir" = SOUTH)
//tools
/obj/item/crowbar/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //1 metal rod each
return list("operation_time" = 2, "new_obj_type" = /obj/item/crowbar/brass, "power_cost" = POWER_ROD * 1, "spawn_dir" = SOUTH)
/obj/item/screwdriver/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return list("operation_time" = 2, "new_obj_type" = /obj/item/screwdriver/brass, "power_cost" = POWER_ROD * 1, "spawn_dir" = SOUTH)
/obj/item/weldingtool/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return list("operation_time" = 2, "new_obj_type" = /obj/item/weldingtool/experimental/brass, "power_cost" = POWER_ROD * 1, "spawn_dir" = SOUTH)
/obj/item/wirecutters/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return list("operation_time" = 2, "new_obj_type" = /obj/item/wirecutters/brass, "power_cost" = POWER_ROD * 1, "spawn_dir" = SOUTH)
/obj/item/wrench/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return list("operation_time" = 2, "new_obj_type" = /obj/item/wrench/brass, "power_cost" = POWER_ROD * 1, "spawn_dir" = SOUTH)
/obj/item/multitool/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return list("operation_time" = 2, "new_obj_type" = /obj/item/multitool/advanced/brass, "power_cost" = POWER_ROD * 1, "spawn_dir" = SOUTH)
@@ -5,7 +5,7 @@
name = "clock-themed arm-mounted implant"
var/clockwork_desc = "According to Ratvar, this really shouldn't exist. Tell Him about this immediately."
syndicate_implant = TRUE
icon_state = "clock_arm_implant"
icon_state = "toolkit_implant"
/obj/item/organ/cyberimp/arm/clockwork/ui_action_click()
if(is_servant_of_ratvar(owner) || (obj_flags & EMAGGED)) //If you somehow manage to steal a clockie's implant AND have an emag AND manage to get it implanted for yourself, good on ya!
@@ -251,7 +251,9 @@
var/mob/camera/eminence/E = owner
E.eminence_help()
/*
//Returns to the Ark - Commented out and replaced with obelisk_jump
/datum/action/innate/eminence/ark_jump
name = "Return to Ark"
@@ -265,7 +267,7 @@
owner.playsound_local(owner, 'sound/magic/magic_missile.ogg', 50, TRUE)
flash_color(owner, flash_color = "#AF0AAF", flash_time = 25)
else
to_chat(owner, "<span class='warning'>There is no Ark!</span>")
to_chat(owner, "<span class='warning '>There is no Ark!</span>")
*/
//Warps to a chosen Obelisk
@@ -0,0 +1,432 @@
//Clockwork guardian: Slow but with high damage, resides inside of a servant. Created via the Memory Allocation scripture.
/mob/living/simple_animal/hostile/clockwork/guardian
name = "clockwork guardian"
desc = "A slow, armored clockwork machine, blazing with magenta flames. It's armed with a gladius and shield, and stands ready by its master."
icon_state = "clockwork_guardian"
health = 300
maxHealth = 300
speed = 1
obj_damage = 40
melee_damage_lower = 20//ranged attacks are the way to go for fighting these
melee_damage_upper = 20
attack_verb_continuous = "slashes"
attack_verb_simple = "slash"
attack_sound = 'sound/weapons/bladeslice.ogg'
weather_immunities = list("lava")
movement_type = FLYING
AIStatus = AI_OFF //this has to be manually set so that the guardian doesn't start bashing the host, how annoying -_-
loot = list(/obj/structure/destructible/clockwork/taunting_trail)
var/true_name = "Meme Master 69" //Required to call forth the guardian
var/global/list/possible_true_names = list("Servant", "Warden", "Serf", "Page", "Usher", "Knave", "Vassal", "Escort")
var/mob/living/host //The mob that the guardian is living inside of
var/recovering = FALSE //If the guardian is recovering from recalling
var/blockchance = 17 //chance to block attacks entirely
var/counterchance = 30 //chance to counterattack after blocking
var/static/list/damage_heal_order = list(OXY, BURN, BRUTE, TOX) //we heal our host's damage in this order
light_color = "#AF0AAF"
light_range = 2
light_power = 1.1
playstyle_string = "<span class='sevtug'>You are a clockwork guardian</span><b>, a living extension of Sevtug's will. As a guardian, you are somewhat slow, but may block attacks, \
and have a chance to also counter blocked melee attacks for extra damage, in addition to being immune to extreme temperatures and pressures. \
Your primary goal is to serve the creature that you are now a part of, as well as The Clockwork Justiciar, Ratvar. You can use <span class='sevtug_small'><i>The Hierophant Network</i></span> to communicate silently with your master and their allies, \
but can only exit if your master calls your true name or if they are exceptionally damaged. \
\n\n\
Stay near your host to protect and heal them; being too far from your host will rapidly cause you massive damage. Recall to your host if you are too weak and believe you cannot continue \
fighting safely. As a final note, you should probably avoid harming any fellow servants of Ratvar.</span>"
/mob/living/simple_animal/hostile/clockwork/guardian/Initialize()
. = ..()
true_name = pick(possible_true_names)
/mob/living/simple_animal/hostile/clockwork/guardian/BiologicalLife(seconds, times_fired)
..()
if(is_in_host())
if(!is_servant_of_ratvar(host))
emerge_from_host(FALSE, TRUE)
unbind_from_host()
return
if(!GLOB.ratvar_awakens && host.stat == DEAD)
death()
return
if(GLOB.ratvar_awakens)
adjustHealth(-50)
else
adjustHealth(-10)
if(!recovering)
heal_host() //also heal our host if inside of them and we aren't recovering
else if(health == maxHealth)
to_chat(src, "<span class='userdanger'>Your strength has returned. You can once again come forward!</span>")
to_chat(host, "<span class='userdanger'>Your guardian is now strong enough to come forward again!</span>")
recovering = FALSE
else
if(GLOB.ratvar_awakens) //If Ratvar is alive, guardians don't need a host and are downright impossible to kill
adjustHealth(-5)
heal_host()
else if(host)
if(!is_servant_of_ratvar(host))
unbind_from_host()
return
if(host.stat == DEAD)
adjustHealth(50)
to_chat(src, "<span class='userdanger'>Your host is dead!</span>")
return
if(z && host.z && z == host.z)
switch(get_dist(get_turf(src), get_turf(host)))
if(2)
adjustHealth(-1)
if(3)
//EQUILIBRIUM
if(4)
adjustHealth(1)
if(5)
adjustHealth(3)
if(6)
adjustHealth(6)
if(7)
adjustHealth(9)
if(8 to INFINITY)
adjustHealth(15)
to_chat(src, "<span class='userdanger'>You're too far from your host and rapidly taking damage!</span>")
else //right next to or on top of host
adjustHealth(-2)
heal_host() //gradually heal host if nearby and host is very weak
else //well then, you're not even in the same zlevel
adjustHealth(15)
to_chat(src, "<span class='userdanger'>You're too far from your host and rapidly taking damage!</span>")
/mob/living/simple_animal/hostile/clockwork/guardian/death(gibbed)
emerge_from_host(FALSE, TRUE)
unbind_from_host()
visible_message("<span class='warning'>[src]'s equipment fades into a purple mist as the flames within sputter and dissipate.</span>", \
"<span class='userdanger'>Your equipment fades away. You feel a moment of confusion before your fragile form is annihilated.</span>")
. = ..()
/mob/living/simple_animal/hostile/clockwork/guardian/Stat()
..()
if(statpanel("Status"))
stat(null, "Current True Name: [true_name]")
stat(null, "Host: [host ? host : "NONE"]")
if(host)
var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
if(iscarbon(host))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
stat(null, "Host Health: [resulthealth]%")
if(GLOB.ratvar_awakens)
stat(null, "You are [recovering ? "un" : ""]able to deploy!")
else
if(resulthealth > GUARDIAN_EMERGE_THRESHOLD)
stat(null, "You are [recovering ? "unable to deploy" : "able to deploy on hearing your True Name"]!")
else
stat(null, "You are [recovering ? "unable to deploy" : "able to deploy to protect your host"]!")
stat(null, "You do [melee_damage_upper] damage on melee attacks.")
/mob/living/simple_animal/hostile/clockwork/guardian/Process_Spacemove(movement_dir = 0)
return 1
/mob/living/simple_animal/hostile/clockwork/guardian/proc/bind_to_host(mob/living/new_host)
if(!new_host)
return FALSE
host = new_host
var/datum/action/innate/summon_guardian/SG = new()
SG.linked_guardian = src
SG.Grant(host)
var/datum/action/innate/linked_minds/LM = new()
LM.linked_guardian = src
LM.Grant(host)
return TRUE
/mob/living/simple_animal/hostile/clockwork/guardian/proc/unbind_from_host()
if(host)
for(var/datum/action/innate/summon_guardian/SG in host.actions)
qdel(SG)
for(var/datum/action/innate/linked_minds/LM in host.actions)
qdel(LM)
host = null
return TRUE
return FALSE
//DAMAGE and FATIGUE
/mob/living/simple_animal/hostile/clockwork/guardian/proc/heal_host()
if(!host)
return
var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
if(iscarbon(host))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
if(GLOB.ratvar_awakens || resulthealth <= GUARDIAN_EMERGE_THRESHOLD)
new /obj/effect/temp_visual/heal(host.loc, "#AF0AAF")
host.heal_ordered_damage(4, damage_heal_order)
/mob/living/simple_animal/hostile/clockwork/guardian/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
if(amount > 0)
for(var/mob/living/L in view(2, src))
if(L.is_holding_item_of_type(/obj/item/nullrod))
to_chat(src, "<span class='userdanger'>The presence of a brandished holy artifact weakens your armor!</span>")
amount *= 4 //if a wielded null rod is nearby, it takes four times the health damage
break
. = ..()
if(src && updating_health)
update_health_hud()
update_stats()
/mob/living/simple_animal/hostile/clockwork/guardian/update_health_hud()
if(hud_used && hud_used.healths)
if(istype(hud_used, /datum/hud))
var/datum/hud/marauder/G = hud_used
var/resulthealth
if(host)
if(iscarbon(host))
resulthealth = "[round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)]%"
else
resulthealth = "[round((host.health / host.maxHealth) * 100, 0.5)]%"
else
resulthealth = "NONE"
G.hosthealth.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#AF0AAF'>HOST<br>[resulthealth]</font></div>"
hud_used.healths.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#AF0AAF'>[round((health / maxHealth) * 100, 0.5)]%</font>"
/mob/living/simple_animal/hostile/clockwork/guardian/proc/update_stats()
if(GLOB.ratvar_awakens)
speed = 0
melee_damage_lower = 20
melee_damage_upper = 20
attack_verb_continuous = "devastates"
else
var/healthpercent = (health/maxHealth) * 100
switch(healthpercent)
if(100 to 70) //Bonuses to speed and damage at high health
speed = 0
melee_damage_lower = 16
melee_damage_upper = 16
attack_verb_continuous = "viciously slashes"
if(70 to 40)
speed = initial(speed)
melee_damage_lower = initial(melee_damage_lower)
melee_damage_upper = initial(melee_damage_upper)
attack_verb_continuous = initial(attack_verb_continuous)
if(40 to 30) //Damage decrease, but not speed
speed = initial(speed)
melee_damage_lower = 10
melee_damage_upper = 10
attack_verb_continuous = "lightly slashes"
if(30 to 20) //Speed decrease
speed = 2
melee_damage_lower = 8
melee_damage_upper = 8
attack_verb_continuous = "lightly slashes"
if(20 to 10) //Massive speed decrease and weak melee attacks
speed = 3
melee_damage_lower = 6
melee_damage_upper = 6
attack_verb_continuous = "weakly slashes"
if(10 to 0) //We are super weak and going to die
speed = 4
melee_damage_lower = 4
melee_damage_upper = 4
attack_verb_continuous = "taps"
//ATTACKING, BLOCKING, and COUNTERING
/mob/living/simple_animal/hostile/clockwork/guardian/AttackingTarget()
if(is_in_host())
return FALSE
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/bullet_act(obj/item/projectile/Proj)
if(blockOrCounter(null, Proj))
return
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/hitby(atom/movable/AM, skipcatch, hitpush, blocked, atom/movable/AM, datum/thrownthing/throwingdatum)
if(blockOrCounter(null, AM))
return
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/attack_animal(mob/living/simple_animal/M)
if(istype(M, /mob/living/simple_animal/hostile/clockwork/guardian) || !blockOrCounter(M, M)) //we don't want infinite blockcounter loops if fighting another guardian
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/attack_paw(mob/living/carbon/monkey/M)
if(!blockOrCounter(M, M))
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/attack_alien(mob/living/carbon/alien/humanoid/M)
if(!blockOrCounter(M, M))
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/attack_slime(mob/living/simple_animal/slime/M)
if(!blockOrCounter(M, M))
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/attack_hand(mob/living/carbon/human/M)
if(!blockOrCounter(M, M))
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/nullrod) || !blockOrCounter(user, I))
return ..()
/mob/living/simple_animal/hostile/clockwork/guardian/proc/blockOrCounter(mob/target, atom/textobject)
if(GLOB.ratvar_awakens) //if ratvar has woken, we block nearly everything at a very high chance
blockchance = 90
counterchance = 90
if(prob(blockchance))
. = TRUE
if(target)
target.do_attack_animation(src)
target.DelayNextAction(CLICK_CD_MELEE)
blockchance = initial(blockchance)
playsound(src, 'sound/magic/clockwork/fellowship_armory.ogg', 30, 1, 0, 1) //clang
visible_message("<span class='boldannounce'>[src] blocks [target && isitem(textobject) ? "[target]'s [textobject.name]":"\the [textobject]"]!</span>", \
"<span class='userdanger'>You block [target && isitem(textobject) ? "[target]'s [textobject.name]":"\the [textobject]"]!</span>")
if(target && Adjacent(target))
if(prob(counterchance))
counterchance = initial(counterchance)
var/previousattack_verb_continuous = attack_verb_continuous
attack_verb_continuous = "counters"
UnarmedAttack(target)
attack_verb_continuous = previousattack_verb_continuous
else
counterchance = min(counterchance + initial(counterchance), 100)
else
blockchance = min(blockchance + initial(blockchance), 100)
if(GLOB.ratvar_awakens)
blockchance = 90
counterchance = 90
//COMMUNICATION and EMERGENCE
/*
/mob/living/simple_animal/hostile/clockwork/guardian/handle_inherent_channels(message, message_mode)
if(host && (is_in_host() || message_mode == MODE_BINARY))
guardian_comms(message)
return TRUE
return ..()
*/
/mob/living/simple_animal/hostile/clockwork/guardian/proc/guardian_comms(message)
var/name_part = "<span class='sevtug'>[src] ([true_name])</span>"
message = "<span class='sevtug_small'>\"[message]\"</span>" //Processed output
to_chat(src, "[name_part]<span class='sevtug_small'>:</span> [message]")
to_chat(host, "[name_part]<span class='sevtug_small'>:</span> [message]")
for(var/M in GLOB.mob_list)
if(isobserver(M))
var/link = FOLLOW_LINK(M, src)
to_chat(M, "[link] [name_part] <span class='sevtug_small'>(to</span> <span class='sevtug'>[findtextEx(host.name, host.real_name) ? "[host.name]" : "[host.real_name] (as [host.name])"]</span><span class='sevtug_small'>):</span> [message] ")
return TRUE
/mob/living/simple_animal/hostile/clockwork/guardian/proc/return_to_host()
if(is_in_host())
return FALSE
if(!host)
to_chat(src, "<span class='warning'>You don't have a host!</span>")
return FALSE
var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
if(iscarbon(host))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
host.visible_message("<span class='warning'>[host]'s skin flashes magenta!</span>", "<span class='sevtug'>You feel [true_name]'s consciousness settle in your mind.</span>")
visible_message("<span class='warning'>[src] suddenly disappears!</span>", "<span class='sevtug'>You return to [host].</span>")
forceMove(host)
if(resulthealth > GUARDIAN_EMERGE_THRESHOLD && health != maxHealth)
recovering = TRUE
to_chat(src, "<span class='userdanger'>You have weakened and will need to recover before manifesting again!</span>")
to_chat(host, "<span class='sevtug'>[true_name] has weakened and will need to recover before manifesting again!</span>")
return TRUE
/mob/living/simple_animal/hostile/clockwork/guardian/proc/try_emerge()
if(!host)
to_chat(src, "<span class='warning'>You don't have a host!</span>")
return FALSE
if(!GLOB.ratvar_awakens)
var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
if(iscarbon(host))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
if(host.stat != DEAD && resulthealth > GUARDIAN_EMERGE_THRESHOLD) //if above 20 health, fails
to_chat(src, "<span class='warning'>Your host must be at [GUARDIAN_EMERGE_THRESHOLD]% or less health to emerge like this!</span>")
return FALSE
return emerge_from_host(FALSE)
/mob/living/simple_animal/hostile/clockwork/guardian/proc/emerge_from_host(hostchosen, force) //Notice that this is a proc rather than a verb - guardians can NOT exit at will, but they CAN return
if(!is_in_host())
return FALSE
if(!force && recovering)
if(hostchosen)
to_chat(host, "<span class='sevtug'>[true_name] is too weak to come forth!</span>")
else
to_chat(host, "<span class='sevtug'>[true_name] tries to emerge to protect you, but it's too weak!</span>")
to_chat(src, "<span class='userdanger'>You try to come forth, but you're too weak!</span>")
return FALSE
if(!force)
if(hostchosen) //guardian approved
to_chat(host, "<span class='sevtug'>Your words echo with power as [true_name] emerges from your body!</span>")
else
to_chat(host, "<span class='sevtug'>[true_name] emerges from your body to protect you!</span>")
forceMove(host.loc)
visible_message("<span class='warning'>[host]'s skin glows red as [name] emerges from their body!</span>", "<span class='sevtug_small'>You exit the safety of [host]'s body!</span>")
return TRUE
/mob/living/simple_animal/hostile/clockwork/guardian/get_alt_name()
return " ([text2ratvar(true_name)])"
/mob/living/simple_animal/hostile/clockwork/guardian/proc/is_in_host() //Checks if the guardian is inside of their host
return host && loc == host
//HOST ACTIONS
//Summon guardian action: Calls forth or recalls your guardian
/datum/action/innate/summon_guardian
name = "Force Guardian to Emerge/Recall"
desc = "Allows you to force your clockwork guardian to emerge or recall as required."
button_icon_state = "clockwork_marauder"
background_icon_state = "bg_clock"
check_flags = AB_CHECK_CONSCIOUS
buttontooltipstyle = "clockcult"
var/mob/living/simple_animal/hostile/clockwork/guardian/linked_guardian
var/list/defend_phrases = list("Defend me", "Come forth", "Assist me", "Protect me", "Give aid", "Help me")
var/list/return_phrases = list("Return", "Return to me", "Your job is done", "You have served", "Come back", "Retreat")
/datum/action/innate/summon_guardian/IsAvailable()
if(!linked_guardian)
return FALSE
if(isliving(owner))
var/mob/living/L = owner
if(!L.can_speak_vocal() || L.stat)
return FALSE
return ..()
/datum/action/innate/summon_guardian/Activate()
if(linked_guardian.is_in_host())
clockwork_say(owner, text2ratvar("[pick(defend_phrases)], [linked_guardian.true_name]!"))
linked_guardian.emerge_from_host(TRUE)
else
clockwork_say(owner, text2ratvar("[pick(return_phrases)], [linked_guardian.true_name]!"))
linked_guardian.return_to_host()
return TRUE
//Linked Minds action: talks to your guardian
/datum/action/innate/linked_minds
name = "Linked Minds"
desc = "Allows you to silently communicate with your guardian."
button_icon_state = "linked_minds"
background_icon_state = "bg_clock"
check_flags = AB_CHECK_CONSCIOUS
buttontooltipstyle = "clockcult"
var/mob/living/simple_animal/hostile/clockwork/guardian/linked_guardian
/datum/action/innate/linked_minds/IsAvailable()
if(!linked_guardian)
return FALSE
return ..()
/datum/action/innate/linked_minds/Activate()
var/message = stripped_input(owner, "Enter a message to tell your guardian.", "Telepathy")
if(!owner || !message)
return FALSE
if(!linked_guardian)
to_chat(owner, "<span class='warning'>Your guardian seems to have been destroyed!</span>")
return FALSE
var/name_part = "<span class='sevtug'>Servant [findtextEx(owner.name, owner.real_name) ? "[owner.name]" : "[owner.real_name] (as [owner.name])"]</span>"
message = "<span class='sevtug_small'>\"[message]\"</span>" //Processed output
to_chat(owner, "[name_part]<span class='sevtug_small'>:</span> [message]")
to_chat(linked_guardian, "[name_part]<span class='sevtug_small'>:</span> [message]")
for(var/M in GLOB.mob_list)
if(isobserver(M))
var/link = FOLLOW_LINK(M, src)
to_chat(M, "[link] [name_part] <span class='sevtug_small'>(to</span> <span class='sevtug'>[linked_guardian] ([linked_guardian.true_name])</span><span class='sevtug_small'>):</span> [message]")
return TRUE
@@ -123,437 +123,3 @@
#undef MARAUDER_SLOWDOWN_PERCENTAGE
#undef MARAUDER_SHIELD_REGEN_TIME
//Clockwork guardian: Slow but with high damage, resides inside of a servant. Created via the Memory Allocation scripture.
/mob/living/simple_animal/hostile/clockwork/marauder/guardian
name = "clockwork guardian"
desc = "A stalwart apparition of a soldier, blazing with crimson flames. It's armed with a gladius and shield and stands ready by its master."
icon_state = "clockwork_marauder"
health = 300
maxHealth = 300
speed = 1
obj_damage = 40
melee_damage_lower = 12
melee_damage_upper = 12
attack_verb_continuous = "slashes"
attack_verb_simple = "slash"
attack_sound = 'sound/weapons/bladeslice.ogg'
weather_immunities = list("lava")
movement_type = FLYING
AIStatus = AI_OFF //this has to be manually set so that the guardian doesn't start bashing the host, how annoying -_-
loot = list(/obj/item/clockwork/component/geis_capacitor/fallen_armor)
max_shield_health = 0
shield_health = 0
var/true_name = "Meme Master 69" //Required to call forth the guardian
var/global/list/possible_true_names = list("Servant", "Warden", "Serf", "Page", "Usher", "Knave", "Vassal", "Escort")
var/mob/living/host //The mob that the guardian is living inside of
var/recovering = FALSE //If the guardian is recovering from recalling
var/blockchance = 17 //chance to block attacks entirely
var/counterchance = 30 //chance to counterattack after blocking
var/static/list/damage_heal_order = list(OXY, BURN, BRUTE, TOX) //we heal our host's damage in this order
light_range = 2
light_power = 1.1
playstyle_string = "<span class='sevtug'>You are a clockwork guardian</span><b>, a living extension of Sevtug's will. As a guardian, you are somewhat slow, but may block attacks, \
and have a chance to also counter blocked melee attacks for extra damage, in addition to being immune to extreme temperatures and pressures. \
Your primary goal is to serve the creature that you are now a part of, as well as The Clockwork Justiciar, Ratvar. You can use <span class='sevtug_small'><i>The Hierophant Network</i></span> to communicate silently with your master and their allies, \
but can only exit if your master calls your true name or if they are exceptionally damaged. \
\n\n\
Stay near your host to protect and heal them; being too far from your host will rapidly cause you massive damage. Recall to your host if you are too weak and believe you cannot continue \
fighting safely. As a final note, you should probably avoid harming any fellow servants of Ratvar.</span>"
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/Initialize()
. = ..()
true_name = pick(possible_true_names)
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/BiologicalLife(seconds, times_fired)
..()
if(is_in_host())
if(!is_servant_of_ratvar(host))
emerge_from_host(FALSE, TRUE)
unbind_from_host()
return
if(!GLOB.ratvar_awakens && host.stat == DEAD)
death()
return
if(GLOB.ratvar_awakens)
adjustHealth(-50)
else
adjustHealth(-10)
if(!recovering)
heal_host() //also heal our host if inside of them and we aren't recovering
else if(health == maxHealth)
to_chat(src, "<span class='userdanger'>Your strength has returned. You can once again come forward!</span>")
to_chat(host, "<span class='userdanger'>Your guardian is now strong enough to come forward again!</span>")
recovering = FALSE
else
if(GLOB.ratvar_awakens) //If Ratvar is alive, guardians don't need a host and are downright impossible to kill
adjustHealth(-5)
heal_host()
else if(host)
if(!is_servant_of_ratvar(host))
unbind_from_host()
return
if(host.stat == DEAD)
adjustHealth(50)
to_chat(src, "<span class='userdanger'>Your host is dead!</span>")
return
if(z && host.z && z == host.z)
switch(get_dist(get_turf(src), get_turf(host)))
if(2)
adjustHealth(-1)
if(3)
//EQUILIBRIUM
if(4)
adjustHealth(1)
if(5)
adjustHealth(3)
if(6)
adjustHealth(6)
if(7)
adjustHealth(9)
if(8 to INFINITY)
adjustHealth(15)
to_chat(src, "<span class='userdanger'>You're too far from your host and rapidly taking damage!</span>")
else //right next to or on top of host
adjustHealth(-2)
heal_host() //gradually heal host if nearby and host is very weak
else //well then, you're not even in the same zlevel
adjustHealth(15)
to_chat(src, "<span class='userdanger'>You're too far from your host and rapidly taking damage!</span>")
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/death(gibbed)
emerge_from_host(FALSE, TRUE)
unbind_from_host()
visible_message("<span class='warning'>[src]'s equipment clatters lifelessly to the ground as the red flames within dissipate.</span>", \
"<span class='userdanger'>Your equipment falls away. You feel a moment of confusion before your fragile form is annihilated.</span>")
. = ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/Stat()
..()
if(statpanel("Status"))
stat(null, "Current True Name: [true_name]")
stat(null, "Host: [host ? host : "NONE"]")
if(host)
var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
if(iscarbon(host))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
stat(null, "Host Health: [resulthealth]%")
if(GLOB.ratvar_awakens)
stat(null, "You are [recovering ? "un" : ""]able to deploy!")
else
if(resulthealth > GUARDIAN_EMERGE_THRESHOLD)
stat(null, "You are [recovering ? "unable to deploy" : "able to deploy on hearing your True Name"]!")
else
stat(null, "You are [recovering ? "unable to deploy" : "able to deploy to protect your host"]!")
stat(null, "You do [melee_damage_upper] damage on melee attacks.")
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/Process_Spacemove(movement_dir = 0)
return 1
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/bind_to_host(mob/living/new_host)
if(!new_host)
return FALSE
host = new_host
var/datum/action/innate/summon_guardian/SG = new()
SG.linked_guardian = src
SG.Grant(host)
var/datum/action/innate/linked_minds/LM = new()
LM.linked_guardian = src
LM.Grant(host)
return TRUE
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/unbind_from_host()
if(host)
for(var/datum/action/innate/summon_guardian/SG in host.actions)
qdel(SG)
for(var/datum/action/innate/linked_minds/LM in host.actions)
qdel(LM)
host = null
return TRUE
return FALSE
//DAMAGE and FATIGUE
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/heal_host()
if(!host)
return
var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
if(iscarbon(host))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
if(GLOB.ratvar_awakens || resulthealth <= GUARDIAN_EMERGE_THRESHOLD)
new /obj/effect/temp_visual/heal(host.loc, "#AF0AAF")
host.heal_ordered_damage(4, damage_heal_order)
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
if(amount > 0)
for(var/mob/living/L in view(2, src))
if(L.is_holding_item_of_type(/obj/item/nullrod))
to_chat(src, "<span class='userdanger'>The presence of a brandished holy artifact weakens your armor!</span>")
amount *= 4 //if a wielded null rod is nearby, it takes four times the health damage
break
. = ..()
if(src && updating_health)
update_health_hud()
update_stats()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/update_health_hud()
if(hud_used && hud_used.healths)
if(istype(hud_used, /datum/hud/marauder))
var/datum/hud/marauder/G = hud_used
var/resulthealth
if(host)
if(iscarbon(host))
resulthealth = "[round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)]%"
else
resulthealth = "[round((host.health / host.maxHealth) * 100, 0.5)]%"
else
resulthealth = "NONE"
G.hosthealth.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#AF0AAF'>HOST<br>[resulthealth]</font></div>"
hud_used.healths.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#AF0AAF'>[round((health / maxHealth) * 100, 0.5)]%</font>"
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/update_stats()
if(GLOB.ratvar_awakens)
speed = 0
melee_damage_lower = 20
melee_damage_upper = 20
attack_verb_continuous = "devastates"
else
var/healthpercent = (health/maxHealth) * 100
switch(healthpercent)
if(100 to 70) //Bonuses to speed and damage at high health
speed = 0
melee_damage_lower = 16
melee_damage_upper = 16
attack_verb_continuous = "viciously slashes"
if(70 to 40)
speed = initial(speed)
melee_damage_lower = initial(melee_damage_lower)
melee_damage_upper = initial(melee_damage_upper)
attack_verb_continuous = initial(attack_verb_continuous)
if(40 to 30) //Damage decrease, but not speed
speed = initial(speed)
melee_damage_lower = 10
melee_damage_upper = 10
attack_verb_continuous = "lightly slashes"
if(30 to 20) //Speed decrease
speed = 2
melee_damage_lower = 8
melee_damage_upper = 8
attack_verb_continuous = "lightly slashes"
if(20 to 10) //Massive speed decrease and weak melee attacks
speed = 3
melee_damage_lower = 6
melee_damage_upper = 6
attack_verb_continuous = "weakly slashes"
if(10 to 0) //We are super weak and going to die
speed = 4
melee_damage_lower = 4
melee_damage_upper = 4
attack_verb_continuous = "taps"
//ATTACKING, BLOCKING, and COUNTERING
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/AttackingTarget()
if(is_in_host())
return FALSE
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/bullet_act(obj/item/projectile/Proj)
if(blockOrCounter(null, Proj))
return
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/hitby(atom/movable/AM, skipcatch, hitpush, blocked, atom/movable/AM, datum/thrownthing/throwingdatum)
if(blockOrCounter(null, AM))
return
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_animal(mob/living/simple_animal/M)
if(istype(M, /mob/living/simple_animal/hostile/clockwork/marauder/guardian) || !blockOrCounter(M, M)) //we don't want infinite blockcounter loops if fighting another guardian
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_paw(mob/living/carbon/monkey/M)
if(!blockOrCounter(M, M))
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_alien(mob/living/carbon/alien/humanoid/M)
if(!blockOrCounter(M, M))
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_slime(mob/living/simple_animal/slime/M)
if(!blockOrCounter(M, M))
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_hand(mob/living/carbon/human/M)
if(!blockOrCounter(M, M))
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/nullrod) || !blockOrCounter(user, I))
return ..()
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/blockOrCounter(mob/target, atom/textobject)
if(GLOB.ratvar_awakens) //if ratvar has woken, we block nearly everything at a very high chance
blockchance = 90
counterchance = 90
if(prob(blockchance))
. = TRUE
if(target)
target.do_attack_animation(src)
target.DelayNextAction(CLICK_CD_MELEE)
blockchance = initial(blockchance)
playsound(src, 'sound/magic/clockwork/fellowship_armory.ogg', 30, 1, 0, 1) //clang
visible_message("<span class='boldannounce'>[src] blocks [target && isitem(textobject) ? "[target]'s [textobject.name]":"\the [textobject]"]!</span>", \
"<span class='userdanger'>You block [target && isitem(textobject) ? "[target]'s [textobject.name]":"\the [textobject]"]!</span>")
if(target && Adjacent(target))
if(prob(counterchance))
counterchance = initial(counterchance)
var/previousattack_verb_continuous = attack_verb_continuous
attack_verb_continuous = "counters"
UnarmedAttack(target)
attack_verb_continuous = previousattack_verb_continuous
else
counterchance = min(counterchance + initial(counterchance), 100)
else
blockchance = min(blockchance + initial(blockchance), 100)
if(GLOB.ratvar_awakens)
blockchance = 90
counterchance = 90
//COMMUNICATION and EMERGENCE
/*
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/handle_inherent_channels(message, message_mode)
if(host && (is_in_host() || message_mode == MODE_BINARY))
guardian_comms(message)
return TRUE
return ..()
*/
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/guardian_comms(message)
var/name_part = "<span class='sevtug'>[src] ([true_name])</span>"
message = "<span class='sevtug_small'>\"[message]\"</span>" //Processed output
to_chat(src, "[name_part]<span class='sevtug_small'>:</span> [message]")
to_chat(host, "[name_part]<span class='sevtug_small'>:</span> [message]")
for(var/M in GLOB.mob_list)
if(isobserver(M))
var/link = FOLLOW_LINK(M, src)
to_chat(M, "[link] [name_part] <span class='sevtug_small'>(to</span> <span class='sevtug'>[findtextEx(host.name, host.real_name) ? "[host.name]" : "[host.real_name] (as [host.name])"]</span><span class='sevtug_small'>):</span> [message] ")
return TRUE
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/return_to_host()
if(is_in_host())
return FALSE
if(!host)
to_chat(src, "<span class='warning'>You don't have a host!</span>")
return FALSE
var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
if(iscarbon(host))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
host.visible_message("<span class='warning'>[host]'s skin flashes crimson!</span>", "<span class='sevtug'>You feel [true_name]'s consciousness settle in your mind.</span>")
visible_message("<span class='warning'>[src] suddenly disappears!</span>", "<span class='sevtug'>You return to [host].</span>")
forceMove(host)
if(resulthealth > GUARDIAN_EMERGE_THRESHOLD && health != maxHealth)
recovering = TRUE
to_chat(src, "<span class='userdanger'>You have weakened and will need to recover before manifesting again!</span>")
to_chat(host, "<span class='sevtug'>[true_name] has weakened and will need to recover before manifesting again!</span>")
return TRUE
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/try_emerge()
if(!host)
to_chat(src, "<span class='warning'>You don't have a host!</span>")
return FALSE
if(!GLOB.ratvar_awakens)
var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
if(iscarbon(host))
resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
if(host.stat != DEAD && resulthealth > GUARDIAN_EMERGE_THRESHOLD) //if above 20 health, fails
to_chat(src, "<span class='warning'>Your host must be at [GUARDIAN_EMERGE_THRESHOLD]% or less health to emerge like this!</span>")
return FALSE
return emerge_from_host(FALSE)
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/emerge_from_host(hostchosen, force) //Notice that this is a proc rather than a verb - guardians can NOT exit at will, but they CAN return
if(!is_in_host())
return FALSE
if(!force && recovering)
if(hostchosen)
to_chat(host, "<span class='sevtug'>[true_name] is too weak to come forth!</span>")
else
to_chat(host, "<span class='sevtug'>[true_name] tries to emerge to protect you, but it's too weak!</span>")
to_chat(src, "<span class='userdanger'>You try to come forth, but you're too weak!</span>")
return FALSE
if(!force)
if(hostchosen) //guardian approved
to_chat(host, "<span class='sevtug'>Your words echo with power as [true_name] emerges from your body!</span>")
else
to_chat(host, "<span class='sevtug'>[true_name] emerges from your body to protect you!</span>")
forceMove(host.loc)
visible_message("<span class='warning'>[host]'s skin glows red as [name] emerges from their body!</span>", "<span class='sevtug_small'>You exit the safety of [host]'s body!</span>")
return TRUE
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/get_alt_name()
return " ([text2ratvar(true_name)])"
/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/is_in_host() //Checks if the guardian is inside of their host
return host && loc == host
//HOST ACTIONS
//Summon guardian action: Calls forth or recalls your guardian
/datum/action/innate/summon_guardian
name = "Force Guardian to Emerge/Recall"
desc = "Allows you to force your clockwork guardian to emerge or recall as required."
button_icon_state = "clockwork_marauder"
background_icon_state = "bg_clock"
check_flags = AB_CHECK_CONSCIOUS
buttontooltipstyle = "clockcult"
var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/linked_guardian
var/list/defend_phrases = list("Defend me", "Come forth", "Assist me", "Protect me", "Give aid", "Help me")
var/list/return_phrases = list("Return", "Return to me", "Your job is done", "You have served", "Come back", "Retreat")
/datum/action/innate/summon_guardian/IsAvailable()
if(!linked_guardian)
return FALSE
if(isliving(owner))
var/mob/living/L = owner
if(!L.can_speak_vocal() || L.stat)
return FALSE
return ..()
/datum/action/innate/summon_guardian/Activate()
if(linked_guardian.is_in_host())
clockwork_say(owner, text2ratvar("[pick(defend_phrases)], [linked_guardian.true_name]!"))
linked_guardian.emerge_from_host(TRUE)
else
clockwork_say(owner, text2ratvar("[pick(return_phrases)], [linked_guardian.true_name]!"))
linked_guardian.return_to_host()
return TRUE
//Linked Minds action: talks to your guardian
/datum/action/innate/linked_minds
name = "Linked Minds"
desc = "Allows you to silently communicate with your guardian."
button_icon_state = "linked_minds"
background_icon_state = "bg_clock"
check_flags = AB_CHECK_CONSCIOUS
buttontooltipstyle = "clockcult"
var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/linked_guardian
/datum/action/innate/linked_minds/IsAvailable()
if(!linked_guardian)
return FALSE
return ..()
/datum/action/innate/linked_minds/Activate()
var/message = stripped_input(owner, "Enter a message to tell your guardian.", "Telepathy")
if(!owner || !message)
return FALSE
if(!linked_guardian)
to_chat(owner, "<span class='warning'>Your guardian seems to have been destroyed!</span>")
return FALSE
var/name_part = "<span class='sevtug'>Servant [findtextEx(owner.name, owner.real_name) ? "[owner.name]" : "[owner.real_name] (as [owner.name])"]</span>"
message = "<span class='sevtug_small'>\"[message]\"</span>" //Processed output
to_chat(owner, "[name_part]<span class='sevtug_small'>:</span> [message]")
to_chat(linked_guardian, "[name_part]<span class='sevtug_small'>:</span> [message]")
for(var/M in GLOB.mob_list)
if(isobserver(M))
var/link = FOLLOW_LINK(M, src)
to_chat(M, "[link] [name_part] <span class='sevtug_small'>(to</span> <span class='sevtug'>[linked_guardian] ([linked_guardian.true_name])</span><span class='sevtug_small'>):</span> [message]")
return TRUE
@@ -5,7 +5,7 @@ Pieces of scripture require certain follower counts, contruction value, and acti
Drivers: Unlocked by default
Scripts: 35k power or one convert
Applications: 50k or three converts
Judgement 5 converts
Judgement 80k power or nine converts
*/
/datum/clockwork_scripture
@@ -18,7 +18,7 @@
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 1
sort_priority = 2
important = TRUE
quickbind = TRUE
quickbind_desc = "Creates a Sigil of Transmission, which can drain and will store power for clockwork structures."
@@ -72,7 +72,7 @@
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 2
sort_priority = 5
quickbind = TRUE
quickbind_desc = "Creates a Mania Motor, which causes minor damage and negative mental effects in non-Servants."
requires_full_power = TRUE
@@ -101,7 +101,7 @@
//Memory Allocation: Finds a willing ghost and makes them into a clockwork guardian for the invoker.
/datum/clockwork_scripture/memory_allocation
descname = "Personal Guardian, A Peice Of Your Mind."
descname = "Personal Guardian housed in the brain."
name = "Memory Allocation"
desc = "Allocates part of your consciousness to a Clockwork Guardian, a variant of Marauder that lives within you, able to be \
called forth by Speaking its True Name or if you become exceptionally low on health.<br>\
@@ -109,13 +109,13 @@
invocations = list("Fright's will...", "...call forth...")
channel_time = 100
power_cost = 8000
usage_tip = "guardians are useful as personal bodyguards and frontline warriors."
usage_tip = "Guardians are useful as personal bodyguards and frontline warriors."
tier = SCRIPTURE_APPLICATION
primary_component = GEIS_CAPACITOR
sort_priority = 5
sort_priority = 6
/datum/clockwork_scripture/memory_allocation/check_special_requirements()
for(var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/M in GLOB.all_clockwork_mobs)
for(var/mob/living/simple_animal/hostile/clockwork/guardian/M in GLOB.all_clockwork_mobs)
if(M.host == invoker)
to_chat(invoker, "<span class='warning'>You can only house one guardian at a time!</span>")
return FALSE
@@ -151,7 +151,7 @@
return FALSE
clockwork_say(invoker, text2ratvar("...sword and shield!"))
var/mob/dead/observer/theghost = pick(marauder_candidates)
var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/M = new(invoker)
var/mob/living/simple_animal/hostile/clockwork/guardian/M = new(invoker)
M.key = theghost.key
M.bind_to_host(invoker)
invoker.visible_message("<span class='warning'>The tendril retracts from [invoker]'s head, sealing the entry wound as it does so!</span>", \
@@ -171,7 +171,7 @@
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
primary_component = BELLIGERENT_EYE
sort_priority = 6
sort_priority = 7
quickbind = TRUE
quickbind_desc = "Creates a clockwork marauder, used for frontline combat."
object_path = /obj/item/clockwork/construct_chassis/clockwork_marauder
@@ -223,7 +223,7 @@
object_path = /obj/mecha/combat/neovgre
tier = SCRIPTURE_APPLICATION
primary_component = BELLIGERENT_EYE
sort_priority = 7
sort_priority = 8
creator_message = "<span class='brass'>Neovgre, the Anima Bulwark towers over you... your enemies reckoning has come.</span>"
/datum/clockwork_scripture/create_object/summon_arbiter/check_special_requirements()
@@ -20,7 +20,7 @@
usage_tip = "The gateway is completely vulnerable to attack during its five-minute duration. It will periodically give indication of its general position to everyone on the station \
as well as being loud enough to be heard throughout the entire sector. Defend it with your life!"
tier = SCRIPTURE_APPLICATION
sort_priority = 8
sort_priority = 1
requires_full_power = TRUE
/datum/clockwork_scripture/create_object/ark_of_the_clockwork_justiciar/check_special_requirements()
@@ -81,7 +81,7 @@
priority_announce("Massive [Gibberish("bluespace", 100)] anomaly detected on all frequencies. All crew are directed to \
@!$, [text2ratvar("PURGE ALL UNTRUTHS")] <&. the anomalies and destroy their source to prevent further damage to corporate property. This is \
not a drill.", "Central Command Higher Dimensional Affairs", 'sound/magic/clockwork/ark_activation_sequence.ogg')
set_security_level("delta")
set_security_level("Delta")
for(var/V in SSticker.mode.servants_of_ratvar)
var/datum/mind/M = V
if(!M || !M.current)
@@ -29,8 +29,9 @@
sound_to_playing_players('sound/effects/ratvar_reveal.ogg')
var/mutable_appearance/alert_overlay = mutable_appearance('icons/effects/clockwork_effects.dmi', "ratvar_alert")
notify_ghosts("The Justiciar's light calls to you! Reach out to Ratvar in [get_area_name(src)] to be granted a shell to spread his glory!", null, source = src, alert_overlay = alert_overlay)
INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency.proc/request, null, 10, null, FALSE, 0)
SSpersistence.station_was_destroyed = TRUE
INVOKE_ASYNC(src, .proc/purge_the_heresy)
/obj/structure/destructible/clockwork/massive/ratvar/Destroy()
GLOB.ratvar_awakens--
@@ -151,3 +152,34 @@
sound_to_playing_players('sound/machines/clockcult/ratvar_scream.ogg', 80)
narsie.clashing = FALSE
qdel(src)
/obj/structure/destructible/clockwork/massive/ratvar/proc/purge_the_heresy()
sleep(50)
priority_announce("Massive energy surge detected. Closest matching threat: Incoming supernova. All crew are advised to evacuate NAN lightyears away from blast zone","Central Command Higher Dimensional Affairs", 'sound/misc/airraid.ogg')
sleep(300)
priority_announce("Gravitational anomalies detected on the station. [Gibberish("There is no additional dat", 100)]-BZZZZZT.","Central Command Higher Dimensional Affairs", 'sound/magic/clockwork/ratvar_announce1.ogg')
sleep(80)
sound_to_playing_players('sound/magic/clockwork/ratvar_announce2.ogg', 70)
send_to_playing_players("<span class='heavy_brass'><font size=5>\"COME, ALL THOSE FAITHFUL! WITNESS THE RAYS OF JUSTICE CAST UPON THE HERETICS!\"</font></span>")
sleep(50)
SSshuttle.registerHostileEnvironment(src)
SSshuttle.lockdown = TRUE
sleep(250)
if(QDELETED(src))
priority_announce("Energy signal no longer detected.","Central Command Higher Dimensional Affairs")
return
sound_to_playing_players('sound/magic/clockwork/ark_activation_sequence.ogg', 80) //if this isn't lessened in volume it peaks for some reason
addtimer(CALLBACK(GLOBAL_PROC, /proc/clockcult_ending_helper), 300)
/proc/clockcult_ending_helper()
for(var/mob/M in GLOB.mob_list)
if(M.client)
SEND_SOUND(M, sound('sound/magic/clockwork/ratvar_attack.ogg'))
SEND_SOUND(M, sound('sound/magic/clockwork/ratvarfire.ogg'))
if(!is_servant_of_ratvar(M) && isliving(M))
var/mob/living/L = M
L.fire_stacks = INFINITY
L.IgniteMob()
sleep(50)
SSticker.force_ending = 1
@@ -1,7 +1,7 @@
/obj/structure/destructible/clockwork/reflector
name = "reflector"
desc = "A large lantern-shaped machine made of thin brass. It looks fragile."
clockwork_desc = "A lantern-shaped generator that produces power when near starlight."
desc = "A large mirror-like structure made of thin brass on one side. It looks fragile."
clockwork_desc = "A large mirror-like structure made of thin brass on one side. It can redirect laser fire on one side"
icon_state = "reflector"
unanchored_icon = "reflector_unwrenched"
max_integrity = 40
@@ -5,7 +5,7 @@
antagpanel_category = "Clockcult"
job_rank = ROLE_SERVANT_OF_RATVAR
antag_moodlet = /datum/mood_event/cult
skill_modifiers = list(/datum/skill_modifier/job/level/wiring)
skill_modifiers = list(/datum/skill_modifier/job/level/wiring, /datum/skill_modifier/job/level/dwarfy/blacksmithing)
var/datum/action/innate/hierophant/hierophant_network = new
threat = 3
var/datum/team/clockcult/clock_team
+1 -1
View File
@@ -83,7 +83,7 @@
if(choice == "Yes" && IsAvailable())
var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
if(!C.cult_team)
to_chat(owner, "<span class='cult bold'>Do you not alreaady lead yourself?</span>")
to_chat(owner, "<span class='cult bold'>Do you not already lead yourself?</span>")
return
pollCultists(owner,C.cult_team)
+48 -38
View File
@@ -105,8 +105,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/be_random_body = 0 //whether we'll have a random body every round
var/gender = MALE //gender of character (well duh)
var/age = 30 //age of character
var/language = "Random" //bonus language
var/choselanguage = "Random" //language appearance
var/underwear = "Nude" //underwear type
var/undie_color = "FFFFFF"
var/undershirt = "Nude" //undershirt type
@@ -130,6 +128,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/custom_speech_verb = "default" //if your say_mod is to be something other than your races
var/custom_tongue = "default" //if your tongue is to be something other than your races
var/additional_language = "None" //additional language your character has
var/modified_limbs = list() //prosthetic/amputated limbs
var/chosen_limb_id //body sprite selected to load for the users limbs, null means default, is sanitized when loaded
@@ -277,10 +276,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<a href='?_src_=prefs;preference=tab;tab=0' [current_tab == 0 ? "class='linkOn'" : ""]>Character Settings</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=2' [current_tab == 2 ? "class='linkOn'" : ""]>Character Appearance</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=3' [current_tab == 3 ? "class='linkOn'" : ""]>Loadout</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=3' [current_tab == 3 ? "class='linkOn'" : ""]>Character Speech</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=4' [current_tab == 4 ? "class='linkOn'" : ""]>Loadout</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=1' [current_tab == 1 ? "class='linkOn'" : ""]>Game Preferences</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=4' [current_tab == 4 ? "class='linkOn'" : ""]>Content Preferences</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=5' [current_tab == 5 ? "class='linkOn'" : ""]>Keybindings</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=5' [current_tab == 5 ? "class='linkOn'" : ""]>Content Preferences</a>"
dat += "<a href='?_src_=prefs;preference=tab;tab=6' [current_tab == 6 ? "class='linkOn'" : ""]>Keybindings</a>"
if(!path)
dat += "<div class='notice'>Please create an account to save your preferences</div>"
@@ -328,7 +328,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Gender:</b> <a href='?_src_=prefs;preference=gender;task=input'>[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]</a><BR>"
dat += "<b>Age:</b> <a style='display:block;width:30px' href='?_src_=prefs;preference=age;task=input'>[age]</a><BR>"
dat += "<b>Language:</b> <a href='?_src_=prefs;preference=language;task=input'>[choselanguage]</a><BR>"
dat += "<b>Special Names:</b><BR>"
var/old_group
@@ -485,13 +484,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else if(use_skintones || mutant_colors)
dat += "</td>"
dat += APPEARANCE_CATEGORY_COLUMN
dat += "<h2>Speech preferences</h2>"
dat += "<b>Custom Speech Verb:</b><BR>"
dat += "</b><a style='display:block;width:100px' href='?_src_=prefs;preference=speech_verb;task=input'>[custom_speech_verb]</a><BR>"
dat += "<b>Custom Tongue:</b><BR>"
dat += "</b><a style='display:block;width:100px' href='?_src_=prefs;preference=tongue;task=input'>[custom_tongue]</a><BR>"
if(HAIR in pref_species.species_traits)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -678,6 +670,36 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</td>"
dat += "</tr></table>"
if(3)
if(path)
var/savefile/S = new /savefile(path)
if(S)
dat += "<center>"
var/name
var/unspaced_slots = 0
for(var/i=1, i<=max_save_slots, i++)
unspaced_slots++
if(unspaced_slots > 4)
dat += "<br>"
unspaced_slots = 0
S.cd = "/character[i]"
S["real_name"] >> name
if(!name)
name = "Character[i]"
dat += "<a style='white-space:nowrap;' href='?_src_=prefs;preference=changeslot;num=[i];' [i == default_slot ? "class='linkOn'" : ""]>[name]</a> "
dat += "</center>"
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>Speech preferences</h2>"
dat += "<b>Custom Speech Verb:</b><BR>"
dat += "</b><a style='display:block;width:100px' href='?_src_=prefs;preference=speech_verb;task=input'>[custom_speech_verb]</a><BR>"
dat += "<b>Custom Tongue:</b><BR>"
dat += "</b><a style='display:block;width:100px' href='?_src_=prefs;preference=tongue;task=input'>[custom_tongue]</a><BR>"
dat += "<b>Additional Language</b><BR>"
dat += "</b><a style='display:block;width:100px' href='?_src_=prefs;preference=language;task=input'>[additional_language]</a><BR>"
dat += "</td>"
dat += "</tr></table>"
if (1) // Game Preferences
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>General Settings</h2>"
@@ -846,7 +868,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<br>"
if(3)
if(4)
//calculate your gear points from the chosen item
gear_points = CONFIG_GET(number/initial_gear_points)
var/list/chosen_gear = loadout_data["SAVE_[loadout_slot]"]
@@ -965,7 +987,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</td><td><font size=2><i>[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description] Progress: [min(progress_made, unlockable.progress_required)]/[unlockable.progress_required]</i></font></td></tr>"
dat += "</table>"
if(4) // Content preferences
if(5) // Content preferences
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>Fetish content prefs</h2>"
dat += "<b>Arousal:</b><a href='?_src_=prefs;preference=arousable'>[arousable == TRUE ? "Enabled" : "Disabled"]</a><BR>"
@@ -989,7 +1011,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Automatic Wagging:</b> <a href='?_src_=prefs;preference=auto_wag'>[(cit_toggles & NO_AUTO_WAG) ? "Disabled" : "Enabled"]</a><br>"
dat += "</tr></table>"
dat += "<br>"
if(5) // Custom keybindings
if(6) // Custom keybindings
dat += "<b>Keybindings:</b> <a href='?_src_=prefs;preference=hotkeys'>[(hotkeys) ? "Hotkeys" : "Input"]</a><br>"
dat += "Keybindings mode controls how the game behaves with tab and map/input focus.<br>If it is on <b>Hotkeys</b>, the game will always attempt to force you to map focus, meaning keypresses are sent \
directly to the map instead of the input. You will still be able to use the command bar, but you need to tab to do it every time you click on the game map.<br>\
@@ -2339,28 +2361,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
features["body_model"] = chosengender
gender = chosengender
if("language")
choselanguage = input(user, "Select a language.", "Language", language) as null|anything in list("Beachtongue","Draconic","Dwarven",
"Chimpanzee","Space Sign Language","Random")
if(!choselanguage)
return
switch(choselanguage)
if("Rachidian")
language = /datum/language/arachnid
if("Beachtongue")
language = /datum/language/beachbum
if("Draconic")
language = /datum/language/draconic
if("Dwarven")
language = /datum/language/dwarf
if("Chimpanzee")
language = /datum/language/monkey
if("Space Sign Language")
language = /datum/language/signlanguage
if("Random")
language = pick(list("Rachidian", "Beachtongue","Draconic","Dwarven",
"Chimpanzee","Space Sign Language"))
if("body_size")
var/new_body_size = input(user, "Choose your desired sprite size: (90-125%)\nWarning: This may make your character look distorted. Additionally, any size under 100% takes a 10% maximum health penalty", "Character Preference", features["body_size"]*100) as num|null
if(new_body_size)
@@ -2370,11 +2370,17 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/selected_custom_tongue = input(user, "Choose your desired tongue (none means your species tongue)", "Character Preference") as null|anything in GLOB.roundstart_tongues
if(selected_custom_tongue)
custom_tongue = selected_custom_tongue
if("speech_verb")
var/selected_custom_speech_verb = input(user, "Choose your desired speech verb (none means your species speech verb)", "Character Preference") as null|anything in GLOB.speech_verbs
if(selected_custom_speech_verb)
custom_speech_verb = selected_custom_speech_verb
if("language")
var/selected_language = input(user, "Choose your desired additional language", "Character Preference") as null|anything in GLOB.roundstart_languages
if(selected_language)
additional_language = selected_language
if("bodysprite")
var/selected_body_sprite = input(user, "Choose your desired body sprite", "Character Preference") as null|anything in pref_species.allowed_limb_ids
if(selected_body_sprite)
@@ -2909,6 +2915,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
new_custom_tongue.Insert(character)
if(custom_speech_verb != "default")
character.dna.species.say_mod = custom_speech_verb
if(additional_language && additional_language != "None")
var/language_entry = GLOB.roundstart_languages[additional_language]
if(language_entry)
character.grant_language(language_entry, TRUE, TRUE)
//limb stuff, only done when initially spawning in
if(initial_spawn)
+3 -4
View File
@@ -604,8 +604,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["body_model"] >> features["body_model"]
S["body_size"] >> features["body_size"]
S["age"] >> age
S["language"] >> language
S["choselanguage"] >> choselanguage
S["hair_color"] >> hair_color
S["facial_hair_color"] >> facial_hair_color
S["eye_type"] >> eye_type
@@ -626,6 +624,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["uplink_loc"] >> uplink_spawn_loc
S["custom_speech_verb"] >> custom_speech_verb
S["custom_tongue"] >> custom_tongue
S["additional_language"] >> additional_language
S["feature_mcolor"] >> features["mcolor"]
S["feature_lizard_tail"] >> features["tail_lizard"]
S["feature_lizard_snout"] >> features["snout"]
@@ -881,6 +880,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
custom_speech_verb = sanitize_inlist(custom_speech_verb, GLOB.speech_verbs, "default")
custom_tongue = sanitize_inlist(custom_tongue, GLOB.roundstart_tongues, "default")
additional_language = sanitize_inlist(additional_language, GLOB.roundstart_languages, "None")
security_records = copytext(security_records, 1, MAX_FLAVOR_LEN)
medical_records = copytext(medical_records, 1, MAX_FLAVOR_LEN)
@@ -964,8 +964,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["body_model"] , features["body_model"])
WRITE_FILE(S["body_size"] , features["body_size"])
WRITE_FILE(S["age"] , age)
WRITE_FILE(S["language"] , language)
WRITE_FILE(S["choselanguage"] , choselanguage)
WRITE_FILE(S["hair_color"] , hair_color)
WRITE_FILE(S["facial_hair_color"] , facial_hair_color)
WRITE_FILE(S["eye_type"] , eye_type)
@@ -987,6 +985,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["species"] , pref_species.id)
WRITE_FILE(S["custom_speech_verb"] , custom_speech_verb)
WRITE_FILE(S["custom_tongue"] , custom_tongue)
WRITE_FILE(S["additional_language"] , additional_language)
// records
WRITE_FILE(S["security_records"] , security_records)
+1
View File
@@ -9,6 +9,7 @@
flags = NO_STUTTER | LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD
icon_state = "arachnid"
chooseable_roundstart = TRUE
/datum/language/arachnid/scramble(input)
. = prob(65) ? "<i>wiff</i>" : "<i>thump</i>"
+1
View File
@@ -18,3 +18,4 @@
)
icon_state = "lizard"
default_priority = 90
chooseable_roundstart = TRUE
+1
View File
@@ -11,3 +11,4 @@
default_priority = 90
icon_state = "dwarf"
chooseable_roundstart = TRUE
+2
View File
@@ -22,6 +22,8 @@
var/list/scramble_cache = list()
var/default_priority = 0 // the language that an atom knows with the highest "default_priority" is selected by default.
var/chooseable_roundstart = FALSE // can we pick it from the customization menu as an additional language?
// if you are seeing someone speak popcorn language, then something is wrong.
var/icon = 'icons/misc/language.dmi'
var/icon_state = "popcorn"
+1
View File
@@ -10,3 +10,4 @@
default_priority = 80
icon_state = "animal"
chooseable_roundstart = TRUE
+1
View File
@@ -9,3 +9,4 @@
sentence_chance = 0
default_priority = 80
syllables = list("poof", "pff", "pFfF", "piff", "puff", "pooof", "pfffff", "piffpiff", "puffpuff", "poofpoof", "pifpafpofpuf")
chooseable_roundstart = TRUE
+1
View File
@@ -10,3 +10,4 @@
default_priority = 70
icon_state = "slime"
chooseable_roundstart = TRUE
+1
View File
@@ -16,3 +16,4 @@
)
icon_state = "plant"
default_priority = 90
chooseable_roundstart = TRUE
+1
View File
@@ -12,3 +12,4 @@
)
icon_state = "volt"
default_priority = 90
chooseable_roundstart = TRUE
@@ -928,7 +928,10 @@
ghost.ManualFollow(src)
/obj/item/melee/ghost_sword/process()
ghost_check()
force = 0
var/ghost_counter = ghost_check()
force = clamp((ghost_counter * 4), 0, 75)
/obj/item/melee/ghost_sword/proc/recursive_orbit_collect(atom/A, list/L)
for(var/i in A.orbiters?.orbiters)
+2 -2
View File
@@ -1237,7 +1237,7 @@
if(user.incapacitated() || !user.Adjacent(src))
return FALSE
if(W && user.a_intent == INTENT_HELP && W.can_give())
user.give()
user.give(src)
return TRUE
/mob/living/carbon/verb/give_verb()
@@ -1253,4 +1253,4 @@
var/obj/item/I = usr.get_active_held_item()
var/mob/living/carbon/C = usr
if(I.can_give())
C.give()
C.give(src)
@@ -625,7 +625,7 @@
say_mod = "clicks"
limbs_id = "clockgolem"
info_text = "<span class='bold alloy'>As a </span><span class='bold brass'>Clockwork Golem</span><span class='bold alloy'>, you are faster than other types of golems, and are capable of using guns. On death, you will break down into scrap.</span>"
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYES,NOGENITALS,NOAROUSAL)
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYES,NOGENITALS,NOAROUSAL,ROBOTIC_LIMBS)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
@@ -667,6 +667,10 @@
/datum/species/golem/clockwork/no_scrap //These golems are created through the herald's beacon and leave normal corpses on death.
id = "clockwork golem servant"
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYES,NOSTOMACH,NOLIVER,NOGENITALS,NOAROUSAL,NOTRANSSTING,ROBOTIC_LIMBS,HAS_BONE)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_NOHUNGER,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
armor = 15 //Balance reasons make this armor weak
no_equip = list()
nojumpsuit = FALSE
@@ -675,6 +679,8 @@
dangerous_existence = TRUE
random_eligible = FALSE
info_text = "<span class='bold alloy'>As a </span><span class='bold brass'>Clockwork Golem Servant</span><span class='bold alloy'>, you are faster than other types of golems, and are capable of using guns.</span>" //warcult golems leave a corpse
gib_types = list(/obj/effect/gibspawner/ipc, /obj/effect/gibspawner/ipc/bodypartless)
/datum/species/golem/cloth
name = "Cloth Golem"
+12 -1
View File
@@ -514,10 +514,21 @@
/mob/living/ratvar_act()
if(status_flags & GODMODE)
return
if(stat != DEAD && !is_servant_of_ratvar(src))
if(stat == DEAD || is_servant_of_ratvar(src))
return
if(is_eligible_servant(src))
add_servant_of_ratvar(src)
to_chat(src, "<span class='heavy_brass'>Ratvar's influence invades your mind, praise the Justiciar!</span>")
else
to_chat(src, "<span class='userdanger'>A blinding light boils you alive! <i>Run!</i></span>")
adjust_fire_stacks(20)
adjustFireLoss(35)
IgniteMob()
if(iscultist(src))
to_chat(src, "<span class='userdanger'>You resist Ratvar's influence... but not all of it! <i>Run!</i></span>")
adjustFireLoss(35)
if(src && reagents)
reagents.add_reagent(/datum/reagent/fuel/holyoil, 5)
return FALSE
+3
View File
@@ -80,6 +80,9 @@
SSshuttle.lockdown = TRUE
SSpersistence.station_was_destroyed = TRUE
sleep(600)
if(QDELETED(src))
priority_announce("Accausal event alert rescinded. Eldritch presence no longer reading on sensors. Solution package disarmed. Reccomend immediate evacuation","Central Command Higher Dimensional Affairs")
return
if(resolved == FALSE)
resolved = TRUE
sound_to_playing_players('sound/machines/alarm.ogg')
@@ -94,7 +94,7 @@
/datum/design/medicinalsmartdart
name = "Medicinal Smartdart"
desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using it's smart nanofilter technology only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented."
desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using its smart nanofilter technology, only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented."
id = "medicinalsmartdart"
build_type = PROTOLATHE
materials = list(/datum/material/glass = 100, /datum/material/plastic = 100, /datum/material/iron = 100)
@@ -192,6 +192,16 @@
category = list("Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/hypospraykit
name = "Empty Hypospray Kit"
desc = "A plastic medical kit for storing hyposprays and hypospray accessories."
id = "hypokit"
build_type = PROTOLATHE
materials = list(/datum/material/plastic = 5000)
build_path = /obj/item/storage/hypospraykit // let's not summon new hyposprays thanks
category = list("Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/blood_bag
name = "Empty Blood Bag"
desc = "A small sterilized plastic bag for blood."
@@ -203,7 +213,7 @@
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
/datum/design/bsblood_bag
name = "Blue Space Empty Blood Bag"
name = "Empty Bluespace Blood Bag"
desc = "A large sterilized plastic bag for blood."
id = "bsblood_bag"
build_path = /obj/item/reagent_containers/blood/bluespace
@@ -104,5 +104,6 @@
// Default research tech, prevents bricking
design_ids = list("basic_matter_bin", "basic_cell", "basic_scanning", "basic_capacitor", "basic_micro_laser", "micro_mani", "desttagger", "handlabel", "packagewrap",
"destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "bepis", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab", "paystand",
"space_heater", "beaker", "large_beaker", "bucket", "xlarge_beaker", "sec_shellclip", "sec_beanbag", "sec_rshot", "sec_bshot", "sec_slug", "sec_islug", "sec_dart", "sec_38", "sec_38lethal",
"space_heater", "beaker", "large_beaker", "xlarge_beaker", "bucket", "hypovial", "large_hypovial",
"sec_shellclip", "sec_beanbag", "sec_rshot", "sec_bshot", "sec_slug", "sec_islug", "sec_dart", "sec_38", "sec_38lethal",
"rglass","plasteel","plastitanium","plasmaglass","plasmareinforcedglass","titaniumglass","plastitaniumglass")
@@ -5,7 +5,7 @@
display_name = "Biological Technology"
description = "What makes us tick." //the MC, silly!
prereq_ids = list("base")
design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibrillator", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen", "telescopiciv", "medspray","genescanner","chem_pack", "portable_chem_mixer")
design_ids = list("medicalkit", "hypokit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibrillator", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen", "telescopiciv", "medspray","genescanner","chem_pack", "portable_chem_mixer")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
/datum/techweb_node/adv_biotech
@@ -24,6 +24,14 @@
design_ids = list("bluespace_matter_bin", "femto_mani", "triphasic_scanning", "bluespace_crystal", "xenobio_slimeadv")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000)
/datum/techweb_node/emp_super
id = "emp_super"
display_name = "Quantum Electromagnetic Technology"
description = "Even better electromagnetic technology."
prereq_ids = list("emp_adv", "adv_bluespace") // why should the rest of T4 be locked but not this node? grmblgrmbl
design_ids = list("quadultra_micro_laser")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000)
/datum/techweb_node/bluespace_power
id = "bluespace_power"
display_name = "Bluespace Power Technology"
@@ -37,7 +45,7 @@
display_name = "Bluespace Pockets"
description = "Studies into the mysterious alternate dimension known as bluespace and how to place items in the threads of reality."
prereq_ids = list("adv_power", "adv_bluespace", "adv_biotech", "adv_plasma")
design_ids = list( "bluespacebodybag","bag_holding", "bluespace_pod", "borg_upgrade_trashofholding", "blutrash", "satchel_holding", "bsblood_bag", "duffelbag_holding")
design_ids = list("bluespacebodybag","bag_holding", "bluespace_pod", "borg_upgrade_trashofholding", "blutrash", "satchel_holding", "bsblood_bag", "duffelbag_holding")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5500)
/datum/techweb_node/bluespace_portal
@@ -49,14 +49,6 @@
design_ids = list("ultra_micro_laser")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000)
/datum/techweb_node/emp_super
id = "emp_super"
display_name = "Quantum Electromagnetic Technology" //bs
description = "Even better electromagnetic technology."
prereq_ids = list("emp_adv")
design_ids = list("quadultra_micro_laser")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000)
/////////////////////////Clown tech/////////////////////////
/datum/techweb_node/clown
id = "clown"
+23
View File
@@ -50,6 +50,29 @@
-->
<div class="commit sansserif">
<h2 class="date">18 March 2021</h2>
<h3 class="author">Arturlang updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Combat mode right click and right click verb give's are now actualyl targeted</li>
</ul>
<h3 class="author">Hatterhat updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Hypospray vials are now printable from the medical techshift start.</li>
<li class="rscadd">Empty hypospray kits are now printable behind biological technology. tweak: Quantum electromag (T4 lasers) are now behind Advanced Bluespace like the rest of T4.</li>
</ul>
<h2 class="date">17 March 2021</h2>
<h3 class="author">KeRSedChaplain updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Added three new rites, and makes soul vessels obtainable</li>
<li class="bugfix">fixes clockwork guardians inheriting marauders blocking</li>
<li class="soundadd">added sounds for the ratvar end sequence, voiced by @dzahlus</li>
</ul>
<h3 class="author">timothyteakettle updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">speech panel added to main menu customization</li>
</ul>
<h2 class="date">16 March 2021</h2>
<h3 class="author">GrayRachnid updated:</h3>
<ul class="changes bgimages16">
+15
View File
@@ -28737,3 +28737,18 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
- balance: Made nitryl's cargo sell value less (10 instead of 30)
SandPoot:
- bugfix: Fixed interacting with telecomms.
2021-03-17:
KeRSedChaplain:
- rscadd: Added three new rites, and makes soul vessels obtainable
- bugfix: fixes clockwork guardians inheriting marauders blocking
- soundadd: added sounds for the ratvar end sequence, voiced by @dzahlus
timothyteakettle:
- rscadd: speech panel added to main menu customization
2021-03-18:
Arturlang:
- bugfix: Combat mode right click and right click verb give's are now actualyl targeted
Hatterhat:
- rscadd: Hypospray vials are now printable from the medical techshift start.
- rscadd: 'Empty hypospray kits are now printable behind biological technology.
tweak: Quantum electromag (T4 lasers) are now behind Advanced Bluespace like
the rest of T4.'
Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
View File
@@ -1617,6 +1617,7 @@
#include "code\modules\antagonists\clockcult\clock_items\clock_weapons\ratvarian_shield.dm"
#include "code\modules\antagonists\clockcult\clock_items\clock_weapons\ratvarian_spear.dm"
#include "code\modules\antagonists\clockcult\clock_mobs\_eminence.dm"
#include "code\modules\antagonists\clockcult\clock_mobs\clockwork_guardian.dm"
#include "code\modules\antagonists\clockcult\clock_mobs\clockwork_marauder.dm"
#include "code\modules\antagonists\clockcult\clock_scriptures\scripture_applications.dm"
#include "code\modules\antagonists\clockcult\clock_scriptures\scripture_cyborg.dm"