Virology rebalance

- Effects can now appear and be spliced in at higher stages than their set stages (e.g. Waiting Syndrome can now occur in any block)
- Gibbingtons changed to not instantly gib infected on activation, instead either dealing massive brute damage or making humanoids' limbs fall off; this avoids three copies of Waiting Syndrome then Gibbingtons going undetected until it instagibs the entire station one after the other.
- New effect: chemical synthesis. Picks one reagent from its list, and keeps infected at 5-7u of that reagent. Infecting others, splicing the gene, etc does not change the reagent, only generating an entirely new chemical synthesis effect does that.
- Admin panel for spawning viruses
- Virus dish examine() now doesn't print 15+ lines to output, instead printing one line and a link to open a window with the rest (and it calls ..() now)
- Lowercased most virology machinery's names
- Renamed/reordered antigens, there are now 16 antigens rather than 11, and they don't use the blood markers' names despite not being affected by blood type at all
- Generating random effects does not rely so much on the GC
This commit is contained in:
GinjaNinja32
2015-01-20 09:57:47 +00:00
parent 9890bdc86d
commit a1e5194c34
13 changed files with 309 additions and 39 deletions

View File

@@ -1429,6 +1429,7 @@
#include "code\modules\vehicles\cargo_train.dm"
#include "code\modules\vehicles\train.dm"
#include "code\modules\vehicles\vehicle.dm"
#include "code\modules\virus2\admin.dm"
#include "code\modules\virus2\analyser.dm"
#include "code\modules\virus2\antibodies.dm"
#include "code\modules\virus2\centrifuge.dm"

View File

