(Ready) Clockwork Cult Rework: Proof-of-concept

This commit is contained in:
Ashe Higgs
2017-09-26 15:22:09 -05:00
committed by CitadelStationBot
parent b51e4457f5
commit e575bd6685
103 changed files with 4394 additions and 2615 deletions
@@ -1,93 +1,3 @@
//generates a component in the global component cache, either random based on lowest or a specific component
/proc/generate_cache_component(specific_component_id, atom/A)
if(!specific_component_id)
specific_component_id = get_weighted_component_id()
GLOB.clockwork_component_cache[specific_component_id]++
if(A)
var/component_animation_type = get_component_animation_type(specific_component_id)
new component_animation_type(get_turf(A))
update_slab_info()
return specific_component_id
//returns a chosen component id based on the lowest amount of that component in the global cache, the global cache plus the slab if there are caches, or the slab if there are no caches.
/proc/get_weighted_component_id(obj/item/clockwork/slab/storage_slab)
. = list()
if(storage_slab)
if(GLOB.clockwork_caches)
for(var/i in GLOB.clockwork_component_cache)
.[i] = max(MAX_COMPONENTS_BEFORE_RAND - LOWER_PROB_PER_COMPONENT*(GLOB.clockwork_component_cache[i] + storage_slab.stored_components[i]), 1)
else
for(var/i in GLOB.clockwork_component_cache)
.[i] = max(MAX_COMPONENTS_BEFORE_RAND - LOWER_PROB_PER_COMPONENT*storage_slab.stored_components[i], 1)
else
for(var/i in GLOB.clockwork_component_cache)
.[i] = max(MAX_COMPONENTS_BEFORE_RAND - LOWER_PROB_PER_COMPONENT*GLOB.clockwork_component_cache[i], 1)
for(var/obj/structure/destructible/clockwork/massive/celestial_gateway/G in GLOB.all_clockwork_objects)
if(G.still_needs_components())
for(var/i in G.required_components)
if(!G.required_components[i])
. -= i
break
. = pickweight(.)
//returns a component name from a component id
/proc/get_component_name(id)
switch(id)
if(BELLIGERENT_EYE)
return "Belligerent Eye"
if(VANGUARD_COGWHEEL)
return "Vanguard Cogwheel"
if(GEIS_CAPACITOR)
return "Geis Capacitor"
if(REPLICANT_ALLOY)
return "Replicant Alloy"
if(HIEROPHANT_ANSIBLE)
return "Hierophant Ansible"
else
return null
//returns a component acronym from a component id
/proc/get_component_acronym(id)
switch(id)
if(BELLIGERENT_EYE)
return "BE"
if(VANGUARD_COGWHEEL)
return "VC"
if(GEIS_CAPACITOR)
return "GC"
if(REPLICANT_ALLOY)
return "RA"
if(HIEROPHANT_ANSIBLE)
return "HA"
else
return null
//returns a component icon from a component id
/proc/get_component_icon(id)
var/static/list/tgui_component_icons = list(
BELLIGERENT_EYE = icon2base64(icon('icons/obj/tgui_components.dmi', BELLIGERENT_EYE)),
VANGUARD_COGWHEEL = icon2base64(icon('icons/obj/tgui_components.dmi', VANGUARD_COGWHEEL)),
GEIS_CAPACITOR = icon2base64(icon('icons/obj/tgui_components.dmi', GEIS_CAPACITOR)),
REPLICANT_ALLOY = icon2base64(icon('icons/obj/tgui_components.dmi', REPLICANT_ALLOY)),
HIEROPHANT_ANSIBLE = icon2base64(icon('icons/obj/tgui_components.dmi', HIEROPHANT_ANSIBLE)))
return "<img style='width:14px; height:14px' src='data:image/png;base64,[tgui_component_icons[id]]'/>"
//returns a component id from a component name
/proc/get_component_id(name)
switch(name)
if("Belligerent Eye")
return BELLIGERENT_EYE
if("Vanguard Cogwheel")
return VANGUARD_COGWHEEL
if("Geis Capacitor")
return GEIS_CAPACITOR
if("Replicant Alloy")
return REPLICANT_ALLOY
if("Hierophant Ansible")
return HIEROPHANT_ANSIBLE
else
return null
//returns a component spanclass from a component id
/proc/get_component_span(id)
switch(id)
@@ -129,35 +39,3 @@
return "#DAAA18"
else
return "#BE8700"
//returns a type for a floating component animation from a component id
/proc/get_component_animation_type(id)
switch(id)
if(BELLIGERENT_EYE)
return /obj/effect/temp_visual/ratvar/component
if(VANGUARD_COGWHEEL)
return /obj/effect/temp_visual/ratvar/component/cogwheel
if(GEIS_CAPACITOR)
return /obj/effect/temp_visual/ratvar/component/capacitor
if(REPLICANT_ALLOY)
return /obj/effect/temp_visual/ratvar/component/alloy
if(HIEROPHANT_ANSIBLE)
return /obj/effect/temp_visual/ratvar/component/ansible
else
return null
//returns a type for a component from a component id
/proc/get_component_type(id)
switch(id)
if(BELLIGERENT_EYE)
return /obj/item/clockwork/component/belligerent_eye
if(VANGUARD_COGWHEEL)
return /obj/item/clockwork/component/vanguard_cogwheel
if(GEIS_CAPACITOR)
return /obj/item/clockwork/component/geis_capacitor
if(REPLICANT_ALLOY)
return /obj/item/clockwork/component/replicant_alloy
if(HIEROPHANT_ANSIBLE)
return /obj/item/clockwork/component/hierophant_ansible
else
return null
@@ -9,7 +9,7 @@
return FALSE
/atom/proc/consume_visual(obj/item/clockwork/replica_fabricator/fabricator, power_amount)
if(fabricator.can_use_power(power_amount))
if(get_clockwork_power(power_amount))
var/obj/effect/temp_visual/ratvar/beam/itemconsume/B = new /obj/effect/temp_visual/ratvar/beam/itemconsume(get_turf(src))
B.pixel_x = pixel_x
B.pixel_y = pixel_y
@@ -240,7 +240,7 @@
extra_checks = CALLBACK(fabricator, /obj/item/clockwork/replica_fabricator.proc/fabricator_repair_checks, repair_values, src, user, TRUE)))
break
obj_integrity = Clamp(obj_integrity + repair_values["healing_for_cycle"], 0, max_integrity)
fabricator.modify_stored_power(-repair_values["power_required"])
adjust_clockwork_power(-repair_values["power_required"])
playsound(src, 'sound/machines/click.ogg', 50, 1)
if(fabricator)
@@ -249,28 +249,6 @@
user.visible_message("<span class='notice'>[user]'s [fabricator.name] stops covering [src] with glowing orange energy.</span>", \
"<span class='alloy'>You finish repairing [src]. It is now at <b>[obj_integrity]/[max_integrity]</b> integrity.</span>")
//Hitting a sigil of transmission will try to charge from it.
/obj/effect/clockwork/sigil/transmission/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
. = TRUE
var/list/charge_values = list()
if(!fabricator.sigil_charge_checks(charge_values, src, user))
return
user.visible_message("<span class='notice'>[user]'s [fabricator.name] starts draining glowing orange energy from [src]...</span>", \
"<span class='alloy'>You start recharging your [fabricator.name]...</span>")
fabricator.recharging = src
while(fabricator && user && src)
if(!do_after(user, 10, target = src, extra_checks = CALLBACK(fabricator, /obj/item/clockwork/replica_fabricator.proc/sigil_charge_checks, charge_values, src, user, TRUE)))
break
modify_charge(charge_values["power_gain"])
fabricator.modify_stored_power(charge_values["power_gain"])
playsound(src, 'sound/effects/light_flicker.ogg', charge_values["power_gain"] * 0.1, 1)
if(fabricator)
fabricator.recharging = null
if(user)
user.visible_message("<span class='notice'>[user]'s [fabricator.name] stops draining glowing orange energy from [src].</span>", \
"<span class='alloy'>You finish recharging your [fabricator.name]. It now contains <b>[DisplayPower(fabricator.get_power())]/[DisplayPower(fabricator.get_max_power())]</b> power.</span>")
//Fabricator mob heal proc, to avoid as much copypaste as possible.
/mob/living/proc/fabricator_heal(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator)
var/list/repair_values = list()
@@ -284,7 +262,7 @@
extra_checks = CALLBACK(fabricator, /obj/item/clockwork/replica_fabricator.proc/fabricator_repair_checks, repair_values, src, user, TRUE)))
break
fabricator_heal_tick(repair_values["healing_for_cycle"])
fabricator.modify_stored_power(-repair_values["power_required"])
adjust_clockwork_power(-repair_values["power_required"])
playsound(src, 'sound/machines/click.ogg', 50, 1)
if(fabricator)
@@ -26,6 +26,7 @@
/datum/action/innate/hierophant
name = "Hierophant Network"
desc = "Allows you to communicate with other Servants."
icon_icon = 'icons/mob/actions/actions_clockcult.dmi'
button_icon_state = "hierophant"
background_icon_state = "bg_clock"
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS
@@ -43,6 +44,7 @@
var/input = stripped_input(usr, "Please enter a message to send to other servants.", "Hierophant Network", "")
if(!input || !IsAvailable())
return
if(ishuman(owner))
clockwork_say(owner, "[text2ratvar("Servants, hear my words: [input]")]", TRUE)
log_talk(owner,"CLOCK:[key_name(owner)] : [input]",LOGSAY)
titled_hierophant_message(owner, input, span_for_name, span_for_message, title)
@@ -0,0 +1,25 @@
//Helper procs for clockwork power, used by structures and items and that kind of jazz.
/proc/get_clockwork_power(amount) //If no amount is provided, returns the clockwork power; otherwise, returns if there's enough power for that amount.
return amount ? GLOB.clockwork_power >= amount : GLOB.clockwork_power
/proc/adjust_clockwork_power(amount) //Adjusts the global clockwork power by this amount (min 0.)
if(GLOB.ratvar_approaches)
amount *= 0.75 //The herald's beacon reduces power costs by 25% across the board!
GLOB.clockwork_power = GLOB.ratvar_awakens ? INFINITY : max(0, GLOB.clockwork_power + amount)
for(var/obj/effect/clockwork/sigil/transmission/T in GLOB.all_clockwork_objects)
T.update_icon()
var/power_overwhelming = GLOB.clockwork_power
if(power_overwhelming >= SCRIPT_UNLOCK_THRESHOLD && !GLOB.script_scripture_unlocked)
GLOB.script_scripture_unlocked = TRUE
hierophant_message("<span class='large_brass bold'>The Ark swells as a key power threshold is reached. Script scriptures are now available.</span>")
if(power_overwhelming >= APPLICATION_UNLOCK_THRESHOLD && !GLOB.application_scripture_unlocked)
GLOB.application_scripture_unlocked = TRUE
hierophant_message("<span class='large_brass bold'>The Ark surges as a key power threshold is reached. Application scriptures are now available.</span>")
return TRUE
/proc/can_access_clockwork_power(atom/movable/access_point, amount) //Returns true if the access point has access to clockwork power (and optionally, a number of watts for it)
if(amount && !get_clockwork_power(amount)) //No point in trying if we don't have the power anyway
return
var/list/possible_conduits = view(5, access_point)
return locate(/obj/effect/clockwork/sigil/transmission) in possible_conduits || GLOB.ratvar_awakens
@@ -1,39 +1,23 @@
//returns a list of scriptures and if they're unlocked or not
/proc/scripture_unlock_check()
var/servants = 0
var/unconverted_ai_exists = get_unconverted_ais()
for(var/mob/living/M in GLOB.living_mob_list)
if(is_servant_of_ratvar(M) && (ishuman(M) || issilicon(M)))
servants++
. = list(SCRIPTURE_DRIVER = TRUE, SCRIPTURE_SCRIPT = FALSE, SCRIPTURE_APPLICATION = FALSE, SCRIPTURE_JUDGEMENT = FALSE)
. = list(SCRIPTURE_DRIVER = TRUE, SCRIPTURE_SCRIPT = FALSE, SCRIPTURE_APPLICATION = FALSE)
//Drivers: always unlocked
.[SCRIPTURE_SCRIPT] = (SSticker.scripture_states[SCRIPTURE_SCRIPT] || \
(servants >= SCRIPT_SERVANT_REQ && GLOB.clockwork_caches >= SCRIPT_CACHE_REQ))
//Script: SCRIPT_SERVANT_REQ or more non-brain servants and SCRIPT_CACHE_REQ or more clockwork caches
.[SCRIPTURE_APPLICATION] = (SSticker.scripture_states[SCRIPTURE_APPLICATION] || \
(servants >= APPLICATION_SERVANT_REQ && GLOB.clockwork_caches >= APPLICATION_CACHE_REQ && GLOB.clockwork_construction_value >= APPLICATION_CV_REQ))
.[SCRIPTURE_SCRIPT] = GLOB.script_scripture_unlocked
//Script: Convert a new servant using a sigil of submission.
.[SCRIPTURE_APPLICATION] = GLOB.application_scripture_unlocked
//Application: APPLICATION_SERVANT_REQ or more non-brain servants, APPLICATION_CACHE_REQ or more clockwork caches, and at least APPLICATION_CV_REQ CV
.[SCRIPTURE_JUDGEMENT] = (SSticker.scripture_states[SCRIPTURE_JUDGEMENT] || \
(servants >= JUDGEMENT_SERVANT_REQ && GLOB.clockwork_caches >= JUDGEMENT_CACHE_REQ && GLOB.clockwork_construction_value >= JUDGEMENT_CV_REQ && !unconverted_ai_exists))
//Judgement: JUDGEMENT_SERVANT_REQ or more non-brain servants, JUDGEMENT_CACHE_REQ or more clockwork caches, at least JUDGEMENT_CV_REQ CV, and there are no living, non-servant ais
//reports to servants when scripture is locked or unlocked
/proc/scripture_unlock_alert(list/previous_states)
. = scripture_unlock_check()
for(var/i in .)
if(.[i] != previous_states[i])
hierophant_message("<span class='large_brass'><i>Hierophant Network:</i> <b>[i] Scripture has been [.[i] ? "un":""]locked.</b></span>") //maybe admins fucked with scripture states?
update_slab_info()
/proc/get_unconverted_ais()
. = 0
for(var/ai in GLOB.ai_list)
var/mob/living/silicon/ai/AI = ai
if(AI.deployed_shell && is_servant_of_ratvar(AI.deployed_shell))
continue
if(is_servant_of_ratvar(AI) || !isturf(AI.loc) || !(AI.z in GLOB.station_z_levels) || AI.stat == DEAD)
continue
.++
for(var/mob/M in GLOB.player_list)
if(is_servant_of_ratvar(M) || isobserver(M))
M.playsound_local(M, 'sound/magic/clockwork/scripture_tier_up.ogg', 50, FALSE, pressure_affected = FALSE)
/proc/update_slab_info(obj/item/clockwork/slab/set_slab)
generate_all_scripture()
@@ -21,70 +21,58 @@
remove_ranged_ability()
return TRUE
//For the Geis scripture; binds a target to convert.
/obj/effect/proc_holder/slab/geis
ranged_mousepointer = 'icons/effects/geis_target.dmi'
//For the Hateful Manacles scripture; applies replicant handcuffs to the target.
/obj/effect/proc_holder/slab/hateful_manacles
/obj/effect/proc_holder/slab/geis/InterceptClickOn(mob/living/caller, params, atom/target)
/obj/effect/proc_holder/slab/hateful_manacles/InterceptClickOn(mob/living/caller, params, atom/target)
if(..())
return TRUE
var/turf/T = ranged_ability_user.loc
if(!isturf(T))
return TRUE
var/target_is_binding = istype(target, /obj/structure/destructible/clockwork/geis_binding)
if(iscarbon(target) && target.Adjacent(ranged_ability_user))
var/mob/living/carbon/L = target
if(is_servant_of_ratvar(L))
to_chat(ranged_ability_user, "<span class='neovgre'>\"They're a servant.\"</span>")
return TRUE
else if(L.stat)
to_chat(ranged_ability_user, "<span class='neovgre'>\"There is use in shackling the dead, but for examples.\"</span>")
return TRUE
else if(L.handcuffed)
to_chat(ranged_ability_user, "<span class='neovgre'>\"They are already helpless, no?\"</span>")
return TRUE
if((target_is_binding || isliving(target)) && ranged_ability_user.Adjacent(target))
if(target_is_binding)
var/obj/structure/destructible/clockwork/geis_binding/GB = target
GB.repair_and_interrupt()
for(var/m in GB.buckled_mobs)
if(m)
add_logs(ranged_ability_user, m, "rebound with Geis")
successful = TRUE
playsound(loc, 'sound/weapons/handcuffs.ogg', 30, TRUE)
ranged_ability_user.visible_message("<span class='danger'>[ranged_ability_user] begins forming manacles around [L]'s wrists!</span>", \
"<span class='neovgre_small'>You begin shaping replicant alloy into manacles around [L]'s wrists...</span>")
to_chat(L, "<span class='userdanger'>[ranged_ability_user] begins forming manacles around your wrists!</span>")
if(do_mob(ranged_ability_user, L, 30))
if(!L.handcuffed)
L.handcuffed = new/obj/item/restraints/handcuffs/clockwork(L)
L.update_handcuffed()
to_chat(ranged_ability_user, "<span class='neovgre_small'>You shackle [L].</span>")
add_logs(ranged_ability_user, L, "handcuffed")
else
var/mob/living/L = target
if(L.null_rod_check())
to_chat(ranged_ability_user, "<span class='sevtug'>\"A void weapon? Really, you expect me to be able to do anything?\"</span>")
return TRUE
if(is_servant_of_ratvar(L))
if(L != ranged_ability_user)
to_chat(ranged_ability_user, "<span class='sevtug'>\"[L.p_they(TRUE)] already serve[L.p_s()] Ratvar. [text2ratvar("Perhaps [ranged_ability_user.p_theyre()] into bondage?")]\"</span>")
return TRUE
if(L.stat == DEAD)
to_chat(ranged_ability_user, "<span class='sevtug'>\"[L.p_theyre(TRUE)] dead, idiot.\"</span>")
return TRUE
to_chat(ranged_ability_user, "<span class='warning'>You fail to shackle [L].</span>")
if(istype(L.buckled, /obj/structure/destructible/clockwork/geis_binding)) //if they're already bound, just stun them
var/obj/structure/destructible/clockwork/geis_binding/GB = L.buckled
GB.repair_and_interrupt()
add_logs(ranged_ability_user, L, "rebound with Geis")
successful = TRUE
else
clockwork_say(ranged_ability_user, text2ratvar("Be bound, heathen!"))
add_logs(ranged_ability_user, L, "bound with Geis")
playsound(target, 'sound/magic/blink.ogg', 50, TRUE, -4, frequency = 0.5)
if(slab.speed_multiplier >= 0.5) //excuse my debug...
ranged_ability_user.notransform = TRUE
addtimer(CALLBACK(src, .proc/reset_user_notransform, ranged_ability_user), 4) //stop us moving for a little bit so we don't break the binding immediately
if(L.buckled)
L.buckled.unbuckle_mob(target, TRUE)
var/obj/structure/destructible/clockwork/geis_binding/binding = new(get_turf(target))
binding.setDir(target.dir)
binding.buckle_mob(target, TRUE)
ranged_ability_user.start_pulling(binding)
ranged_ability_user.apply_status_effect(STATUS_EFFECT_GEISTRACKER, binding)
successful = TRUE
successful = TRUE
remove_ranged_ability()
else
..()
return TRUE
/obj/effect/proc_holder/slab/geis/proc/reset_user_notransform(mob/living/user)
if(user)
user.notransform = FALSE
/obj/item/restraints/handcuffs/clockwork
name = "replicant manacles"
desc = "Cold, heavy manacles made out of some strange black metal."
origin_tech = "materials=2;magnets=5"
flags_1 = DROPDEL_1
/obj/item/restraints/handcuffs/clockwork/dropped(mob/user)
user.visible_message("<span class='danger'>[user]'s [name] come apart at the seams!</span>", \
"<span class='userdanger'>Your [name] break apart as they're removed!</span>")
. = ..()
//For the Sentinel's Compromise scripture; heals a target servant.
/obj/effect/proc_holder/slab/compromise
@@ -140,12 +128,83 @@
playsound(targetturf, 'sound/magic/staff_healing.ogg', 50, 1)
if(has_holy_water)
L.reagents.del_reagent("holywater")
L.reagents.remove_reagent("holywater", 1000)
remove_ranged_ability()
return TRUE
//For the Kindle scripture; stuns and mutes a target non-servant.
/obj/effect/proc_holder/slab/kindle
ranged_mousepointer = 'icons/effects/volt_target.dmi'
/obj/effect/proc_holder/slab/kindle/InterceptClickOn(mob/living/caller, params, atom/target)
if(..())
return TRUE
var/turf/T = ranged_ability_user.loc
if(!isturf(T))
return TRUE
if(target in view(7, get_turf(ranged_ability_user)))
successful = TRUE
var/turf/U = get_turf(target)
to_chat(ranged_ability_user, "<span class='brass'>You release the light of Ratvar!</span>")
clockwork_say(ranged_ability_user, text2ratvar("Purge all untruths and honor Engine!"))
add_logs(ranged_ability_user, U, "fired at with Kindle")
playsound(ranged_ability_user, 'sound/magic/blink.ogg', 50, TRUE, frequency = 0.5)
var/obj/item/projectile/kindle/A = new(T)
A.original = target
A.starting = T
A.current = T
A.yo = U.y - T.y
A.xo = U.x - T.x
A.fire()
remove_ranged_ability()
return TRUE
/obj/item/projectile/kindle
name = "kindled flame"
icon_state = "pulse0"
nodamage = TRUE
damage = 0 //We're just here for the stunning!
damage_type = BURN
flag = "bomb"
range = 3
log_override = TRUE
/obj/item/projectile/kindle/Destroy()
visible_message("<span class='warning'>[src] flickers out!</span>")
. = ..()
/obj/item/projectile/kindle/on_hit(atom/target, blocked = FALSE)
if(isliving(target))
var/mob/living/L = target
if(is_servant_of_ratvar(L) || L.stat || L.has_status_effect(STATUS_EFFECT_KINDLE))
return
var/obj/O = L.null_rod_check()
playsound(L, 'sound/magic/fireball.ogg', 50, TRUE, frequency = 1.25)
if(O)
L.visible_message("<span class='warning'>[L]'s eyes flare with dim light as they stumble!</span>", \
"<span class='userdanger'>Your [O] glows white-hot against you as it absorbs some sort of power!</span>")
L.adjustFireLoss(5)
L.Stun(40)
playsound(L, 'sound/weapons/sear.ogg', 50, TRUE)
else
L.visible_message("<span class='warning'>[L]'s eyes blaze with brilliant light!</span>", \
"<span class='userdanger'>Your vision suddenly screams with white-hot light!</span>")
L.Knockdown(15)
L.apply_status_effect(STATUS_EFFECT_KINDLE)
L.flash_act(1, 1)
if(iscultist(L))
L.adjustFireLoss(15)
..()
//For the cyborg Linked Vanguard scripture, grants you and a nearby ally Vanguard
/obj/effect/proc_holder/slab/vanguard
ranged_mousepointer = 'icons/effects/vanguard_target.dmi'