Merge remote-tracking branch 'upstream/master' into smoothlattice

This commit is contained in:
xxalpha
2015-09-22 19:40:01 +01:00
230 changed files with 5954 additions and 6070 deletions
+1 -141
View File
@@ -267,144 +267,4 @@ var/pipenetwarnings = 10
corresponding = new trace_gas.type()
G.trace_gases += corresponding
corresponding.moles = trace_gas.moles*G.volume/total_volume
/*
/datum/pipeline/proc/mingle_with_turf(turf/simulated/target, mingle_volume)
var/datum/gas_mixture/air_sample = air.remove_ratio(mingle_volume/air.volume)
air_sample.volume = mingle_volume
var/datum/gas_mixture/turf_air = target.return_air()
equalize_gases(list(air_sample, turf_air))
air.merge(air_sample)
//turf_air already modified by equalize_gases()
if(istype(target))
if(target.air)
if(target.air.check_tile_graphic())
target.update_visuals(target.air)
update = 1
/datum/pipeline/proc/reconcile_air()
//Perfectly equalize all gases members instantly
//Calculate totals from individual components
var/total_thermal_energy = 0
var/total_heat_capacity = 0
var/datum/gas_mixture/air_transient = new()
var/list/gases = list(air)
gases.Add(other_airs)
for(var/datum/gas_mixture/gas in gases)
air_transient.volume += gas.volume
total_thermal_energy += gas.thermal_energy()
total_heat_capacity += gas.heat_capacity()
air_transient.oxygen += gas.oxygen
air_transient.nitrogen += gas.nitrogen
air_transient.toxins += gas.toxins
air_transient.carbon_dioxide += gas.carbon_dioxide
if(gas.trace_gases.len)
for(var/datum/gas/trace_gas in gas.trace_gases)
var/datum/gas/corresponding = locate(trace_gas.type) in air_transient.trace_gases
if(!corresponding)
corresponding = new trace_gas.type()
air_transient.trace_gases += corresponding
corresponding.moles += trace_gas.moles
if(air_transient.volume > 0)
if(total_heat_capacity > 0)
air_transient.temperature = total_thermal_energy/total_heat_capacity
//Allow air mixture to react
if(air_transient.react())
update = 1
else
air_transient.temperature = 0
//Update individual gas_mixtures by volume ratio
for(var/datum/gas_mixture/gas in gases)
gas.oxygen = air_transient.oxygen*gas.volume/air_transient.volume
gas.nitrogen = air_transient.nitrogen*gas.volume/air_transient.volume
gas.toxins = air_transient.toxins*gas.volume/air_transient.volume
gas.carbon_dioxide = air_transient.carbon_dioxide*gas.volume/air_transient.volume
gas.temperature = air_transient.temperature
if(air_transient.trace_gases.len)
for(var/datum/gas/trace_gas in air_transient.trace_gases)
var/datum/gas/corresponding = locate(trace_gas.type) in gas.trace_gases
if(!corresponding)
corresponding = new trace_gas.type()
gas.trace_gases += corresponding
corresponding.moles = trace_gas.moles*gas.volume/air_transient.volume
return 1
/proc/equalize_gases(datum/gas_mixture/list/gases)
//Perfectly equalize all gases members instantly
//Calculate totals from individual components
var/total_volume = 0
var/total_thermal_energy = 0
var/total_heat_capacity = 0
var/total_oxygen = 0
var/total_nitrogen = 0
var/total_toxins = 0
var/total_carbon_dioxide = 0
var/list/total_trace_gases = list()
for(var/datum/gas_mixture/gas in gases)
total_volume += gas.volume
total_thermal_energy += gas.thermal_energy()
total_heat_capacity += gas.heat_capacity()
total_oxygen += gas.oxygen
total_nitrogen += gas.nitrogen
total_toxins += gas.toxins
total_carbon_dioxide += gas.carbon_dioxide
if(gas.trace_gases.len)
for(var/datum/gas/trace_gas in gas.trace_gases)
var/datum/gas/corresponding = locate(trace_gas.type) in total_trace_gases
if(!corresponding)
corresponding = new trace_gas.type()
total_trace_gases += corresponding
corresponding.moles += trace_gas.moles
if(total_volume > 0)
//Calculate temperature
var/temperature = 0
if(total_heat_capacity > 0)
temperature = total_thermal_energy/total_heat_capacity
//Update individual gas_mixtures by volume ratio
for(var/datum/gas_mixture/gas in gases)
gas.oxygen = total_oxygen*gas.volume/total_volume
gas.nitrogen = total_nitrogen*gas.volume/total_volume
gas.toxins = total_toxins*gas.volume/total_volume
gas.carbon_dioxide = total_carbon_dioxide*gas.volume/total_volume
gas.temperature = temperature
if(total_trace_gases.len)
for(var/datum/gas/trace_gas in total_trace_gases)
var/datum/gas/corresponding = locate(trace_gas.type) in gas.trace_gases
if(!corresponding)
corresponding = new trace_gas.type()
gas.trace_gases += corresponding
corresponding.moles = trace_gas.moles*gas.volume/total_volume
return 1
*/
corresponding.moles = trace_gas.moles*G.volume/total_volume
+5 -3
View File
@@ -55,18 +55,20 @@
/turf/simulated/New()
..()
levelupdate()
if(smooth)
smooth_icon(src)
visibilityChanged()
if(!blocks_air)
air = new
air.oxygen = oxygen
air.carbon_dioxide = carbon_dioxide
air.nitrogen = nitrogen
air.toxins = toxins
air.temperature = temperature
/turf/simulated/Del()
visibilityChanged()
if(active_hotspot)
active_hotspot.Kill()
..()
+5 -4
View File
@@ -23,12 +23,13 @@
#define FRIDAY_13TH "Friday the 13th"
//Human Overlays Indexes/////////
#define SPECIES_LAYER 26 // mutantrace colors... these are on a seperate layer in order to prvent
#define SPECIES_LAYER 27 // mutantrace colors... these are on a seperate layer in order to prvent
#define MUTATIONS_LAYER 26 //mutations. Hulk, Tk headglows, etc
#define BODY_BEHIND_LAYER 25
#define BODY_LAYER 24 //underwear, undershirts, socks, eyes, lips(makeup)
#define BODY_ADJ_LAYER 23
#define MUTATIONS_LAYER 22 //Tk headglows etc.
#define AUGMENTS_LAYER 21
#define AUGMENTS_LAYER 22
#define FRONT_MUTATIONS_LAYER 21 //mutations that should appear above body and augments layer (e.g. laser eyes)
#define DAMAGE_LAYER 20 //damage indicators (cuts and burns)
#define UNIFORM_LAYER 19
#define ID_LAYER 18
@@ -49,7 +50,7 @@
#define R_HAND_LAYER 3 //Having the two hands seperate seems rather silly, merge them together? It'll allow for code to be reused on mobs with arbitarily many hands
#define BODY_FRONT_LAYER 2
#define FIRE_LAYER 1 //If you're on fire
#define TOTAL_LAYERS 26 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_;
#define TOTAL_LAYERS 27 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_;
//Human Overlay Index Shortcuts for alternate_worn_layer, layers
//Because I *KNOW* somebody will think layer+1 means "above"
+53
View File
@@ -380,3 +380,56 @@
return new /datum/projectile_data(src_x, src_y, time, distance, power_x, power_y, dest_x, dest_y)
/proc/pollCandidates(var/Question, var/jobbanType, var/datum/game_mode/gametypeCheck, var/be_special_flag = 0, var/poll_time = 300)
var/list/mob/dead/observer/candidates = list()
var/time_passed = world.time
if (!Question)
Question = "Would you like to be a special role?"
for(var/mob/dead/observer/G in player_list)
if(!G.key || !G.client)
continue
if(be_special_flag)
if(!(G.client.prefs.be_special & be_special_flag))
continue
if (gametypeCheck)
if(!gametypeCheck.age_check(G.client))
continue
if (jobbanType)
if(jobban_isbanned(G, jobbanType) || jobban_isbanned(G, "Syndicate"))
continue
spawn(0)
G << 'sound/misc/notice2.ogg' //Alerting them to their consideration
switch(alert(G,Question,"Please answer in [poll_time/10] seconds!","Yes","No"))
if("Yes")
G << "<span class='notice'>Choice registered: Yes.</span>"
if((world.time-time_passed)>poll_time)//If more than 30 game seconds passed.
G << "<span class='danger'>Sorry, you were too late for the consideration!</span>"
G << 'sound/machines/buzz-sigh.ogg'
return
candidates += G
if("No")
G << "<span class='danger'>Choice registered: No.</span>"
return
else
return
sleep(poll_time)
//Check all our candidates, to make sure they didn't log off during the 30 second wait period.
for(var/mob/dead/observer/G in candidates)
if(!G.key || !G.client)
candidates.Remove(G)
return candidates
/proc/makeBody(mob/dead/observer/G_found) // Uses stripped down and bastardized code from respawn character
if(!G_found || !G_found.key) return
//First we spawn a dude.
var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned.
G_found.client.prefs.copy_to(new_character)
new_character.dna.update_dna_identity()
new_character.key = G_found.key
return new_character
+15 -9
View File
@@ -1415,26 +1415,32 @@ B --><-- A
*/
/atom/movable/var/atom/orbiting = null
//This is just so you can stop an orbit.
//orbit() can run without it (swap orbiting for A)
//but then you can never stop it and that's just silly.
/atom/movable/var/atom/orbiting = null
//we raise this each time orbit is called to prevent mutiple calls in a short time frame from breaking things
/atom/movable/var/orbitid = 0
/atom/movable/proc/orbit(atom/A, radius = 10, clockwise = 1, angle_increment = 15)
/atom/movable/proc/orbit(atom/A, radius = 10, clockwise = 1, angle_increment = 15, lockinorbit = 0)
if(!istype(A))
return
orbitid++
var/myid = orbitid
if (orbiting)
stop_orbit()
sleep(1) //sadly this is the only way to ensure the original orbit proc stops and resets the atom's transform.
if (orbiting || !istype(A)) //post sleep re-check
return
//sadly this is the only way to ensure the original orbit proc stops and resets the atom's transform.
sleep(1)
if (orbiting || !istype(A) || orbitid != myid) //post sleep re-check
return
orbiting = A
var/lastloc = loc
var/angle = 0
var/matrix/initial_transform = matrix(transform)
spawn
while(orbiting && orbiting.loc)
loc = orbiting.loc
while(orbiting && orbiting.loc && orbitid == myid && (!lockinorbit || loc == lastloc))
loc = get_turf(orbiting.loc)
lastloc = loc
angle += angle_increment
var/matrix/shift = matrix(initial_transform)
@@ -1489,4 +1495,4 @@ B --><-- A
I.pixel_x = x_offset
I.pixel_y = y_offset
return I
return I
+2 -1
View File
@@ -14,4 +14,5 @@ var/global/list/chemical_reagents_list //list of all /datum/reagent datums in
var/global/list/surgeries_list = list() //list of all surgeries by name, associated with their path.
var/global/list/table_recipes = list() //list of all table craft recipes
var/global/list/rcd_list = list() //list of Rapid Construction Devices.
var/global/list/apcs_list = list() //list of all Area Power Controller machines, seperate from machines for powernet speeeeeeed.
var/global/list/apcs_list = list() //list of all Area Power Controller machines, seperate from machines for powernet speeeeeeed.
var/global/list/tracking_implants = list() //list of all tracking implants to work out what treks everyone are on. Sadly not on lavaworld not implemented...
+3 -1
View File
@@ -5,8 +5,10 @@
recieving object instead, so that's the default action. This allows you to drag
almost anything into a trash can.
*/
/atom/MouseDrop(atom/over)
/atom/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params)
if(!usr || !over) return
if(over == src)
return usr.client.Click(src, src_location, src_control, params)
if(!Adjacent(usr) || !over.Adjacent(usr)) return // should stop you from dragging through windows
over.MouseDrop_T(src,usr)
+4
View File
@@ -64,6 +64,8 @@ var/datum/subsystem/events/SSevent
for(var/datum/round_event_control/E in control)
if(E.occurrences >= E.max_occurrences) continue
if(E.earliest_start >= world.time) continue
if(ticker.mode.config_tag in E.gamemode_blacklist) continue
if(E.gamemode_whitelist && !(ticker.mode.config_tag in E.gamemode_whitelist)) continue
if(E.holidayID)
if(!holidays || !holidays[E.holidayID]) continue
if(E.weight < 0) //for round-start events etc.
@@ -81,6 +83,8 @@ var/datum/subsystem/events/SSevent
for(var/datum/round_event_control/E in control)
if(E.occurrences >= E.max_occurrences) continue
if(E.earliest_start >= world.time) continue
if(ticker.mode.config_tag in E.gamemode_blacklist) continue
if(E.gamemode_whitelist && !(ticker.mode.config_tag in E.gamemode_whitelist)) continue
if(E.holidayID)
if(!holidays || !holidays[E.holidayID]) continue
sum_of_weights -= E.weight
+1
View File
@@ -15,6 +15,7 @@ var/datum/subsystem/objects/SSobj
NEW_SS_GLOBAL(SSobj)
/datum/subsystem/objects/Initialize(timeofday, zlevel)
setupGenetics()
for(var/atom/movable/AM in world)
if (zlevel && AM.z != zlevel)
continue
-1
View File
@@ -59,7 +59,6 @@ var/datum/subsystem/ticker/ticker
return ..()
if(!syndicate_code_phrase) syndicate_code_phrase = generate_code_phrase()
if(!syndicate_code_response) syndicate_code_response = generate_code_phrase()
setupGenetics()
setupFactions()
..()
+26 -3
View File
@@ -252,6 +252,7 @@
body += "<option value='?_src_=vars;direct_control=\ref[D]'>Assume Direct Control</option>"
body += "<option value='?_src_=vars;drop_everything=\ref[D]'>Drop Everything</option>"
body += "<option value='?_src_=vars;regenerateicons=\ref[D]'>Regenerate Icons</option>"
body += "<option value='?_src_=vars;offer_control=\ref[D]'>Offer Control to Ghosts</option>"
if(iscarbon(D))
body += "<option value>---</option>"
body += "<option value='?_src_=vars;editorgans=\ref[D]'>Modify organs</option>"
@@ -592,6 +593,29 @@ body
if(usr.client)
usr.client.cmd_assume_direct_control(M)
else if(href_list["offer_control"])
if(!check_rights(0)) return
var/mob/M = locate(href_list["offer_control"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
M << "Control of your mob has been offered to dead players."
log_admin("[key_name(usr)] has offered control of ([key_name(M)]) to ghosts.")
message_admins("[key_name_admin(usr)] has offered control of ([key_name_admin(M)]) to ghosts")
var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as [M.real_name]?", "pAI", null, FALSE, 100)
var/mob/dead/observer/theghost = null
if(candidates.len)
theghost = pick(candidates)
M << "Your mob has been taken over by a ghost!"
message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(M)])")
M.ghostize()
M.key = theghost.key
else
M << "There were no ghosts willing to take control."
message_admins("No ghosts were willing to take control of [key_name_admin(M)])")
else if(href_list["delall"])
if(!check_rights(R_DEBUG|R_SERVER)) return
@@ -813,8 +837,7 @@ body
if(result)
var/newtype = species_list[result]
hardset_dna(H, null, null, null, null, newtype)
H.regenerate_icons()
H.set_species(newtype)
else if(href_list["purrbation"])
if(!check_rights(R_SPAWN)) return
@@ -828,7 +851,7 @@ body
usr << "Mob doesn't exist anymore"
return
if(H.dna && H.dna.species.id == "human")
if(H.dna.species.id == "human")
if(H.dna.features["tail_human"] == "None" || H.dna.features["ears"] == "None")
usr << "Put [H] on purrbation."
H << "You suddenly feel valid."
@@ -35,6 +35,6 @@ Bonus
M << "<span class='notice'>[pick("You feel confused.", "You forgot what you were thinking about.")]</span>"
else
M << "<span class='notice'>You are unable to think straight!</span>"
M.confused = min(100, M.confused + 2)
M.confused = min(100, M.confused + 8)
return
@@ -31,7 +31,8 @@ Bonus
..()
if(prob(SYMPTOM_ACTIVATION_PROB * 5)) // 15% chance
var/mob/living/carbon/M = A.affected_mob
if(!check_dna_integrity(M)) return
if(!M.has_dna())
return
switch(A.stage)
if(4, 5)
M << "<span class='notice'>[pick("Your skin feels itchy.", "You feel light headed.")]</span>"
@@ -44,7 +45,7 @@ Bonus
possible_mutations = (bad_mutations | not_good_mutations) - mutations_list[RACEMUT]
var/mob/living/carbon/M = A.affected_mob
if(M)
if(!check_dna_integrity(M))
if(!M.has_dna())
return
archived_dna = M.dna.struc_enzymes
@@ -52,10 +53,10 @@ Bonus
/datum/symptom/genetic_mutation/End(datum/disease/advance/A)
var/mob/living/carbon/M = A.affected_mob
if(M && archived_dna)
if(!check_dna_integrity(M))
if(!M.has_dna())
return
hardset_dna(M, se = archived_dna)
domutcheck(M)
M.dna.struc_enzymes = archived_dna
M.domutcheck()
/*
//////////////////////////////////////
+9 -11
View File
@@ -43,7 +43,7 @@
affected_mob.adjustToxLoss(2)
affected_mob.updatehealth()
if(4)
if(!src.transformed && !src.carrier)
if(!transformed && !carrier)
//Save original dna for when the disease is cured.
original_dna = new affected_mob.dna.type
affected_mob.dna.copy_dna(original_dna)
@@ -51,24 +51,22 @@
affected_mob << "<span class='danger'>You don't feel like yourself..</span>"
var/datum/dna/transform_dna = strain_data["dna"]
transform_dna.transfer_identity(affected_mob)
transform_dna.transfer_identity(affected_mob, transfer_SE = 1)
affected_mob.real_name = affected_mob.dna.real_name
affected_mob.updateappearance(mutcolor_update=1)
affected_mob.domutcheck()
updateappearance(affected_mob)
domutcheck(affected_mob)
src.transformed = 1
src.carrier = 1 //Just chill out at stage 4
transformed = 1
carrier = 1 //Just chill out at stage 4
return
/datum/disease/dnaspread/Del()
if (original_dna && transformed && affected_mob)
original_dna.transfer_identity(affected_mob)
original_dna.transfer_identity(affected_mob, transfer_SE = 1)
affected_mob.real_name = affected_mob.dna.real_name
updateappearance(affected_mob)
domutcheck(affected_mob)
affected_mob.updateappearance(mutcolor_update=1)
affected_mob.domutcheck()
affected_mob << "<span class='notice'>You feel more like yourself.</span>"
..()
+2 -3
View File
@@ -201,9 +201,8 @@
if(3)
if(ishuman(affected_mob))
var/mob/living/carbon/human/human = affected_mob
if(human.dna && human.dna.species.id != "slime")
hardset_dna(human, null, null, null, null, /datum/species/slime)
human.regenerate_icons()
if(human.dna.species.id != "slime")
human.set_species(/datum/species/slime)
/datum/disease/transformation/corgi
name = "The Barkening"
+13 -31
View File
@@ -27,34 +27,22 @@
/datum/martial_art/proc/basic_hit(mob/living/carbon/human/A,mob/living/carbon/human/D)
A.do_attack_animation(D)
var/damage = rand(0,9)
var/damage = rand(0,9) + A.dna.species.punchmod
var/atk_verb = "punch"
var/atk_verb = A.dna.species.attack_verb
if(D.lying)
atk_verb = "kick"
else if(A.dna)
atk_verb = A.dna.species.attack_verb
if(A.dna)
damage += A.dna.species.punchmod
if(!damage)
if(A.dna)
playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1)
else
playsound(D.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
D.visible_message("<span class='warning'>[A] has attempted to [atk_verb] [D]!</span>")
add_logs(A, D, "attempted to [atk_verb]")
return 0
playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1)
D.visible_message("<span class='warning'>[A] has attempted to [atk_verb] [D]!</span>")
add_logs(A, D, "attempted to [atk_verb]")
return 0
var/obj/item/organ/limb/affecting = D.get_organ(ran_zone(A.zone_sel.selecting))
var/armor_block = D.run_armor_check(affecting, "melee")
if(A.dna)
playsound(D.loc, A.dna.species.attack_sound, 25, 1, -1)
else
playsound(D.loc, 'sound/weapons/punch1.ogg', 25, 1, -1)
playsound(D.loc, A.dna.species.attack_sound, 25, 1, -1)
D.visible_message("<span class='danger'>[A] has [atk_verb]ed [D]!</span>", \
"<span class='userdanger'>[A] has [atk_verb]ed [D]!</span>")
@@ -104,24 +92,18 @@
var/atk_verb = pick("left hook","right hook","straight punch")
var/damage = rand(5,8)
if(A.dna)
damage += A.dna.species.punchmod
var/damage = rand(5,8) + A.dna.species.punchmod
if(!damage)
if(A.dna)
playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1)
else
playsound(D.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
D.visible_message("<span class='warning'>[A] has attempted to hit [D] with a [atk_verb]!</span>")
add_logs(A, D, "attempted to hit", atk_verb)
return 0
playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1)
D.visible_message("<span class='warning'>[A] has attempted to hit [D] with a [atk_verb]!</span>")
add_logs(A, D, "attempted to hit", atk_verb)
return 0
var/obj/item/organ/limb/affecting = D.get_organ(ran_zone(A.zone_sel.selecting))
var/armor_block = D.run_armor_check(affecting, "melee")
playsound(D.loc, 'sound/weapons/punch1.ogg', 25, 1, -1)
playsound(D.loc, A.dna.species.attack_sound, 25, 1, -1)
D.visible_message("<span class='danger'>[A] has hit [D] with a [atk_verb]!</span>", \
"<span class='userdanger'>[A] has hit [D] with a [atk_verb]!</span>")
+4 -4
View File
@@ -976,10 +976,10 @@
usr << "<span class='danger'>Resetting DNA failed!</span>"
else
var/mob/living/carbon/C = current
C.dna = changeling.first_prof.dna
changeling.first_prof.dna.transfer_identity(C, transfer_SE=1)
C.real_name = changeling.first_prof.name
updateappearance(C)
domutcheck(C)
C.updateappearance(mutcolor_update=1)
C.domutcheck()
else if (href_list["nuclear"])
switch(href_list["nuclear"])
@@ -1409,7 +1409,7 @@
var/mob/living/carbon/human/H = current
hardset_dna(H,null,null,null,null,/datum/species/abductor,null)
H.set_species(/datum/species/abductor)
var/datum/species/abductor/S = H.dna.species
switch(role)
+52 -22
View File
@@ -16,6 +16,9 @@
var/text_gain_indication = ""
var/text_lose_indication = ""
var/list/visual_indicators = list()
var/layer_used = MUTATIONS_LAYER //which mutation layer to use
var/list/species_allowed = list() //to restrict mutation to only certain species
var/health_req //minimum health required to acquire the mutation
/datum/mutation/human/proc/force_give(mob/living/carbon/human/owner)
set_block(owner)
@@ -33,7 +36,7 @@
return before + injection + after
/datum/mutation/human/proc/set_block(mob/living/carbon/owner, on = 1)
if(owner && istype(owner) && owner.dna)
if(owner && owner.has_dna())
owner.dna.struc_enzymes = set_se(owner.dna.struc_enzymes, on)
/datum/mutation/human/proc/check_block_string(se_string)
@@ -51,17 +54,25 @@
/datum/mutation/human/proc/on_acquiring(mob/living/carbon/human/owner)
if(!owner || !istype(owner) || (src in owner.dna.mutations))
return 1
if(species_allowed.len && !species_allowed.Find(owner.dna.species.id))
return 1
if(health_req && owner.health < health_req)
return 1
owner.dna.mutations.Add(src)
owner << text_gain_indication
if(text_gain_indication)
owner << text_gain_indication
if(visual_indicators.len)
owner.update_mutation_overlays()
var/list/mut_overlay = list(get_visual_indicator(owner))
if(owner.overlays_standing[layer_used])
mut_overlay = owner.overlays_standing[layer_used]
mut_overlay |= get_visual_indicator(owner)
owner.remove_overlay(layer_used)
owner.overlays_standing[layer_used] = mut_overlay
owner.apply_overlay(layer_used)
/datum/mutation/human/proc/get_visual_indicator(mob/living/carbon/human/owner)
return
/datum/mutation/human/proc/lose_indication(mob/living/carbon/human/owner)
owner.overlays.Remove(visual_indicators)
/datum/mutation/human/proc/on_attack_hand(mob/living/carbon/human/owner, atom/target)
return
@@ -76,9 +87,16 @@
/datum/mutation/human/proc/on_losing(mob/living/carbon/human/owner)
if(owner && istype(owner) && (owner.dna.mutations.Remove(src)))
owner << text_lose_indication
if(text_lose_indication)
owner << text_lose_indication
if(visual_indicators.len)
owner.update_mutation_overlays()
var/list/mut_overlay = list()
if(owner.overlays_standing[layer_used])
mut_overlay = owner.overlays_standing[layer_used]
owner.remove_overlay(layer_used)
mut_overlay.Remove(get_visual_indicator(owner))
owner.overlays_standing[layer_used] = mut_overlay
owner.apply_overlay(layer_used)
return 0
return 1
@@ -96,6 +114,8 @@
get_chance = 15
lowest_value = 256 * 12
text_gain_indication = "<span class='notice'>Your muscles hurt!</span>"
species_allowed = list("human") //no skeleton/lizard hulk
health_req = 25
/datum/mutation/human/hulk/New()
..()
@@ -583,32 +603,42 @@
message = replacetext(message," muh valids "," getting my kicks ")
return trim(message)
/datum/mutation/human/laser_eyes
name = "Laser Eyes"
quality = POSITIVE
dna_block = NON_SCANNABLE
text_gain_indication = "<span class='notice'>You feel pressure building up behind your eyes.</span>"
layer_used = FRONT_MUTATIONS_LAYER
/datum/mutation/human/laser_eyes/New()
..()
visual_indicators |= image("icon"='icons/effects/genetics.dmi', "icon_state"="lasereyes_s", "layer"=-FRONT_MUTATIONS_LAYER)
/datum/mutation/human/laser_eyes/get_visual_indicator(mob/living/carbon/human/owner)
return visual_indicators[1]
/datum/mutation/human/laser_eyes/on_ranged_attack(mob/living/carbon/human/owner, atom/target)
if(owner.a_intent == "harm")
owner.LaserEyes(target)
/mob/living/carbon/human/proc/update_mutation_overlays()
remove_overlay(MUTATIONS_LAYER)
var/image/standing
/mob/living/carbon/proc/update_mutations_overlay()
return
/mob/living/carbon/human/update_mutations_overlay()
for(var/datum/mutation/human/CM in dna.mutations)
if(CM.species_allowed.len && !CM.species_allowed.Find(dna.species.id))
CM.force_lose(src) //shouldn't have that mutation at all
continue
if(CM.visual_indicators.len)
var/list/mut_overlay = list()
if(overlays_standing[CM.layer_used])
mut_overlay = overlays_standing[CM.layer_used]
var/image/V = CM.get_visual_indicator(src)
if(!standing)
standing = V
else
standing.overlays += V
if(standing)
overlays_standing[MUTATIONS_LAYER] = standing
apply_overlay(MUTATIONS_LAYER)
if(!mut_overlay.Find(V)) //either we lack the visual indicator or we have the wrong one
remove_overlay(CM.layer_used)
for(var/image/I in CM.visual_indicators)
mut_overlay.Remove(I)
mut_overlay |= V
overlays_standing[CM.layer_used] = mut_overlay
apply_overlay(CM.layer_used)
+8 -7
View File
@@ -1,13 +1,14 @@
/obj/effect/proc_holder/spell/bloodcrawl
name = "Blood crawl"
desc = "Use blood to travel."
charge_max = 10
name = "Blood Crawl"
desc = "Use pools of blood to phase out of existence."
charge_max = 0
clothes_req = 0
selection_type = "range"
range = 1
cooldown_min = 0
overlay = null
action_icon_state = "bloodcrawl"
action_background_icon_state = "bg_demon"
var/phased = 0
/obj/effect/proc_holder/spell/bloodcrawl/choose_targets(mob/user = usr)
@@ -16,7 +17,7 @@
perform(target)
return
revert_cast()
user << "<span class='warning'>You need blood to blood crawl.</span>"
user << "<span class='warning'>There must be a nearby source of blood!</span>"
/obj/effect/proc_holder/spell/bloodcrawl/perform(obj/effect/decal/cleanable/target, recharge = 1, mob/living/user = usr)
if(istype(user))
@@ -24,9 +25,9 @@
if(user.phasein(target))
phased = 0
else
user.phaseout(target)
phased = 1
if(user.phaseout(target))
phased = 1
start_recharge()
return
revert_cast()
user << "<span class='warning'>You cannot blood crawl.</span>"
user << "<span class='warning'>You are unable to blood crawl!</span>"
+2 -2
View File
@@ -55,7 +55,7 @@
lich.real_name = user.mind.name
user.mind.transfer_to(lich)
hardset_dna(lich,null,null,lich.real_name,null,/datum/species/skeleton)
lich.hardset_dna(null,null,lich.real_name,null,/datum/species/skeleton)
lich << "<span class='warning'>Your bones clatter and shutter as they're pulled back into this world!</span>"
charge_max += 600
var/mob/old_body = current_body
@@ -98,7 +98,7 @@
marked_item.desc = "A terrible aura surrounds this item, its very existence is offensive to life itself..."
marked_item.color = "#003300"
user << "<span class='userdanger'>With a hideous feeling of emptiness you watch in horrified fascination as skin sloughs off bone! Blood boils, nerves disintegrate, eyes boil in their sockets! As your organs crumble to dust in your fleshless chest you come to terms with your choice. You're a lich!</span>"
hardset_dna(user, null, null, null, null, /datum/species/skeleton)
user.set_species(/datum/species/skeleton)
current_body = user.mind.current
if(ishuman(user))
var/mob/living/carbon/human/H = user
+1 -2
View File
@@ -41,7 +41,6 @@
clothes_req = 1
invocation = "BIRUZ BENNAR"
invocation_type = "shout"
message = "<span class='notice'>You feel strong! You feel a pressure building behind your eyes!</span>"
range = -1
include_user = 1
centcom_cancast = 0
@@ -248,7 +247,7 @@
sound="sound/magic/Blind.ogg"
/obj/effect/proc_holder/spell/targeted/genetic/blind
disabilities = 1
disabilities = BLIND
duration = 300
sound="sound/magic/Blind.ogg"
+3 -3
View File
@@ -280,11 +280,11 @@ var/list/blood_splatter_icons = list()
//returns 1 if made bloody, returns 0 otherwise
/atom/proc/add_blood(mob/living/carbon/M)
if(ishuman(M) && M.dna)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(NOBLOOD in H.dna.species.specflags)
return 0
if(rejects_blood() || !istype(M) || !check_dna_integrity(M))
if(rejects_blood() || !M.has_dna())
return 0
return 1
@@ -358,7 +358,7 @@ var/list/blood_splatter_icons = list()
// Only adds blood on the floor -- Skie
/atom/proc/add_blood_floor(mob/living/carbon/M)
if(istype(src, /turf/simulated))
if(check_dna_integrity(M)) //mobs with dna = (monkeys + humans at time of writing)
if(M.has_dna()) //mobs with dna = (monkeys + humans at time of writing)
var/obj/effect/decal/cleanable/blood/B = locate() in contents
if(!B)
blood_splatter(src,M,1)
+175 -809
View File
File diff suppressed because it is too large Load Diff
+7 -9
View File
@@ -107,7 +107,7 @@
H = agent.current
L = agent_landmarks[team_number]
H.loc = L.loc
hardset_dna(H, null, null, null, null, /datum/species/abductor)
H.set_species(/datum/species/abductor)
S = H.dna.species
S.agent = 1
S.team = team_number
@@ -115,13 +115,12 @@
equip_common(H,team_number)
equip_agent(H,team_number)
greet_agent(agent,team_number)
H.regenerate_icons()
scientist = scientists[team_number]
H = scientist.current
L = scientist_landmarks[team_number]
H.loc = L.loc
hardset_dna(H, null, null, null, null, /datum/species/abductor)
H.set_species(/datum/species/abductor)
S = H.dna.species
S.scientist = 1
S.team = team_number
@@ -129,7 +128,6 @@
equip_common(H,team_number)
equip_scientist(H,team_number)
greet_scientist(scientist,team_number)
H.regenerate_icons()
return ..()
//Used for create antag buttons
@@ -156,7 +154,7 @@
H = agent.current
L = agent_landmarks[team_number]
H.loc = L.loc
hardset_dna(H, null, null, null, null, /datum/species/abductor)
H.set_species(/datum/species/abductor)
S = H.dna.species
S.agent = 1
S.team = team_number
@@ -164,13 +162,13 @@
equip_common(H,team_number)
equip_agent(H,team_number)
greet_agent(agent,team_number)
H.regenerate_icons()
scientist = scientists[team_number]
H = scientist.current
L = scientist_landmarks[team_number]
H.loc = L.loc
hardset_dna(H, null, null, null, null, /datum/species/abductor)
H.set_species(/datum/species/abductor)
S = H.dna.species
S.scientist = 1
S.team = team_number
@@ -178,7 +176,7 @@
equip_common(H,team_number)
equip_scientist(H,team_number)
greet_scientist(scientist,team_number)
H.regenerate_icons()
/datum/game_mode/abduction/proc/greet_agent(datum/mind/abductor,team_number)
@@ -332,7 +330,7 @@
if(!owner.current || !ishuman(owner.current))
return 0
var/mob/living/carbon/human/H = owner.current
if(!H.dna || !H.dna.species || !(H.dna.species.id == "abductor"))
if(H.dna.species.id != "abductor")
return 0
var/datum/species/abductor/S = H.dna.species
ab_team = S.team
@@ -288,7 +288,7 @@
var/obj/machinery/abductor/console/console
if(ishuman(source))
var/mob/living/carbon/human/H = source
if(H.dna && istype(H.dna.species, /datum/species/abductor))
if(H.dna.species.id == "abductor")
var/datum/species/abductor/S = H.dna.species
console = get_team_console(S.team)
home = console.pad
@@ -405,8 +405,6 @@ Congratulations! You are now trained for xenobiology research!"}
if(!ishuman(user))
return 0
var/mob/living/carbon/human/H = user
if(!H.dna)
return 0
if(H.dna.species.id != "abductor")
return 0
return 1
@@ -460,11 +458,16 @@ Congratulations! You are now trained for xenobiology research!"}
/obj/item/weapon/abductor_baton/proc/SleepAttack(mob/living/L,mob/living/user)
if(L.stunned)
L.SetSleeping(60)
L.visible_message("<span class='danger'>[user] has induced sleep in [L] with [src]!</span>", \
L.visible_message("<span class='danger'>[user] has induced sleep in [L] with [src]!</span>", \
"<span class='userdanger'>You suddenly feel very drowsy!</span>")
playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
add_logs(user, L, "put to sleep")
add_logs(user, L, "put to sleep")
else
L.drowsyness += 1
user << "<span class='warning'>Sleep inducement works fully only on stunned specimens! </span>"
L.visible_message("<span class='danger'>[user] tried to induce sleep in [L] with [src]!</span>", \
"<span class='userdanger'>You suddenly feel drowsy!</span>")
return
/obj/item/weapon/abductor_baton/proc/CuffAttack(mob/living/L,mob/living/user)
@@ -490,13 +493,21 @@ Congratulations! You are now trained for xenobiology research!"}
"<span class='userdanger'>[user] probes you!</span>")
var/species = "<span class='warning'>Unknown species</span>"
var/helptext = "<span class='warning'>Species unsuitable for experiments.</span>"
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.dna && H.dna.species)
species = "<span clas=='notice'>[H.dna.species.name]</span>"
species = "<span clas=='notice'>[H.dna.species.name]</span>"
if(L.mind && L.mind.changeling)
species = "<span class='warning'>Changeling lifeform</span>"
var/obj/item/organ/internal/gland/temp = locate() in H.internal_organs
if(temp)
helptext = "<span class='warning'>Experimental gland detected!</span>"
else
helptext = "<span class='notice'>Subject suitable for experiments.</span>"
user << "<span class='notice'>Probing result:</span>[species]"
user << "[helptext]"
/obj/item/weapon/restraints/handcuffs/energy
name = "hard-light energy field"
@@ -8,7 +8,7 @@
if(!ishuman(user))
return 0
var/mob/living/carbon/human/H = user
if(H.dna && istype(H.dna.species, /datum/species/abductor))
if(H.dna.species.id == "abductor")
return 1
if((locate(/obj/item/weapon/implant/abductor) in H))
return 1
+2 -4
View File
@@ -120,9 +120,7 @@
/obj/item/organ/internal/gland/pop/activate()
owner << "<span class='notice'>You feel unlike yourself.</span>"
var/species = pick(list(/datum/species/lizard,/datum/species/slime,/datum/species/plant/pod,/datum/species/fly))
hardset_dna(owner, null, null, null, null, species)
owner.regenerate_icons()
return
owner.set_species(species)
/obj/item/organ/internal/gland/ventcrawling
origin_tech = "materials=4;biotech=5;bluespace=3"
@@ -241,7 +239,7 @@
/obj/effect/cocoon/abductor/proc/Copy(mob/living/carbon/human/H)
var/mob/living/carbon/human/interactive/greytide/clone = new(src)
hardset_dna(clone,H.dna.uni_identity,H.dna.struc_enzymes,H.real_name, H.dna.blood_type, H.dna.species.type, H.dna.features)
clone.hardset_dna(H.dna.uni_identity,H.dna.struc_enzymes,H.real_name, H.dna.blood_type, H.dna.species.type, H.dna.features)
//There's no define for this / get all items ?
var/list/slots = list(slot_back,slot_w_uniform,slot_wear_suit,\
@@ -4,8 +4,6 @@
var/team = 0
/obj/machinery/abductor/proc/IsAbductor(mob/living/carbon/human/H)
if(!H.dna)
return 0
return H.dna.species.id == "abductor"
/obj/machinery/abductor/proc/IsAgent(mob/living/carbon/human/H)
+1
View File
@@ -98,6 +98,7 @@
M.mind.name = newname
M.real_name = newname
M.name = newname
M.dna.update_dna_identity()
var/datum/objective/protect/new_objective = new /datum/objective/protect
new_objective.owner = M:mind
new_objective:target = usr:mind
+5 -5
View File
@@ -346,7 +346,8 @@ var/list/slot2type = list("head" = /obj/item/clothing/head/changeling, "wear_mas
return
if(has_dna(target.dna))
user << "<span class='warning'>We already have this DNA in storage!</span>"
if(!check_dna_integrity(target))
return
if(!target.has_dna())
user << "<span class='warning'>[target] is not compatible with our biology.</span>"
return
return 1
@@ -405,10 +406,9 @@ var/list/slot2type = list("head" = /obj/item/clothing/head/changeling, "wear_mas
/proc/changeling_transform(var/mob/living/carbon/human/user, var/datum/changelingprofile/chosen_prof)
var/datum/dna/chosen_dna = chosen_prof.dna
user.real_name = chosen_prof.name
user.dna = chosen_dna
hardset_dna(user, null, null, null, null, chosen_dna.species.type, chosen_dna.features)
domutcheck(user)
updateappearance(user)
chosen_dna.transfer_identity(user, 1)
user.updateappearance(mutcolor_update=1)
user.domutcheck()
//vars hackery. not pretty, but better than the alternative.
for(var/slot in slots)
@@ -20,6 +20,9 @@
/obj/effect/proc_holder/changeling/proc/on_purchase(mob/user)
return
/obj/effect/proc_holder/changeling/proc/on_refund(mob/user)
return
/obj/effect/proc_holder/changeling/Click()
var/mob/user = usr
if(!user || !user.mind || !user.mind.changeling)
@@ -388,16 +388,13 @@ var/list/sting_paths
/mob/proc/remove_changeling_powers(keep_free_powers=0)
if(ishuman(src) || ismonkey(src))
if(mind && mind.changeling)
digitalcamo = 0
digitalinvis = 0
mind.changeling.changeling_speak = 0
mind.changeling.reset()
for(var/obj/effect/proc_holder/changeling/p in mind.changeling.purchasedpowers)
if(!(p.dna_cost == 0 && keep_free_powers))
mind.changeling.purchasedpowers -= p
if(istype(p,/obj/effect/proc_holder/changeling/augmented_eyesight))
permanent_sight_flags -= SEE_MOBS
sight -= SEE_MOBS
if(p.dna_cost == 0 && keep_free_powers)
continue
mind.changeling.purchasedpowers -= p
p.on_refund(src)
if(hud_used)
hud_used.lingstingdisplay.icon_state = null
hud_used.lingstingdisplay.invisibility = 101
@@ -130,7 +130,7 @@
if((target.disabilities & NOCLONE) || (target.disabilities & HUSK))
user << "<span class='warning'>DNA of [target] is ruined beyond usability!</span>"
return
if(!check_dna_integrity(target) || !ishuman(target))
if(!ishuman(target))
user << "<span class='warning'>[target] is not compatible with this ability.</span>"
return
return 1
@@ -28,3 +28,8 @@
user.see_in_dark = 0
user.dna.species.invis_sight = initial(user.dna.species.invis_sight)
return 1
/obj/effect/proc_holder/changeling/augmented_eyesight/on_refund(mob/user)
user.permanent_sight_flags &= ~SEE_MOBS
user.sight &= ~SEE_MOBS
@@ -10,17 +10,21 @@
/obj/effect/proc_holder/changeling/chameleon_skin/sting_action(mob/user)
var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1
if(!istype(H))
var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1 //phil235 so why is it needd?
if(!istype(H)) // req_human could be done in can_sting stuff.
return
var/datum/mutation/human/HM = mutations_list[CHAMELEON]
if(H.dna && H.dna.mutations)
if(HM in H.dna.mutations)
HM.force_lose(H)
else
HM.force_give(H)
if(HM in H.dna.mutations)
HM.force_lose(H)
else
HM.force_give(H)
feedback_add_details("changeling_powers","CS")
return 1
/obj/effect/proc_holder/changeling/chameleon_skin/on_refund(mob/user)
if(user.has_dna())
var/mob/living/carbon/C = user
var/datum/mutation/human/HM = mutations_list[CHAMELEON]
if(HM in C.dna.mutations)
HM.force_lose(C)
@@ -18,3 +18,7 @@
feedback_add_details("changeling_powers","CAM")
return 1
/obj/effect/proc_holder/changeling/digitalcamo/on_refund(mob/user)
user.digitalcamo = 0
user.digitalinvis = 0
@@ -24,12 +24,11 @@
if(!user || user.notransform)
return 0
user << "<span class='notice'>We transform our appearance.</span>"
user.humanize((TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPSRC), chosen_prof.name)
changeling_transform(user, chosen_prof)
changeling.purchasedpowers -= src
var/newmob = user.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS)
changeling_transform(newmob, chosen_prof)
feedback_add_details("changeling_powers","LFT")
qdel(user)
return 1
@@ -12,9 +12,7 @@
return 0
user << "<span class='warning'>Our genes cry out!</span>"
user.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPSE | TR_KEEPSRC)
user.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
// Human-form power now handled in monkeyize()
feedback_add_details("changeling_powers","LF")
.=1
qdel(user)
return 1
@@ -21,20 +21,23 @@
var/weapon_name_simple
/obj/effect/proc_holder/changeling/weapon/try_to_sting(mob/user, mob/target)
if(istype(user.l_hand, weapon_type)) //Not the nicest way to do it, but eh
playsound(user, 'sound/effects/blobattack.ogg', 30, 1)
qdel(user.l_hand)
user.visible_message("<span class='warning'>With a sickening crunch, [user] reforms their [weapon_name_simple] into an arm!</span>", "<span class='notice'>We assimilate the [weapon_name_simple] back into our body.</span>", "<span class='italics>You hear organic matter ripping and tearing!</span>")
user.update_inv_l_hand()
if(check_weapon(user, user.r_hand, 1))
return
if(istype(user.r_hand, weapon_type))
playsound(user, 'sound/effects/blobattack.ogg', 30, 1)
qdel(user.r_hand)
user.visible_message("<span class='warning'>With a sickening crunch, [user] reforms their [weapon_name_simple] into an arm!</span>", "<span class='notice'>We assimilate the [weapon_name_simple] back into our body.</span>", "<span class='italics>You hear organic matter ripping and tearing!</span>")
user.update_inv_r_hand()
if(check_weapon(user, user.l_hand, 0))
return
..(user, target)
/obj/effect/proc_holder/changeling/weapon/proc/check_weapon(mob/user, obj/item/hand_item, right_hand=1)
if(istype(hand_item, weapon_type))
playsound(user, 'sound/effects/blobattack.ogg', 30, 1)
qdel(hand_item)
user.visible_message("<span class='warning'>With a sickening crunch, [user] reforms their [weapon_name_simple] into an arm!</span>", "<span class='notice'>We assimilate the [weapon_name_simple] back into our body.</span>", "<span class='italics>You hear organic matter ripping and tearing!</span>")
if(right_hand)
user.update_inv_r_hand()
else
user.update_inv_l_hand()
return 1
/obj/effect/proc_holder/changeling/weapon/sting_action(mob/user)
if(!user.drop_item())
user << "<span class='warning'>The [user.get_active_hand()] is stuck to your hand, you cannot grow a [weapon_name_simple] over it!</span>"
@@ -44,6 +47,10 @@
playsound(user, 'sound/effects/blobattack.ogg', 30, 1)
return W
/obj/effect/proc_holder/changeling/weapon/on_refund(mob/user)
check_weapon(user, user.r_hand, 1)
check_weapon(user, user.l_hand, 0)
//Parent to space suits and armor.
/obj/effect/proc_holder/changeling/suit
name = "Organic Suit"
@@ -61,10 +68,16 @@
var/blood_on_castoff = 0
/obj/effect/proc_holder/changeling/suit/try_to_sting(mob/user, mob/target)
if(check_suit(user))
return
var/mob/living/carbon/human/H = user
..(H, target)
//checks if we already have an organic suit and casts it off.
/obj/effect/proc_holder/changeling/suit/proc/check_suit(mob/user)
var/datum/changeling/changeling = user.mind.changeling
if(!ishuman(user) || !changeling)
return
return 1
var/mob/living/carbon/human/H = user
if(istype(H.wear_suit, suit_type) || istype(H.head, helmet_type))
H.visible_message("<span class='warning'>[H] casts off their [suit_name_simple]!</span>", "<span class='warning'>We cast off our [suit_name_simple][genetic_damage > 0 ? ", temporarily weakening our genomes." : "."]</span>", "<span class='italics'>You hear the organic matter ripping and tearing!</span>")
@@ -82,8 +95,13 @@
changeling.geneticdamage += genetic_damage //Casting off a space suit leaves you weak for a few seconds.
changeling.chem_recharge_slowdown -= recharge_slowdown
return 1
/obj/effect/proc_holder/changeling/suit/on_refund(mob/user)
if(!ishuman(user))
return
..(H, target)
var/mob/living/carbon/human/H = user
check_suit(H)
/obj/effect/proc_holder/changeling/suit/sting_action(mob/living/carbon/human/user)
if(!user.canUnEquip(user.wear_suit))
@@ -16,6 +16,9 @@
for(var/datum/disease/D in user.viruses)
D.cure()
for(var/obj/item/organ/internal/I in user)
if(istype(I,/obj/item/organ/internal/body_egg/alien_embryo))
I.Remove(user)
I.loc = get_turf(user)
feedback_add_details("changeling_powers","AP")
return 1
@@ -12,7 +12,7 @@
if(iscarbon(M))
if(!M.mind || !M.mind.changeling)
M.adjustEarDamage(0,30)
M.confused += 20
M.confused += 25
M.Jitter(50)
else
M << sound('sound/effects/screech.ogg')
@@ -81,7 +81,7 @@
/obj/effect/proc_holder/changeling/sting/transformation/can_sting(mob/user, mob/target)
if(!..())
return
if((target.disabilities & HUSK) || !check_dna_integrity(target))
if((target.disabilities & HUSK) || !target.has_dna())
user << "<span class='warning'>Our sting appears ineffective against its DNA.</span>"
return 0
return 1
@@ -92,15 +92,17 @@
if(ismonkey(target))
user << "<span class='notice'>Our genes cry out as we sting [target.name]!</span>"
if(iscarbon(target) && (target.status_flags & CANWEAKEN))
if(iscarbon(target))
var/mob/living/carbon/C = target
C.do_jitter_animation(500)
C.take_organ_damage(20, 0) //The process is extremely painful
if(C.status_flags & CANWEAKEN)
C.do_jitter_animation(500)
C.take_organ_damage(20, 0) //The process is extremely painful
target.visible_message("<span class='danger'>[target] begins to violenty convulse!</span>","<span class='userdanger'>You feel a tiny prick and a begin to uncontrollably convulse!</span>")
spawn(10)
hardset_dna(target, NewDNA.uni_identity, NewDNA.struc_enzymes, NewDNA.real_name, NewDNA.blood_type, NewDNA.species.type, NewDNA.features)
updateappearance(target)
target.visible_message("<span class='danger'>[target] begins to violenty convulse!</span>","<span class='userdanger'>You feel a tiny prick and a begin to uncontrollably convulse!</span>")
spawn(10)
NewDNA.transfer_identity(C, transfer_SE=1)
C.updateappearance(mutcolor_update=1)
C.domutcheck()
feedback_add_details("changeling_powers","TS")
return 1
@@ -125,7 +127,7 @@
/obj/effect/proc_holder/changeling/sting/false_armblade/can_sting(mob/user, mob/target)
if(!..())
return
if((target.disabilities & HUSK) || !check_dna_integrity(target))
if((target.disabilities & HUSK) || !target.has_dna())
user << "<span class='warning'>Our sting appears ineffective against its DNA.</span>"
return 0
return 1
+8 -7
View File
@@ -92,7 +92,8 @@
if(config.protect_assistant_from_antagonist)
restricted_jobs += "Assistant"
acolytes_needed = max(2, round(num_players()/5)) //Scales the escape requirement with the amount of people in the round
acolytes_needed = round(num_players()/5,1) //Scales the escape requirement with the amount of people in the round; for every 5 players, one cultist added to the count, i.e. 25 players = 5 to escape
acolytes_needed = Clamp(acolytes_needed, 1, 15) //Max at 15 and minimum at 1 - before the update, people rarely got even 15
for(var/cultists_number = 1 to recommended_enemies)
if(!antag_candidates.len)
@@ -141,11 +142,11 @@
explanation = "Our knowledge must live on. Make sure at least [acolytes_needed] acolytes escape on the shuttle to spread their work on an another station."
if("sacrifice")
if(sacrifice_target)
explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. You will need the Rite of Tribute and three acolytes to do so."
explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. You will need the Sacrifice rune and three acolytes to do so."
else
explanation = "Free objective."
if("eldergod")
explanation = "Summon Nar-Sie via the use of the Ritual of Dimensional Rending. It will only work if nine cultists stand on and around it."
explanation = "Summon Nar-Sie via the rune 'Call Forth The Geometer'. It will only work if nine acolytes stand on and around it."
cult_mind.current << "<B>Objective #[obj_count]</B>: [explanation]"
cult_mind.memory += "<B>Objective #[obj_count]</B>: [explanation]<BR>"
@@ -171,7 +172,7 @@
if(!where)
mob << "Unfortunately, you weren't able to get a talisman. This is very bad and you should adminhelp immediately."
else
mob << "You have a talisman in your [where], one that will help you start the cult on this station. Use it well, and remember - you are not the only one."
mob << "<span class='danger'>You have a talisman in your [where], one that will help you start the cult on this station. Use it well, and remember - you are not the only one.</span>"
mob.update_icons()
if(where == "backpack")
var/obj/item/weapon/storage/B = mob.back
@@ -203,13 +204,13 @@
cult -= cult_mind
cult_mind.current.verbs -= /mob/living/proc/cult_innate_comm
cult_mind.current.Paralyse(5)
cult_mind.current << "<span class='userdanger'>An unfamiliar white light flashes through your mind, cleansing the taint of the dark-one and the memories of your time as his servant with it.</span>"
cult_mind.current << "<span class='userdanger'>An unfamiliar white light flashes through your mind, cleansing the taint of the Dark One and all your memories as its servant.</span>"
cult_mind.memory = ""
update_cult_icons_removed(cult_mind)
cult_mind.current.attack_log += "\[[time_stamp()]\] <span class='danger'>Has renounced the cult!</span>"
if(show_message)
for(var/mob/M in viewers(cult_mind.current))
M << "<FONT size = 3>[cult_mind.current] looks like they just reverted to their old faith!</FONT>"
M << "<span class='big'>[cult_mind.current] looks like they just reverted to their old faith!</span>"
/datum/game_mode/proc/update_cult_icons_added(datum/mind/cult_mind)
var/datum/atom_hud/antag/culthud = huds[ANTAG_HUD_CULT]
@@ -259,7 +260,7 @@
if(!check_cult_victory())
feedback_set_details("round_end_result","win - cult win")
feedback_set("round_end_result",acolytes_survived)
world << "<span class='redtext'>The cult wins! It has succeeded in serving its dark masters!</span>"
world << "<span class='greentext'>The cult wins! It has succeeded in serving its dark master!</span>"
else
feedback_set_details("round_end_result","loss - staff stopped the cult")
feedback_set("round_end_result",acolytes_survived)
+31 -32
View File
@@ -138,83 +138,82 @@ It also contains rune words, which are soon to be removed.
<i>Rite of Knowledge:</i> \"karazet nahlizet ego\"<br>\
<br><br><br>"*/
text += "<font color='red'><b>Rite of Translocation</b></font><br>The Rite of Translocation is a unique rite in that it requires a keyword before the scribing can begin. When invoked, the rune will \
text += "<font color='red'><b>Teleport</b></font><br>The Rite of Translocation is a unique rite in that it requires a keyword before the scribing can begin. When invoked, the rune will \
search for other Rites of Translocation with the same keyword. Assuming one is found, the user will be instantaneously transported to the location of the other rune. If more than two runes are scribed \
with the same keyword, it will choose randomly between all eligible runes and send the invoker to one of them.<br><br>"
text += "<font color='red'><b>Rite of Forced Translocation</b></font><br>The Rite of Forced Translocation, like the Rite of Translocation, works by teleporting the person on the rune to one of the \
text += "<font color='red'><b>Teleport Other</b></font><br>The Rite of Forced Translocation, like the Rite of Translocation, works by teleporting the person on the rune to one of the \
same keyword. However, this rune will only work on people other than the user, allowing the user to send any living creature somewhere else.<br><br>"
text += "<font color='red'><b>Rite of Knowledge</b></font><br>The Rite of Knowledge is a simplistic rune. When invoked, it will summon a single arcane tome to the rune's location before vanishing. \
text += "<font color='red'><b>Summon Tome</b></font><br>The Rite of Knowledge is a simplistic rune. When invoked, it will summon a single arcane tome to the rune's location before vanishing. \
<br><br>"
text += "<font color='red'><b>Rite of Enlightenment</b></font><br>The Rite of Enlightment is paramount to the success of the cult. It will allow you to convert normal crew members into cultists. \
To do this, simply place the crew member upon the rune and invoke it. This may take some time, depending on the amount of cultists nearby. It takes twenty seconds, with each additional cultist shaving \
off ten seconds of the conversion. With three or more cultists, conversion is instantaneous. Once invoked, only the original user must remain. If the target is loyalty-implanted or has a null rod in \
their possession, this will not work.<br><br>"
text += "<font color='red'><b>Convert</b></font><br>The Rite of Enlightment is paramount to the success of the cult. It will allow you to convert normal crew members into cultists. \
To do this, simply place the crew member upon the rune and invoke it. This rune requires two acolytes to use. If the target to be converted is loyalty-implanted or a certain assignment, they will \
be unable to be converted. People the Geometer wishes sacrificed will also be ineligible for conversion, and anyone with a shielding presence like a null rod will not be converted.<br><br>"
text += "<font color='red'><b>Rite of Tribute</b></font><br>The Rite of Tribute is used to offer sacrifice to the Geometer. Simply place any living creature upon the rune and invoke it (this will not \
text += "<font color='red'><b>Sacrifice</b></font><br>The Rite of Tribute is used to offer sacrifice to the Geometer. Simply place any living creature upon the rune and invoke it (this will not \
target cultists!). If this creature has a mind, a soul shard will be created and the creature's soul transported to it. This rune is required if the cult's objectives include the sacrifice of a crew \
member.<br><br>"
text += "<font color='red'><b>Rite of Resurrection</b></font><br>The Rite of Resurrection is a delicate rite that requires two corpses. To perform the ritual, place the corpse you wish to revive onto \
text += "<font color='red'><b>Raise Dead</b></font><br>The Rite of Resurrection is a delicate rite that requires two corpses. To perform the ritual, place the corpse you wish to revive onto \
the rune and the offering body adjacent to it. When the rune is invoked, the body to be sacrificed will turn to ashes, the life force flowing into the revival target. Assuming the target is not moved \
within a few seconds, they will be brought back to life, healed of all ailments.<br><br>"
text += "<font color='red'><b>Rite of Obscurity</b></font><br>The Rite of Obscurity is a rite that will cause all nearby runes to become invisible. The runes will still be considered by other rites \
text += "<font color='red'><b>Veil Runes</b></font><br>The Rite of Obscurity is a rite that will cause all nearby runes to become invisible. The runes will still be considered by other rites \
(such as the Rite of Translocation) but is unusuable directly.<br><br>"
text += "<font color='red'><b>Rite of True Sight</b></font><br>The Rite of True Sight is the foil of the Rite of Obscurity. It will turn all invisible runes visible once more, in addition to causing \
text += "<font color='red'><b>Reveal Runes</b></font><br>The Rite of True Sight is the foil of the Rite of Obscurity. It will turn all invisible runes visible once more, in addition to causing \
all spirits nearby to become partially corporeal.<br><br>"
text += "<font color='red'><b>Rite of False Truths</b></font><br>Many crew men enjoy drawing runes in crayon that resemble spell circles in order to play pranks on their fellow crewmen. The Rite of \
text += "<font color='red'><b>Disguise Runes</b></font><br>Many crew men enjoy drawing runes in crayon that resemble spell circles in order to play pranks on their fellow crewmen. The Rite of \
False Truths takes advantage of this very joke. When invoked, all nearby runes will appear dull, precisely resembling those drawn in crayon. They still cannot be cleaned by conventional means, so \
anyone trying to clean up the rune may become suspicious as it does not respond.<br><br>"
text += "<font color='red'><b>Rite of Disruption</b></font><br>Robotic lifeforms have time and time again been the downfall of fledgling cults. The Rite of Disruption may allow you to gain the upper \
text += "<font color='red'><b>Electromagnetic Disruption</b></font><br>Robotic lifeforms have time and time again been the downfall of fledgling cults. The Rite of Disruption may allow you to gain the upper \
hand against these pests. By using the rune, a large electromagnetic pulse will be emitted from the rune's location.<br><br>"
text += "<font color='red'><b>Rite of Astral Communion</b></font><br>The Rite of Astral Communion is perhaps the most ingenious rune that is usable by a single person. Upon invoking the rune, the \
text += "<font color='red'><b>Astral Communion</b></font><br>The Rite of Astral Communion is perhaps the most ingenious rune that is usable by a single person. Upon invoking the rune, the \
user's spirit will be ripped from their body. In this state, the user's physical body will be locked in place to the rune itself - any attempts to move it will result in the rune pulling it back. \
The body will also take constant damage while in this form, and may even die. The user's spirit will contain their consciousness, and will allow them to freely wander the station as a ghost. This may \
also be used to commune with the dead.<br><br>"
text += "<font color='red'><b>Rite of the Corporeal Shield</b></font><br>While simple, the Rite of the Corporeal Shield serves an important purpose in defense and hindering passage. When invoked, the \
text += "<font color='red'><b>Form Shield</b></font><br>While simple, the Rite of the Corporeal Shield serves an important purpose in defense and hindering passage. When invoked, the \
rune will draw a small amount of life force from the user and make the space above the rune completely dense, rendering it impassable to all but the most complex means. The rune may be invoked again to \
undo this effect and allow passage again.<br><br>"
text += "<font color='red'><b>Rite of the Unheard Whisper</b></font><br>The Rite of the Unheard Whisper is simple. When invoked, it will cause all non-cultists within a radius of seven tiles to become \
text += "<font color='red'><b>Deafen</b></font><br>The Rite of the Unheard Whisper is simple. When invoked, it will cause all non-cultists within a radius of seven tiles to become \
completely deaf for a large amount of time.<br><br>"
text += "<font color='red'><b>Rite of the Unseen Glance</b></font><br>Much like the Rite of the Unheard Whisper, the Rite of the Unseen Glance serves a single purpose. Any non-cultists who can see \
text += "<font color='red'><b>Blind</b></font><br>Much like the Rite of the Unheard Whisper, the Rite of the Unseen Glance serves a single purpose. Any non-cultists who can see \
the rune will instantly be blinded for a substantial amount of time.<br><br>"
text += "<font color='red'><b>Rite of Disorientation</b></font><br>A somewhat empowered version of the Rite of the Unseen Glance, this rune will cause any non-cultists that can see the rune to become \
text += "<font color='red'><b>Stun</b></font><br>A somewhat empowered version of the Rite of the Unseen Glance, this rune will cause any non-cultists that can see the rune to become \
disoriented, disabling them for a short time.<br><br>"
text += "<font color='red'><b>Rite of Joined Souls</b></font><br>The Rite of Joined Souls requires two acolytes to use. When invoked, it will allow the user to summon a single cultist to the rune from \
text += "<font color='red'><b>Summon Cultist</b></font><br>The Rite of Joined Souls requires two acolytes to use. When invoked, it will allow the user to summon a single cultist to the rune from \
any location. This will deal a moderate amount of damage to all invokers.<br><br>"
text += "<font color='red'><b>Rite of Binding</b></font><br>The Rite of Binding is the only way to create talismans. A blank sheet of paper must be on top of the rune, with a valid rune nearby. After \
text += "<font color='red'><b>Imbue Talisman</b></font><br>The Rite of Binding is the only way to create talismans. A blank sheet of paper must be on top of the rune, with a valid rune nearby. After \
invoking it, the paper will be converted into a talisman, and the rune inlaid upon it.<br><br>"
text += "<font color='red'><b>Rite of Fabrication</b></font><br>The Rite of Fabrication is the main way of creating construct shells. To use it, one must place five sheets of plasteel on top of the rune \
text += "<font color='red'><b>Fabricate Shell</b></font><br>The Rite of Fabrication is the main way of creating construct shells. To use it, one must place five sheets of plasteel on top of the rune \
and invoke it. The sheets will them be twisted into a construct shell, ready to recieve a soul to occupy it.<br><br>"
text += "<font color='red'><b>Rite of Arming</b></font><br>The Rite of Arming will equip the user with invoker's robes, a backpack, a Nar-Sian longsword, and a pair of boots. Any items that cannot \
text += "<font color='red'><b>Summon Arnaments</b></font><br>The Rite of Arming will equip the user with invoker's robes, a backpack, a Nar-Sian longsword, and a pair of boots. Any items that cannot \
be equipped will instead not be summoned regardless.<br><br>"
text += "<font color='red'><b>Rite of Leeching</b></font><br>The Rite of Leeching will drain the life of any non-cultist above the rune and heal the invoker for the same amount.<br><br>"
text += "<font color='red'><b>Drain Life</b></font><br>The Rite of Leeching will drain the life of any non-cultist above the rune and heal the invoker for the same amount.<br><br>"
text += "<font color='red'><b>Rite of Boiling Blood</b></font><br>The Rite of Boiling Blood may be considered one of the most dangerous rites composed by the Nar-Sian cult. When invoked, it will do a \
text += "<font color='red'><b>Boil Blood</b></font><br>The Rite of Boiling Blood may be considered one of the most dangerous rites composed by the Nar-Sian cult. When invoked, it will do a \
massive amount of damage to all non-cultist viewers, but it will also emit an explosion upon invocation. Use with caution<br><br>"
text += "<font color='red'><b>Rite of Spectral Manifestation</b></font><br>If you wish to bring a spirit back from the dead with a wish for vengeance and desire to serve, the Rite of Spectral \
text += "<font color='red'><b>Manifest Spirit</b></font><br>If you wish to bring a spirit back from the dead with a wish for vengeance and desire to serve, the Rite of Spectral \
Manifestation can do just that. When invoked, any spirits above the rune will be brought to life as a human wearing nothing that seeks only to serve you and the Geometer. However, the spirit's link \
to reality is fragile - you must remain on top of the rune, and you will slowly take damage. Upon stepping off the rune, the spirits will dissipate, dropping their items to the ground. You may manifest \
multiple spirits with one rune, but you will rapidly take damage in doing so.<br><br>"
text += "<font color='red'><b><i>Ritual of Dimensional Rending</i></b></font><br>There is only one way to summon the avatar of Nar-Sie, and that is the Ritual of Dimensional Rending. This ritual, in \
text += "<font color='red'><b><i>Call Forth The Geometer</i></b></font><br>There is only one way to summon the avatar of Nar-Sie, and that is the Ritual of Dimensional Rending. This ritual, in \
comparison to other runes, is very large, requiring a 3x3 space of empty tiles to create. To invoke the rune, nine cultists must stand on the rune, so that all of them are within its circle. Then, \
simply invoke it. A brief tearing will be heard as the barrier between dimensions is torn open, and the avatar will come forth.<br><br><br>"
@@ -222,17 +221,17 @@ It also contains rune words, which are soon to be removed.
rune inlaid within it. The words of the rune can be whispered in order to invoke its effects, although usually to a lesser extent. To create a talisman, simply use a Rite of Binding as described above. \
Unless stated otherwise, talismans are invoked by activating them in your hand. A list of valid rites, as well as the effects of their talisman form, can be found below.<br><br><br>"
text += "<font color='red'><b>Talisman of Translocation</b></font><br>The talisman form of the Rite of Translocation will transport the invoker to a randomly chosen rune of the same keyword, then \
text += "<font color='red'><b>Talisman of Teleportation</b></font><br>The talisman form of the Rite of Translocation will transport the invoker to a randomly chosen rune of the same keyword, then \
disappear.<br><br>"
text += "<font color='red'><b>Talisman of Knowledge</b></font><br>This talisman functions identically to the rune. It can be used once, then disappears.<br><br>"
text += "<font color='red'><b>Talisman of Tome summoning</b></font><br>This talisman functions identically to the rune. It can be used once, then disappears.<br><br>"
text += "<font color='red'><b>Talismans of Obscurity, True Sight, and False Truths</b></font><br>These talismans all function identically to their rune counterparts, but with less range. In addition, \
text += "<font color='red'><b>Talismans of Veiling, Revealing, and Disguising</b></font><br>These talismans all function identically to their rune counterparts, but with less range. In addition, \
the Talisman of True Sight will not reveal spirits. They will disappear after one use.<br><br>"
text += "<font color='red'><b>Talisman of Disruption</b></font><br>This talisman functions like the Rite of Disruption, but with halved range. It disappears after one use.<br><br>"
text += "<font color='red'><b>Talisman of Electromagnets</b></font><br>This talisman functions like the Rite of Disruption. It disappears after one use.<br><br>"
text += "<font color='red'><b>Talisman of Disorientation</b></font><br>Without this talisman, the cult would have no way of easily acquiring targets to convert. Commonly called \"stunpapers\", this \
text += "<font color='red'><b>Talisman of Stunning</b></font><br>Without this talisman, the cult would have no way of easily acquiring targets to convert. Commonly called \"stunpapers\", this \
talisman functions differently from others. Rather than simply reading the words, the target must be attacked directly with the talisman. The talisman will then knock down the target for a long \
duration in addition to rendering them incapable of speech. Robotic lifeforms will suffer the effects of a heavy electromagnetic pulse instead."
@@ -269,7 +268,7 @@ It also contains rune words, which are soon to be removed.
"<span class='danger'>You slice open your arm and begin drawing a sigil of the Geometer.</span>")
if(iscarbon(user))
var/mob/living/carbon/C = user
C.apply_damage(1, BRUTE, pick("l_arm", "r_arm"))
C.apply_damage(0.1, BRUTE, pick("l_arm", "r_arm"))
if(!do_after(user, 50, target = get_turf(user)))
return
user.visible_message("<span class='warning'>[user] creates a strange circle in their own blood.</span>", \
+65 -85
View File
@@ -171,7 +171,7 @@ structure_check() searches for nearby cultist structures required for the invoca
var/list/teleport_runes = list()
//Rite of Translocation: Warps the user to a random teleport rune with the same keyword.
/obj/effect/rune/teleport
cultist_name = "Rite of Translocation"
cultist_name = "Teleport"
cultist_desc = "Warps the user to a random rune of the same keyword."
invocation = "Sas'so c'arta forbici!"
icon_state = "2"
@@ -210,7 +210,7 @@ var/list/teleport_runes = list()
var/list/teleport_other_runes = list()
//Rite of Forced Translocation: Warps the target to a random teleport rune with the same keyword.
/obj/effect/rune/teleport_other
cultist_name = "Rite of Forced Translocation"
cultist_name = "Teleport Other"
cultist_desc = "Warps the target to a random rune of the same keyword."
invocation = "Sas'so c'arta forbica!"
icon_state = "1"
@@ -266,8 +266,8 @@ var/list/teleport_other_runes = list()
//Rite of Knowledge: Creates an arcane tome at the rune's location and destroys the rune.
/obj/effect/rune/summon_tome
cultist_name = "Rite of Knowledge"
cultist_desc = "Pulls an unstranslated arcane tome from the archives of the Geometer."
cultist_name = "Summon Tome"
cultist_desc = "Pulls an arcane tome from the archives of the Geometer."
invocation = "N'ath reth sh'yro eth d'raggathnor!"
icon_state = "5"
color = rgb(0, 0, 255)
@@ -281,12 +281,13 @@ var/list/teleport_other_runes = list()
//Rite of Enlightenment: Converts a normal crewmember to the cult. Faster for every cultist nearby.
/obj/effect/rune/convert
cultist_name = "Rite of Enlightenment"
cultist_name = "Convert"
cultist_desc = "Converts a normal crewmember on top of it to the cult. Does not work on loyalty-implanted crew."
invocation = "Mah'weyh pleggh at e'ntrath!"
icon_state = "3"
color = rgb(255, 0, 0)
grammar = "certum nahlizet ego"
req_cultists = 2
/obj/effect/rune/convert/invoke(mob/living/user)
var/list/convertees = list()
@@ -308,31 +309,6 @@ var/list/teleport_other_runes = list()
if(iscultist(M))
M << "<span class='cult'>\"I desire this one for myself. <i>SACRIFICE THEM!</i>\"</span>"
return
var/time = 300
for(var/mob/living/M in orange(1,src))
if(iscultist(M))
time -= 100
time = Clamp(time, 0, 300)
if(time)
visible_message("<span class='warning'>[src] begins to glow with a sinister light...</span>")
for(var/mob/living/M in orange(1,src))
if(iscultist(M))
if(M != user)
M << "<span class='warning'>You have aided [user] in invoking the [cultist_name]. You may now safely depart.</span>"
else
M << "<span class='warning'>You begin the enlightenment of [new_cultist]. This will take [time / 10] seconds and you must stand still.</span>"
new_cultist << "<span class='userdanger'>Your head begins to ache...</span>"
if(!do_mob(user, new_cultist, time))
visible_message("<span class='warning'>[src] reluctantly falls dark.</span>")
new_cultist << "<span class='danger'>Your headache fades.</span>"
return
if(is_sacrifice_target(new_cultist.mind))
for(var/mob/living/M in orange(1,src))
if(iscultist(M))
M << "<span class='cult'>\"I desire this one for myself. <i>SACRIFICE THEM!</i>\"</span>"
fail_invoke()
log_game("Convert rune failed - convertee is sacrifice target")
return
new_cultist.visible_message("<span class='warning'>[new_cultist] writhes in pain as the markings below them glow a bloody red!</span>", \
"<span class='userdanger'><i>AAAAAAAAAAAAAA-</i></span>")
ticker.mode.add_cultist(new_cultist.mind)
@@ -345,14 +321,18 @@ var/list/teleport_other_runes = list()
//Rite of Tribute: Sacrifices a crew member to Nar-Sie. Places them into a soul shard if they're in their body.
/obj/effect/rune/sacrifice
cultist_name = "Rite of Tribute"
cultist_name = "Sacrifice"
cultist_desc = "Sacrifices a crew member to the Geometer. May place them into a soul shard if their spirit remains in their body."
icon_state = "3"
invocation = "Barhah hra zar'garis!"
invocation = "Ih wah'kd in teh'tin!"
color = rgb(255, 255, 255)
grammar = "veri nahlizet certum"
var/rune_in_use = 0
/obj/effect/rune/sacrifice/New()
..()
icon_state = "[rand(1,6)]"
/obj/effect/rune/sacrifice/invoke(mob/living/user)
if(rune_in_use)
return
@@ -397,28 +377,16 @@ var/list/teleport_other_runes = list()
/obj/effect/rune/sacrifice/proc/sac(mob/living/T)
var/sacrifice_fulfilled
if(T)
if(T.mind)
var/obj/item/device/soulstone/stone = new /obj/item/device/soulstone(get_turf(src))
if(!stone.transfer_soul("FORCE", T, usr)) //If it cannot be added
qdel(stone)
if(!T)
rune_in_use = 0
return
if(istype(T, /mob/living/simple_animal/pet/dog/corgi))
for(var/mob/living/carbon/C in orange(1,src))
if(iscultist(C))
C << "<span class='warning'>Even dark gods from another plane have standards, sicko.</span>"
if(C.reagents)
C.reagents.add_reagent("hell_water", 2)
sacrificed.Add(T.mind)
if(is_sacrifice_target(T.mind))
sacrifice_fulfilled = 1
if(isrobot(T))
playsound(T, 'sound/magic/Disable_Tech.ogg', 100, 1)
T.dust() //To prevent the MMI from remaining
else
playsound(T, 'sound/magic/Disintegrate.ogg', 100, 1)
T.gib()
if(T.mind)
sacrificed.Add(T.mind)
if(is_sacrifice_target(T.mind))
sacrifice_fulfilled = 1
for(var/mob/living/M in orange(1,src))
if(iscultist(M))
if(sacrifice_fulfilled)
@@ -428,12 +396,25 @@ var/list/teleport_other_runes = list()
M << "<span class='cult'>\"I accept this sacrifice.\"</span>"
else
M << "<span class='cult'>\"I accept this meager sacrifice.\"</span>"
if(T.mind)
var/obj/item/device/soulstone/stone = new /obj/item/device/soulstone(get_turf(src))
if(!stone.transfer_soul("FORCE", T, usr)) //If it cannot be added
qdel(stone)
if(!T)
rune_in_use = 0
return
if(isrobot(T))
playsound(T, 'sound/magic/Disable_Tech.ogg', 100, 1)
T.dust() //To prevent the MMI from remaining
else
playsound(T, 'sound/magic/Disintegrate.ogg', 100, 1)
T.gib()
rune_in_use = 0
//Ritual of Dimensional Rending: Calls forth the avatar of Nar-Sie upon the station.
/obj/effect/rune/narsie
cultist_name = "Ritual of Dimensional Rending"
cultist_name = "Call Forth The Geometer"
cultist_desc = "Tears apart dimensional barriers, calling forth the avatar of the Geometer."
invocation = "Tok-lyr rqa'nap g'olt-ulotf!"
req_cultists = 9
@@ -489,10 +470,11 @@ var/list/teleport_other_runes = list()
//Rite of Resurrection: Requires two corpses. Revives one and gibs the other.
/obj/effect/rune/raise_dead
cultist_name = "Rite of Resurrection"
cultist_name = "Raise Dead"
cultist_desc = "Requires two corpses. The one placed upon the rune is brought to life, the other is turned to ash."
invocation = null //Depends on the name of the user - see below
color = rgb(150, 0, 0)
icon_state = "1"
color = rgb(255, 0, 0)
grammar = "nahlizet certum veri"
/obj/effect/rune/raise_dead/invoke(mob/living/user)
@@ -557,11 +539,11 @@ var/list/teleport_other_runes = list()
//Rite of Obscurity: Turns all runes within a 3-tile radius invisible.
/obj/effect/rune/hide_runes
cultist_name = "Rite of Obscurity"
cultist_desc = "Turns nearby runes invisible. They can be revealed by using the Rite of True Sight."
cultist_name = "Veil Runes"
cultist_desc = "Turns nearby runes invisible. They can be revealed by using the Reveal Runes rune."
invocation = "Kla'atu barada nikt'o!"
icon_state = "3"
color = rgb(255,255,255)
icon_state = "1"
color = rgb(0,0,255)
grammar = "geeri karazet nahlizet"
/obj/effect/rune/hide_runes/invoke(mob/living/user)
@@ -579,11 +561,11 @@ var/list/teleport_other_runes = list()
//Rite of True Sight: Turns ghosts and obscured runes visible
/obj/effect/rune/true_sight
cultist_name = "Rite of True Sight"
cultist_name = "Reveal Runes"
cultist_desc = "Reveals all invisible objects nearby, from spirits to runes."
invocation = "Nikt'o barada kla'atu!"
icon_state = "6"
color = rgb(255, 162, 33)
icon_state = "4"
color = rgb(255, 255, 255)
grammar = "karazet geeri nahlizet"
/obj/effect/rune/true_sight/invoke()
@@ -599,7 +581,7 @@ var/list/teleport_other_runes = list()
//Rite of False Truths: Makes runes appear like crayon ones
/obj/effect/rune/make_runes_fake
cultist_name = "Rite of False Truths"
cultist_name = "Disguise Runes"
cultist_desc = "Causes all nearby runes (including itself) to resemble those drawn in crayon."
invocation = "By'o isit!"
icon_state = "4"
@@ -614,11 +596,11 @@ var/list/teleport_other_runes = list()
//Rite of Disruption: Emits an EMP blast.
/obj/effect/rune/emp
cultist_name = "Rite of Disruption"
cultist_name = "Electromagnetic Disruption"
cultist_desc = "Emits a large electromagnetic pulse, hindering electronics and disabling silicons."
invocation = "Ta'gh fara'qha fel d'amar det!"
icon_state = "1"
color = rgb(0, 0, 255)
icon_state = "5"
color = rgb(255, 0, 0)
grammar = "mgar karazet balaq"
/obj/effect/rune/emp/invoke(mob/living/user)
@@ -632,11 +614,11 @@ var/list/teleport_other_runes = list()
//Rite of Astral Communion: Separates one's spirit from their body. They will take damage while it is active.
/obj/effect/rune/astral
cultist_name = "Rite of Astral Communion"
cultist_name = "Astral Communion"
cultist_desc = "Severs the link between one's spirit and body. This effect is taxing and one's physical body will take damage while this is active."
invocation = "Fwe'sh mah erl nyag r'ya!"
icon_state = "1"
color = rgb(68, 47, 255)
icon_state = "6"
color = rgb(0, 0, 255)
var/rune_in_use = 0 //One at a time, please!
var/mob/living/affecting = null
grammar = "veri ire ego"
@@ -702,10 +684,11 @@ var/list/teleport_other_runes = list()
//Rite of the Corporeal Shield: When invoked, becomes solid and cannot be passed. Invoke again to undo.
/obj/effect/rune/wall
cultist_name = "Rite of the Corporeal Shield"
cultist_name = "Form Shield"
cultist_desc = "When invoked, makes the rune block passage. Can be invoked again to reverse this."
invocation = "Khari'd! Eske'te tannin!"
icon_state = "1"
color = rgb(255, 0, 0)
grammar = "mgar ire ego"
/obj/effect/rune/wall/examine(mob/user)
@@ -724,10 +707,12 @@ var/list/teleport_other_runes = list()
//Rite of the Unheard Whisper: Deafens all non-cultists nearby.
/obj/effect/rune/deafen
cultist_name = "Rite of the Unheard Whisper"
cultist_name = "Deafen"
cultist_desc = "Causes all non-followers nearby to lose their hearing."
invocation = "Sti kaliedir!"
grammar = "geeri jatkaa karazet"
color = rgb(0, 255, 0)
icon_state = "4"
/obj/effect/rune/deafen/invoke(mob/living/user)
visible_message("<span class='warning'>[src] blurs for a moment before fading away.</span>")
@@ -740,11 +725,11 @@ var/list/teleport_other_runes = list()
//Rite of the Unseen Glance: Blinds all non-cultists nearby.
/obj/effect/rune/blind
cultist_name = "Rite of the Unseen Glance"
cultist_name = "Blind"
cultist_desc = "Causes all non-followers nearby to lose their sight."
invocation = "Sti kaliesin!"
icon_state = "1"
color = rgb(0, 255, 0)
icon_state = "4"
color = rgb(0, 0, 255)
grammar = "mgar jatkaa karazet"
/obj/effect/rune/blind/invoke(mob/living/user)
@@ -760,11 +745,11 @@ var/list/teleport_other_runes = list()
//Rite of Disorientation: Stuns all non-cultists nearby for a brief time
/obj/effect/rune/stun
cultist_name = "Rite of Disorientation"
cultist_name = "Stun"
cultist_desc = "Stuns all nearby non-followers for a brief time."
invocation = "Fuu ma'jin!"
icon_state = "2"
color = rgb(150, 0, 255)
color = rgb(100, 0, 100)
grammar = "certum geeri balaq"
/obj/effect/rune/stun/invoke(mob/living/user)
@@ -780,7 +765,7 @@ var/list/teleport_other_runes = list()
//Rite of Joined Souls: Summons a single cultist. Requires 2 cultists.
/obj/effect/rune/summon
cultist_name = "Rite of Joined Souls"
cultist_name = "Summon Cultist"
cultist_desc = "Summons a single cultist to the rune."
invocation = "N'ath reth sh'yro eth d'rekkathnor!"
req_cultists = 2
@@ -817,11 +802,11 @@ var/list/teleport_other_runes = list()
//Rite of Binding: Turns a nearby rune and a paper on top of the rune to a talisman, if both are valid.
/obj/effect/rune/imbue
cultist_name = "Rite of Binding"
cultist_name = "Bind Talisman"
cultist_desc = "Transforms papers and valid runes into talismans."
invocation = "H'drak v'loso, mir'kanas verbot!"
icon_state = "3"
color = rgb(150, 0, 255)
color = rgb(0, 0, 255)
grammar = "veri balaq certum"
/obj/effect/rune/imbue/invoke(mob/living/user)
@@ -860,18 +845,13 @@ var/list/teleport_other_runes = list()
log_game("Talisman Imbue rune failed - chosen rune invalid")
return
visible_message("<span class='warning'>[picked_rune] crumbles to dust, and bloody images form themselves on [paper_to_imbue].</span>")
if(iscarbon(user))
var/mob/living/carbon/C = user
C.apply_damage(5, BRUTE, pick("l_arm", "r_arm"))
else
user.adjustBruteLoss(5)
qdel(paper_to_imbue)
qdel(picked_rune)
//Rite of Fabrication: Creates a construct shell out of 5 metal sheets.
/obj/effect/rune/construct_shell
cultist_name = "Rite of Fabrication"
cultist_name = "Fabricate Shell"
cultist_desc = "Turns five plasteel sheets into an empty construct shell, suitable for containing a soul shard."
invocation = "Ethra p'ni dedol!"
icon_state = "5"
@@ -900,7 +880,7 @@ var/list/teleport_other_runes = list()
//Rite of Arming: Creates cult robes, a trophy rack, and a cult sword on the rune.
/obj/effect/rune/armor
cultist_name = "Rite of Arming"
cultist_name = "Summon Arnaments"
cultist_desc = "Equips the user with robes, shoes, a backpack, and a longsword. Items that cannot be equipped will not be summoned."
invocation = "N'ath reth sh'yro eth draggathnor!"
icon_state = "4"
@@ -919,7 +899,7 @@ var/list/teleport_other_runes = list()
//Rite of Leeching: Deals brute damage to the target and heals the same amount to the invoker.
/obj/effect/rune/leeching
cultist_name = "Rite of Leeching"
cultist_name = "Drain Life"
cultist_desc = "Drains the life of the target on the rune, restoring it to the user."
invocation = "Yu'gular faras desdae. Havas mithum javara. Umathar uf'kal thenar!" //that's a mouthful
icon_state = "2"
@@ -948,7 +928,7 @@ var/list/teleport_other_runes = list()
//Rite of Boiling Blood: Deals extremely high amounts of damage to non-cultists nearby
/obj/effect/rune/blood_boil
cultist_name = "Rite of Boiling Blood"
cultist_name = "Boil Blood"
cultist_desc = "Boils the blood of non-believers who can see the rune, dealing extreme amounts of damage."
invocation = "Dedo ol'btoh!"
icon_state = "4"
@@ -975,7 +955,7 @@ var/list/teleport_other_runes = list()
//Rite of Spectral Manifestation: Summons a ghost on top of the rune as a cultist human with no items. User must stand on the rune at all times, and takes damage for each summoned ghost.
/obj/effect/rune/manifest
cultist_name = "Rite of Spectral Manifestation"
cultist_name = "Manifest Spirit"
cultist_desc = "Manifests a spirit as a servant of the Geometer. The invoker must not move from atop the rune, and will take damage for each summoned spirit."
invocation = "Gal'h'rfikk harfrandid mud'gib!" //how the fuck do you pronounce this
icon_state = "6"
+43 -11
View File
@@ -19,6 +19,7 @@ Rite of Disorientation
var/cultist_desc = "A basic talisman. It serves no purpose."
var/invocation = "Naise meam!"
var/uses = 1
var/health_cost = 0 //The amount of health taken from the user when invoking the talisman
/obj/item/weapon/paper/talisman/examine(mob/user)
..()
@@ -40,7 +41,9 @@ Rite of Disorientation
qdel(src)
/obj/item/weapon/paper/talisman/proc/invoke(mob/living/user)
if(health_cost && iscarbon(user))
var/mob/living/carbon/C = user
C.apply_damage(health_cost, BRUTE, pick("l_arm", "r_arm"))
//Malformed Talisman: If something goes wrong.
/obj/item/weapon/paper/talisman/malformed
@@ -124,9 +127,10 @@ Rite of Disorientation
//Rite of Translocation: Same as rune
/obj/item/weapon/paper/talisman/teleport
cultist_name = "Rite of Translocation"
cultist_name = "Talisman of Teleportation"
cultist_desc = "A single-use talisman that will teleport a user to a random rune of the same keyword."
invocation = "Sas'so c'arta forbici!"
health_cost = 5
var/keyword = "ire"
/obj/item/weapon/paper/talisman/teleport/invoke(mob/living/user)
@@ -135,7 +139,7 @@ Rite of Disorientation
if(R.keyword == src.keyword)
possible_runes.Add(R)
if(!possible_runes.len)
user << "<span class='warning'>There are no Rites of Translocation with the same keyword!</span>"
user << "<span class='warning'>There are no Teleport runes with the same keyword!</span>"
log_game("Teleportation talisman failed - no teleport runes of the same keyword")
uses++ //To prevent deletion
return
@@ -151,12 +155,18 @@ Rite of Disorientation
spawn(1) //To give the keyword time to change from the imbue rune
info += keyword
/obj/item/weapon/paper/talisman/teleport/examine(mob/user)
..()
if(iscultist(user) && keyword)
user << "<b>Keyword:</b> [keyword]"
//Rite of Knowledge: Same as rune, but has two uses
/obj/item/weapon/paper/talisman/summon_tome
cultist_name = "Rite of Knowledge"
cultist_name = "Talisman of Tome Summoning"
cultist_desc = "A two-use talisman that will call untranslated tomes from the archives of the Geometer."
invocation = "N'ath reth sh'yro eth d'raggathnor!"
health_cost = 1
/obj/item/weapon/paper/talisman/summon_tome/invoke(mob/living/user)
user.visible_message("<span class='warning'>Dust flows from [user]'s hand for a moment.</span>", \
@@ -171,9 +181,10 @@ Rite of Disorientation
//Rite of Obscurity: Same as rune, but less range
/obj/item/weapon/paper/talisman/hide_runes
cultist_name = "Rite of Obscurity"
cultist_name = "Talisman of Veiling"
cultist_desc = "A talisman that will make all runes within a small radius invisible."
invocation = "Kla'atu barada nikt'o!"
health_cost = 1
/obj/item/weapon/paper/talisman/hide_runes/invoke(mob/living/user)
user.visible_message("<span class='warning'>Dust flows from [user]'s hand.</span>", \
@@ -185,9 +196,10 @@ Rite of Disorientation
//Rite of True Sight: Same as rune, but doesn't work on ghosts
/obj/item/weapon/paper/talisman/true_sight
cultist_name = "Rite of True Sight"
cultist_name = "Talisman of Revealing"
cultist_desc = "A talisman that reveals nearby invisible runes."
invocation = "Nikt'o barada kla'atu!"
health_cost = 1
/obj/item/weapon/paper/talisman/true_sight/invoke(mob/living/user)
user.visible_message("<span class='warning'>A flash of light shines from [user]'s hand!</span>", \
@@ -198,9 +210,10 @@ Rite of Disorientation
//Rite of False Truths: Same as rune
/obj/item/weapon/paper/talisman/make_runes_fake
cultist_name = "Rite of False Truths"
cultist_name = "Talisman of Disguising"
cultist_desc = "A talisman that will make nearby runes appear fake."
invocation = "By'o isit!"
health_cost = 3
/obj/item/weapon/paper/talisman/make_runes_fake/invoke(mob/living/user)
user.visible_message("<span class='warning'>Dust flows from [user]s hand.</span>", \
@@ -211,21 +224,23 @@ Rite of Disorientation
//Rite of Disruption: Same as rune, halved radius
/obj/item/weapon/paper/talisman/emp
cultist_name = "Rite of Disruption"
cultist_name = "Talisman of Electromagnets"
cultist_desc = "A talisman that will cause a moderately-sized electromagnetic pulse."
invocation = "Ta'gh fara'qha fel d'amar det!"
health_cost = 5
/obj/item/weapon/paper/talisman/emp/invoke(mob/living/user)
user.visible_message("<span class='warning'>[user]'s hand glows a bright blue!</span>", \
user.visible_message("<span class='warning'>[user]'s hand flashes a bright blue!</span>", \
"<span class='warning'>You speak the words of the talisman, emitting an EMP blast.</span>")
empulse(src, 2, 4)
empulse(src, 4, 8)
//Rite of Disorientation: Stuns and mutes a single target for quite some time
/obj/item/weapon/paper/talisman/stun
cultist_name = "Rite of Disorientation"
cultist_name = "Talisman of Stunning"
cultist_desc = "A talisman that will stun and mute a single target. To use, attack target directly."
invocation = "Fuu ma'jin!"
health_cost = 10 //A lot of health because of how powerful this is
/obj/item/weapon/paper/talisman/stun/attack_self(mob/living/user)
user << "<span class='warning'>To use this talisman, attack the target directly.</span>"
@@ -254,3 +269,20 @@ Rite of Disorientation
qdel(src)
return
..()
//Rite of Arming: Equips cultist armor on the user, where available
/obj/item/weapon/paper/talisman/armor
cultist_name = "Talisman of Arming"
cultist_desc = "A talisman that will equip the invoker with cultist equipment where available."
invocation = "N'ath reth sh'yro eth draggathnor!"
health_cost = 3
/obj/item/weapon/paper/talisman/armor/invoke(mob/living/user)
user.visible_message("<span class='warning'>Otherworldy objects suddenly appear on [user]!</span>", \
"<span class='warning'>You speak the words of the talisman, arming yourself!</span>")
user.equip_to_slot_or_del(new /obj/item/clothing/head/culthood/alt(user), slot_head)
user.equip_to_slot_or_del(new /obj/item/clothing/suit/cultrobes/alt(user), slot_wear_suit)
user.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult/alt(user), slot_shoes)
user.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/cultpack(user), slot_back)
user.put_in_hands(new /obj/item/weapon/melee/cultblade(user))
+4 -4
View File
@@ -147,11 +147,11 @@
var/DNAstring = input("Input DNA string to search for." , "Please Enter String." , "")
if(!DNAstring)
return
for(var/mob/living/carbon/M in mob_list)
if(!M.dna)
for(var/mob/living/carbon/C in mob_list)
if(!C.dna)
continue
if(M.dna.unique_enzymes == DNAstring)
target = M
if(C.dna.unique_enzymes == DNAstring)
target = C
break
return attack_self()
+1 -1
View File
@@ -807,7 +807,7 @@ var/global/list/possible_items_special = list()
var/turf/cloc = get_turf(changeling.current)
if(cloc && cloc.onCentcom() && (changeling.current.stat != DEAD)) //Living changeling on centcomm....
for(var/name in check_names) //Is he (disguised as) one of the staff?
if(H.dna && H.dna.real_name == name)
if(H.dna.real_name == name)
check_names -= name //This staff member is accounted for, remove them, so the team don't succeed by escape as 7 of the same engineer
success++ //A living changeling staff member made it to centcomm
continue changelings
+1 -1
View File
@@ -1,4 +1,4 @@
/datum/subsystem/ticker/proc/setupGenetics()
/datum/subsystem/objects/proc/setupGenetics()
var/list/avnums = new /list(DNA_STRUC_ENZYMES_BLOCKS)
for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++)
avnums[i] = i
+27 -5
View File
@@ -166,10 +166,8 @@ Made by Xhuis
thralls.Remove(thrall_mind)
thrall_mind.current.attack_log += "\[[time_stamp()]\] <span class='danger'>Dethralled</span>"
thrall_mind.special_role = null
thrall_mind.remove_spell(/obj/effect/proc_holder/spell/targeted/lesser_shadowling_hivemind)
thrall_mind.remove_spell(/obj/effect/proc_holder/spell/targeted/lesser_glare)
thrall_mind.remove_spell(/obj/effect/proc_holder/spell/targeted/lesser_shadow_walk)
thrall_mind.remove_spell(/obj/effect/proc_holder/spell/targeted/thrall_vision)
for(var/obj/effect/proc_holder/spell/S in thrall_mind.spell_list)
thrall_mind.remove_spell(S)
if(kill && ishuman(thrall_mind.current)) //If dethrallization surgery fails, kill the mob as well as dethralling them
var/mob/living/carbon/human/H = thrall_mind.current
H.visible_message("<span class='warning'>[H] jerks violently and falls still.</span>", \
@@ -186,6 +184,30 @@ Made by Xhuis
under their command...</span>")
return 1
/datum/game_mode/proc/remove_shadowling(datum/mind/ling_mind)
if(!istype(ling_mind) || !(ling_mind in shadows)) return 0
update_shadow_icons_removed(ling_mind)
shadows.Remove(ling_mind)
ling_mind.current.attack_log += "\[[time_stamp()]\] <span class='danger'>Deshadowlinged</span>"
ling_mind.special_role = null
for(var/obj/effect/proc_holder/spell/S in ling_mind.spell_list)
ling_mind.remove_spell(S)
var/mob/living/M = ling_mind.current
if(issilicon(M))
M.audible_message("<span class='notice'>[M] lets out a short blip.</span>", \
"<span class='userdanger'>You have been turned into a robot! You are no longer a shadowling! Though you try, you cannot remember anything about your time as one...</span>")
else
M.visible_message("<span class='big'>[M] screams and contorts!</span>", \
"<span class='userdanger'>THE LIGHT-- YOUR MIND-- <i>BURNS--</i></span>")
spawn(30)
if(!M || qdeleted(M))
return
M.visible_message("<span class='warning'>[M] suddenly bloats and explodes!</span>", \
"<span class='warning'><b>AAAAAAAAA<font size=3>AAAAAAAAAAAAA</font><font size=4>AAAAAAAAAAAA----</font></span>")
playsound(M, 'sound/magic/Disintegrate.ogg', 100, 1)
M.gib()
/datum/game_mode/shadowling/proc/check_shadow_victory()
var/success = 0 //Did they win?
if(shadow_objectives.Find("enthrall"))
@@ -244,7 +266,7 @@ Made by Xhuis
light_amount = T.get_lumcount()
if(light_amount > LIGHT_DAM_THRESHOLD && !H.incorporeal_move) //Can survive in very small light levels. Also doesn't take damage while incorporeal, for shadow walk purposes
H.take_overall_damage(0, LIGHT_DAMAGE_TAKEN)
H << "<span class='userdanger'>The light burns you!</span>"
H << "<span class='userdanger'>The light burns you!</span>" //Message spam to say "GET THE FUCK OUT"
H << 'sound/weapons/sear.ogg'
else if (light_amount < LIGHT_HEAL_THRESHOLD)
H.heal_overall_damage(5,5)
@@ -90,7 +90,7 @@
for(var/obj/machinery/computer/C in T.contents)
C.SetLuminosity(0)
C.visible_message("<span class='warning'>[C] grows dim, its screen barely readable.</span>")
for(var/obj/effect/glowshroom/G in orange(2, usr)) //Very small radius
for(var/obj/effect/glowshroom/G in orange(7, usr)) //High radius because glowshroom spam wrecks shadowlings
G.visible_message("<span class='warning'>[G] withers away!</span>")
qdel(G)
for(var/mob/living/H in T.contents)
@@ -297,7 +297,7 @@
user.equip_to_slot_or_del(new /obj/item/clothing/gloves/shadowling(usr), slot_gloves)
user.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/shadowling(usr), slot_wear_mask)
user.equip_to_slot_or_del(new /obj/item/clothing/glasses/night/shadowling(usr), slot_glasses)
hardset_dna(user, null, null, null, null, /datum/species/shadow/ling)
user.set_species(/datum/species/shadow/ling)
/obj/effect/proc_holder/spell/targeted/collective_mind //Lets a shadowling bring together their thralls' strength, granting new abilities and a headcount
@@ -334,27 +334,28 @@
user << "<span class='warning'>Your concentration has been broken. The mental hooks you have sent out now retract into your mind.</span>"
return
if(thralls >= 3 && !blind_smoke_acquired)
if(thralls >= 3 && !screech_acquired)
screech_acquired = 1
user << "<span class='shadowling'><i>The power of your thralls has granted you the <b>Sonic Screech</b> ability. This ability will shatter nearby windows and deafen enemies, plus stunning silicon lifeforms.</span>"
user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/unearthly_screech(null))
if(thralls >= 5 && !blind_smoke_acquired)
blind_smoke_acquired = 1
user << "<span class='shadowling'><i>The power of your thralls has granted you the <b>Blinding Smoke</b> ability. It will create a choking cloud that will blind any non-thralls who enter. \
</i></span>"
user.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/blindness_smoke
user.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/blindness_smoke(null))
if(thralls >= 5 && !drainLifeAcquired)
if(thralls >= 7 && !drainLifeAcquired)
drainLifeAcquired = 1
user << "<span class='shadowling'><i>The power of your thralls has granted you the <b>Drain Life</b> ability. You can now drain the health of nearby humans to heal yourself.</i></span>"
user.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/drain_life
user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/drain_life(null))
if(thralls >= 7 && !screech_acquired)
screech_acquired = 1
user << "<span class='shadowling'><i>The power of your thralls has granted you the <b>Sonic Screech</b> ability. This ability will shatter nearby windows and deafen enemies, plus stunning silicon lifeforms.</span>"
user.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/unearthly_screech
if(thralls >= 9 && !reviveThrallAcquired)
reviveThrallAcquired = 1
user << "<span class='shadowling'><i>The power of your thralls has granted you the <b>Black Recuperation</b> ability. This will, after a short time, bring a dead thrall completely back to life \
with no bodily defects.</i></span>"
user.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/revive_thrall
user.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/revive_thrall(null))
if(thralls < victory_threshold)
user << "<span class='shadowling'>You do not have the power to ascend. You require [victory_threshold] thralls, but only [thralls] living thralls are present.</span>"
@@ -492,7 +493,7 @@ datum/reagent/shadowling_blindness_smoke //Reagent used for above spell
nearbyTargets = list()
for(var/turf/T in targets)
for(var/mob/living/carbon/M in T.contents)
if(M == src) continue
if(M == usr) continue
targetsDrained++
nearbyTargets.Add(M)
if(!targetsDrained)
@@ -568,7 +569,7 @@ datum/reagent/shadowling_blindness_smoke //Reagent used for above spell
thrallToRevive.visible_message("<span class='warning'>[thrallToRevive] slowly rises, no longer recognizable as human.</span>", \
"<span class='shadowling'><b>You feel new power flow into you. You have been gifted by your masters. You now closely resemble them. You are empowered in \
darkness but wither slowly in light. In addition, Lesser Glare and Guise have been upgraded into their true forms.</b></span>")
hardset_dna(thrallToRevive, null, null, null, null, /datum/species/shadow/ling/lesser)
thrallToRevive.set_species(/datum/species/shadow/ling/lesser)
thrallToRevive.mind.remove_spell(/obj/effect/proc_holder/spell/targeted/lesser_glare)
thrallToRevive.mind.remove_spell(/obj/effect/proc_holder/spell/targeted/lesser_shadow_walk)
thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/glare(null))
@@ -606,10 +607,56 @@ datum/reagent/shadowling_blindness_smoke //Reagent used for above spell
return
/obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle
name = "Destroy Engines"
desc = "Extends the time of the emergency shuttle's arrival by ten to fifteen minutes."
panel = "Shadowling Abilities"
range = 1
clothes_req = 0
charge_max = 600
action_icon_state = "extend_shuttle"
/obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle/cast(list/targets, mob/living/carbon/human/U = usr)
if(!shadowling_check(usr))
charge_counter = charge_max
return
for(var/mob/living/carbon/human/target in targets)
if(target.stat)
charge_counter = charge_max
return
if(!is_thrall(target))
usr << "<span class='warning'>[target] must be a thrall.</span>"
charge_counter = charge_max
return
if(SSshuttle.emergency.mode != SHUTTLE_CALL)
usr << "<span class='warning'>The shuttle must be inbound only to the station.</span>"
charge_counter = charge_max
return
var/mob/living/carbon/human/M = target
U.visible_message("<span class='warning'>[U]'s eyes flash a bright red!</span>", \
"<span class='notice'>You begin to draw [M]'s life force.</span>")
M.visible_message("<span class='warning'>[M]'s face falls slack, their jaw slightly distending.</span>", \
"<span class='boldannounce'>You are suddenly transported... far, far away...</span>")
if(!do_after(U, 50, target = M))
M << "<span class='warning'>You are snapped back to reality, your haze dissipating!</span>"
U << "<span class='warning'>You have been interrupted. The draw has failed.</span>"
return
U << "<span class='notice'>You project [M]'s life force toward the approaching shuttle, extending its arrival duration!</span>"
M.visible_message("<span class='warning'>[M]'s eyes suddenly flare red. They proceed to collapse on the floor, not breathing.</span>", \
"<span class='warning'><b>...speeding by... ...pretty blue glow... ...touch it... ...no glow now... ...no light... ...nothing at all...</span>")
M.death()
if(SSshuttle.emergency.mode == SHUTTLE_CALL)
var/more_minutes = 9000
var/timer = SSshuttle.emergency.timeLeft()
timer += more_minutes
priority_announce("Major system failure aboard the emergency shuttle. This will extend its arrival time by approximately 15 minutes..", "System Failure", 'sound/misc/notice1.ogg')
SSshuttle.emergency.setTimer(timer)
// THRALL ABILITIES BEYOND THIS POINT //
/obj/effect/proc_holder/spell/targeted/lesser_glare //Thrall version of Glare - same effects but for 3 seconds
/obj/effect/proc_holder/spell/targeted/lesser_glare //Thrall version of Glare - same effects but for 5 seconds
name = "Lesser Glare"
desc = "Stuns and mutes a target for a short duration."
panel = "Thrall Abilities"
@@ -636,8 +683,8 @@ datum/reagent/shadowling_blindness_smoke //Reagent used for above spell
target << "<span class='userdanger'>Your gaze is forcibly drawn into [usr]'s eyes, and you are starstruck by the heavenly lights...</span>"
else //Only alludes to the shadowling if the target is close by
target << "<span class='userdanger'>Red lights suddenly dance in your vision, and you are starstruck by their heavenly beauty...</span>"
target.Stun(3) //Roughly 30% as long as the normal one
M.silent += 3
target.Stun(5) //Roughly 50% as long as the normal one
M.silent += 5
/obj/effect/proc_holder/spell/targeted/lesser_shadow_walk //Thrall version of Shadow Walk, only works in darkness, doesn't grant phasing, but gives near-invisibility
@@ -730,11 +777,11 @@ datum/reagent/shadowling_blindness_smoke //Reagent used for above spell
return
for(var/mob/living/boom in targets)
if(is_shadow_or_thrall(boom))
if(is_shadow(boom)) //Used to not work on thralls. Now it does so you can PUNISH THEM LIKE THE WRATHFUL GOD YOU ARE.
usr << "<span class='warning'>Making an ally explode seems unwise.<span>"
charge_counter = charge_max
return
usr.visible_message("<span class='danger'>[usr]'s markings flare as they gesture at [boom]!</span>", \
usr.visible_message("<span class='warning'>[usr]'s markings flare as they gesture at [boom]!</span>", \
"<span class='shadowling'>You direct a lance of telekinetic energy into [boom].</span>")
playMagSound()
sleep(4)
@@ -835,8 +882,7 @@ datum/reagent/shadowling_blindness_smoke //Reagent used for above spell
for(var/turf/T in targets)
for(var/mob/living/carbon/human/target in T.contents)
if(is_shadow_or_thrall(target))
if(target == usr) //No message for the user, of course
continue
continue
target << "<span class='userdanger'>You are struck by a bolt of lightning!</span>"
playsound(target, 'sound/magic/LightningShock.ogg', 50, 1)
target.Weaken(8)
@@ -84,7 +84,7 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/shadowling(H), slot_gloves)
H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/shadowling(H), slot_wear_mask)
H.equip_to_slot_or_del(new /obj/item/clothing/glasses/night/shadowling(H), slot_glasses)
hardset_dna(H, null, null, null, null, /datum/species/shadow/ling) //can't be a shadowling without being a shadowling
H.set_species(/datum/species/shadow/ling) //can't be a shadowling without being a shadowling
sleep(10)
H << "<span class='shadowling'><b><i>Your powers are awoken. You may now live to your fullest extent. Remember your goal. Cooperate with your thralls and allies.</b></i></span>"
@@ -95,6 +95,7 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/flashfreeze(null))
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/collective_mind(null))
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_regenarmor(null))
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle(null))
+18 -15
View File
@@ -22,9 +22,9 @@
/obj/item/weapon/veilrender/attack_self(mob/user)
if(charges > 0)
new /obj/effect/rend(get_turf(usr), spawn_type, spawn_amt, rend_desc, spawn_fast)
new /obj/effect/rend(get_turf(user), spawn_type, spawn_amt, rend_desc, spawn_fast)
charges--
user.visible_message("<span class='boldannounce'>[src] hums with power as [usr] deals a blow to [activate_descriptor] itself!</span>")
user.visible_message("<span class='boldannounce'>[src] hums with power as [user] deals a blow to [activate_descriptor] itself!</span>")
else
user << "<span class='danger'>The unearthly energies that powered the blade are now dormant.</span>"
@@ -59,7 +59,7 @@
/obj/effect/rend/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/nullrod))
user.visible_message("<span class='danger'>[usr] seals \the [src] with \the [I].</span>")
user.visible_message("<span class='danger'>[user] seals \the [src] with \the [I].</span>")
qdel(src)
return
..()
@@ -97,7 +97,7 @@
/obj/item/weapon/scrying/attack_self(mob/user)
user << "<span class='notice'>You can see...everything!</span>"
visible_message("<span class='danger'>[usr] stares into [src], their eyes glazing over.</span>")
visible_message("<span class='danger'>[user] stares into [src], their eyes glazing over.</span>")
user.ghostize(1)
return
@@ -118,7 +118,7 @@
unlimited = 1
/obj/item/device/necromantic_stone/attack(mob/living/carbon/human/M, mob/living/carbon/human/user)
if(!istype(M, /mob/living/carbon/human))
if(!istype(M))
return ..()
if(!istype(user) || !user.canUseTopic(M,1))
@@ -137,7 +137,7 @@
user << "<span class='warning'>This artifact can only affect three undead at a time!</span>"
return
hardset_dna(M, null, null, null, null, /datum/species/skeleton)
M.set_species(/datum/species/skeleton, icon_update=0)
M.revive()
spooky_scaries |= M
M << "<span class='userdanger'>You have been revived by </span><B>[user.real_name]!</B>"
@@ -261,13 +261,24 @@ var/global/list/multiverse = list()
/obj/item/weapon/multisword/proc/spawn_copy(var/client/C, var/turf/T)
var/mob/living/carbon/human/M = new/mob/living/carbon/human(T)
C.prefs.copy_to(M)
C.prefs.copy_to(M, icon_updates=0)
M.key = C.key
M.mind.name = usr.real_name
M << "<B>You are an alternate version of [usr.real_name] from another universe! Help them accomplish their goals at all costs.</B>"
M.real_name = usr.real_name
M.name = usr.real_name
M.faction = list("[usr.real_name]")
if(prob(50))
var/list/all_species = list()
for(var/speciestype in typesof(/datum/species) - /datum/species)
var/datum/species/S = new speciestype()
if(!S.dangerous_existence)
all_species += speciestype
M.set_species(pick(all_species), icon_update=0)
M.update_body()
M.update_hair()
M.update_mutcolor()
M.dna.update_dna_identity()
equip_copy(M)
if(evil)
@@ -440,14 +451,6 @@ var/global/list/multiverse = list()
else
return
ready_dna(M)
if(M.dna && prob(50))
var/list/all_species = list()
for(var/speciestype in typesof(/datum/species) - /datum/species)
var/datum/species/S = new speciestype()
if(!S.dangerous_existence)
all_species += speciestype
hardset_dna(M, null, null, null, null, pick(all_species))
M.update_icons()
M.update_augments()
+1 -1
View File
@@ -130,7 +130,7 @@
var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned.
G_found.client.prefs.copy_to(new_character)
ready_dna(new_character)
new_character.dna.update_dna_identity()
new_character.key = G_found.key
return new_character
+1 -1
View File
@@ -19,7 +19,7 @@
return 0
return 1
/datum/spellbook_entry/proc/Buy(mob/living/carbon/human/user,obj/item/weapon/spellbook/book) //return 1 on success
if(!S)
if(!S || qdeleted(S))
S = new spell_type()
//Check if we got the spell already
+2 -4
View File
@@ -50,14 +50,12 @@
return 0
//Equip the rest of the gear
if(H.dna)
H.dna.species.before_equip_job(src, H)
H.dna.species.before_equip_job(src, H)
if(outfit)
H.equipOutfit(outfit)
if(H.dna)
H.dna.species.after_equip_job(src, H)
H.dna.species.after_equip_job(src, H)
/datum/job/proc/apply_fingerprints(mob/living/carbon/human/H)
if(!istype(H))
+10 -2
View File
@@ -30,16 +30,17 @@
var/emped = 0 //Number of consecutive EMP's on this camera
/obj/machinery/camera/New()
..()
assembly = new(src)
assembly.state = 4
cameranet.cameras += src
cameranet.addCamera(src)
/* // Use this to look for cameras that have the same c_tag.
for(var/obj/machinery/camera/C in cameranet.cameras)
var/list/tempnetwork = C.network&src.network
if(C != src && C.c_tag == src.c_tag && tempnetwork.len)
world.log << "[src.c_tag] [src.x] [src.y] [src.z] conflicts with [C.c_tag] [C.x] [C.y] [C.z]"
*/
..()
/obj/machinery/camera/initialize()
if(z == 1 && prob(3) && !start_active)
@@ -56,6 +57,8 @@
bug.current = null
bug = null
cameranet.removeCamera(src) //Will handle removal from the camera network and the chunks, so we don't need to worry about that
cameranet.cameras -= src
cameranet.removeCamera(src)
return ..()
/obj/machinery/camera/emp_act(severity)
@@ -235,6 +238,11 @@
return
/obj/machinery/camera/proc/deactivate(mob/user, displaymessage = 1) //this should be called toggle() but doing a find and replace for this would be ass
if(can_use())
cameranet.addCamera(src)
else
SetLuminosity(0)
cameranet.removeCamera(src)
status = !status
cameranet.updateChunk(x, y, z)
var/change_msg = "deactivates"
+15 -15
View File
@@ -185,7 +185,7 @@
H.ckey = ckey
H << "<span class='notice'><b>Consciousness slowly creeps over you as your body regenerates.</b><br><i>So this is what cloning feels like?</i></span>"
hardset_dna(H, ui, se, null, null, mrace, features)
H.hardset_dna(ui, se, H.real_name, null, mrace, features)
H.faction |= factions
H.set_cloned_appearance()
@@ -301,13 +301,13 @@
return
/obj/machinery/clonepod/proc/go_out()
if (src.locked)
if (locked)
return
if (src.mess) //Clean that mess and dump those gibs!
src.mess = 0
gibs(src.loc)
src.icon_state = "pod_0"
if (mess) //Clean that mess and dump those gibs!
mess = 0
gibs(loc)
icon_state = "pod_0"
/*
for(var/obj/O in src)
@@ -315,22 +315,22 @@
*/
return
if (!(src.occupant))
if (!occupant)
return
/*
for(var/obj/O in src)
O.loc = src.loc
*/
if (src.occupant.client)
src.occupant.client.eye = src.occupant.client.mob
src.occupant.client.perspective = MOB_PERSPECTIVE
if (occupant.client)
occupant.client.eye = occupant.client.mob
occupant.client.perspective = MOB_PERSPECTIVE
if(occupant.loc == src)
src.occupant.loc = src.loc
src.icon_state = "pod_0"
src.eject_wait = 0 //If it's still set somehow.
domutcheck(src.occupant) //Waiting until they're out before possible monkeyizing.
src.occupant = null
occupant.loc = loc
icon_state = "pod_0"
eject_wait = 0 //If it's still set somehow.
occupant.domutcheck() //Waiting until they're out before possible monkeyizing.
occupant = null
return
/obj/machinery/clonepod/proc/malfunction()
+261 -221
View File
@@ -297,6 +297,7 @@
src.updateUsrDialog()
// *** THE ORION TRAIL ** //
#define ORION_TRAIL_WINTURN 9
@@ -313,6 +314,10 @@
#define ORION_TRAIL_SPACEPORT "Spaceport"
#define ORION_TRAIL_BLACKHOLE "BlackHole"
#define ORION_STATUS_START 1
#define ORION_STATUS_NORMAL 2
#define ORION_STATUS_GAMEOVER 3
#define ORION_STATUS_MARKET 4
/obj/machinery/computer/arcade/orion_trail
name = "The Orion Trail"
@@ -326,8 +331,6 @@
var/food = 80
var/fuel = 60
var/turns = 4
var/playing = 0
var/gameover = 0
var/alive = 4
var/eventdat = null
var/event = null
@@ -347,6 +350,8 @@
var/spaceport_raided = 0
var/spaceport_freebie = 0
var/last_spaceport_action = ""
var/gameStatus = ORION_STATUS_START
var/canContinueEvent = 0
/obj/machinery/computer/arcade/orion_trail/New()
..()
@@ -379,8 +384,7 @@
alive = 4
turns = 1
event = null
playing = 1
gameover = 0
gameStatus = ORION_STATUS_NORMAL
lings_aboard = 0
//spaceport junk
@@ -392,11 +396,11 @@
if(..())
return
if(fuel <= 0 || food <=0 || settlers.len == 0)
gameover = 1
gameStatus = ORION_STATUS_GAMEOVER
event = null
user.set_machine(src)
var/dat = ""
if(gameover)
if(gameStatus == ORION_STATUS_GAMEOVER)
dat = "<center><h1>Game Over</h1></center>"
dat += "Like many before you, your crew never made it to Orion, lost to space... <br><b>Forever</b>."
if(settlers.len == 0)
@@ -420,13 +424,13 @@
user << "<span class='userdanger'><font size=3>You're never going to make it to Orion...</span></font>"
user.death()
emagged = 0 //removes the emagged status after you lose
playing = 0 //also a new game
gameStatus = ORION_STATUS_START
name = "The Orion Trail"
desc = "Learn how our ancestors got to Orion, and have fun in the process!"
else if(event)
dat = eventdat
else if(playing)
else if(gameStatus == ORION_STATUS_NORMAL)
var/title = stops[turns]
var/subtext = stopblurbs[turns]
dat = "<center><h1>[title]</h1></center>"
@@ -453,8 +457,7 @@
return
/obj/machinery/computer/arcade/orion_trail/Topic(href, href_list)
. = ..()
if(.)
if(..())
return
if(href_list["close"])
usr.unset_machine()
@@ -465,247 +468,275 @@
busy = 1
if (href_list["continue"]) //Continue your travels
if(turns >= ORION_TRAIL_WINTURN)
win()
else
food -= (alive+lings_aboard)*2
fuel -= 5
if(turns == 2 && prob(30))
event = ORION_TRAIL_COLLISION
event()
else if(prob(75))
event = pickweight(events)
if(lings_aboard)
if(event == ORION_TRAIL_LING || prob(55))
event = ORION_TRAIL_LING_ATTACK
event()
turns += 1
if(emagged)
var/mob/living/carbon/M = usr //for some vars
switch(event)
if(ORION_TRAIL_RAIDERS)
if(prob(50))
usr << "<span class='userdanger'>You hear battle shouts. The tramping of boots on cold metal. Screams of agony. The rush of venting air. Are you going insane?</span>"
M.hallucination += 30
else
usr << "<span class='userdanger'>Something strikes you from behind! It hurts like hell and feel like a blunt weapon, but nothing is there...</span>"
M.take_organ_damage(30)
playsound(loc, 'sound/weapons/genhit2.ogg', 100, 1)
if(ORION_TRAIL_ILLNESS)
var/severity = rand(1,3) //pray to RNGesus. PRAY, PIGS
if(severity == 1)
M << "<span class='userdanger'>You suddenly feel slightly nauseous.</span>" //got off lucky
if(severity == 2)
usr << "<span class='userdanger'>You suddenly feel extremely nauseous and hunch over until it passes.</span>"
M.Stun(3)
if(severity >= 3) //you didn't pray hard enough
M << "<span class='warning'>An overpowering wave of nausea consumes over you. You hunch over, your stomach's contents preparing for a spectacular exit.</span>"
M.Stun(5)
sleep(30)
say("[M] violently throws up!")
playsound(loc, 'sound/effects/splat.ogg', 50, 1)
M.nutrition -= 50 //lose a lot of food
var/turf/location = usr.loc
if(istype(location, /turf/simulated))
location.add_vomit_floor(src, 1)
if(ORION_TRAIL_FLUX)
if(prob(75))
M.Weaken(3)
say("A sudden gust of powerful wind slams [M] into the floor!")
M.take_organ_damage(25)
playsound(src.loc, 'sound/weapons/Genhit.ogg', 100, 1)
else
M << "<span class='userdanger'>A violent gale blows past you, and you barely manage to stay standing!</span>"
if(ORION_TRAIL_COLLISION) //by far the most damaging event
if(prob(90))
playsound(src.loc, 'sound/effects/bang.ogg', 100, 1)
var/turf/simulated/floor/F
for(F in orange(1, src))
F.ChangeTurf(F.baseturf)
say("Something slams into the floor around [src], exposing it to space!")
if(hull)
sleep(10)
say("A new floor suddenly appears around [src]. What the hell?")
if(gameStatus == ORION_STATUS_NORMAL && !event && turns != 7)
if(turns >= ORION_TRAIL_WINTURN)
win()
else
food -= (alive+lings_aboard)*2
fuel -= 5
if(turns == 2 && prob(30))
event = ORION_TRAIL_COLLISION
event()
else if(prob(75))
event = pickweight(events)
if(lings_aboard)
if(event == ORION_TRAIL_LING || prob(55))
event = ORION_TRAIL_LING_ATTACK
event()
turns += 1
if(emagged)
var/mob/living/carbon/M = usr //for some vars
switch(event)
if(ORION_TRAIL_RAIDERS)
if(prob(50))
usr << "<span class='userdanger'>You hear battle shouts. The tramping of boots on cold metal. Screams of agony. The rush of venting air. Are you going insane?</span>"
M.hallucination += 30
else
usr << "<span class='userdanger'>Something strikes you from behind! It hurts like hell and feel like a blunt weapon, but nothing is there...</span>"
M.take_organ_damage(30)
playsound(loc, 'sound/weapons/genhit2.ogg', 100, 1)
if(ORION_TRAIL_ILLNESS)
var/severity = rand(1,3) //pray to RNGesus. PRAY, PIGS
if(severity == 1)
M << "<span class='userdanger'>You suddenly feel slightly nauseous.</span>" //got off lucky
if(severity == 2)
usr << "<span class='userdanger'>You suddenly feel extremely nauseous and hunch over until it passes.</span>"
M.Stun(3)
if(severity >= 3) //you didn't pray hard enough
M << "<span class='warning'>An overpowering wave of nausea consumes over you. You hunch over, your stomach's contents preparing for a spectacular exit.</span>"
M.Stun(5)
sleep(30)
say("[M] violently throws up!")
playsound(loc, 'sound/effects/splat.ogg', 50, 1)
M.nutrition -= 50 //lose a lot of food
var/turf/location = usr.loc
if(istype(location, /turf/simulated))
location.add_vomit_floor(src, 1)
if(ORION_TRAIL_FLUX)
if(prob(75))
M.Weaken(3)
say("A sudden gust of powerful wind slams [M] into the floor!")
M.take_organ_damage(25)
playsound(src.loc, 'sound/weapons/Genhit.ogg', 100, 1)
var/turf/space/T
for(T in orange(1, src))
T.ChangeTurf(/turf/simulated/floor/plating/)
else
say("Something slams into the floor around [src] - luckily, it didn't get through!")
playsound(src.loc, 'sound/effects/bang.ogg', 50, 1)
if(ORION_TRAIL_MALFUNCTION)
playsound(src.loc, 'sound/effects/EMPulse.ogg', 50, 1)
src.visible_message("<span class='danger'>[src] malfunctions, randomizing in-game stats!</span>")
var/oldfood = food
var/oldfuel = fuel
food = rand(10,80) / rand(1,2)
fuel = rand(10,60) / rand(1,2)
if(electronics)
sleep(10)
if(oldfuel > fuel && oldfood > food)
src.audible_message("<span class='danger'>[src] lets out a somehow reassuring chime.</span>")
else if(oldfuel < fuel || oldfood < food)
src.audible_message("<span class='danger'>[src] lets out a somehow ominous chime.</span>")
food = oldfood
fuel = oldfuel
playsound(src.loc, 'sound/machines/chime.ogg', 50, 1)
else
M << "<span class='userdanger'>A violent gale blows past you, and you barely manage to stay standing!</span>"
if(ORION_TRAIL_COLLISION) //by far the most damaging event
if(prob(90))
playsound(src.loc, 'sound/effects/bang.ogg', 100, 1)
var/turf/simulated/floor/F
for(F in orange(1, src))
F.ChangeTurf(F.baseturf)
say("Something slams into the floor around [src], exposing it to space!")
if(hull)
sleep(10)
say("A new floor suddenly appears around [src]. What the hell?")
playsound(src.loc, 'sound/weapons/Genhit.ogg', 100, 1)
var/turf/space/T
for(T in orange(1, src))
T.ChangeTurf(/turf/simulated/floor/plating/)
else
say("Something slams into the floor around [src] - luckily, it didn't get through!")
playsound(src.loc, 'sound/effects/bang.ogg', 50, 1)
if(ORION_TRAIL_MALFUNCTION)
playsound(src.loc, 'sound/effects/EMPulse.ogg', 50, 1)
src.visible_message("<span class='danger'>[src] malfunctions, randomizing in-game stats!</span>")
var/oldfood = food
var/oldfuel = fuel
food = rand(10,80) / rand(1,2)
fuel = rand(10,60) / rand(1,2)
if(electronics)
sleep(10)
if(oldfuel > fuel && oldfood > food)
src.audible_message("<span class='danger'>[src] lets out a somehow reassuring chime.</span>")
else if(oldfuel < fuel || oldfood < food)
src.audible_message("<span class='danger'>[src] lets out a somehow ominous chime.</span>")
food = oldfood
fuel = oldfuel
playsound(src.loc, 'sound/machines/chime.ogg', 50, 1)
else if(href_list["newgame"]) //Reset everything
newgame()
if(gameStatus == ORION_STATUS_START)
newgame()
else if(href_list["menu"]) //back to the main menu
playing = 0
event = null
gameover = 0
food = 80
fuel = 60
settlers = list("Harry","Larry","Bob")
if(gameStatus == ORION_STATUS_GAMEOVER)
gameStatus = ORION_STATUS_START
event = null
food = 80
fuel = 60
settlers = list("Harry","Larry","Bob")
else if(href_list["slow"]) //slow down
food -= (alive+lings_aboard)*2
fuel -= 5
if(event == ORION_TRAIL_FLUX)
food -= (alive+lings_aboard)*2
fuel -= 5
event = null
else if(href_list["pastblack"]) //slow down
food -= ((alive+lings_aboard)*2)*3
fuel -= 15
turns += 1
event = null
else if(href_list["useengine"]) //use parts
engine = max(0, --engine)
event = null
else if(href_list["useelec"]) //use parts
electronics = max(0, --electronics)
event = null
else if(href_list["usehull"]) //use parts
hull = max(0, --hull)
event = null
else if(href_list["wait"]) //wait 3 days
food -= ((alive+lings_aboard)*2)*3
event = null
else if(href_list["keepspeed"]) //keep speed
if(prob(75))
event = "Breakdown"
event()
else
event = null
else if(href_list["blackhole"]) //keep speed past a black hole
if(prob(75))
event = ORION_TRAIL_BLACKHOLE
event()
if(emagged) //has to be here because otherwise it doesn't work
playsound(src.loc, 'sound/effects/supermatter.ogg', 100, 1)
say("A miniature black hole suddenly appears in front of [src], devouring [usr] alive!")
usr.Stun(10) //you can't run :^)
var/S = new /obj/singularity/academy(usr.loc)
emagged = 0 //immediately removes emagged status so people can't kill themselves by sprinting up and interacting
sleep(50)
say("[S] winks out, just as suddenly as it appeared.")
qdel(S)
else
event = null
if(turns == 7)
food -= ((alive+lings_aboard)*2)*3
fuel -= 15
turns += 1
event = null
else if(href_list["useengine"]) //use parts
if(event == ORION_TRAIL_BREAKDOWN)
engine = max(0, --engine)
event = null
else if(href_list["useelec"]) //use parts
if(event == ORION_TRAIL_MALFUNCTION)
electronics = max(0, --electronics)
event = null
else if(href_list["usehull"]) //use parts
if(event == ORION_TRAIL_COLLISION)
hull = max(0, --hull)
event = null
else if(href_list["wait"]) //wait 3 days
if(event == ORION_TRAIL_BREAKDOWN || event == ORION_TRAIL_MALFUNCTION || event == ORION_TRAIL_COLLISION)
food -= ((alive+lings_aboard)*2)*3
event = null
else if(href_list["keepspeed"]) //keep speed
if(event == ORION_TRAIL_FLUX)
if(prob(75))
event = "Breakdown"
event()
else
event = null
else if(href_list["blackhole"]) //keep speed past a black hole
if(turns == 7)
if(prob(75))
event = ORION_TRAIL_BLACKHOLE
event()
if(emagged) //has to be here because otherwise it doesn't work
playsound(src.loc, 'sound/effects/supermatter.ogg', 100, 1)
say("A miniature black hole suddenly appears in front of [src], devouring [usr] alive!")
usr.Stun(10) //you can't run :^)
var/S = new /obj/singularity/academy(usr.loc)
emagged = 0 //immediately removes emagged status so people can't kill themselves by sprinting up and interacting
sleep(50)
say("[S] winks out, just as suddenly as it appeared.")
qdel(S)
else
event = null
turns += 1
else if(href_list["holedeath"])
gameover = 1
event = null
if(event == ORION_TRAIL_BLACKHOLE)
gameStatus = ORION_STATUS_GAMEOVER
event = null
else if(href_list["eventclose"]) //end an event
event = null
if(canContinueEvent)
event = null
else if(href_list["killcrew"]) //shoot a crewmember
var/sheriff = remove_crewmember() //I shot the sheriff
playsound(loc,'sound/weapons/Gunshot.ogg', 100, 1)
if(gameStatus == ORION_STATUS_NORMAL || event == ORION_TRAIL_LING)
var/sheriff = remove_crewmember() //I shot the sheriff
playsound(loc,'sound/weapons/Gunshot.ogg', 100, 1)
if(settlers.len == 0 || alive == 0)
say("The last crewmember [sheriff], shot themselves, GAME OVER!")
if(emagged)
usr.death(0)
emagged = 0
gameover = 1
event = null
else if(emagged)
if(usr.name == sheriff)
say("The crew of the ship chose to kill [usr.name]!")
usr.death(0)
if(settlers.len == 0 || alive == 0)
say("The last crewmember [sheriff], shot themselves, GAME OVER!")
if(emagged)
usr.death(0)
emagged = 0
gameStatus = ORION_STATUS_GAMEOVER
event = null
else if(emagged)
if(usr.name == sheriff)
say("The crew of the ship chose to kill [usr.name]!")
usr.death(0)
if(event == ORION_TRAIL_LING) //only ends the ORION_TRAIL_LING event, since you can do this action in multiple places
event = null
if(event == ORION_TRAIL_LING) //only ends the ORION_TRAIL_LING event, since you can do this action in multiple places
event = null
//Spaceport specific interactions
//they get a header because most of them don't reset event (because it's a shop, you leave when you want to)
//they also call event() again, to regen the eventdata, which is kind of odd but necessary
else if(href_list["buycrew"]) //buy a crewmember
var/bought = add_crewmember()
last_spaceport_action = "You hired [bought] as a new crewmember."
fuel -= 10
food -= 10
event()
if(gameStatus == ORION_STATUS_MARKET)
if(!spaceport_raided && food >= 10 && fuel >= 10)
var/bought = add_crewmember()
last_spaceport_action = "You hired [bought] as a new crewmember."
fuel -= 10
food -= 10
event()
else if(href_list["sellcrew"]) //sell a crewmember
var/sold = remove_crewmember()
last_spaceport_action = "You sold your crewmember, [sold]!"
fuel += 7
food += 7
event()
if(gameStatus == ORION_STATUS_MARKET)
if(!spaceport_raided && settlers.len > 1)
var/sold = remove_crewmember()
last_spaceport_action = "You sold your crewmember, [sold]!"
fuel += 7
food += 7
event()
else if(href_list["leave_spaceport"])
event = null
spaceport_raided = 0
spaceport_freebie = 0
last_spaceport_action = ""
if(gameStatus == ORION_STATUS_MARKET)
event = null
gameStatus = ORION_STATUS_NORMAL
spaceport_raided = 0
spaceport_freebie = 0
last_spaceport_action = ""
else if(href_list["raid_spaceport"])
var/success = min(15 * alive,100) //default crew (4) have a 60% chance
spaceport_raided = 1
if(gameStatus == ORION_STATUS_MARKET)
if(!spaceport_raided)
var/success = min(15 * alive,100) //default crew (4) have a 60% chance
spaceport_raided = 1
var/FU = 0
var/FO = 0
if(prob(success))
FU = rand(5,15)
FO = rand(5,15)
last_spaceport_action = "You successfully raided the spaceport! you gained [FU] Fuel and [FO] Food! (+[FU]FU,+[FO]FO)"
else
FU = rand(-5,-15)
FO = rand(-5,-15)
last_spaceport_action = "You failed to raid the spaceport! you lost [FU*-1] Fuel and [FO*-1] Food in your scramble to escape! ([FU]FU,[FO]FO)"
var/FU = 0
var/FO = 0
if(prob(success))
FU = rand(5,15)
FO = rand(5,15)
last_spaceport_action = "You successfully raided the spaceport! you gained [FU] Fuel and [FO] Food! (+[FU]FU,+[FO]FO)"
else
FU = rand(-5,-15)
FO = rand(-5,-15)
last_spaceport_action = "You failed to raid the spaceport! you lost [FU*-1] Fuel and [FO*-1] Food in your scramble to escape! ([FU]FU,[FO]FO)"
//your chance of lose a crewmember is 1/2 your chance of success
//this makes higher % failures hurt more, don't get cocky space cowboy!
if(prob(success*5))
var/lost_crew = remove_crewmember()
last_spaceport_action = "You failed to raid the spaceport! you lost [FU*-1] Fuel and [FO*-1] Food, AND [lost_crew] in your scramble to escape! ([FU]FI,[FO]FO,-Crew)"
if(emagged)
say("WEEWOO WEEWOO, Spaceport Security en route!")
for(var/i, i<=3, i++)
var/mob/living/simple_animal/hostile/syndicate/ranged/orion/O = new/mob/living/simple_animal/hostile/syndicate/ranged/orion(get_turf(src))
O.target = usr
//your chance of lose a crewmember is 1/2 your chance of success
//this makes higher % failures hurt more, don't get cocky space cowboy!
if(prob(success*5))
var/lost_crew = remove_crewmember()
last_spaceport_action = "You failed to raid the spaceport! you lost [FU*-1] Fuel and [FO*-1] Food, AND [lost_crew] in your scramble to escape! ([FU]FI,[FO]FO,-Crew)"
if(emagged)
say("WEEWOO WEEWOO, Spaceport Security en route!")
for(var/i, i<=3, i++)
var/mob/living/simple_animal/hostile/syndicate/ranged/orion/O = new/mob/living/simple_animal/hostile/syndicate/ranged/orion(get_turf(src))
O.target = usr
fuel += FU
food += FO
event()
fuel += FU
food += FO
event()
else if(href_list["buyparts"])
switch(text2num(href_list["buyparts"]))
if(1) //Engine Parts
engine++
last_spaceport_action = "Bought Engine Parts"
if(2) //Hull Plates
hull++
last_spaceport_action = "Bought Hull Plates"
if(3) //Spare Electronics
electronics++
last_spaceport_action = "Bought Spare Electronics"
fuel -= 5 //they all cost 5
event()
if(gameStatus == ORION_STATUS_MARKET)
if(!spaceport_raided && fuel > 5)
switch(text2num(href_list["buyparts"]))
if(1) //Engine Parts
engine++
last_spaceport_action = "Bought Engine Parts"
if(2) //Hull Plates
hull++
last_spaceport_action = "Bought Hull Plates"
if(3) //Spare Electronics
electronics++
last_spaceport_action = "Bought Spare Electronics"
fuel -= 5 //they all cost 5
event()
else if(href_list["trade"])
switch(text2num(href_list["trade"]))
if(1) //Fuel
fuel -= 5
food += 5
last_spaceport_action = "Traded Fuel for Food"
if(2) //Food
fuel += 5
food -= 5
last_spaceport_action = "Traded Food for Fuel"
event()
if(gameStatus == ORION_STATUS_MARKET)
if(!spaceport_raided)
switch(text2num(href_list["trade"]))
if(1) //Fuel
if(fuel > 5)
fuel -= 5
food += 5
last_spaceport_action = "Traded Fuel for Food"
event()
if(2) //Food
if(food > 5)
fuel += 5
food -= 5
last_spaceport_action = "Traded Food for Fuel"
event()
src.add_fingerprint(usr)
src.updateUsrDialog()
@@ -715,7 +746,7 @@
/obj/machinery/computer/arcade/orion_trail/proc/event()
eventdat = "<center><h1>[event]</h1></center>"
canContinueEvent = 0
switch(event)
if(ORION_TRAIL_RAIDERS)
eventdat += "Raiders have come aboard your ship!"
@@ -732,6 +763,7 @@
eventdat += "<br>Fortunately you fended them off without any trouble."
eventdat += "<P ALIGN=Right><a href='byond://?src=\ref[src];eventclose=1'>Continue</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=\ref[src];close=1'>Close</a></P>"
canContinueEvent = 1
if(ORION_TRAIL_FLUX)
eventdat += "This region of space is highly turbulent. <br>If we go slowly we may avoid more damage, but if we keep our speed we won't waste supplies."
@@ -745,6 +777,7 @@
eventdat += "<br>[deadname] was killed by the disease."
eventdat += "<P ALIGN=Right><a href='byond://?src=\ref[src];eventclose=1'>Continue</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=\ref[src];close=1'>Close</a></P>"
canContinueEvent = 1
if(ORION_TRAIL_BREAKDOWN)
eventdat += "Oh no! The engine has broken down!"
@@ -806,6 +839,7 @@
eventdat += "<P ALIGN=Right><a href='byond://?src=\ref[src];killcrew=1'>Kill a crewmember</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=\ref[src];eventclose=1'>Risk it</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=\ref[src];close=1'>Close</a></P>"
canContinueEvent = 1
if(ORION_TRAIL_LING_ATTACK)
if(lings_aboard <= 0) //shouldn't trigger, but hey.
@@ -847,9 +881,11 @@
eventdat += "<P ALIGN=Right><a href='byond://?src=\ref[src];eventclose=1'>Continue</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=\ref[src];close=1'>Close</a></P>"
canContinueEvent = 1
if(ORION_TRAIL_SPACEPORT)
gameStatus = ORION_STATUS_MARKET
if(spaceport_raided)
eventdat += "The Spaceport is on high alert! they wont let you dock since you tried to attack them!"
if(last_spaceport_action)
@@ -978,8 +1014,7 @@
/obj/machinery/computer/arcade/orion_trail/proc/win()
playing = 0
turns = 1
gameStatus = ORION_STATUS_START
say("Congratulations, you made it to Orion!")
if(emagged)
new /obj/item/weapon/orion_ship(src.loc)
@@ -1071,3 +1106,8 @@
#undef ORION_TRAIL_COLLISION
#undef ORION_TRAIL_SPACEPORT
#undef ORION_TRAIL_BLACKHOLE
#undef ORION_STATUS_START
#undef ORION_STATUS_NORMAL
#undef ORION_STATUS_GAMEOVER
#undef ORION_STATUS_MARKET
@@ -38,7 +38,7 @@
GrantActions(user)
current_user = user
eyeobj.user = user
eyeobj.name = "Camere Eye ([user.name])"
eyeobj.name = "Camera Eye ([user.name])"
L.remote_view = 1
L.remote_control = eyeobj
L.client.perspective = EYE_PERSPECTIVE
+1 -1
View File
@@ -350,7 +350,7 @@
return
/obj/machinery/computer/cloning/proc/scan_mob(mob/living/carbon/human/subject)
if (!check_dna_integrity(subject) || !istype(subject))
if (!istype(subject))
scantemp = "<font class='bad'>Unable to locate valid genetic data.</font>"
return
if (!subject.getorgan(/obj/item/organ/internal/brain))
+482
View File
@@ -0,0 +1,482 @@
#define INJECTOR_TIMEOUT 300
#define REJUVENATORS_INJECT 15
#define REJUVENATORS_MAX 90
#define NUMBER_OF_BUFFERS 3
#define RADIATION_STRENGTH_MAX 15
#define RADIATION_STRENGTH_MULTIPLIER 1 //larger has a more range
#define RADIATION_DURATION_MAX 30
#define RADIATION_ACCURACY_MULTIPLIER 3 //larger is less accurate
#define RADIATION_IRRADIATION_MULTIPLIER 0.2 //multiplier for how much radiation a test subject recieves
/obj/machinery/computer/scan_consolenew
name = "\improper DNA scanner access console"
desc = "Scan DNA."
icon_screen = "dna"
icon_keyboard = "med_key"
density = 1
circuit = /obj/item/weapon/circuitboard/scan_consolenew
var/radduration = 2
var/radstrength = 1
var/list/buffer[NUMBER_OF_BUFFERS]
var/injectorready = 0 //Quick fix for issue 286 (screwdriver the screen twice to restore injector) -Pete
var/current_screen = "mainmenu"
var/obj/machinery/dna_scannernew/connected = null
var/obj/item/weapon/disk/data/diskette = null
anchored = 1
use_power = 1
idle_power_usage = 10
active_power_usage = 400
/obj/machinery/computer/scan_consolenew/attackby(obj/item/I, mob/user, params)
if (istype(I, /obj/item/weapon/disk/data)) //INSERT SOME DISKETTES
if (!src.diskette)
if(!user.drop_item())
return
I.loc = src
src.diskette = I
user << "<span class='notice'>You insert [I].</span>"
src.updateUsrDialog()
return
else
..()
return
/obj/machinery/computer/scan_consolenew/New()
..()
spawn(5)
for(dir in list(NORTH,EAST,SOUTH,WEST))
connected = locate(/obj/machinery/dna_scannernew, get_step(src, dir))
if(!isnull(connected))
break
spawn(250)
injectorready = 1
return
return
/obj/machinery/computer/scan_consolenew/attack_hand(mob/user)
if(..())
return
ShowInterface(user)
/obj/machinery/computer/scan_consolenew/proc/ShowInterface(mob/user, last_change)
if(!user) return
var/datum/browser/popup = new(user, "scannernew", "DNA Modifier Console", 800, 630) // Set up the popup browser window
if(!( in_range(src, user) || istype(user, /mob/living/silicon) ))
popup.close()
return
popup.add_stylesheet("scannernew", 'html/browser/scannernew.css')
var/mob/living/carbon/viable_occupant
var/occupant_status = "<div class='line'><div class='statusLabel'>Subject Status:</div><div class='statusValue'>"
var/scanner_status
var/temp_html
if(connected && connected.is_operational())
if(connected.occupant) //set occupant_status message
viable_occupant = connected.occupant
if(viable_occupant.has_dna() && (!(viable_occupant.disabilities & NOCLONE) || (connected.scan_level == 3))) //occupent is viable for dna modification
occupant_status += "[viable_occupant.name] => "
switch(viable_occupant.stat)
if(CONSCIOUS) occupant_status += "<span class='good'>Conscious</span>"
if(UNCONSCIOUS) occupant_status += "<span class='average'>Unconscious</span>"
else occupant_status += "<span class='bad'>DEAD - Cannot Operate</span>"
occupant_status += "</div></div>"
occupant_status += "<div class='line'><div class='statusLabel'>Health:</div><div class='progressBar'><div style='width: [viable_occupant.health]%;' class='progressFill good'></div></div><div class='statusValue'>[viable_occupant.health] %</div></div>"
occupant_status += "<div class='line'><div class='statusLabel'>Radiation Level:</div><div class='progressBar'><div style='width: [viable_occupant.radiation]%;' class='progressFill bad'></div></div><div class='statusValue'>[viable_occupant.radiation] %</div></div>"
var/rejuvenators = viable_occupant.reagents.get_reagent_amount("epinephrine")
occupant_status += "<div class='line'><div class='statusLabel'>Rejuvenators:</div><div class='progressBar'><div style='width: [round((rejuvenators / REJUVENATORS_MAX) * 100)]%;' class='progressFill highlight'></div></div><div class='statusValue'>[rejuvenators] units</div></div>"
occupant_status += "<div class='line'><div class='statusLabel'>Unique Enzymes :</div><div class='statusValue'><span class='highlight'>[viable_occupant.dna.unique_enzymes]</span></div></div>"
occupant_status += "<div class='line'><div class='statusLabel'>Last Operation:</div><div class='statusValue'>[last_change ? last_change : "----"]</div></div>"
else
viable_occupant = null
occupant_status += "<span class='bad'>Invalid DNA structure</span></div></div>"
if (viable_occupant && viable_occupant.stat == DEAD)
viable_occupant = null // No editing the dead.
else
occupant_status += "<span class='bad'>No subject detected</span></div></div>"
if(connected.state_open)
scanner_status = "Open"
else
scanner_status = "Closed"
if(connected.locked)
scanner_status += " <span class='bad'>(Locked)</span>"
else
scanner_status += " <span class='good'>(Unlocked)</span>"
else
occupant_status += "<span class='bad'>----</span></div></div>"
scanner_status += "<span class='bad'>Error: No scanner detected</span>"
var/status = "<div class='statusDisplay'>"
status += "<div class='line'><div class='statusLabel'>Scanner:</div><div class='statusValue'>[scanner_status]</div></div>"
status += "[occupant_status]"
status += "<div class='line'><h3>Radiation Emitter Status</h3></div>"
var/stddev = radstrength*RADIATION_STRENGTH_MULTIPLIER
status += "<div class='line'><div class='statusLabel'>Output Level:</div><div class='statusValue'>[radstrength]</div></div>"
status += "<div class='line'><div class='statusLabel'>&nbsp;&nbsp;\> Mutation:</div><div class='statusValue'>(-[stddev] to +[stddev] = 68 %) (-[2*stddev] to +[2*stddev] = 95 %)</div></div>"
if(connected)
stddev = RADIATION_ACCURACY_MULTIPLIER/(radduration + (connected.precision_coeff ** 2))
else
stddev = RADIATION_ACCURACY_MULTIPLIER/radduration
var/chance_to_hit
switch(stddev) //hardcoded values from a z-table for a normal distribution
if(0 to 0.25) chance_to_hit = ">95 %"
if(0.25 to 0.5) chance_to_hit = "68-95 %"
if(0.5 to 0.75) chance_to_hit = "55-68 %"
else chance_to_hit = "<38 %"
status += "<div class='line'><div class='statusLabel'>Pulse Duration:</div><div class='statusValue'>[radduration]</div></div>"
status += "<div class='line'><div class='statusLabel'>&nbsp;&nbsp;\> Accuracy:</div><div class='statusValue'>[chance_to_hit]</div></div>"
status += "<br></div>" // Close statusDisplay div
var/buttons = "<a href='?src=\ref[src];'>Scan</a> "
if(connected)
buttons += " <a href='?src=\ref[src];task=toggleopen;'>[connected.state_open ? "Close" : "Open"] Scanner</a> "
if (connected.state_open)
buttons += "<span class='linkOff'>[connected.locked ? "Unlock" : "Lock"] Scanner</span> "
else
buttons += "<a href='?src=\ref[src];task=togglelock;'>[connected.locked ? "Unlock" : "Lock"] Scanner</a> "
else buttons += "<span class='linkOff'>Open Scanner</span> <span class='linkOff'>Lock Scanner</span> "
if(viable_occupant) buttons += "<a href='?src=\ref[src];task=rejuv'>Inject Rejuvenators</a> "
else buttons += "<span class='linkOff'>Inject Rejuvenators</span> "
if(diskette) buttons += "<a href='?src=\ref[src];task=ejectdisk'>Eject Disk</a> "
else buttons += "<span class='linkOff'>Eject Disk</span> "
if(current_screen == "buffer") buttons += "<a href='?src=\ref[src];task=screen;text=mainmenu;'>Radiation Emitter Menu</a> "
else buttons += "<a href='?src=\ref[src];task=screen;text=buffer;'>Buffer Menu</a> "
switch(current_screen)
if("working")
temp_html += status
temp_html += "<h1>System Busy</h1>"
temp_html += "Working ... Please wait ([radduration] Seconds)"
if("buffer")
temp_html += status
temp_html += buttons
temp_html += "<h1>Buffer Menu</h1>"
if(istype(buffer))
for(var/i=1, i<=buffer.len, i++)
temp_html += "<br>Slot [i]: "
var/list/buffer_slot = buffer[i]
if( !buffer_slot || !buffer_slot.len || !buffer_slot["name"] || !((buffer_slot["UI"] && buffer_slot["UE"]) || buffer_slot["SE"]) )
temp_html += "<br>\tNo Data"
if(viable_occupant) temp_html += "<br><a href='?src=\ref[src];task=setbuffer;num=[i];'>Save to Buffer</a> "
else temp_html += "<br><span class='linkOff'>Save to Buffer</span> "
temp_html += "<span class='linkOff'>Clear Buffer</span> "
if(diskette) temp_html += "<a href='?src=\ref[src];task=loaddisk;num=[i];'>Load from Disk</a> "
else temp_html += "<span class='linkOff'>Load from Disk</span> "
temp_html += "<span class='linkOff'>Save to Disk</span> "
else
var/ui = buffer_slot["UI"]
var/se = buffer_slot["SE"]
var/ue = buffer_slot["UE"]
var/name = buffer_slot["name"]
var/label = buffer_slot["label"]
var/blood_type = buffer_slot["blood_type"]
temp_html += "<br>\t<a href='?src=\ref[src];task=setbufferlabel;num=[i];'>Label</a>: [label ? label : name]"
temp_html += "<br>\tSubject: [name]"
if(ue && name && blood_type)
temp_html += "<br>\tBlood Type: [blood_type]"
temp_html += "<br>\tUE: [ue] "
if(viable_occupant) temp_html += "<a href='?src=\ref[src];task=transferbuffer;num=[i];text=ue'>Occupant</a> "
else temp_html += "<span class='linkOff'>Occupant</span>"
if(injectorready) temp_html += "<a href='?src=\ref[src];task=injector;num=[i];text=ue'>Injector</a>"
else temp_html += "<span class='linkOff'>Injector</span>"
else
temp_html += "<br>\tBlood Type: No Data"
temp_html += "<br>\tUE: No Data"
if(ui)
temp_html += "<br>\tUI: [ui] "
if(viable_occupant) temp_html += "<a href='?src=\ref[src];task=transferbuffer;num=[i];text=ui'>Occupant</a> "
else temp_html += "<span class='linkOff'>Occupant</span>"
if(injectorready) temp_html += "<a href='?src=\ref[src];task=injector;num=[i];text=ui'>Injector</a>"
else temp_html += "<span class='linkOff'>Injector</span>"
else
temp_html += "<br>\tUI: No Data"
if(se)
temp_html += "<br>\tSE: [se] "
if(viable_occupant && viable_occupant.stat != DEAD) temp_html += "<a href='?src=\ref[src];task=transferbuffer;num=[i];text=se'>Occupant</a> "
else temp_html += "<span class='linkOff'>Occupant</span> "
if(injectorready) temp_html += "<a href='?src=\ref[src];task=injector;num=[i];text=se'>Injector</a>"
else temp_html += "<span class='linkOff'>Injector</span>"
else
temp_html += "<br>\tSE: No Data"
if(viable_occupant) temp_html += "<br><a href='?src=\ref[src];task=setbuffer;num=[i];'>Save to Buffer</a> "
else temp_html += "<br><span class='linkOff'>Save to Buffer</span> "
temp_html += "<a href='?src=\ref[src];task=clearbuffer;num=[i];'>Clear Buffer</a> "
if(diskette) temp_html += "<a href='?src=\ref[src];task=loaddisk;num=[i];'>Load from Disk</a> "
else temp_html += "<span class='linkOff'>Load from Disk</span> "
if(diskette && !diskette.read_only) temp_html += "<a href='?src=\ref[src];task=savedisk;num=[i];'>Save to Disk</a> "
else temp_html += "<span class='linkOff'>Save to Disk</span> "
else
temp_html += status
temp_html += buttons
temp_html += "<h1>Radiation Emitter Menu</h1>"
temp_html += "<a href='?src=\ref[src];task=setstrength;num=[radstrength-1];'>--</a> <a href='?src=\ref[src];task=setstrength;'>Output Level</a> <a href='?src=\ref[src];task=setstrength;num=[radstrength+1];'>++</a>"
temp_html += "<br><a href='?src=\ref[src];task=setduration;num=[radduration-1];'>--</a> <a href='?src=\ref[src];task=setduration;'>Pulse Duration</a> <a href='?src=\ref[src];task=setduration;num=[radduration+1];'>++</a>"
temp_html += "<h3>Irradiate Subject</h3>"
temp_html += "<div class='line'><div class='statusLabel'>Unique Identifier:</div><div class='statusValue'><div class='clearBoth'>"
var/max_line_len = 7*DNA_BLOCK_SIZE
if(viable_occupant)
temp_html += "<div class='dnaBlockNumber'>1</div>"
var/len = length(viable_occupant.dna.uni_identity)
for(var/i=1, i<=len, i++)
temp_html += "<a class='dnaBlock' href='?src=\ref[src];task=pulseui;num=[i];'>[copytext(viable_occupant.dna.uni_identity,i,i+1)]</a>"
if ((i % max_line_len) == 0)
temp_html += "</div><div class='clearBoth'>"
if((i % DNA_BLOCK_SIZE) == 0 && i < len)
temp_html += "<div class='dnaBlockNumber'>[(i / DNA_BLOCK_SIZE) + 1]</div>"
else
temp_html += "----"
temp_html += "</div></div></div><br>"
temp_html += "<br><div class='line'><div class='statusLabel'>Structural Enzymes:</div><div class='statusValue'><div class='clearBoth'>"
if(viable_occupant)
temp_html += "<div class='dnaBlockNumber'>1</div>"
var/len = length(viable_occupant.dna.struc_enzymes)
for(var/i=1, i<=len, i++)
temp_html += "<a class='dnaBlock' href='?src=\ref[src];task=pulsese;num=[i];'>[copytext(viable_occupant.dna.struc_enzymes,i,i+1)]</a>"
if ((i % max_line_len) == 0)
temp_html += "</div><div class='clearBoth'>"
if((i % DNA_BLOCK_SIZE) == 0 && i < len)
temp_html += "<div class='dnaBlockNumber'>[(i / DNA_BLOCK_SIZE) + 1]</div>"
else
temp_html += "----"
temp_html += "</div></div></div>"
popup.set_content(temp_html)
popup.open()
/obj/machinery/computer/scan_consolenew/Topic(href, href_list)
if(..())
return
if(!isturf(usr.loc))
return
if(!( (isturf(loc) && in_range(src, usr)) || istype(usr, /mob/living/silicon) ))
return
if(current_screen == "working")
return
add_fingerprint(usr)
usr.set_machine(src)
var/mob/living/carbon/viable_occupant
if(connected)
viable_occupant = connected.occupant
if(!istype(viable_occupant) || !viable_occupant.dna || (viable_occupant.disabilities & NOCLONE))
viable_occupant = null
//Basic Tasks///////////////////////////////////////////
var/num = round(text2num(href_list["num"]))
var/last_change
switch(href_list["task"])
if("togglelock")
if(connected) connected.locked = !connected.locked
if("toggleopen")
if(connected) connected.toggle_open(usr)
if("setduration")
if(!num)
num = round(input(usr, "Choose pulse duration:", "Input an Integer", null) as num|null)
if(num)
radduration = Wrap(num, 1, RADIATION_DURATION_MAX+1)
if("setstrength")
if(!num)
num = round(input(usr, "Choose pulse strength:", "Input an Integer", null) as num|null)
if(num)
radstrength = Wrap(num, 1, RADIATION_STRENGTH_MAX+1)
if("screen")
current_screen = href_list["text"]
if("rejuv")
if(viable_occupant && viable_occupant.reagents)
var/epinephrine_amount = viable_occupant.reagents.get_reagent_amount("epinephrine")
var/can_add = max(min(REJUVENATORS_MAX - epinephrine_amount, REJUVENATORS_INJECT), 0)
viable_occupant.reagents.add_reagent("epinephrine", can_add)
if("setbufferlabel")
var/text = sanitize(input(usr, "Input a new label:", "Input an Text", null) as text|null)
if(num && text)
num = Clamp(num, 1, NUMBER_OF_BUFFERS)
var/list/buffer_slot = buffer[num]
if(istype(buffer_slot))
buffer_slot["label"] = text
if("setbuffer")
if(num && viable_occupant)
num = Clamp(num, 1, NUMBER_OF_BUFFERS)
buffer[num] = list(
"label"="Buffer[num]:[viable_occupant.real_name]",
"UI"=viable_occupant.dna.uni_identity,
"SE"=viable_occupant.dna.struc_enzymes,
"UE"=viable_occupant.dna.unique_enzymes,
"name"=viable_occupant.real_name,
"blood_type"=viable_occupant.dna.blood_type
)
if("clearbuffer")
if(num)
num = Clamp(num, 1, NUMBER_OF_BUFFERS)
var/list/buffer_slot = buffer[num]
if(istype(buffer_slot))
buffer_slot.Cut()
if("transferbuffer")
if(num && viable_occupant && viable_occupant.stat != DEAD)
num = Clamp(num, 1, NUMBER_OF_BUFFERS)
var/list/buffer_slot = buffer[num]
if(istype(buffer_slot)) //15 and 40 are just magic numbers that were here before so i didnt touch them, they are initial boundaries of damage
viable_occupant.radiation += rand(15/(connected.damage_coeff ** 2),40/(connected.damage_coeff ** 2)) //Each laser level reduces damage by lvl^2, so no effect on 1 lvl, 4 times less damage on 2 and 9 times less damage on 3
switch(href_list["text"]) //Numbers are this high because other way upgrading laser is just not worth the hassle, and i cant think of anything better to inmrove
if("se")
if(buffer_slot["SE"])
viable_occupant.dna.struc_enzymes = buffer_slot["SE"]
viable_occupant.domutcheck()
if("ui")
if(buffer_slot["UI"])
viable_occupant.dna.uni_identity = buffer_slot["UI"]
viable_occupant.updateappearance(mutations_overlay_update=1)
else
if(buffer_slot["name"] && buffer_slot["UE"] && buffer_slot["blood_type"])
viable_occupant.real_name = buffer_slot["name"]
viable_occupant.name = buffer_slot["name"]
viable_occupant.dna.unique_enzymes = buffer_slot["UE"]
viable_occupant.dna.blood_type = buffer_slot["blood_type"]
if("injector")
if(num && injectorready)
num = Clamp(num, 1, NUMBER_OF_BUFFERS)
var/list/buffer_slot = buffer[num]
if(istype(buffer_slot))
var/obj/item/weapon/dnainjector/I
switch(href_list["text"])
if("se")
if(buffer_slot["SE"])
I = new /obj/item/weapon/dnainjector(loc)
for(var/datum/mutation/human/HM in good_mutations + bad_mutations + not_good_mutations)
if(HM.check_block_string(buffer_slot["SE"]))
if(prob(HM.get_chance))
I.add_mutations.Add(HM)
else
I.remove_mutations.Add(HM)
I.damage_coeff = connected.damage_coeff
if("ui")
if(buffer_slot["UI"])
I = new /obj/item/weapon/dnainjector(loc)
I.fields = list("UI"=buffer_slot["UI"])
I.damage_coeff = connected.damage_coeff
else
if(buffer_slot["name"] && buffer_slot["UE"] && buffer_slot["blood_type"])
I = new /obj/item/weapon/dnainjector(loc)
I.fields = list("name"=buffer_slot["name"], "UE"=buffer_slot["UE"], "blood_type"=buffer_slot["blood_type"])
I.damage_coeff = connected.damage_coeff
if(I)
injectorready = 0
spawn(INJECTOR_TIMEOUT)
injectorready = 1
if("loaddisk")
if(num && diskette && diskette.fields)
num = Clamp(num, 1, NUMBER_OF_BUFFERS)
buffer[num] = diskette.fields.Copy()
if("savedisk")
if(num && diskette && !diskette.read_only)
num = Clamp(num, 1, NUMBER_OF_BUFFERS)
var/list/buffer_slot = buffer[num]
if(istype(buffer_slot))
diskette.name = "data disk \[[buffer_slot["label"]]\]"
diskette.fields = buffer_slot.Copy()
if("ejectdisk")
if(diskette)
diskette.loc = get_turf(src)
diskette = null
if("pulseui","pulsese")
if(num && viable_occupant && connected && viable_occupant.stat != DEAD)
radduration = Wrap(radduration, 1, RADIATION_DURATION_MAX+1)
radstrength = Wrap(radstrength, 1, RADIATION_STRENGTH_MAX+1)
var/locked_state = connected.locked
connected.locked = 1
current_screen = "working"
ShowInterface(usr)
sleep(radduration*10)
current_screen = "mainmenu"
if(viable_occupant && connected && connected.occupant==viable_occupant)
viable_occupant.radiation += (RADIATION_IRRADIATION_MULTIPLIER*radduration*radstrength)/(connected.damage_coeff ** 2) //Read comment in "transferbuffer" section above for explanation
switch(href_list["task"]) //Same thing as there but values are even lower, on best part they are about 0.0*, effectively no damage
if("pulseui")
var/len = length(viable_occupant.dna.uni_identity)
num = Wrap(num, 1, len+1)
num = randomize_radiation_accuracy(num, radduration + (connected.precision_coeff ** 2), len) //Each manipulator level above 1 makes randomization as accurate as selected time + manipulator lvl^2
//Value is this high for the same reason as with laser - not worth the hassle of upgrading if the bonus is low
var/block = round((num-1)/DNA_BLOCK_SIZE)+1
var/subblock = num - block*DNA_BLOCK_SIZE
last_change = "UI #[block]-[subblock]; "
var/hex = copytext(viable_occupant.dna.uni_identity, num, num+1)
last_change += "[hex]"
hex = scramble(hex, radstrength, radduration)
last_change += "->[hex]"
viable_occupant.dna.uni_identity = copytext(viable_occupant.dna.uni_identity, 1, num) + hex + copytext(viable_occupant.dna.uni_identity, num+1, 0)
viable_occupant.updateappearance(mutations_overlay_update=1)
if("pulsese")
var/len = length(viable_occupant.dna.struc_enzymes)
num = Wrap(num, 1, len+1)
num = randomize_radiation_accuracy(num, radduration + (connected.precision_coeff ** 2), len)
var/block = round((num-1)/DNA_BLOCK_SIZE)+1
var/subblock = num - block*DNA_BLOCK_SIZE
last_change = "SE #[block]-[subblock]; "
var/hex = copytext(viable_occupant.dna.struc_enzymes, num, num+1)
last_change += "[hex]"
hex = scramble(hex, radstrength, radduration)
last_change += "->[hex]"
viable_occupant.dna.struc_enzymes = copytext(viable_occupant.dna.struc_enzymes, 1, num) + hex + copytext(viable_occupant.dna.struc_enzymes, num+1, 0)
viable_occupant.domutcheck()
else
current_screen = "mainmenu"
if(connected)
connected.locked = locked_state
ShowInterface(usr,last_change)
/obj/machinery/computer/scan_consolenew/proc/scramble(input,rs,rd)
var/length = length(input)
var/ran = gaussian(0, rs*RADIATION_STRENGTH_MULTIPLIER)
if(ran == 0) ran = pick(-1,1) //hacky, statistically should almost never happen. 0-change makes people mad though
else if(ran < 0) ran = round(ran) //negative, so floor it
else ran = -round(-ran) //positive, so ceiling it
return num2hex(Wrap(hex2num(input)+ran, 0, 16**length), length)
/obj/machinery/computer/scan_consolenew/proc/randomize_radiation_accuracy(position_we_were_supposed_to_hit, radduration, number_of_blocks)
return Wrap(round(position_we_were_supposed_to_hit + gaussian(0, RADIATION_ACCURACY_MULTIPLIER/radduration), 1), 1, number_of_blocks+1)
/////////////////////////// DNA MACHINES
#undef INJECTOR_TIMEOUT
#undef REJUVENATORS_INJECT
#undef REJUVENATORS_MAX
#undef NUMBER_OF_BUFFERS
#undef RADIATION_STRENGTH_MAX
#undef RADIATION_STRENGTH_MULTIPLIER
#undef RADIATION_DURATION_MAX
#undef RADIATION_ACCURACY_MULTIPLIER
#undef RADIATION_IRRADIATION_MULTIPLIER
//#undef BAD_MUTATION_DIFFICULTY
//#undef GOOD_MUTATION_DIFFICULTY
//#undef OP_MUTATION_DIFFICULTY
+2 -2
View File
@@ -33,7 +33,7 @@
dat += "<H3>Prisoner Implant Management</H3>"
dat += "<HR>Chemical Implants<BR>"
var/turf/Tr = null
for(var/obj/item/weapon/implant/chem/C in world)
for(var/obj/item/weapon/implant/chem/C in tracking_implants)
Tr = get_turf(C)
if((Tr) && (Tr.z != src.z)) continue//Out of range
if(!C.implanted) continue
@@ -43,7 +43,7 @@
dat += "<A href='?src=\ref[src];inject10=\ref[C]'>(<font class='bad'>(10)</font>)</A><BR>"
dat += "********************************<BR>"
dat += "<HR>Tracking Implants<BR>"
for(var/obj/item/weapon/implant/tracking/T in world)
for(var/obj/item/weapon/implant/tracking/T in tracking_implants)
if(!iscarbon(T.imp_in))
continue
if(!T.implanted)
+167
View File
@@ -0,0 +1,167 @@
/obj/machinery/dna_scannernew
name = "\improper DNA scanner"
desc = "It scans DNA structures."
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "scanner"
density = 1
var/locked = 0
anchored = 1
use_power = 1
idle_power_usage = 50
active_power_usage = 300
var/damage_coeff
var/scan_level
var/precision_coeff
/obj/machinery/dna_scannernew/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/clonescanner(null)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(null)
component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(null)
component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
component_parts += new /obj/item/stack/cable_coil(null, 1)
component_parts += new /obj/item/stack/cable_coil(null, 1)
RefreshParts()
/obj/machinery/dna_scannernew/RefreshParts()
scan_level = 0
damage_coeff = 0
precision_coeff = 0
for(var/obj/item/weapon/stock_parts/scanning_module/P in component_parts)
scan_level += P.rating
for(var/obj/item/weapon/stock_parts/manipulator/P in component_parts)
precision_coeff = P.rating
for(var/obj/item/weapon/stock_parts/micro_laser/P in component_parts)
damage_coeff = P.rating
/obj/machinery/dna_scannernew/update_icon()
//no power or maintenance
if(stat & (NOPOWER|BROKEN))
icon_state = initial(icon_state)+ (state_open ? "_open" : "") + "_unpowered"
return
if((stat & MAINT) || panel_open)
icon_state = initial(icon_state)+ (state_open ? "_open" : "") + "_maintenance"
return
//running and someone in there
if(occupant)
icon_state = initial(icon_state)+ "_occupied"
return
//running
icon_state = initial(icon_state)+ (state_open ? "_open" : "")
/obj/machinery/dna_scannernew/power_change()
..()
update_icon()
/obj/machinery/dna_scannernew/proc/toggle_open(mob/user)
if(panel_open)
user << "<span class='notice'>Close the maintenance panel first.</span>"
return
if(state_open)
close_machine()
return
else if(locked)
user << "<span class='notice'>The bolts are locked down, securing the door shut.</span>"
return
open_machine()
/obj/machinery/dna_scannernew/container_resist()
var/mob/living/user = usr
var/breakout_time = 2
if(state_open || !locked) //Open and unlocked, no need to escape
state_open = 1
return
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
user << "<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [breakout_time] minutes.)</span>"
user.visible_message("<span class='italics'>You hear a metallic creaking from [src]!</span>")
if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
if(!user || user.stat != CONSCIOUS || user.loc != src || state_open || !locked)
return
locked = 0
visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>")
user << "<span class='notice'>You successfully break out of [src]!</span>"
open_machine()
/obj/machinery/dna_scannernew/close_machine()
if(!state_open)
return 0
..()
// search for ghosts, if the corpse is empty and the scanner is connected to a cloner
if(occupant)
if(locate(/obj/machinery/computer/cloning, get_step(src, NORTH)) \
|| locate(/obj/machinery/computer/cloning, get_step(src, SOUTH)) \
|| locate(/obj/machinery/computer/cloning, get_step(src, EAST)) \
|| locate(/obj/machinery/computer/cloning, get_step(src, WEST)))
occupant.notify_ghost_cloning("Your corpse has been placed into a cloning scanner. Re-enter your corpse if you want to be cloned!")
return 1
/obj/machinery/dna_scannernew/open_machine()
if(state_open)
return 0
..()
return 1
/obj/machinery/dna_scannernew/relaymove(mob/user as mob)
if(user.stat || locked)
return
open_machine()
return
/obj/machinery/dna_scannernew/attackby(obj/item/I, mob/user, params)
if(!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, I))//sent icon_state is irrelevant...
update_icon()//..since we're updating the icon here, since the scanner can be unpowered when opened/closed
return
if(exchange_parts(user, I))
return
if(default_pry_open(I))
return
if(default_deconstruction_crowbar(I))
return
if(istype(I, /obj/item/weapon/grab))
var/obj/item/weapon/grab/G = I
if(!ismob(G.affecting))
return
if(!state_open)
user << "<span class='notice'>Open the scanner first.</span>"
return
var/mob/M = G.affecting
M.loc = loc
user.stop_pulling()
qdel(G)
/obj/machinery/dna_scannernew/attack_hand(mob/user)
if(..(user,1,0)) //don't set the machine, since there's no dialog
return
toggle_open(user)
/obj/machinery/dna_scannernew/blob_act()
if(prob(75))
qdel(src)
+4
View File
@@ -259,6 +259,10 @@
/obj/machinery/door/proc/hasPower()
return !(stat & NOPOWER)
/obj/machinery/door/proc/update_freelook_sight()
if(!glass && cameranet)
cameranet.updateVisibility(src, 0)
/obj/machinery/door/BlockSuperconductivity() // All non-glass airlocks block heat, this is intended.
if(opacity || heat_proof)
return 1
+2 -2
View File
@@ -124,9 +124,9 @@
var/mob/living/carbon/human/T = attached
if(!istype(T)) return
if(!T.dna)
if(!istype(T))
return
if(T.disabilities & NOCLONE)
return
+3 -3
View File
@@ -180,7 +180,7 @@
areaindex[tmpname] = 1
L[tmpname] = R
for (var/obj/item/weapon/implant/tracking/I in world)
for (var/obj/item/weapon/implant/tracking/I in tracking_implants)
if (!I.implanted || !ismob(I.loc))
continue
else
@@ -315,8 +315,8 @@
var/mob/living/carbon/human/human = M
if(human.dna && human.dna.species.id == "human")
M << "<span class='italics'>You hear a buzzing in your ears.</span>"
hardset_dna(human, null, null, null, null, /datum/species/fly)
human.regenerate_icons()
human.set_species(/datum/species/fly)
human.apply_effect((rand(120 - accurate * 40, 180 - accurate * 60)), IRRADIATE, 0)
calibrated = 0
return
+1 -1
View File
@@ -45,7 +45,7 @@
<b>HONK pressure: </b>[cabin_pressure>WARNING_HIGH_PRESSURE ? "<font color='red'>[cabin_pressure]</font>": cabin_pressure]kPa<br>
<b>HONK temperature: </b> [return_temperature()]&deg;K|[return_temperature() - T0C]&deg;C<br>
<b>Lights: </b>[lights?"on":"off"]<br>
[src.dna?"<b>DNA-locked:</b><br> <span style='font-size:10px;letter-spacing:-1px;'>[src.dna]</span> \[<a href='?src=\ref[src];reset_dna=1'>Reset</a>\]<br>":null]
[dna_lock?"<b>DNA-locked:</b><br> <span style='font-size:10px;letter-spacing:-1px;'>[dna_lock]</span> \[<a href='?src=\ref[src];reset_dna=1'>Reset</a>\]<br>":null]
"}
return output
+7 -7
View File
@@ -34,7 +34,7 @@
var/last_message = 0
var/add_req_access = 1
var/maint_access = 0
var/dna //dna-locking the mech
var/dna_lock//dna-locking the mech
var/list/proc_res = list() //stores proc owners, like proc_res["functionname"] = owner reference
var/datum/effect/effect/system/spark_spread/spark_system = new
var/lights = 0
@@ -557,7 +557,7 @@
else if(AI.stat || !AI.client)
user << "<span class='warning'>[AI.name] is currently unresponsive, and cannot be uploaded.</span>"
return
else if(occupant || dna) //Normal AIs cannot steal mechs!
else if(occupant || dna_lock) //Normal AIs cannot steal mechs!
user << "<span class='warning'>Access denied. [name] is [occupant ? "currently occupied" : "secured with a DNA lock"]."
return
AI.control_disabled = 0
@@ -653,10 +653,10 @@
log_append_to_last("Permission denied.")
return
var/passed
if(dna)
if(check_dna_integrity(user))
if(dna_lock)
if(user.has_dna())
var/mob/living/carbon/C = user
if(C.dna.unique_enzymes==src.dna)
if(C.dna.unique_enzymes==dna_lock)
passed = 1
else if(operation_allowed(user))
passed = 1
@@ -711,8 +711,8 @@
else if(occupant)
user << "<span class='warning'>Occupant detected!</span>"
return 0
else if(dna && dna!=mmi_as_oc.brainmob.dna.unique_enzymes)
user << "<span class='warning'>Stop it!</span>"
else if(dna_lock && (!mmi_as_oc.brainmob.dna || dna_lock!=mmi_as_oc.brainmob.dna.unique_enzymes))
user << "<span class='warning'>Access denied. [name] is secured with a DNA lock.</span>"
return 0
visible_message("<span class='notice'>[user] starts to insert an MMI into [src.name].</span>")
+3 -3
View File
@@ -83,7 +83,7 @@
<b>Airtank temperature: </b>[tank_temperature]&deg;K|[tank_temperature - T0C]&deg;C<br>
<b>Cabin pressure: </b>[cabin_pressure>WARNING_HIGH_PRESSURE ? "<span class='danger'>[cabin_pressure]</span>": cabin_pressure]kPa<br>
<b>Cabin temperature: </b> [return_temperature()]&deg;K|[return_temperature() - T0C]&deg;C<br>
[src.dna?"<b>DNA-locked:</b><br> <span style='font-size:10px;letter-spacing:-1px;'>[src.dna]</span> \[<a href='?src=\ref[src];reset_dna=1'>Reset</a>\]<br>":null]
[dna_lock?"<b>DNA-locked:</b><br> <span style='font-size:10px;letter-spacing:-1px;'>[dna_lock]</span> \[<a href='?src=\ref[src];reset_dna=1'>Reset</a>\]<br>":null]
"}
return output
@@ -300,11 +300,11 @@
if(occupant && !iscarbon(occupant))
occupant << "<span class='danger'> You do not have any DNA!</span>"
return
dna = src.occupant.dna.unique_enzymes
dna_lock = occupant.dna.unique_enzymes
occupant_message("You feel a prick as the needle takes your DNA sample.")
if(href_list["reset_dna"])
dna = null
dna_lock = null
if(href_list["repair_int_control_lost"])
occupant_message("Recalibrating coordination system...")
@@ -20,7 +20,6 @@
sleep(3)
if (i > 0)
if (prob(40))
/*var/obj/effect/decal/cleanable/oil/o =*/
new /obj/effect/decal/cleanable/oil/streak(src.loc)
else if (prob(10))
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
@@ -36,10 +35,10 @@
random_icon_states = list("gibarm", "gibleg")
/obj/effect/decal/cleanable/robot_debris/up
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibup1","gibup1") //2:7 is close enough to 1:4
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibup1","gibup1")
/obj/effect/decal/cleanable/robot_debris/down
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibdown1","gibdown1") //2:7 is close enough to 1:4
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibdown1","gibdown1")
/obj/effect/decal/cleanable/oil
name = "motor oil"
@@ -66,4 +65,4 @@
return ..()
/obj/effect/decal/cleanable/oil/streak
random_icon_states = list("streak1", "streak2", "streak3", "streak4", "streak5")
random_icon_states = list("streak1", "streak2", "streak3", "streak4", "streak5")
@@ -13,7 +13,14 @@ would spawn and follow the beaker, even if it is carried or thrown.
unacidable = 1//So effect are not targeted by alien acid.
pass_flags = PASSTABLE | PASSGRILLE
/obj/effect/effect/New()
..()
if(ticker)
cameranet.updateVisibility(src)
/obj/effect/effect/Destroy()
if(ticker)
cameranet.updateVisibility(src)
..()
return QDEL_HINT_PUTINPOOL
/*
@@ -12,6 +12,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
item_state = "electronic"
w_class = 1
slot_flags = SLOT_ID | SLOT_BELT
origin_tech = "programming=2"
//Main variables
var/owner = null // String name of owner
@@ -14,6 +14,7 @@
item_state = "camera_bug"
throw_speed = 4
throw_range = 20
origin_tech = "syndicate=3;engineering=;1"
var/obj/machinery/camera/current = null
@@ -9,6 +9,7 @@
force = 3
attack_verb = list("blown up", "exploded", "detonated")
materials = list(MAT_METAL=50, MAT_GLASS=30)
origin_tech = "syndicate=3;combat=2,"
/obj/item/device/doorCharge/ex_act(severity, target)
switch(severity)
@@ -80,7 +80,7 @@
return
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(H.dna && (H.dna.check_mutation(HULK) || NOGUNS in H.dna.species.specflags))
if(H.dna.check_mutation(HULK) || NOGUNS in H.dna.species.specflags)
user << "<span class='warning'>Your fingers can't press the button!</span>"
return
+1 -2
View File
@@ -162,8 +162,7 @@ MASS SPECTROMETER
// Species and body temperature
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.dna)
user << "<span class='info'>Species: [H.dna.species.name]</span>"
user << "<span class='info'>Species: [H.dna.species.name]</span>"
user << "<span class='info'>Body temperature: [round(M.bodytemperature-T0C,0.1)] &deg;C ([round(M.bodytemperature*1.8-459.67,0.1)] &deg;F)</span>"
// Time of death
+1
View File
@@ -11,6 +11,7 @@
var/tape_type = /obj/item/holotape
var/icon_base
var/charging = 0
origin_tech = "materials=1;engineering=1"
/obj/item/holotape
icon = 'icons/obj/holotape.dmi'
@@ -16,7 +16,6 @@
return 1
return 0
/obj/item/borg/upgrade/reset
name = "cyborg module reset board"
desc = "Used to reset a cyborg's module. Destroys any other upgrades applied to the cyborg."
@@ -197,7 +196,7 @@
R.module.rebuild()
return 1
/obj/item/borg/upgrade/syndicate/
/obj/item/borg/upgrade/syndicate
name = "illegal equipment module"
desc = "Unlocks the hidden, deadlier functions of a cyborg"
icon_state = "cyborg_upgrade3"
@@ -211,3 +210,85 @@
R.SetEmagged(1)
return 1
/obj/item/borg/upgrade/selfrepair
name = "self-repair module"
desc = "This module will repair the cyborg over time."
icon_state = "cyborg_upgrade5"
require_module = 1
var/repair_amount = -1
var/repair_tick = 1
var/msg_cooldown = 0
var/on = 0
var/powercost = 10
var/mob/living/silicon/robot/cyborg
/obj/item/borg/upgrade/selfrepair/action(mob/living/silicon/robot/R)
if(..())
return 0
var/obj/item/borg/upgrade/selfrepair/U = locate() in R
if(U)
usr << "<span class='warning'>This unit is already equipped with a self-repair module.</span>"
return 0
cyborg = R
icon_state = "selfrepair_off"
action_button_name = "Toggle Self-Repair"
return 1
/obj/item/borg/upgrade/selfrepair/ui_action_click()
on = !on
if(on)
cyborg << "<span class='notice'>You activate the self-repair module.</span>"
SSobj.processing |= src
else
cyborg << "<span class='notice'>You deactivate the self-repair module.</span>"
SSobj.processing -= src
update_icon()
/obj/item/borg/upgrade/selfrepair/update_icon()
if(cyborg)
icon_state = "selfrepair_[on ? "on" : "off"]"
else
icon_state = "cyborg_upgrade5"
/obj/item/borg/upgrade/selfrepair/proc/deactivate()
SSobj.processing -= src
on = 0
update_icon()
/obj/item/borg/upgrade/selfrepair/process()
if(!repair_tick)
repair_tick = 1
return
if( cyborg && (cyborg.stat != DEAD) && on)
if(cyborg.cell.charge < powercost*2)
cyborg << "<span class='warning'>Self-repair module deactivated. Please recharge.</span>"
deactivate()
return
if(cyborg.health < cyborg.maxHealth)
if(cyborg.health < 0)
repair_amount = -2.5
powercost = 30
else
repair_amount = -1
powercost = 10
cyborg.adjustBruteLoss(repair_amount)
cyborg.adjustFireLoss(repair_amount)
cyborg.updatehealth()
cyborg.cell.use(powercost)
else
cyborg.cell.use(5)
repair_tick = 0
if( (world.time - 2000) > msg_cooldown )
var/msgmode = "standby"
if(cyborg.health < 0)
msgmode = "critical"
else if(cyborg.health < cyborg.maxHealth)
msgmode = "normal"
cyborg << "<span class='notice'>Self-repair is active in <span class='boldnotice'>[msgmode]</span> mode.</span>"
msg_cooldown = world.time
else
deactivate()
@@ -103,6 +103,7 @@ var/global/list/datum/stack_recipe/wood_recipes = list ( \
new/datum/stack_recipe("book case", /obj/structure/bookcase, 4, time = 15, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("drying rack", /obj/machinery/smartfridge/drying_rack, 10, time = 15, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("dog bed", /obj/structure/stool/bed/dogbed, 10, time = 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("display case chassis", /obj/structure/displaycase_chassis, 5, one_per_turf = 1, on_floor = 1), \
)
/obj/item/stack/sheet/mineral/wood
@@ -17,7 +17,7 @@
/obj/item/weapon/dnainjector/proc/inject(mob/living/carbon/M, mob/user)
if(check_dna_integrity(M) && !(M.disabilities & NOCLONE))
if(M.has_dna() && !(M.disabilities & NOCLONE))
if(M.stat == DEAD) //prevents dead people from having their DNA changed
user << "<span class='notice'>You can't modify [M]'s DNA while \he's dead.</span>"
return
@@ -38,7 +38,7 @@
M.dna.blood_type = fields["blood_type"]
if(fields["UI"]) //UI+UE
M.dna.uni_identity = merge_text(M.dna.uni_identity, fields["UI"])
updateappearance(M)
M.updateappearance(mutations_overlay_update=1)
log_attack(log_msg)
else
user << "<span class='notice'>It appears that [M] does not have compatible DNA.</span>"
@@ -87,6 +87,15 @@
origin_tech = "materials=2;magnets=2;programming=2;biotech=2"
var/id = 1
/obj/item/weapon/implant/tracking/New()
..()
tracking_implants += src
/obj/item/weapon/implant/tracking/Destroy()
..()
tracking_implants -= src
/obj/item/weapon/implant/tracking/get_data()
var/dat = {"<b>Implant Specifications:</b><BR>
<b>Name:</b> Tracking Beacon<BR>
@@ -24,6 +24,14 @@
/obj/item/weapon/implant/chem/New()
..()
create_reagents(50)
tracking_implants += src
/obj/item/weapon/implant/chem/Destroy()
..()
tracking_implants -= src
/obj/item/weapon/implant/chem/trigger(emote, mob/source)
if(emote == "deathgasp")
@@ -78,7 +78,7 @@ Frequency:
src.temp += "[W.code]-[dir2text(get_dir(sr, tr))]-[direct]<BR>"
src.temp += "<B>Extranneous Signals:</B><BR>"
for (var/obj/item/weapon/implant/tracking/W in world)
for (var/obj/item/weapon/implant/tracking/W in tracking_implants)
if (!W.implanted || !ismob(W.loc))
continue
else
+1 -1
View File
@@ -244,7 +244,7 @@
return 1
/obj/item/weapon/twohanded/dualsaber/wield(mob/living/carbon/M) //Specific wield () hulk checks due to reflection chance for balance issues and switches hitsounds.
if(istype(M))
if(M.has_dna())
if(M.dna.check_mutation(HULK))
M << "<span class='warning'>You lack the grace to wield this!</span>"
return
+4
View File
@@ -8,12 +8,16 @@
smooth_icon(src)
smooth_icon_neighbors(src)
icon_state = ""
if(ticker)
cameranet.updateVisibility(src)
/obj/structure/blob_act()
if(prob(50))
qdel(src)
/obj/structure/Destroy()
if(ticker)
cameranet.updateVisibility(src)
if(opacity)
UpdateAffectingLights()
if(smooth)
+150 -25
View File
@@ -1,22 +1,23 @@
/obj/structure/displaycase
name = "display case"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "glassbox1"
desc = "A display case for prized possessions. Hooked up with an anti-theft system."
icon_state = "glassbox0"
desc = "A display case for prized possessions."
density = 1
anchored = 1
unacidable = 1//Dissolving the case would also delete the gun.
var/health = 30
var/occupied = 1
var/destroyed = 0
var/obj/item/showpiece = null
var/alert = 0
var/open = 0
var/obj/item/weapon/electronics/airlock/electronics
/obj/structure/displaycase/ex_act(severity, target)
switch(severity)
if (1)
new /obj/item/weapon/shard( src.loc )
if (occupied)
new /obj/item/weapon/gun/energy/laser/captain( src.loc )
occupied = 0
dump()
qdel(src)
if (2)
if (prob(50))
@@ -27,6 +28,13 @@
src.health -= 5
src.healthcheck()
/obj/structure/displaycase/examine(mob/user)
..()
if(showpiece)
user << "<span class='notice'>There's [showpiece] inside.</span>"
if(alert)
user << "<span class='notice'>Hooked up with an anti-theft system.</span>"
/obj/structure/displaycase/bullet_act(obj/item/projectile/Proj)
if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
@@ -35,16 +43,17 @@
src.healthcheck()
return
/obj/structure/displaycase/proc/dump()
if (showpiece)
showpiece.loc = src.loc
showpiece = null
/obj/structure/displaycase/blob_act()
if (prob(75))
new /obj/item/weapon/shard( src.loc )
if (occupied)
new /obj/item/weapon/gun/energy/laser/captain( src.loc )
occupied = 0
dump()
qdel(src)
/obj/structure/displaycase/proc/healthcheck()
if (src.health <= 0)
if (!( src.destroyed ))
@@ -55,27 +64,76 @@
update_icon()
//Activate Anti-theft
var/area/alarmed = get_area(src)
alarmed.burglaralert(src)
playsound(src, "sound/effects/alert.ogg", 50, 1)
if(alert)
var/area/alarmed = get_area(src)
alarmed.burglaralert(src)
playsound(src, "sound/effects/alert.ogg", 50, 1)
else
playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
return
/obj/structure/displaycase/update_icon()
if(src.destroyed)
src.icon_state = "glassboxb[src.occupied]"
/obj/structure/displaycase/proc/is_directional(atom/A)
try
getFlatIcon(A,defdir=4)
catch
return 0
return 1
/obj/structure/displaycase/proc/get_flat_icon_directional(atom/A)
//Get flatIcon even if dir is mismatched for directionless icons
//SLOW
var/icon/I
if(is_directional(A))
I = getFlatIcon(A)
else
src.icon_state = "glassbox[src.occupied]"
var/old_dir = A.dir
A.dir = 2
I = getFlatIcon(A)
A.dir = old_dir
return I
/obj/structure/displaycase/update_icon()
var/icon/I
if(open)
I = icon('icons/obj/stationobjs.dmi',"glassbox_open")
else
I = icon('icons/obj/stationobjs.dmi',"glassbox0")
if(destroyed)
I = icon('icons/obj/stationobjs.dmi',"glassboxb0")
if(showpiece)
var/icon/S = get_flat_icon_directional(showpiece)
S.Scale(17,17)
I.Blend(S,ICON_UNDERLAY,8,8)
src.icon = I
return
/obj/structure/displaycase/attackby(obj/item/weapon/W, mob/user, params)
user.changeNext_move(CLICK_CD_MELEE)
src.health -= W.force
src.healthcheck()
..()
if(istype(W, /obj/item/weapon/card) && electronics && !destroyed && allowed(user))
user << "<span class='notice'>You [open ? "close":"open"] the [src]</span>"
open = !open
update_icon()
return
if(!alert && istype(W,/obj/item/weapon/crowbar))
if(destroyed && !showpiece)
user << "<span class='notice'>You remove the destroyed case</span>"
qdel(src)
return
user << "<span class='notice'>You start to [open ? "close":"open"] the [src]</span>"
if(do_after(user, 20, target = src))
user << "<span class='notice'>You [open ? "close":"open"] the [src]</span>"
open = !open
update_icon()
else if(open)
if(user.unEquip(W))
W.loc = src
showpiece = W
user << "<span class='notice'>You put [W] on display</span>"
update_icon()
else
user.changeNext_move(CLICK_CD_MELEE)
src.health -= W.force
src.healthcheck()
..()
return
/obj/structure/displaycase/attack_paw(mob/user)
@@ -83,10 +141,9 @@
/obj/structure/displaycase/attack_hand(mob/user)
user.changeNext_move(CLICK_CD_MELEE)
if (src.destroyed && src.occupied)
new /obj/item/weapon/gun/energy/laser/captain( src.loc )
if (showpiece && (destroyed || open))
dump()
user << "<span class='notice'>You deactivate the hover field built into the case.</span>"
src.occupied = 0
src.add_fingerprint(user)
update_icon()
return
@@ -98,3 +155,71 @@
return
/obj/structure/displaycase_chassis
anchored = 1
density = 0
name = "display case chassis"
desc = "wooden base of display case"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "glassbox_chassis"
var/obj/item/weapon/electronics/airlock/electronics
/obj/structure/displaycase_chassis/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/wrench))
user << "<span class='notice'>You start disassembling [src]...</span>"
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
if(do_after(user, 30, target = src))
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
new /obj/item/stack/sheet/mineral/wood(get_turf(src))
qdel(src)
return
if(istype(I, /obj/item/weapon/electronics/airlock))
user << "<span class='notice'>You start installing the electronics into [src]...</span>"
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
if(user.unEquip(I) && do_after(user, 30, target = src))
I.loc = src
electronics = I
user << "<span class='notice'>You install the airlock electronics.</span>"
return
if(istype(I, /obj/item/stack/sheet/glass))
var/obj/item/stack/sheet/glass/G = I
if(G.get_amount() < 10)
user << "<span class='warning'>You need ten glass sheets to do this!</span>"
return
user << "<span class='notice'>You start adding [G] to [src]...</span>"
if(do_after(user, 20, target = src))
G.use(10)
var/obj/structure/displaycase/display = new(src.loc)
if(electronics)
electronics.loc = display
display.electronics = electronics
if(electronics.use_one_access)
display.req_one_access = electronics.conf_access
else
display.req_access = electronics.conf_access
qdel(src)
return
return
/obj/structure/displaycase/captain
alert = 1
/obj/structure/displaycase/captain/New()
..()
showpiece = new /obj/item/weapon/gun/energy/laser/captain (src)
update_icon()
/obj/structure/displaycase/labcage
name = "lab cage"
desc = "A glass lab container for storing interesting creatures."
/obj/structure/displaycase/labcage/New()
..()
var/obj/item/clothing/mask/facehugger/A = new /obj/item/clothing/mask/facehugger(src)
A.sterile = 1
A.name = "Lamarr"
showpiece = A
update_icon()
@@ -1,91 +0,0 @@
/obj/structure/lamarr
name = "lab cage"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "labcage1"
desc = "A glass lab container for storing interesting creatures."
density = 1
anchored = 1
unacidable = 1//Dissolving the case would also delete Lamarr
var/health = 30
var/occupied = 1
var/destroyed = 0
/obj/structure/lamarr/ex_act(severity, target)
switch(severity)
if (1)
new /obj/item/weapon/shard( src.loc )
Break()
qdel(src)
if (2)
if (prob(50))
src.health -= 15
src.healthcheck()
if (3)
if (prob(50))
src.health -= 5
src.healthcheck()
/obj/structure/lamarr/bullet_act(obj/item/projectile/Proj)
health -= Proj.damage
..()
src.healthcheck()
return
/obj/structure/lamarr/blob_act()
if (prob(75))
new /obj/item/weapon/shard( src.loc )
Break()
qdel(src)
/obj/structure/lamarr/proc/healthcheck()
if (src.health <= 0)
if (!( src.destroyed ))
src.density = 0
src.destroyed = 1
new /obj/item/weapon/shard( src.loc )
playsound(src, "shatter", 70, 1)
Break()
else
playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
return
/obj/structure/lamarr/update_icon()
if(src.destroyed)
src.icon_state = "labcageb[src.occupied]"
else
src.icon_state = "labcage[src.occupied]"
return
/obj/structure/lamarr/attackby(obj/item/weapon/W, mob/user, params)
user.changeNext_move(CLICK_CD_MELEE)
src.health -= W.force
src.healthcheck()
..()
return
/obj/structure/lamarr/attack_paw(mob/user)
return src.attack_hand(user)
/obj/structure/lamarr/attack_hand(mob/user)
user.changeNext_move(CLICK_CD_MELEE)
if (src.destroyed)
return
else
user.visible_message("<span class='warning'>[user] kicks the lab cage.</span>", \
"<span class='danger'>You kick the lab cage.</span>")
src.health -= 2
healthcheck()
return
/obj/structure/lamarr/proc/Break()
if(occupied)
var/obj/item/clothing/mask/facehugger/A = new /obj/item/clothing/mask/facehugger( src.loc )
A.sterile = 1
A.name = "Lamarr"
occupied = 0
update_icon()
return
+19 -6
View File
@@ -148,16 +148,17 @@
var/racechoice = input(H, "What are we again?", "Race change") as null|anything in choosable_races
newrace = species_list[racechoice]
if(!newrace || !H.dna)
if(!newrace)
return
hardset_dna(H, null, null, null, null, newrace)
H.set_species(newrace, icon_update=0)
if(H.dna.species.use_skintones)
var/new_s_tone = input(user, "Choose your skin tone:", "Race change") as null|anything in skin_tones
if(new_s_tone)
H.skin_tone = new_s_tone
H.dna.update_ui_block(DNA_SKIN_TONE_BLOCK)
if(MUTCOLORS in H.dna.species.specflags)
var/new_mutantcolor = input(user, "Choose your skin color:", "Race change") as color|null
@@ -170,7 +171,10 @@
else
H << "<span class='notice'>Invalid color. Your color is not bright enough.</span>"
H.regenerate_icons()
H.update_body()
H.update_hair()
H.update_mutcolor()
H.update_mutations_overlay() // no hulk lizard
if("gender")
if(!(H.gender in list("male", "female"))) //blame the patriarchy
@@ -180,12 +184,19 @@
if(alert(H, "Become a Witch?", "Confirmation", "Yes", "No") == "Yes")
H.gender = "female"
H << "<span class='notice'>Man, you feel like a woman!</span>"
H.regenerate_icons()
else
return
else
if(alert(H, "Become a Warlock?", "Confirmation", "Yes", "No") == "Yes")
H.gender = "male"
H << "<span class='notice'>Whoa man, you feel like a man!</span>"
H.regenerate_icons()
else
return
H.dna.update_ui_block(DNA_GENDER_BLOCK)
H.update_body()
H.update_mutations_overlay() //(hulk male/female)
if("hair")
var/hairchoice = alert(H, "Hair style or hair color?", "Change Hair", "Style", "Color")
@@ -196,15 +207,17 @@
var/new_hair_color = input(H, "Choose your hair color", "Hair Color") as null|color
if(new_hair_color)
H.hair_color = sanitize_hexcolor(new_hair_color)
H.dna.update_ui_block(DNA_HAIR_COLOR_BLOCK)
if(H.gender == "male")
var/new_face_color = input(H, "Choose your facial hair color", "Hair Color") as null|color
if(new_face_color)
H.facial_hair_color = sanitize_hexcolor(new_face_color)
H.dna.update_ui_block(DNA_FACIAL_HAIR_COLOR_BLOCK)
H.update_hair()
if("eyes")
var/new_eye_color = input(H, "Choose your eye color", "Eye Color") as null|color
if(new_eye_color)
H.eye_color = sanitize_hexcolor(new_eye_color)
H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK)
H.update_body()
+1 -5
View File
@@ -9,11 +9,7 @@
var/to_be_destroyed = 0 //Used for fire, if a melting temperature was reached, it will be destroyed
var/max_fire_temperature_sustained = 0 //The max temperature of the fire which it was subjected to
/turf/simulated/New()
..()
levelupdate()
if(smooth)
smooth_icon(src)
/turf/simulated/proc/burn_tile()
+1 -1
View File
@@ -9,7 +9,7 @@
/turf/simulated/wall/cult/break_wall()
new /obj/effect/decal/cleanable/blood(src)
new /obj/structure/cultgirder(src)
return (new /obj/structure/cultgirder(src))
/turf/simulated/wall/cult/devastate_wall()
new /obj/effect/decal/cleanable/blood(src)
+10 -1
View File
@@ -26,11 +26,13 @@
flags = 0
var/image/obscured //camerachunks
/turf/New()
..()
for(var/atom/movable/AM in src)
Entered(AM)
return
/turf/Destroy()
return QDEL_HINT_HARDDEL_NOW
@@ -196,6 +198,10 @@
flags |= NOJAUNT
/turf/storage_contents_dump_act(obj/item/weapon/storage/src_object, mob/user)
if(src_object.contents.len)
usr << "<span class='notice'>You start dumping out the contents...</span>"
if(!do_after(usr,20,target=src_object))
return 0
for(var/obj/item/I in src_object)
if(user.s_active != src_object)
if(I.on_found(user))
@@ -281,6 +287,9 @@
/turf/proc/can_lay_cable()
return can_have_cabling() & !intact
/turf/proc/visibilityChanged()
if(ticker)
cameranet.updateVisibility(src)
/turf/indestructible
name = "wall"
+3 -9
View File
@@ -220,7 +220,7 @@
var/dat = "<B>Showing DNA from blood.</B><HR>"
dat += "<table cellspacing=5><tr><th>Name</th><th>DNA</th><th>Blood Type</th></tr>"
for(var/mob/living/carbon/human/H in mob_list)
if(H.dna && H.ckey)
if(H.ckey)
dat += "<tr><td>[H]</td><td>[H.dna.unique_enzymes]</td><td>[H.dna.blood_type]</td></tr>"
dat += "</table>"
usr << browse(dat, "window=DNA;size=440x410")
@@ -231,12 +231,7 @@
dat += "<table cellspacing=5><tr><th>Name</th><th>Fingerprints</th></tr>"
for(var/mob/living/carbon/human/H in mob_list)
if(H.ckey)
if(H.dna && H.dna.uni_identity)
dat += "<tr><td>[H]</td><td>[md5(H.dna.uni_identity)]</td></tr>"
else if(H.dna && !H.dna.uni_identity)
dat += "<tr><td>[H]</td><td>H.dna.uni_identity = null</td></tr>"
else if(!H.dna)
dat += "<tr><td>[H]</td><td>H.dna = null</td></tr>"
dat += "<tr><td>[H]</td><td>[md5(H.dna.uni_identity)]</td></tr>"
dat += "</table>"
usr << browse(dat, "window=fingerprints;size=440x410")
@@ -259,8 +254,7 @@
message_admins("\blue [key_name_admin(usr)] turned all humans into [result]")
var/newtype = species_list[result]
for(var/mob/living/carbon/human/H in mob_list)
hardset_dna(H, null, null, null, null, newtype)
H.regenerate_icons()
H.set_species(newtype)
if("corgi")
if(!check_rights(R_FUN))
-1
View File
@@ -1527,7 +1527,6 @@
var/client/C = usr.client
if(!isobserver(usr)) C.admin_ghost()
var/mob/dead/observer/A = C.mob
sleep(2)
A.ManualFollow(M)
log_admin("[key_name(usr)] followed [key_name(M)]")
message_admins("[key_name_admin(usr)] followed [key_name_admin(M)]")
+1 -1
View File
@@ -26,7 +26,7 @@
for (var/mob/M in player_list)
if (istype(M, /mob/new_player))
continue
if (M.stat == DEAD || (M.client && M.client.holder && (M.client.prefs.chat_toggles & CHAT_DEAD))) //admins can toggle deadchat on and off. This is a proc in admin.dm and is only give to Administrators and above
if (M.stat == DEAD || istype(M, /mob/living/simple_animal/revenant) || (M.client && M.client.holder && (M.client.prefs.chat_toggles & CHAT_DEAD))) //admins can toggle deadchat on and off. This is a proc in admin.dm and is only give to Administrators and above
M.show_message(rendered, 2)
feedback_add_details("admin_verb","D") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+10 -100
View File
@@ -232,7 +232,7 @@
/datum/admins/proc/makeNukeTeam()
var/datum/game_mode/nuclear/temp = new
var/list/mob/dead/observer/candidates = getCandidates("Do you wish to be considered for a nuke team being sent in?", "operative", temp)
var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for a nuke team being sent in?", "operative", temp)
var/list/mob/dead/observer/chosen = list()
var/mob/dead/observer/theghost = null
@@ -306,7 +306,7 @@
// DEATH SQUADS
/datum/admins/proc/makeDeathsquad()
var/mission = input("Assign a mission to the deathsquad", "Assign Mission", "Leave no witnesses.")
var/list/mob/dead/observer/candidates = getCandidates("Do you wish to be considered for an elite Nanotrasen Strike Team?", "deathsquad", null)
var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for an elite Nanotrasen Strike Team?", "deathsquad", null)
var/squadSpawned = 0
if(candidates.len >= 2) //Minimum 2 to be considered a squad
@@ -326,13 +326,13 @@
//Spawn and equip the commando
var/mob/living/carbon/human/Commando = new(spawnloc)
chosen_candidate.client.prefs.copy_to(Commando)
ready_dna(Commando)
if(numagents == 1) //If Squad Leader
Commando.real_name = "Officer [pick(commando_names)]"
Commando.equipOutfit(/datum/outfit/death_commando/officer)
else
Commando.real_name = "Trooper [pick(commando_names)]"
Commando.equipOutfit(/datum/outfit/death_commando)
Commando.dna.update_dna_identity()
Commando.key = chosen_candidate.key
Commando.mind.assigned_role = "Death Commando"
for(var/obj/machinery/door/poddoor/ert/door in airlocks)
@@ -412,7 +412,7 @@
/datum/admins/proc/makeOfficial()
var/mission = input("Assign a task for the official", "Assign Task", "Conduct a routine preformance review of [station_name()] and its Captain.")
var/list/mob/dead/observer/candidates = getCandidates("Do you wish to be considered to be a Centcom Official?", "pAI")
var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered to be a Centcom Official?", "pAI")
if(candidates.len)
var/mob/dead/observer/chosen_candidate = pick(candidates)
@@ -420,8 +420,8 @@
//Create the official
var/mob/living/carbon/human/newmob = new (pick(emergencyresponseteamspawn))
chosen_candidate.client.prefs.copy_to(newmob)
ready_dna(newmob)
newmob.real_name = newmob.dna.species.random_name(newmob.gender,1)
newmob.dna.update_dna_identity()
newmob.key = chosen_candidate.key
newmob.mind.assigned_role = "Centcom Official"
newmob.equipOutfit(/datum/outfit/centcom_official)
@@ -465,7 +465,7 @@
return makeOfficial()
var/teamsize = min(7,input("Maximum size of team? (7 max)", "Select Team Size",4) as null|num)
var/mission = input("Assign a mission to the Emergency Response Team", "Assign Mission", "Assist the station.")
var/list/mob/dead/observer/candidates = getCandidates("Do you wish to be considered for a Code [alert] Nanotrasen Emergency Response Team?", "deathsquad", null)
var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for a Code [alert] Nanotrasen Emergency Response Team?", "deathsquad", null)
var/teamSpawned = 0
if(candidates.len > 0)
@@ -490,7 +490,6 @@
var/mob/living/carbon/human/ERTOperative = new(spawnloc)
var/list/lastname = last_names
chosen_candidate.client.prefs.copy_to(ERTOperative)
ready_dna(ERTOperative)
var/ertname = pick(lastname)
switch(numagents)
if(1)
@@ -514,6 +513,7 @@
if(7)
ERTOperative.real_name = "Engineer [ertname]"
ERTOperative.equipOutfit(redalert ? /datum/outfit/ert/engineer/alert : /datum/outfit/ert/engineer)
ERTOperative.dna.update_dna_identity()
ERTOperative.key = chosen_candidate.key
ERTOperative.mind.assigned_role = "ERT"
@@ -558,50 +558,11 @@
//Abductors
/datum/admins/proc/makeAbductorTeam()
var/list/mob/dead/observer/candidates = getCandidates("Do you wish to be considered for an Abductor Team?", "abductor", null)
if(candidates.len >= 2)
//Oh god why we can't have static functions
var/number = ticker.mode.abductor_teams + 1
var/datum/game_mode/abduction/temp
if(ticker.mode.config_tag == "abduction")
temp = ticker.mode
else
temp = new
var/agent_mind = pick(candidates)
candidates -= agent_mind
var/scientist_mind = pick(candidates)
var/mob/living/carbon/human/agent=makeBody(agent_mind)
var/mob/living/carbon/human/scientist=makeBody(scientist_mind)
agent_mind = agent.mind
scientist_mind = scientist.mind
temp.scientists.len = number
temp.agents.len = number
temp.abductors.len = 2*number
temp.team_objectives.len = number
temp.team_names.len = number
temp.scientists[number] = scientist_mind
temp.agents[number] = agent_mind
temp.abductors |= list(agent_mind,scientist_mind)
temp.make_abductor_team(number,preset_scientist=scientist_mind,preset_agent=agent_mind)
temp.post_setup_team(number)
ticker.mode.abductor_teams++
if(ticker.mode.config_tag != "abduction")
ticker.mode.abductors |= temp.abductors
return 1
else
return
new /datum/round_event/abductor
return 1
/datum/admins/proc/makeRevenant()
var/list/mob/dead/observer/candidates = getCandidates("Do you wish to be considered for becoming a revenant?", "revenant", null)
var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for becoming a revenant?", "revenant", null)
if(candidates.len >= 1)
var/spook_op = pick(candidates)
var/mob/dead/observer/O = spook_op
@@ -643,54 +604,3 @@
candidates.Remove(H)
return 1
return 0
/datum/admins/proc/getCandidates(var/Question, var/jobbanType, var/datum/game_mode/gametypeCheck)
var/list/mob/dead/observer/candidates = list()
var/time_passed = world.time
if (!Question)
Question = "Would you like to be a special role?"
for(var/mob/dead/observer/G in player_list)
if(!G.key || !G.client)
continue
if (gametypeCheck)
if(!gametypeCheck.age_check(G.client))
continue
if (jobbanType)
if(jobban_isbanned(G, jobbanType) || jobban_isbanned(G, "Syndicate"))
continue
spawn(0)
G << 'sound/misc/notice2.ogg' //Alerting them to their consideration
switch(alert(G,Question,"Please answer in 30 seconds!","Yes","No"))
if("Yes")
G << "<span class='notice'>Choice registered: Yes.</span>"
if((world.time-time_passed)>300)//If more than 30 game seconds passed.
G << "<span class='danger'>Sorry, you were too late for the consideration!</span>"
G << 'sound/machines/buzz-sigh.ogg'
return
candidates += G
if("No")
G << "<span class='danger'>Choice registered: No.</span>"
return
else
return
sleep(300)
//Check all our candidates, to make sure they didn't log off during the 30 second wait period.
for(var/mob/dead/observer/G in candidates)
if(!G.key || !G.client)
candidates.Remove(G)
return candidates
/datum/admins/proc/makeBody(mob/dead/observer/G_found) // Uses stripped down and bastardized code from respawn character
if(!G_found || !G_found.key) return
//First we spawn a dude.
var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned.
G_found.client.prefs.copy_to(new_character)
ready_dna(new_character)
new_character.key = G_found.key
return new_character
+6 -13
View File
@@ -300,15 +300,13 @@ Traitors and the like can also be revived with the previous role mostly intact.
new_character.real_name = record_found.fields["name"]
new_character.gender = record_found.fields["sex"]
new_character.age = record_found.fields["age"]
new_character.dna.blood_type = record_found.fields["blood_type"]
new_character.hardset_dna(record_found.fields["identity"], record_found.fields["enzymes"], record_found.fields["name"], record_found.fields["blood_type"], record_found.fields["species"], record_found.fields["features"])
else
new_character.gender = pick(MALE,FEMALE)
var/datum/preferences/A = new()
A.real_name = G_found.real_name
A.copy_to(new_character)
A.real_name = G_found.real_name
new_character.dna.update_dna_identity()
if(!new_character.real_name)
new_character.real_name = new_character.dna.species.random_name(new_character.gender,1)
new_character.name = new_character.real_name
if(G_found.mind && !G_found.mind.active)
@@ -316,13 +314,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
new_character.mind.special_verbs = list()
else
new_character.mind_initialize()
if(!new_character.mind.assigned_role) new_character.mind.assigned_role = "Assistant"//If they somehow got a null assigned role.
//DNA
if(record_found)//Pull up their name from database records if they did have a mind.
hardset_dna(new_character, record_found.fields["identity"], record_found.fields["enzymes"], record_found.fields["name"], record_found.fields["blood_type"], record_found.fields["species"], record_found.fields["features"])
else//If they have no records, we just do a random DNA for them, based on their random appearance/savefile.
ready_dna(new_character)
if(!new_character.mind.assigned_role)
new_character.mind.assigned_role = "Assistant"//If they somehow got a null assigned role.
new_character.key = G_found.key
@@ -822,7 +815,7 @@ var/list/datum/outfit/custom_outfits = list() //Admin created outfits
id_select += "<option value=\"[path]\">[path]</option>"
id_select += "</select>"
var/dat = {"
var/dat = {"
<html><head><title>Create Outfit</title></head><body>
<form name="outfit" action="byond://?src=\ref[src]" method="get">
<input type="hidden" name="src" value="\ref[src]">
+2 -2
View File
@@ -40,7 +40,7 @@
var/turf/T = get_turf(src)
T.visible_message("<span class='disarm'>[src] emits a blinding light!</span>")
for(var/mob/living/carbon/M in viewers(3, null))
flash_carbon(M, null, 2, 0)
flash_carbon(M, null, 5, 0)
/obj/item/device/assembly/flash/proc/burn_out() //Made so you can override it if you want to have an invincible flash from R&D or something.
@@ -79,7 +79,7 @@
return 1
/obj/item/device/assembly/flash/proc/flash_carbon(mob/living/carbon/M, mob/user = null, power = 5, targeted = 1)
/obj/item/device/assembly/flash/proc/flash_carbon(mob/living/carbon/M, mob/user = null, power = 15, targeted = 1)
add_logs(user, M, "flashed", src)
if(user && targeted)
if(M.weakeyes)
+14
View File
@@ -1,3 +1,5 @@
var/obj/machinery/gateway/centerstation/the_gateway = null
/obj/machinery/gateway
name = "gateway"
desc = "A mysterious gateway built by unknown hands, it allows for faster than light travel to far-flung locations."
@@ -9,6 +11,18 @@
var/active = 0
/obj/machinery/gateway/centerstation/New()
..()
if(!the_gateway)
the_gateway = src
/obj/machinery/gateway/centerstation/Destroy()
if(the_gateway == src)
the_gateway = null
..()
/obj/machinery/gateway/initialize()
update_icon()
if(dir == 2)
@@ -80,20 +80,17 @@
user.dna.add_mutation(LASEREYES)
user.dna.add_mutation(COLDRES)
user.dna.add_mutation(XRAY)
hardset_dna(user, null, null, null, null, /datum/species/shadow)
user.regenerate_icons()
user.set_species(/datum/species/shadow)
if("Wealth")
user << "<B>Your wish is granted, but at a terrible cost...</B>"
user << "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart."
new /obj/structure/closet/syndicate/resources/everything(loc)
hardset_dna(user, null, null, null, null, /datum/species/shadow)
user.regenerate_icons()
user.set_species(/datum/species/shadow)
if("Immortality")
user << "<B>Your wish is granted, but at a terrible cost...</B>"
user << "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart."
user.verbs += /mob/living/carbon/proc/immortality
hardset_dna(user, null, null, null, null, /datum/species/shadow)
user.regenerate_icons()
user.set_species(/datum/species/shadow)
if("To Kill")
user << "<B>Your wish is granted, but at a terrible cost...</B>"
user << "The Wish Granter punishes you for your wickedness, claiming your soul and warping your body to match the darkness in your heart."
@@ -107,8 +104,7 @@
for(var/datum/objective/OBJ in user.mind.objectives)
user << "<B>Objective #[obj_count]</B>: [OBJ.explanation_text]"
obj_count++
hardset_dna(user, null, null, null, null, /datum/species/shadow)
user.regenerate_icons()
user.set_species(/datum/species/shadow)
if("Peace")
user << "<B>Whatever alien sentience that the Wish Granter possesses is satisfied with your wish. There is a distant wailing as the last of the Faithless begin to die, then silence.</B>"
user << "You feel as if you just narrowly avoided a terrible fate..."

Some files were not shown because too many files have changed in this diff Show More