@@ -106,7 +106,8 @@ var/list/admin_verbs_fun = list(
)
var/list/admin_verbs_spawn = list(
/datum/admins/proc/spawn_atom, /*allows us to spawn instances*/
/client/proc/respawn_character
/client/proc/respawn_character,
/client/proc/virus2_editor
)
var/list/admin_verbs_server = list(
/client/proc/Set_Holiday,

View File

@@ -0,0 +1,197 @@
/datum/disease2/disease/Topic(href, href_list)
. = ..()
if(.) return
if(href_list["info"])
// spawn or admin privileges to see info about viruses
if(!check_rights(R_ADMIN|R_SPAWN)) return
usr << "Infection chance: [infectionchance]; Speed: [speed]; Spread type: [spreadtype]"
usr << "Affected species: [english_list(affected_species)]"
usr << "Effects:"
for(var/datum/disease2/effectholder/E in effects)
usr << "[E.stage]: [E.effect.name]; chance=[E.chance]; multiplier=[E.multiplier]"
usr << "Antigens: [antigens2string(antigen)]"
/datum/admins/var/datum/virus2_editor/virus2_editor_datum = new
/client/proc/virus2_editor()
set name = "Virus Editor"
set category = "Admin"
if(!holder || !check_rights(R_SPAWN)) return // spawn privileges to create viruses
holder.virus2_editor_datum.show_ui(src)
/datum/virus2_editor
var/list/s = list(/datum/disease2/effect/invisible,/datum/disease2/effect/invisible,/datum/disease2/effect/invisible,/datum/disease2/effect/invisible)
var/list/s_chance = list(1,1,1,1)
var/list/s_multiplier = list(1,1,1,1)
var/species = list()
var/infectionchance = 70
var/spreadtype = "Contact"
var/antigens = 0
var/speed = 1
var/mob/living/carbon/infectee = null
// this holds spawned viruses so that the "Info" links work after the proc exits
var/list/spawned_viruses = list()
proc/select(mob/user, stage)
if(stage < 1 || stage > 4) return
var/list/L = list()
for(var/e in (typesof(/datum/disease2/effect) - /datum/disease2/effect))
var/datum/disease2/effect/f = e
if(initial(f.stage) <= stage)
L[initial(f.name)] = e
var/datum/disease2/effect/Eff = s[stage]
var/C = input("Select effect for stage [stage]:", "Stage [stage]", initial(Eff.name)) as null|anything in L
if(!C) return
return L[C]
proc/show_ui(mob/user)
var/H = {"
<center><h3>Virus2 Virus Editor</h3></center><br />
<b>Effects:</b><br />
"}
for(var/i = 1 to 4)
var/datum/disease2/effect/Eff = s[i]
H += {"
<a href='?src=\ref[src];what=effect;stage=[i];effect=1'>[initial(Eff.name)]</a>
Chance: <a href='?src=\ref[src];what=effect;stage=[i];chance=1'>[s_chance[i]]</a>
Multiplier: <a href='?src=\ref[src];what=effect;stage=[i];multiplier=1'>[s_multiplier[i]]</a>
<br />
"}
H += {"
<br />
<b>Infectable Species:</b><br />
"}
var/f = 1
for(var/k in all_species)
var/datum/species/S = all_species[k]
if(!(S.flags & IS_SYNTHETIC))
if(!f) H += " | "
else f = 0
H += "<a href='?src=\ref[src];what=species;toggle=[k]' style='color:[(k in species) ? "#006600" : "#ff0000"]'>[k]</a>"
H += {"
<a href="?src=\ref[src];what=species;reset=1" style="color:#0000aa">Reset</a>
<br />
<b>Infection Chance:</b> <a href="?src=\ref[src];what=ichance">[infectionchance]</a><br />
<b>Spread Type:</b> <a href="?src=\ref[src];what=stype">[spreadtype]</a><br />
<b>Speed:</b> <a href="?src=\ref[src];what=speed">[speed]</a><br />
<br />
"}
f = 1
for(var/k in ANTIGENS)
if(!f) H += " | "
else f = 0
H += "<a href='?src=\ref[src];what=antigen;toggle=[k]' style='color:[(text2num(k) & antigens) ? "#006600" : "#ff0000"]'>[ANTIGENS[k]]</a>"
H += {"
<a href="?src=\ref[src];what=antigen;reset=1" style="color:#0000aa">Reset</a>
<br />
<hr />
<b>Initial infectee:</b> <a href="?src=\ref[src];what=infectee">[infectee ? infectee : "(choose)"]</a>
<a href="?src=\ref[src];what=go" style="color:#ff0000">RELEASE</a>
"}
user << browse(H, "window=virus2edit")
Topic(href, href_list)
switch(href_list["what"])
if("effect")
var/stage = text2num(href_list["stage"])
if(href_list["effect"])
var/datum/disease2/effect/E = select(usr,stage)
if(!E) return
s[stage] = E
// set a default chance and multiplier of half the maximum (roughly average)
s_chance[stage] = max(1, round(initial(E.chance_maxm)/2))
s_multiplier[stage] = max(1, round(initial(E.maxm)/2))
else if(href_list["chance"])
var/datum/disease2/effect/Eff = s[stage]
var/I = input("Chance, per tick, of this effect happening (min 0, max [initial(Eff.chance_maxm)])", "Effect Chance", s_chance[stage]) as null|num
if(I == null || I < 0 || I > initial(Eff.chance_maxm)) return
s_chance[stage] = I
else if(href_list["multiplier"])
var/datum/disease2/effect/Eff = s[stage]
var/I = input("Multiplier for this effect (min 1, max [initial(Eff.maxm)])", "Effect Multiplier", s_multiplier[stage]) as null|num
if(I == null || I < 1 || I > initial(Eff.maxm)) return
s_multiplier[stage] = I
if("species")
if(href_list["toggle"])
var/T = href_list["toggle"]
if(T in species)
species -= T
else
species |= T
else if(href_list["reset"])
species = list()
if(infectee)
if(!infectee.species || !(infectee.species.name in species))
infectee = null
if("ichance")
var/I = input("Input infection chance", "Infection Chance", infectionchance) as null|num
if(!I) return
infectionchance = I
if("stype")
var/S = alert("Which spread type?", "Spread Type", "Cancel", "Contact", "Airborne")
if(!S || S == "Cancel") return
spreadtype = S
if("speed")
var/S = input("Input speed", "Speed", speed) as null|num
if(!S) return
speed = S
if("antigen")
if(href_list["toggle"])
var/T = text2num(href_list["toggle"])
if(T&antigens)
antigens &= ~T
else
antigens |= T
else if(href_list["reset"])
antigens = 0
if("infectee")
var/list/candidates = list()
for(var/mob/living/carbon/G in living_mob_list)
if(G.stat != DEAD && G.species)
if(G.species.name in species)
candidates["[G.name][G.client ? "" : " (no client)"]"] = G
else
candidates["[G.name] ([G.species.name])[G.client ? "" : " (no client)"]"] = G
if(!candidates.len) usr << "No possible candidates found!"
var/I = input("Choose initial infectee", "Infectee", infectee) as null|anything in candidates
if(!I || !candidates[I]) return
infectee = candidates[I]
species |= infectee.species.name
if("go")
if(!antigens)
var/a = alert("This disease has no antigens; it will be impossible to permanently immunise anyone without them.\
It is strongly recommended to set at least one antigen. Do you want to go back and edit your virus?", "Antigens", "Yes", "Yes", "No")
if(a == "Yes") return
var/datum/disease2/disease/D = new
D.infectionchance = infectionchance
D.spreadtype = spreadtype
D.antigen = antigens
D.affected_species = species
D.speed = speed
for(var/i in 1 to 4)
var/datum/disease2/effectholder/E = new
var/Etype = s[i]
E.effect = new Etype()
E.effect.generate()
E.chance = s_chance[i]
E.multiplier = s_multiplier[i]
E.stage = i
D.effects += E
spawned_viruses += D
message_admins("<span class='danger'>[key_name_admin(usr)] infected [key_name_admin(infectee)] with a virus (<a href='?src=\ref[D];info=1'>Info</a>)</span>")
log_admin("[key_name_admin(usr)] infected [key_name_admin(infectee)] with a virus!")
infect_virus2(infectee, D, forced=1)
show_ui(usr)

View File

@@ -1,5 +1,5 @@
/obj/machinery/disease2/diseaseanalyser
name = "Disease Analyser"
name = "disease analyser"
icon = 'icons/obj/virology.dmi'
icon_state = "analyser"
anchored = 1
@@ -43,7 +43,9 @@
<hr>
<u>Additional Notes:</u>&nbsp;
"}
dish.basic_info = dish.virus2.get_basic_info()
dish.info = r
dish.name = "[initial(dish.name)] ([dish.virus2.name()])"
dish.analysed = 1
dish.loc = src.loc
dish = null

View File

@@ -3,30 +3,38 @@
// reserving some numbers for later special antigens
var/global/const/ANTIGEN_A = 1
var/global/const/ANTIGEN_B = 2
var/global/const/ANTIGEN_RH = 4
var/global/const/ANTIGEN_Q = 8
var/global/const/ANTIGEN_U = 16
var/global/const/ANTIGEN_V = 32
var/global/const/ANTIGEN_X = 64
var/global/const/ANTIGEN_Y = 128
var/global/const/ANTIGEN_Z = 256
var/global/const/ANTIGEN_M = 512
var/global/const/ANTIGEN_N = 1024
var/global/const/ANTIGEN_P = 2048
var/global/const/ANTIGEN_O = 4096
var/global/const/ANTIGEN_C = 4
var/global/const/ANTIGEN_D = 8
var/global/const/ANTIGEN_E = 16
var/global/const/ANTIGEN_M = 32
var/global/const/ANTIGEN_N = 64
var/global/const/ANTIGEN_O = 128
var/global/const/ANTIGEN_P = 256
var/global/const/ANTIGEN_Q = 512
var/global/const/ANTIGEN_U = 1024
var/global/const/ANTIGEN_V = 2048
var/global/const/ANTIGEN_W = 4096
var/global/const/ANTIGEN_X = 8192
var/global/const/ANTIGEN_Y = 16384
var/global/const/ANTIGEN_Z = 32768
var/global/list/ANTIGENS = list(
"[ANTIGEN_A]" = "A",
"[ANTIGEN_B]" = "B",
"[ANTIGEN_RH]" = "RH",
"[ANTIGEN_C]" = "C",
"[ANTIGEN_E]" = "E",
"[ANTIGEN_D]" = "D",
"[ANTIGEN_M]" = "M",
"[ANTIGEN_N]" = "N",
"[ANTIGEN_O]" = "O",
"[ANTIGEN_P]" = "P",
"[ANTIGEN_Q]" = "Q",
"[ANTIGEN_U]" = "U",
"[ANTIGEN_V]" = "V",
"[ANTIGEN_Z]" = "Z",
"[ANTIGEN_M]" = "M",
"[ANTIGEN_N]" = "N",
"[ANTIGEN_P]" = "P",
"[ANTIGEN_O]" = "O"
"[ANTIGEN_W]" = "W",
"[ANTIGEN_X]" = "X",
"[ANTIGEN_Y]" = "Y",
"[ANTIGEN_Z]" = "Z"
)
// pure concentrated antibodies

View File

@@ -1,5 +1,5 @@
/obj/machinery/computer/centrifuge
name = "Isolation Centrifuge"
name = "isolation centrifuge"
desc = "Used to separate things with different weight. Spin 'em round, round, right round."
icon = 'icons/obj/virology.dmi'
icon_state = "centrifuge"

View File

@@ -1,5 +1,5 @@
/obj/machinery/computer/curer
name = "Cure Research Machine"
name = "cure research machine"
icon = 'icons/obj/computer.dmi'
icon_state = "dna"
circuit = /obj/item/weapon/circuitboard/curefab

View File

@@ -133,6 +133,7 @@
for(var/datum/disease2/effectholder/holder in effects)
var/datum/disease2/effectholder/newholder = new /datum/disease2/effectholder
newholder.effect = new holder.effect.type
newholder.effect.generate(holder.effect.data)
newholder.chance = holder.chance
newholder.cure = holder.cure
newholder.multiplier = holder.multiplier
@@ -175,6 +176,12 @@ var/global/list/virusDB = list()
var/datum/data/record/V = virusDB["[uniqueID]"]
.= V.fields["name"]
/datum/disease2/disease/proc/get_basic_info()
var/t = ""
for(var/datum/disease2/effectholder/E in effects)
t += ", [E.effect.name]"
return "[name()] ([copytext(t,3)])"
/datum/disease2/disease/proc/get_info()
var/r = {"
<small>Analysis determined the existence of a GNAv2-based viral lifeform.</small><br>

View File

@@ -1,5 +1,5 @@
/obj/machinery/computer/diseasesplicer
name = "Disease Splicer"
name = "disease splicer"
icon = 'icons/obj/computer.dmi'
icon_state = "crew"
@@ -49,7 +49,7 @@
data["affected_species"] = null
if (memorybank)
data["buffer"] = list("name" = (analysed ? memorybank.effect.name : "Unknown Symptom"), "stage" = memorybank.stage)
data["buffer"] = list("name" = (analysed ? memorybank.effect.name : "Unknown Symptom"), "stage" = memorybank.effect.stage)
if (species_buffer)
data["species_buffer"] = analysed ? list2text(species_buffer, ", ") : "Unknown Species"
@@ -161,8 +161,12 @@
if(href_list["splice"])
if(dish)
if (memorybank)
var/target = text2num(href_list["splice"])
if(target < 1 || target > 4) return // out of bounds
if(target < memorybank.effect.stage) return // too powerful, catching this for href exploit prevention
for(var/datum/disease2/effectholder/e in dish.virus2.effects)
if(e.stage == memorybank.stage)
if(e.stage == target)
e.effect = memorybank.effect
if (species_buffer)

View File

@@ -1,5 +1,5 @@
/obj/machinery/disease2/incubator/
name = "Pathogenic incubator"
name = "pathogenic incubator"
density = 1
anchored = 1
icon = 'icons/obj/virology.dmi'
@@ -108,6 +108,7 @@
dish.virus2.majormutate()
if(dish.info)
dish.info = "OUTDATED : [dish.info]"
dish.basic_info = "OUTDATED: [dish.basic_info]"
dish.analysed = 0
ping("\The [src] pings, \"Mutant viral strain detected.\"")
else if(prob(5))

View File

@@ -16,12 +16,14 @@
/datum/disease2/effectholder/proc/getrandomeffect(var/badness = 1)
var/list/datum/disease2/effect/list = list()
for(var/e in (typesof(/datum/disease2/effect) - /datum/disease2/effect))
var/datum/disease2/effect/f = new e
if (f.badness > badness) //we don't want such strong effects
var/datum/disease2/effect/f = e
if (initial(f.badness) > badness) //we don't want such strong effects
continue
if(f.stage == src.stage)
if(initial(f.stage) <= src.stage)
list += f
effect = pick(list)
var/type = pick(list)
effect = new type()
effect.generate()
chance = rand(0,effect.chance_maxm)
multiplier = rand(1,effect.maxm)
@@ -45,8 +47,11 @@
var/stage = 4
var/maxm = 1
var/badness = 1
var/data = null // For semi-procedural effects; this should be generated in generate() if used
proc/activate(var/mob/living/carbon/mob,var/multiplier)
proc/deactivate(var/mob/living/carbon/mob)
proc/generate(copy_data) // copy_data will be non-null if this is a copy; it should be used to initialise the data for this effect if present
/datum/disease2/effect/invisible
name = "Waiting Syndrome"
@@ -67,7 +72,23 @@
stage = 4
badness = 3
activate(var/mob/living/carbon/mob,var/multiplier)
mob.gib()
// Probabilities have been tweaked to kill in ~2-3 minutes, giving 5-10 messages.
// Probably needs more balancing, but it's better than LOL U GIBBED NOW, especially now that viruses can potentially have no signs up until Gibbingtons.
mob.adjustBruteLoss(10*multiplier)
if(istype(mob, /mob/living/carbon/human))
var/mob/living/carbon/human/H = mob
var/datum/organ/external/O = pick(H.organs)
if(prob(25))
mob << "<span class='warning'>Your [O.display_name] feels as if it might fall off!</span>"
if(prob(10))
spawn(50)
if(O)
O.droplimb(1)
else
if(prob(75))
mob << "<span class='warning'>Your whole body feels like it might fall apart!</span>"
if(prob(10))
mob.adjustBruteLoss(25*multiplier)
/datum/disease2/effect/radian
name = "Radian's Syndrome"
@@ -257,6 +278,26 @@
chance_maxm = 25
activate(var/mob/living/carbon/mob,var/multiplier)
mob.say("*groan")
/datum/disease2/effect/chem_synthesis
name = "Chemical Synthesis"
stage = 3
chance_maxm = 25
generate(c_data)
if(c_data)
data = c_data
else
data = pick("bicaridine", "kelotane", "dylovene", "inaprovaline", "space_drugs", "sugar",
"tramadol", "dexalin", "cryptobiolin", "impedrezene", "hyperzine", "ethylredoxrazine",
"mindbreaker", "nutriment", "ethanol")
var/datum/reagent/R = chemical_reagents_list[data]
name = "[initial(name)] ([initial(R.name)])"
activate(var/mob/living/carbon/mob,var/multiplier)
if (mob.reagents.get_reagent_amount(data) < 5)
mob.reagents.add_reagent(data, 2)
////////////////////////STAGE 2/////////////////////////////////
/datum/disease2/effect/scream

View File

@@ -4,7 +4,7 @@
#define ENTRY "entry"
/obj/machinery/disease2/isolator/
name = "Pathogenic Isolator"
name = "pathogenic isolator"
density = 1
anchored = 1
icon = 'icons/obj/virology.dmi'

View File

@@ -1,7 +1,7 @@
///////////////ANTIBODY SCANNER///////////////
/obj/item/device/antibody_scanner
name = "\improper Antibody Scanner"
name = "antibody scanner"
desc = "Scans living beings for antibodies in their blood."
icon_state = "health"
w_class = 2.0
@@ -36,11 +36,12 @@
///////////////VIRUS DISH///////////////
/obj/item/weapon/virusdish
name = "virus containment/growth dish"
name = "virus dish"
icon = 'icons/obj/items.dmi'
icon_state = "implantcase-b"
var/datum/disease2/disease/virus2 = null
var/growth = 0
var/basic_info = null
var/info = 0
var/analysed = 0
@@ -66,10 +67,17 @@
del src
/obj/item/weapon/virusdish/examine(mob/user)
user << "This is a virus containment dish."
if(src.info)
user << "It has the following information about its contents:"
user << src.info
..()
if(basic_info)
user << "[basic_info] : <a href='?src=\ref[src];info=1'>More Information</a>"
/obj/item/weapon/virusdish/Topic(href, href_list)
. = ..()
if(.) return
if(href_list["info"])
usr << browse(info, "window=virusinfo")
return 1
/obj/item/weapon/ruinedvirusdish
name = "ruined virus sample"