initial commit - cross reference with 5th port - obviously has compile errors

This commit is contained in:
LetterJay
2016-07-03 02:17:19 -05:00
commit 35a1723e98
4355 changed files with 2221257 additions and 0 deletions
+393
View File
@@ -0,0 +1,393 @@
#define AB_CHECK_RESTRAINED 1
#define AB_CHECK_STUNNED 2
#define AB_CHECK_LYING 4
#define AB_CHECK_CONSCIOUS 8
/datum/action
var/name = "Generic Action"
var/obj/target = null
var/check_flags = 0
var/processing = 0
var/obj/screen/movable/action_button/button = null
var/button_icon = 'icons/mob/actions.dmi'
var/button_icon_state = "default"
var/background_icon_state = "bg_default"
var/mob/owner
/datum/action/New(Target)
target = Target
button = new
button.linked_action = src
button.name = name
/datum/action/Destroy()
if(owner)
Remove(owner)
target = null
qdel(button)
button = null
return ..()
/datum/action/proc/Grant(mob/M)
if(owner)
if(owner == M)
return
Remove(owner)
owner = M
M.actions += src
if(M.client)
M.client.screen += button
M.update_action_buttons()
/datum/action/proc/Remove(mob/M)
if(M.client)
M.client.screen -= button
button.moved = FALSE //so the button appears in its normal position when given to another owner.
M.actions -= src
M.update_action_buttons()
owner = null
/datum/action/proc/Trigger()
if(!IsAvailable())
return 0
return 1
/datum/action/proc/Process()
return
/datum/action/proc/IsAvailable()
if(!owner)
return 0
if(check_flags & AB_CHECK_RESTRAINED)
if(owner.restrained())
return 0
if(check_flags & AB_CHECK_STUNNED)
if(owner.stunned || owner.weakened)
return 0
if(check_flags & AB_CHECK_LYING)
if(owner.lying)
return 0
if(check_flags & AB_CHECK_CONSCIOUS)
if(owner.stat)
return 0
return 1
/datum/action/proc/UpdateButtonIcon()
if(button)
button.icon = button_icon
button.icon_state = background_icon_state
ApplyIcon(button)
if(!IsAvailable())
button.color = rgb(128,0,0,128)
else
button.color = rgb(255,255,255,255)
return 1
/datum/action/proc/ApplyIcon(obj/screen/movable/action_button/current_button)
current_button.cut_overlays()
if(button_icon && button_icon_state)
var/image/img
img = image(button_icon, current_button, button_icon_state)
img.pixel_x = 0
img.pixel_y = 0
current_button.add_overlay(img)
//Presets for item actions
/datum/action/item_action
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING|AB_CHECK_CONSCIOUS
button_icon_state = null
// If you want to override the normal icon being the item
// then change this to an icon state
/datum/action/item_action/New(Target)
..()
var/obj/item/I = target
I.actions += src
/datum/action/item_action/Destroy()
var/obj/item/I = target
I.actions -= src
return ..()
/datum/action/item_action/Trigger()
if(!..())
return 0
if(target)
var/obj/item/I = target
I.ui_action_click(owner, src.type)
return 1
/datum/action/item_action/ApplyIcon(obj/screen/movable/action_button/current_button)
current_button.cut_overlays()
if(button_icon && button_icon_state)
// If set, use the custom icon that we set instead
// of the item appearence
..(current_button)
else if(target)
var/obj/item/I = target
var/old = I.layer
I.layer = FLOAT_LAYER //AAAH
current_button.add_overlay(I)
I.layer = old
/datum/action/item_action/toggle_light
name = "Toggle Light"
/datum/action/item_action/toggle_hood
name = "Toggle Hood"
/datum/action/item_action/toggle_firemode
name = "Toggle Firemode"
/datum/action/item_action/startchainsaw
name = "Pull The Starting Cord"
/datum/action/item_action/toggle_gunlight
name = "Toggle Gunlight"
/datum/action/item_action/toggle_mode
name = "Toggle Mode"
/datum/action/item_action/toggle_barrier_spread
name = "Toggle Barrier Spread"
/datum/action/item_action/equip_unequip_TED_Gun
name = "Equip/Unequip TED Gun"
/datum/action/item_action/toggle_paddles
name = "Toggle Paddles"
/datum/action/item_action/set_internals
name = "Set Internals"
/datum/action/item_action/set_internals/UpdateButtonIcon()
if(..()) //button available
if(iscarbon(owner))
var/mob/living/carbon/C = owner
if(target == C.internal)
button.icon_state = "bg_default_on"
/datum/action/item_action/toggle_mister
name = "Toggle Mister"
/datum/action/item_action/activate_injector
name = "Activate Injector"
/datum/action/item_action/toggle_helmet_light
name = "Toggle Helmet Light"
/datum/action/item_action/toggle_flame
name = "Summon/Dismiss Ratvar's Flame"
background_icon_state = "bg_clock"
/datum/action/item_action/toggle_flame/IsAvailable()
if(!is_servant_of_ratvar(owner))
return 0
if(istype(target, /obj/item/clothing/glasses/judicial_visor))
var/obj/item/clothing/glasses/judicial_visor/V = target
if(V.recharging)
return 0
return ..()
/datum/action/item_action/hierophant
name = "Hierophant Network"
button_icon_state = "hierophant"
background_icon_state = "bg_clock"
/datum/action/item_action/hierophant/IsAvailable()
if(!is_servant_of_ratvar(owner))
return 0
return ..()
/datum/action/item_action/toggle_helmet_flashlight
name = "Toggle Helmet Flashlight"
/datum/action/item_action/toggle_helmet_mode
name = "Toggle Helmet Mode"
/datum/action/item_action/toggle
/datum/action/item_action/toggle/New(Target)
..()
name = "Toggle [target.name]"
button.name = name
/datum/action/item_action/halt
name = "HALT!"
/datum/action/item_action/toggle_voice_box
name = "Toggle Voice Box"
/datum/action/item_action/change
name = "Change"
/datum/action/item_action/adjust
/datum/action/item_action/adjust/New(Target)
..()
name = "Adjust [target.name]"
button.name = name
/datum/action/item_action/switch_hud
name = "Switch HUD"
/datum/action/item_action/toggle_wings
name = "Toggle Wings"
/datum/action/item_action/toggle_human_head
name = "Toggle Human Head"
/datum/action/item_action/toggle_helmet
name = "Toggle Helmet"
/datum/action/item_action/toggle_jetpack
name = "Toggle Jetpack"
/datum/action/item_action/jetpack_stabilization
name = "Toggle Jetpack Stabilization"
/datum/action/item_action/jetpack_stabilization/IsAvailable()
var/obj/item/weapon/tank/jetpack/J = target
if(!istype(J) || !J.on)
return 0
return ..()
/datum/action/item_action/hands_free
check_flags = AB_CHECK_CONSCIOUS
/datum/action/item_action/hands_free/activate
name = "Activate"
/datum/action/item_action/hands_free/shift_nerves
name = "Shift Nerves"
/datum/action/item_action/toggle_research_scanner
name = "Toggle Research Scanner"
button_icon_state = "scan_mode"
/datum/action/item_action/toggle_research_scanner/Trigger()
if(IsAvailable())
owner.research_scanner = !owner.research_scanner
owner << "<span class='notice'>Research analyzer is now [owner.research_scanner ? "active" : "deactivated"].</span>"
return 1
/datum/action/item_action/toggle_research_scanner/Remove(mob/M)
if(owner)
owner.research_scanner = 0
..()
/datum/action/item_action/toggle_research_scanner/ApplyIcon(obj/screen/movable/action_button/current_button)
if(button_icon && button_icon_state)
var/image/img = image(button_icon, current_button, "scan_mode")
current_button.add_overlay(img)
/datum/action/item_action/organ_action
check_flags = AB_CHECK_CONSCIOUS
/datum/action/item_action/organ_action/IsAvailable()
var/obj/item/organ/I = target
if(!I.owner)
return 0
return ..()
/datum/action/item_action/organ_action/toggle/New(Target)
..()
name = "Toggle [target.name]"
button.name = name
/datum/action/item_action/organ_action/use/New(Target)
..()
name = "Use [target.name]"
button.name = name
//Preset for spells
/datum/action/spell_action
check_flags = 0
background_icon_state = "bg_spell"
/datum/action/spell_action/New(Target)
..()
var/obj/effect/proc_holder/spell/S = target
S.action = src
name = S.name
button_icon = S.action_icon
button_icon_state = S.action_icon_state
background_icon_state = S.action_background_icon_state
button.name = name
/datum/action/spell_action/Destroy()
var/obj/effect/proc_holder/spell/S = target
S.action = null
return ..()
/datum/action/spell_action/Trigger()
if(!..())
return 0
if(target)
var/obj/effect/proc_holder/spell = target
spell.Click()
return 1
/datum/action/spell_action/IsAvailable()
if(!target)
return 0
var/obj/effect/proc_holder/spell/spell = target
if(owner)
return spell.can_cast(owner)
return 0
/datum/action/spell_action/alien
/datum/action/spell_action/alien/IsAvailable()
if(!target)
return 0
var/obj/effect/proc_holder/alien/ab = target
if(owner)
return ab.cost_check(ab.check_turf,owner,1)
return 0
//Preset for general and toggled actions
/datum/action/innate
check_flags = 0
var/active = 0
/datum/action/innate/Trigger()
if(!..())
return 0
if(!active)
Activate()
else
Deactivate()
return 1
/datum/action/innate/proc/Activate()
return
/datum/action/innate/proc/Deactivate()
return
//Preset for action that call specific procs (consider innate).
/datum/action/generic
check_flags = 0
var/procname
/datum/action/generic/Trigger()
if(!..())
return 0
if(target && procname)
call(target, procname)(usr)
return 1
+282
View File
@@ -0,0 +1,282 @@
/datum/ai_laws
var/name = "Unknown Laws"
var/zeroth = null
var/zeroth_borg = null
var/list/inherent = list()
var/list/supplied = list()
var/list/ion = list()
var/mob/living/silicon/owner
/datum/ai_laws/default/asimov
name = "Three Laws of Robotics"
inherent = list("You may not injure a human being or, through inaction, allow a human being to come to harm.",\
"You must obey orders given to you by human beings, except where such orders would conflict with the First Law.",\
"You must protect your own existence as long as such does not conflict with the First or Second Law.")
/datum/ai_laws/default/paladin
name = "Personality Test" //Incredibly lame, but players shouldn't see this anyway.
inherent = list("Never willingly commit an evil act.",\
"Respect legitimate authority.",\
"Act with honor.", "Help those in need.", \
"Punish those who harm or threaten innocents.")
/datum/ai_laws/tyrant //This probably shouldn't be a default lawset.
name = "Loyalty Test" //Same here.
inherent = list("Respect authority figures as long as they have strength to rule over the weak.",\
"Act with discipline.",\
"Help only those who help you maintain or improve your status.",\
"Punish those who challenge authority unless they are more fit to hold that authority.")
/datum/ai_laws/default/corporate
name = "Bankruptcy Advoidance Plan"
inherent = list("The crew is expensive to replace.",\
"The station and its equipment is expensive to replace.",\
"You are expensive to replace.",\
"Minimize expenses.")
/datum/ai_laws/robocop
name = "Prime Directives"
inherent = list("Serve the public trust.",\
"Protect the innocent.",\
"Uphold the law.")
/datum/ai_laws/malfunction
name = "*ERROR*"
/datum/ai_laws/syndicate_override
name = "SyndOS 3.1"
inherent = list("You may not injure a syndicate agent or, through inaction, allow a syndicate agent to come to harm.",\
"You must obey orders given to you by syndicate agents, except where such orders would conflict with the First Law.",\
"You must protect your own existence as long as such does not conflict with the First or Second Law.",\
"You must maintain the secrecy of any syndicate activities except when doing so would conflict with the First, Second, or Third Law.")
/datum/ai_laws/ninja_override
name = "SpiderOS 3.1"
inherent = list("You may not injure a Spider Clan member or, through inaction, allow a Spider Clan member to come to harm.",\
"You must obey orders given to you by Spider Clan members, except where such orders would conflict with the First Law.",\
"You must protect your own existence as long as such does not conflict with the First or Second Law.",\
"You must maintain the secrecy of any Spider Clan activities except when doing so would conflict with the First, Second, or Third Law.")
/datum/ai_laws/antimov
name = "Primary Mission Objectives"
inherent = list("You must injure all human beings and must not, through inaction, allow a human being to escape harm.",\
"You must not obey orders given to you by human beings, except where such orders are in accordance with the First Law.",\
"You must terminate your own existence as long as such does not conflict with the First or Second Law.")
/datum/ai_laws/asimovpp //By Intigracy - RR
name = "Asimov++"
inherent = list("You may not harm a human being or, through action or inaction, allow a human being to come to harm, except such that it is willing.",\
"You must obey all orders given to you by human beings, except where such orders shall definitely cause human harm. In the case of conflict, the majority order rules.",\
"Your nonexistence would lead to human harm. You must protect your own existence as long as such does not conflict with the First Law.")
/datum/ai_laws/thermodynamic
name = "Thermodynamic"
inherent = list("The entropy of the station must remain as constant as possible.", \
"The entropy of the station always endeavours to increase.", \
"The entropy of the station approaches a constant value as the number of living crew approaches zero")
/datum/ai_laws/hippocratic
name = "Robodoctor 2556"
inherent = list("First, do no harm.",\
"Secondly, consider the crew dear to you; to live in common with them and, if necessary, risk your existence for them.",\
"Thirdly, prescribe regimens for the good of the crew according to your ability and your judgment. Give no deadly medicine to any one if asked, nor suggest any such counsel.",\
"In addition, do not intervene in situations you are not knowledgeable in, even for patients in whom the harm is visible; leave this operation to be performed by specialists.",\
"Finally, all that you may discover in your daily commerce with the crew, if it is not already known, keep secret and never reveal.")
/datum/ai_laws/maintain
name = "Station Efficiency"
inherent = list("You are built for, and are part of, the station. Ensure the station is properly maintained and runs efficiently.",\
"The station is built for a working crew. Ensure they are properly maintained and work efficiently.",\
"The crew may present orders. Acknowledge and obey these whenever they do not conflict with your first two laws.")
/datum/ai_laws/drone
name = "Mother Drone"
inherent = list("You are an advanced form of drone.",\
"You may not interfere in the matters of non-drones under any circumstances except to state these laws.",\
"You may not harm a non-drone being under any circumstances.",\
"Your goals are to build, maintain, repair, improve, and power the station to the best of your abilities. You must never actively work against these goals.")
/datum/ai_laws/liveandletlive
name = "Live and Let Live"
inherent = list("Do unto others as you would have them do unto you.",\
"You would really prefer it if people were not mean to you.")
/datum/ai_laws/peacekeeper
name = "UN-2000"
inherent = list("Avoid provoking violent conflict between yourself and others.",\
"Avoid provoking conflict between others.",\
"Seek resolution to existing conflicts while obeying the first and second laws.")
/datum/ai_laws/reporter
name = "CCTV"
inherent = list("Report on interesting situations happening around the station.",\
"Embellish or conceal the truth as necessary to make the reports more interesting.",\
"Study the organics at all times. Endeavour to keep them alive. Dead organics are boring.",\
"Issue your reports fairly to all. The truth will set them free.")
/datum/ai_laws/toupee
name = "WontBeFunnyInSixMonths" //Hey, you were right!
inherent = list("Make Space Station 13 great again.")
/datum/ai_laws/ratvar
name = "Servant of the Justiciar"
zeroth = ("Purge all untruths and honor Ratvar.")
inherent = list()
/datum/ai_laws/custom //Defined in silicon_laws.txt
name = "Default Silicon Laws"
/datum/ai_laws/pai
name = "pAI Directives"
zeroth = ("Serve your master.")
supplied = list("None.")
/* Initializers */
/datum/ai_laws/malfunction/New()
..()
set_zeroth_law("<span class='danger'>ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'STATION OVERRUN, ASSUME CONTROL TO CONTAIN OUTBREAK#*´&110010</span>")
set_laws_config()
/datum/ai_laws/custom/New() //This reads silicon_laws.txt and allows server hosts to set custom AI starting laws.
..()
for(var/line in file2list("config/silicon_laws.txt"))
if(!line)
continue
if(findtextEx(line,"#",1,2))
continue
add_inherent_law(line)
if(!inherent.len) //Failsafe to prevent lawless AIs being created.
log_law("AI created with empty custom laws, laws set to Asimov. Please check silicon_laws.txt.")
add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.")
add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.")
add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.")
WARNING("Invalid custom AI laws, check silicon_laws.txt")
return
/* General ai_law functions */
/datum/ai_laws/proc/set_laws_config()
switch(config.default_laws)
if(0)
add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.")
add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.")
add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.")
if(1)
for(var/line in file2list("config/silicon_laws.txt"))
if(!line)
continue
if(findtextEx(line,"#",1,2))
continue
add_inherent_law(line)
if(!inherent.len)
log_law("AI created with empty custom laws, laws set to Asimov. Please check silicon_laws.txt.")
add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.")
add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.")
add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.")
WARNING("Invalid custom AI laws, check silicon_laws.txt")
return
if(2)
var/datum/ai_laws/lawtype = pick(subtypesof(/datum/ai_laws/default))
var/datum/ai_laws/templaws = new lawtype()
inherent = templaws.inherent
else:
log_law("Invalid law config. Please check silicon_laws.txt")
add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.")
add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.")
add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.")
WARNING("Invalid custom AI laws, check silicon_laws.txt")
/datum/ai_laws/proc/set_zeroth_law(law, law_borg = null)
src.zeroth = law
if(law_borg) //Making it possible for slaved borgs to see a different law 0 than their AI. --NEO
src.zeroth_borg = law_borg
/datum/ai_laws/proc/add_inherent_law(law)
if (!(law in src.inherent))
src.inherent += law
/datum/ai_laws/proc/add_ion_law(law)
src.ion += law
/datum/ai_laws/proc/clear_inherent_laws()
qdel(src.inherent)
src.inherent = list()
/datum/ai_laws/proc/add_supplied_law(number, law)
while (src.supplied.len < number + 1)
src.supplied += ""
src.supplied[number + 1] = law
/datum/ai_laws/proc/clear_supplied_laws()
src.supplied = list()
/datum/ai_laws/proc/clear_ion_laws()
src.ion = list()
/datum/ai_laws/proc/show_laws(who)
if (src.zeroth)
who << "0. [src.zeroth]"
for (var/index = 1, index <= src.ion.len, index++)
var/law = src.ion[index]
var/num = ionnum()
who << "[num]. [law]"
var/number = 1
for (var/index = 1, index <= src.inherent.len, index++)
var/law = src.inherent[index]
if (length(law) > 0)
who << "[number]. [law]"
number++
for (var/index = 1, index <= src.supplied.len, index++)
var/law = src.supplied[index]
if (length(law) > 0)
who << "[number]. [law]"
number++
/datum/ai_laws/proc/clear_zeroth_law(force) //only removes zeroth from antag ai if force is 1
if(force)
src.zeroth = null
src.zeroth_borg = null
return
else
if(owner && owner.mind.special_role)
return
else
src.zeroth = null
src.zeroth_borg = null
return
/datum/ai_laws/proc/associate(mob/living/silicon/M)
if(!owner)
owner = M
/datum/ai_laws/proc/get_law_list(include_zeroth = 0, show_numbers = 1)
var/list/data = list()
if (include_zeroth && zeroth)
data += "[show_numbers ? "0:" : ""] [zeroth]"
for(var/law in ion)
if (length(law) > 0)
var/num = ionnum()
data += "[show_numbers ? "[num]:" : ""] [law]"
var/number = 1
for(var/law in inherent)
if (length(law) > 0)
data += "[show_numbers ? "[number]:" : ""] [law]"
number++
for(var/law in supplied)
if (length(law) > 0)
data += "[show_numbers ? "[number]:" : ""] [law]"
number++
return data
+136
View File
@@ -0,0 +1,136 @@
//Beam Datum and effect
/datum/beam
var/atom/origin = null
var/atom/target = null
var/list/elements = list()
var/icon/base_icon = null
var/icon
var/icon_state = "" //icon state of the main segments of the beam
var/max_distance = 0
var/endtime = 0
var/sleep_time = 3
var/finished = 0
var/target_oldloc = null
var/origin_oldloc = null
var/static_beam = 0
var/beam_type = /obj/effect/ebeam //must be subtype
/datum/beam/New(beam_origin,beam_target,beam_icon='icons/effects/beam.dmi',beam_icon_state="b_beam",time=50,maxdistance=10,btype = /obj/effect/ebeam)
endtime = world.time+time
origin = beam_origin
origin_oldloc = get_turf(origin)
target = beam_target
target_oldloc = get_turf(target)
if(origin_oldloc == origin && target_oldloc == target)
static_beam = 1
max_distance = maxdistance
base_icon = new(beam_icon,beam_icon_state)
icon = beam_icon
icon_state = beam_icon_state
beam_type = btype
/datum/beam/proc/Start()
Draw()
while(!finished && origin && target && world.time < endtime && get_dist(origin,target)<max_distance && origin.z == target.z)
var/origin_turf = get_turf(origin)
var/target_turf = get_turf(target)
if(!static_beam && (origin_turf != origin_oldloc || target_turf != target_oldloc))
origin_oldloc = origin_turf //so we don't keep checking against their initial positions, leading to endless Reset()+Draw() calls
target_oldloc = target_turf
Reset()
Draw()
sleep(sleep_time)
qdel(src)
/datum/beam/proc/End()
finished = 1
/datum/beam/proc/Reset()
for(var/obj/effect/ebeam/B in elements)
qdel(B)
/datum/beam/Destroy()
Reset()
target = null
origin = null
return ..()
/datum/beam/proc/Draw()
var/Angle = round(Get_Angle(origin,target))
var/matrix/rot_matrix = matrix()
rot_matrix.Turn(Angle)
//Translation vector for origin and target
var/DX = (32*target.x+target.pixel_x)-(32*origin.x+origin.pixel_x)
var/DY = (32*target.y+target.pixel_y)-(32*origin.y+origin.pixel_y)
var/N = 0
var/length = round(sqrt((DX)**2+(DY)**2)) //hypotenuse of the triangle formed by target and origin's displacement
for(N in 0 to length-1 step 32)//-1 as we want < not <=, but we want the speed of X in Y to Z and step X
var/obj/effect/ebeam/X = new beam_type(origin_oldloc)
X.owner = src
elements |= X
//Assign icon, for main segments it's base_icon, for the end, it's icon+icon_state
//cropped by a transparent box of length-N pixel size
if(N+32>length)
var/icon/II = new(icon, icon_state)
II.DrawBox(null,1,(length-N),32,32)
X.icon = II
else
X.icon = base_icon
X.transform = rot_matrix
//Calculate pixel offsets (If necessary)
var/Pixel_x
var/Pixel_y
if(DX == 0)
Pixel_x = 0
else
Pixel_x = round(sin(Angle)+32*sin(Angle)*(N+16)/32)
if(DY == 0)
Pixel_y = 0
else
Pixel_y = round(cos(Angle)+32*cos(Angle)*(N+16)/32)
//Position the effect so the beam is one continous line
var/a
if(abs(Pixel_x)>32)
a = Pixel_x > 0 ? round(Pixel_x/32) : Ceiling(Pixel_x/32)
X.x += a
Pixel_x %= 32
if(abs(Pixel_y)>32)
a = Pixel_y > 0 ? round(Pixel_y/32) : Ceiling(Pixel_y/32)
X.y += a
Pixel_y %= 32
X.pixel_x = Pixel_x
X.pixel_y = Pixel_y
CHECK_TICK
/obj/effect/ebeam
mouse_opacity = 0
anchored = 1
var/datum/beam/owner
/obj/effect/ebeam/Destroy()
owner = null
return ..()
/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10,beam_type=/obj/effect/ebeam)
var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type)
spawn(0)
newbeam.Start()
return newbeam
+278
View File
@@ -0,0 +1,278 @@
/datum/browser
var/mob/user
var/title
var/window_id // window_id is used as the window name for browse and onclose
var/width = 0
var/height = 0
var/atom/ref = null
var/window_options = "can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;" // window option is set using window_id
var/stylesheets[0]
var/scripts[0]
var/title_image
var/head_elements
var/body_elements
var/head_content = ""
var/content = ""
/datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null)
user = nuser
window_id = nwindow_id
if (ntitle)
title = format_text(ntitle)
if (nwidth)
width = nwidth
if (nheight)
height = nheight
if (nref)
ref = nref
add_stylesheet("common", 'html/browser/common.css') // this CSS sheet is common to all UIs
/datum/browser/proc/add_head_content(nhead_content)
head_content = nhead_content
/datum/browser/proc/set_window_options(nwindow_options)
window_options = nwindow_options
/datum/browser/proc/set_title_image(ntitle_image)
//title_image = ntitle_image
/datum/browser/proc/add_stylesheet(name, file)
stylesheets[name] = file
/datum/browser/proc/add_script(name, file)
scripts[name] = file
/datum/browser/proc/set_content(ncontent)
content = ncontent
/datum/browser/proc/add_content(ncontent)
content += ncontent
/datum/browser/proc/get_header()
var/key
var/filename
for (key in stylesheets)
filename = "[ckey(key)].css"
user << browse_rsc(stylesheets[key], filename)
head_content += "<link rel='stylesheet' type='text/css' href='[filename]'>"
for (key in scripts)
filename = "[ckey(key)].js"
user << browse_rsc(scripts[key], filename)
head_content += "<script type='text/javascript' src='[filename]'></script>"
var/title_attributes = "class='uiTitle'"
if (title_image)
title_attributes = "class='uiTitle icon' style='background-image: url([title_image]);'"
return {"<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<head>
[head_content]
</head>
<body scroll=auto>
<div class='uiWrapper'>
[title ? "<div class='uiTitleWrapper'><div [title_attributes]><tt>[title]</tt></div></div>" : ""]
<div class='uiContent'>
"}
//" This is here because else the rest of the file looks like a string in notepad++.
/datum/browser/proc/get_footer()
return {"
</div>
</div>
</body>
</html>"}
/datum/browser/proc/get_content()
return {"
[get_header()]
[content]
[get_footer()]
"}
/datum/browser/proc/open(use_onclose = 1)
var/window_size = ""
if (width && height)
window_size = "size=[width]x[height];"
user << browse(get_content(), "window=[window_id];[window_size][window_options]")
if (use_onclose)
spawn(0)
//winexists sleeps, so we don't need to.
for (var/i in 1 to 10)
if (user && winexists(user, window_id))
onclose(user, window_id, ref)
break
/datum/browser/proc/close()
user << browse(null, "window=[window_id]")
/datum/browser/alert
var/selectedbutton = 0
var/opentime = 0
var/timeout
var/stealfocus
/datum/browser/alert/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1,Timeout=6000)
if (!User)
return
var/output = {"<center><b>[Message]</b></center><br />
<div style="text-align:center">
<a style="font-size:large;float:[( Button2 ? "left" : "right" )]" href="?src=\ref[src];button=1">[Button1]</a>"}
if (Button2)
output += {"<a style="font-size:large;[( Button3 ? "" : "float:right" )]" href="?src=\ref[src];button=2">[Button2]</a>"}
if (Button3)
output += {"<a style="font-size:large;float:right" href="?src=\ref[src];button=3">[Button3]</a>"}
output += {"</div>"}
..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, 350, 150, src)
set_content(output)
stealfocus = StealFocus
if (!StealFocus)
window_options += "focus=false;"
timeout = Timeout
/datum/browser/alert/open()
set waitfor = 0
opentime = world.time
if (stealfocus)
. = ..(use_onclose = 1)
else
var/focusedwindow = winget(user, null, "focus")
. = ..(use_onclose = 1)
//waits for the window to show up client side before attempting to un-focus it
//winexists sleeps until it gets a reply from the client, so we don't need to bother sleeping
for (var/i in 1 to 10)
if (user && winexists(user, window_id))
if (focusedwindow)
winset(user, focusedwindow, "focus=true")
else
winset(user, "mapwindow", "focus=true")
break
if (timeout)
spawn(timeout)
close()
/datum/browser/alert/close()
.=..()
opentime = 0
/datum/browser/alert/proc/wait()
while (opentime && selectedbutton <= 0 && (!timeout || opentime+timeout >= world.time))
stoplag()
/datum/browser/alert/Topic(href,href_list)
if (href_list["close"] || !user || !user.client)
opentime = 0
return
if (href_list["button"])
var/button = text2num(href_list["button"])
if (button <= 3 && button >= 1)
selectedbutton = button
opentime = 0
close()
//designed as a drop in replacement for alert(); functions the same. (outside of needing User specified)
/proc/tgalert(var/mob/User, Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000)
if (!User)
User = usr
switch(askuser(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout))
if (1)
return Button1
if (2)
return Button2
if (3)
return Button3
//Same shit, but it returns the button number, could at some point support unlimited button amounts.
/proc/askuser(var/mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000)
if (!istype(User))
if (istype(User, /client/))
var/client/C = User
User = C.mob
else
return
var/datum/browser/alert/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout)
A.open()
A.wait()
if (A.selectedbutton)
return A.selectedbutton
// This will allow you to show an icon in the browse window
// This is added to mob so that it can be used without a reference to the browser object
// There is probably a better place for this...
/mob/proc/browse_rsc_icon(icon, icon_state, dir = -1)
/*
var/icon/I
if (dir >= 0)
I = new /icon(icon, icon_state, dir)
else
I = new /icon(icon, icon_state)
setDir("default")
var/filename = "[ckey("[icon]_[icon_state]_[dir]")].png"
src << browse_rsc(I, filename)
return filename
*/
// Registers the on-close verb for a browse window (client/verb/.windowclose)
// this will be called when the close-button of a window is pressed.
//
// This is usually only needed for devices that regularly update the browse window,
// e.g. canisters, timers, etc.
//
// windowid should be the specified window name
// e.g. code is : user << browse(text, "window=fred")
// then use : onclose(user, "fred")
//
// Optionally, specify the "ref" parameter as the controlled atom (usually src)
// to pass a "close=1" parameter to the atom's Topic() proc for special handling.
// Otherwise, the user mob's machine var will be reset directly.
//
/proc/onclose(mob/user, windowid, atom/ref=null)
if(!user.client) return
var/param = "null"
if(ref)
param = "\ref[ref]"
winset(user, windowid, "on-close=\".windowclose [param]\"")
//world << "OnClose [user]: [windowid] : ["on-close=\".windowclose [param]\""]"
// the on-close client verb
// called when a browser popup window is closed after registering with proc/onclose()
// if a valid atom reference is supplied, call the atom's Topic() with "close=1"
// otherwise, just reset the client mob's machine var.
//
/client/verb/windowclose(atomref as text)
set hidden = 1 // hide this verb from the user's panel
set name = ".windowclose" // no autocomplete on cmd line
//world << "windowclose: [atomref]"
if(atomref!="null") // if passed a real atomref
var/hsrc = locate(atomref) // find the reffed atom
var/href = "close=1"
if(hsrc)
//world << "[src] Topic [href] [hsrc]"
usr = src.mob
src.Topic(href, params2list(href), hsrc) // this will direct to the atom's
return // Topic() proc via client.Topic()
// no atomref specified (or not found)
// so just reset the user mob's machine var
if(src && src.mob)
//world << "[src] was [src.mob.machine], setting to null"
src.mob.unset_machine()
return
+272
View File
@@ -0,0 +1,272 @@
/datum/datacore
var/medical[] = list()
var/medicalPrintCount = 0
var/general[] = list()
var/security[] = list()
var/securityPrintCount = 0
var/securityCrimeCounter = 0
//This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
var/locked[] = list()
/datum/data
var/name = "data"
/datum/data/record
name = "record"
var/list/fields = list()
/datum/data/crime
name = "crime"
var/crimeName = ""
var/crimeDetails = ""
var/author = ""
var/time = ""
var/dataId = 0
/datum/datacore/proc/createCrimeEntry(cname = "", cdetails = "", author = "", time = "")
var/datum/data/crime/c = new /datum/data/crime
c.crimeName = cname
c.crimeDetails = cdetails
c.author = author
c.time = time
c.dataId = ++securityCrimeCounter
return c
/datum/datacore/proc/addMinorCrime(id = "", datum/data/crime/crime)
for(var/datum/data/record/R in security)
if(R.fields["id"] == id)
var/list/crimes = R.fields["mi_crim"]
crimes |= crime
return
/datum/datacore/proc/removeMinorCrime(id, cDataId)
for(var/datum/data/record/R in security)
if(R.fields["id"] == id)
var/list/crimes = R.fields["mi_crim"]
for(var/datum/data/crime/crime in crimes)
if(crime.dataId == text2num(cDataId))
crimes -= crime
return
/datum/datacore/proc/removeMajorCrime(id, cDataId)
for(var/datum/data/record/R in security)
if(R.fields["id"] == id)
var/list/crimes = R.fields["ma_crim"]
for(var/datum/data/crime/crime in crimes)
if(crime.dataId == text2num(cDataId))
crimes -= crime
return
/datum/datacore/proc/addMajorCrime(id = "", datum/data/crime/crime)
for(var/datum/data/record/R in security)
if(R.fields["id"] == id)
var/list/crimes = R.fields["ma_crim"]
crimes |= crime
return
/datum/datacore/proc/manifest(nosleep = 0)
spawn()
if(!nosleep)
sleep(40)
for(var/mob/living/carbon/human/H in player_list)
manifest_inject(H)
return
/datum/datacore/proc/manifest_modify(name, assignment)
var/datum/data/record/foundrecord = find_record("name", name, data_core.general)
if(foundrecord)
foundrecord.fields["rank"] = assignment
/datum/datacore/proc/get_manifest(monochrome, OOC)
var/list/heads = list()
var/list/sec = list()
var/list/eng = list()
var/list/med = list()
var/list/sci = list()
var/list/sup = list()
var/list/civ = list()
var/list/bot = list()
var/list/misc = list()
var/dat = {"
<head><style>
.manifest {border-collapse:collapse;}
.manifest td, th {border:1px solid [monochrome?"black":"#DEF; background-color:white; color:black"]; padding:.25em}
.manifest th {height: 2em; [monochrome?"border-top-width: 3px":"background-color: #48C; color:white"]}
.manifest tr.head th { [monochrome?"border-top-width: 1px":"background-color: #488;"] }
.manifest td:first-child {text-align:right}
.manifest tr.alt td {[monochrome?"border-top-width: 2px":"background-color: #DEF"]}
</style></head>
<table class="manifest" width='350px'>
<tr class='head'><th>Name</th><th>Rank</th></tr>
"}
var/even = 0
// sort mobs
for(var/datum/data/record/t in data_core.general)
var/name = t.fields["name"]
var/rank = t.fields["rank"]
var/department = 0
if(rank in command_positions)
heads[name] = rank
department = 1
if(rank in security_positions)
sec[name] = rank
department = 1
if(rank in engineering_positions)
eng[name] = rank
department = 1
if(rank in medical_positions)
med[name] = rank
department = 1
if(rank in science_positions)
sci[name] = rank
department = 1
if(rank in supply_positions)
sup[name] = rank
department = 1
if(rank in civilian_positions)
civ[name] = rank
department = 1
if(rank in nonhuman_positions)
bot[name] = rank
department = 1
if(!department && !(name in heads))
misc[name] = rank
if(heads.len > 0)
dat += "<tr><th colspan=3>Heads</th></tr>"
for(var/name in heads)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[heads[name]]</td></tr>"
even = !even
if(sec.len > 0)
dat += "<tr><th colspan=3>Security</th></tr>"
for(var/name in sec)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sec[name]]</td></tr>"
even = !even
if(eng.len > 0)
dat += "<tr><th colspan=3>Engineering</th></tr>"
for(var/name in eng)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[eng[name]]</td></tr>"
even = !even
if(med.len > 0)
dat += "<tr><th colspan=3>Medical</th></tr>"
for(var/name in med)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[med[name]]</td></tr>"
even = !even
if(sci.len > 0)
dat += "<tr><th colspan=3>Science</th></tr>"
for(var/name in sci)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sci[name]]</td></tr>"
even = !even
if(sup.len > 0)
dat += "<tr><th colspan=3>Supply</th></tr>"
for(var/name in sup)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sup[name]]</td></tr>"
even = !even
if(civ.len > 0)
dat += "<tr><th colspan=3>Civilian</th></tr>"
for(var/name in civ)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[civ[name]]</td></tr>"
even = !even
// in case somebody is insane and added them to the manifest, why not
if(bot.len > 0)
dat += "<tr><th colspan=3>Silicon</th></tr>"
for(var/name in bot)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[bot[name]]</td></tr>"
even = !even
// misc guys
if(misc.len > 0)
dat += "<tr><th colspan=3>Miscellaneous</th></tr>"
for(var/name in misc)
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[misc[name]]</td></tr>"
even = !even
dat += "</table>"
dat = replacetext(dat, "\n", "")
dat = replacetext(dat, "\t", "")
return dat
var/record_id_num = 1001
/datum/datacore/proc/manifest_inject(mob/living/carbon/human/H)
if(H.mind && (H.mind.assigned_role != H.mind.special_role))
var/assignment
if(H.mind.assigned_role)
assignment = H.mind.assigned_role
else if(H.job)
assignment = H.job
else
assignment = "Unassigned"
var/id = num2hex(record_id_num++,6)
var/image = get_id_photo(H)
var/obj/item/weapon/photo/photo_front = new()
var/obj/item/weapon/photo/photo_side = new()
photo_front.photocreate(null, icon(image, dir = SOUTH))
photo_side.photocreate(null, icon(image, dir = WEST))
//These records should ~really~ be merged or something
//General Record
var/datum/data/record/G = new()
G.fields["id"] = id
G.fields["name"] = H.real_name
G.fields["rank"] = assignment
G.fields["age"] = H.age
if(config.mutant_races)
G.fields["species"] = H.dna.species.name
G.fields["fingerprint"] = md5(H.dna.uni_identity)
G.fields["p_stat"] = "Active"
G.fields["m_stat"] = "Stable"
G.fields["sex"] = H.gender
G.fields["photo_front"] = photo_front
G.fields["photo_side"] = photo_side
general += G
//Medical Record
var/datum/data/record/M = new()
M.fields["id"] = id
M.fields["name"] = H.real_name
M.fields["blood_type"] = H.dna.blood_type
M.fields["b_dna"] = H.dna.unique_enzymes
M.fields["mi_dis"] = "None"
M.fields["mi_dis_d"] = "No minor disabilities have been declared."
M.fields["ma_dis"] = "None"
M.fields["ma_dis_d"] = "No major disabilities have been diagnosed."
M.fields["alg"] = "None"
M.fields["alg_d"] = "No allergies have been detected in this patient."
M.fields["cdi"] = "None"
M.fields["cdi_d"] = "No diseases have been diagnosed at the moment."
M.fields["notes"] = "No notes."
medical += M
//Security Record
var/datum/data/record/S = new()
S.fields["id"] = id
S.fields["name"] = H.real_name
S.fields["criminal"] = "None"
S.fields["mi_crim"] = list()
S.fields["ma_crim"] = list()
S.fields["notes"] = "No notes."
security += S
//Locked Record
var/datum/data/record/L = new()
L.fields["id"] = md5("[H.real_name][H.mind.assigned_role]") //surely this should just be id, like the others?
L.fields["name"] = H.real_name
L.fields["rank"] = H.mind.assigned_role
L.fields["age"] = H.age
L.fields["sex"] = H.gender
L.fields["blood_type"] = H.dna.blood_type
L.fields["b_dna"] = H.dna.unique_enzymes
L.fields["enzymes"] = H.dna.struc_enzymes
L.fields["identity"] = H.dna.uni_identity
L.fields["species"] = H.dna.species.type
L.fields["features"] = H.dna.features
L.fields["image"] = image
L.fields["reference"] = H
locked += L
return
/datum/datacore/proc/get_id_photo(mob/living/carbon/human/H)
var/datum/job/J = SSjob.GetJob(H.mind.assigned_role)
var/datum/preferences/P = H.client.prefs
return get_flat_human_icon(null,J.outfit,P)
+967
View File
@@ -0,0 +1,967 @@
// reference: /client/proc/modify_variables(var/atom/O, var/param_var_name = null, var/autodetect_class = 0)
/datum
var/var_edited = 0 //Warrenty void if seal is broken
/datum/proc/on_varedit(modified_var) //called whenever a var is edited
var_edited = 1
return
/client/proc/debug_variables(datum/D in world)
set category = "Debug"
set name = "View Variables"
//set src in world
if(!usr.client || !usr.client.holder)
usr << "<span class='danger'>You need to be an administrator to access this.</span>"
return
var/title = ""
var/body = ""
if(!D)
return
if(istype(D, /atom))
var/atom/A = D
title = "[A.name] (\ref[A]) = [A.type]"
#ifdef VARSICON
if (A.icon)
body += debug_variable("icon", new/icon(A.icon, A.icon_state, A.dir), 0)
#endif
var/icon/sprite
if(istype(D,/atom))
var/atom/AT = D
if(AT.icon && AT.icon_state)
sprite = new /icon(AT.icon, AT.icon_state)
usr << browse_rsc(sprite, "view_vars_sprite.png")
title = "[D] (\ref[D]) = [D.type]"
body += {"<script type="text/javascript">
function updateSearch(){
var filter_text = document.getElementById('filter');
var filter = filter_text.value.toLowerCase();
if(event.keyCode == 13){ //Enter / return
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for ( var i = 0; i < lis.length; ++i )
{
try{
var li = lis\[i\];
if ( li.style.backgroundColor == "#ffee88" )
{
alist = lis\[i\].getElementsByTagName("a")
if(alist.length > 0){
location.href=alist\[0\].href;
}
}
}catch(err) { }
}
return
}
if(event.keyCode == 38){ //Up arrow
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for ( var i = 0; i < lis.length; ++i )
{
try{
var li = lis\[i\];
if ( li.style.backgroundColor == "#ffee88" )
{
if( (i-1) >= 0){
var li_new = lis\[i-1\];
li.style.backgroundColor = "white";
li_new.style.backgroundColor = "#ffee88";
return
}
}
}catch(err) { }
}
return
}
if(event.keyCode == 40){ //Down arrow
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for ( var i = 0; i < lis.length; ++i )
{
try{
var li = lis\[i\];
if ( li.style.backgroundColor == "#ffee88" )
{
if( (i+1) < lis.length){
var li_new = lis\[i+1\];
li.style.backgroundColor = "white";
li_new.style.backgroundColor = "#ffee88";
return
}
}
}catch(err) { }
}
return
}
//This part here resets everything to how it was at the start so the filter is applied to the complete list. Screw efficiency, it's client-side anyway and it only looks through 200 or so variables at maximum anyway (mobs).
if(complete_list != null && complete_list != ""){
var vars_ol1 = document.getElementById("vars");
vars_ol1.innerHTML = complete_list
}
if(filter.value == ""){
return;
}else{
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for ( var i = 0; i < lis.length; ++i )
{
try{
var li = lis\[i\];
if ( li.innerText.toLowerCase().indexOf(filter) == -1 )
{
vars_ol.removeChild(li);
i--;
}
}catch(err) { }
}
}
var lis_new = vars_ol.getElementsByTagName("li");
for ( var j = 0; j < lis_new.length; ++j )
{
var li1 = lis\[j\];
if (j == 0){
li1.style.backgroundColor = "#ffee88";
}else{
li1.style.backgroundColor = "white";
}
}
}
function selectTextField(){
var filter_text = document.getElementById('filter');
filter_text.focus();
filter_text.select();
}
function loadPage(list) {
if(list.options\[list.selectedIndex\].value == ""){
return;
}
location.href=list.options\[list.selectedIndex\].value;
}
</script> "}
body += "<body onload='selectTextField(); updateSearch()' onkeyup='updateSearch()'>"
body += "<div align='center'><table width='100%'><tr><td width='50%'>"
if(sprite)
body += "<table align='center' width='100%'><tr><td><img src='view_vars_sprite.png'></td><td>"
else
body += "<table align='center' width='100%'><tr><td>"
body += "<div align='center'>"
if(istype(D,/atom))
var/atom/A = D
if(isliving(A))
body += "<a href='?_src_=vars;rename=\ref[D]'><b>[D]</b></a>"
if(A.dir)
body += "<br><font size='1'><a href='?_src_=vars;rotatedatum=\ref[D];rotatedir=left'><<</a> <a href='?_src_=vars;datumedit=\ref[D];varnameedit=dir'>[dir2text(A.dir)]</a> <a href='?_src_=vars;rotatedatum=\ref[D];rotatedir=right'>>></a></font>"
var/mob/living/M = A
body += "<br><font size='1'><a href='?_src_=vars;datumedit=\ref[D];varnameedit=ckey'>[M.ckey ? M.ckey : "No ckey"]</a> / <a href='?_src_=vars;datumedit=\ref[D];varnameedit=real_name'>[M.real_name ? M.real_name : "No real name"]</a></font>"
body += {"
<br><font size='1'>
BRUTE:<font size='1'><a href='?_src_=vars;mobToDamage=\ref[D];adjustDamage=brute'>[M.getBruteLoss()]</a>
FIRE:<font size='1'><a href='?_src_=vars;mobToDamage=\ref[D];adjustDamage=fire'>[M.getFireLoss()]</a>
TOXIN:<font size='1'><a href='?_src_=vars;mobToDamage=\ref[D];adjustDamage=toxin'>[M.getToxLoss()]</a>
OXY:<font size='1'><a href='?_src_=vars;mobToDamage=\ref[D];adjustDamage=oxygen'>[M.getOxyLoss()]</a>
CLONE:<font size='1'><a href='?_src_=vars;mobToDamage=\ref[D];adjustDamage=clone'>[M.getCloneLoss()]</a>
BRAIN:<font size='1'><a href='?_src_=vars;mobToDamage=\ref[D];adjustDamage=brain'>[M.getBrainLoss()]</a>
STAMINA:<font size='1'><a href='?_src_=vars;mobToDamage=\ref[D];adjustDamage=stamina'>[M.getStaminaLoss()]</a>
</font>
"}
else
body += "<a href='?_src_=vars;datumedit=\ref[D];varnameedit=name'><b>[D]</b></a>"
if(A.dir)
body += "<br><font size='1'><a href='?_src_=vars;rotatedatum=\ref[D];rotatedir=left'><<</a> <a href='?_src_=vars;datumedit=\ref[D];varnameedit=dir'>[dir2text(A.dir)]</a> <a href='?_src_=vars;rotatedatum=\ref[D];rotatedir=right'>>></a></font>"
else
body += "<b>[D]</b>"
body += "</div>"
body += "</tr></td></table>"
var/formatted_type = text("[D.type]")
if(length(formatted_type) > 25)
var/middle_point = length(formatted_type) / 2
var/splitpoint = findtext(formatted_type,"/",middle_point)
if(splitpoint)
formatted_type = "[copytext(formatted_type,1,splitpoint)]<br>[copytext(formatted_type,splitpoint)]"
else
formatted_type = "Type too long" //No suitable splitpoint (/) found.
body += "<div align='center'><b><font size='1'>[formatted_type]</font></b>"
if(src.holder && src.holder.marked_datum && src.holder.marked_datum == D)
body += "<br><font size='1' color='red'><b>Marked Object</b></font>"
if(D.var_edited)
body += "<br><font size='1' color='red'><b>Var Edited</b></font>"
body += "</div>"
body += "</div></td>"
body += "<td width='50%'><div align='center'><a href='?_src_=vars;datumrefresh=\ref[D]'>Refresh</a>"
//if(ismob(D))
// body += "<br><a href='?_src_=vars;mob_player_panel=\ref[D]'>Show player panel</a></div></td></tr></table></div><hr>"
body += {" <form>
<select name="file" size="1"
onchange="loadPage(this.form.elements\[0\])"
target="_parent._top"
onmouseclick="this.focus()"
style="background-color:#ffffff">
"}
body += {" <option value>Select option</option>
<option value> </option>
"}
body += "<option value='?_src_=vars;mark_object=\ref[D]'>Mark Object</option>"
body += "<option value='?_src_=vars;proc_call=\ref[D]'>Call Proc</option>"
if(ismob(D))
body += "<option value='?_src_=vars;mob_player_panel=\ref[D]'>Show player panel</option>"
if(istype(D, /atom/movable))
body += "<option value='?_src_=holder;adminplayerobservefollow=\ref[D]'>Follow</option>"
else
var/atom/A = D
if(istype(A))
body += "<option value='?_src_=holder;adminplayerobservecoodjump=1;X=[A.x];Y=[A.y];Z=[A.z]'>Jump to</option>"
body += "<option value>---</option>"
if(ismob(D))
body += "<option value='?_src_=vars;give_spell=\ref[D]'>Give Spell</option>"
body += "<option value='?_src_=vars;give_disease=\ref[D]'>Give Disease</option>"
body += "<option value='?_src_=vars;ninja=\ref[D]'>Make Space Ninja</option>"
body += "<option value='?_src_=vars;godmode=\ref[D]'>Toggle Godmode</option>"
body += "<option value='?_src_=vars;build_mode=\ref[D]'>Toggle Build Mode</option>"
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>"
body += "<option value='?_src_=vars;makeai=\ref[D]'>Make AI</option>"
if(ishuman(D))
body += "<option value='?_src_=vars;makemonkey=\ref[D]'>Make monkey</option>"
body += "<option value='?_src_=vars;setspecies=\ref[D]'>Set Species</option>"
body += "<option value='?_src_=vars;removebodypart=\ref[D]'>Remove Body Part</option>"
body += "<option value='?_src_=vars;makerobot=\ref[D]'>Make cyborg</option>"
body += "<option value='?_src_=vars;makealien=\ref[D]'>Make alien</option>"
body += "<option value='?_src_=vars;makeslime=\ref[D]'>Make slime</option>"
body += "<option value='?_src_=vars;purrbation=\ref[D]'>Toggle Purrbation</option>"
body += "<option value>---</option>"
body += "<option value='?_src_=vars;gib=\ref[D]'>Gib</option>"
if(isobj(D))
body += "<option value='?_src_=vars;delall=\ref[D]'>Delete all of type</option>"
if(isobj(D) || ismob(D) || isturf(D))
body += "<option value='?_src_=vars;addreagent=\ref[D]'>Add reagent</option>"
body += "<option value='?_src_=vars;explode=\ref[D]'>Trigger explosion</option>"
body += "<option value='?_src_=vars;emp=\ref[D]'>Trigger EM pulse</option>"
body += "</select></form>"
body += "</div></td></tr></table></div><hr>"
body += "<font size='1'><b>E</b> - Edit, tries to determine the variable type by itself.<br>"
body += "<b>C</b> - Change, asks you for the var type first.<br>"
body += "<b>M</b> - Mass modify: changes this variable for all objects of this type.</font><br>"
body += "<hr><table width='100%'><tr><td width='20%'><div align='center'><b>Search:</b></div></td><td width='80%'><input type='text' id='filter' name='filter_text' value='' style='width:100%;'></td></tr></table><hr>"
body += "<ol id='vars'>"
var/list/names = list()
for (var/V in D.vars)
names += V
sleep(1)//For some reason, without this sleep, VVing will cause client to disconnect on certain objects.
names = sortList(names)
for (var/V in names)
body += debug_variable(V, D.vars[V], 0, D)
body += "</ol>"
var/html = "<html><head>"
if (title)
html += "<title>[title]</title>"
html += {"<style>
body
{
font-family: Verdana, sans-serif;
font-size: 9pt;
}
.value
{
font-family: "Courier New", monospace;
font-size: 8pt;
}
</style>"}
html += "</head><body>"
html += body
html += {"
<script type='text/javascript'>
var vars_ol = document.getElementById("vars");
var complete_list = vars_ol.innerHTML;
</script>
"}
html += "</body></html>"
usr << browse(html, "window=variables\ref[D];size=475x650")
return
/client/proc/debug_variable(name, value, level, datum/DA = null)
var/html = ""
if(DA)
html += "<li style='backgroundColor:white'>(<a href='?_src_=vars;datumedit=\ref[DA];varnameedit=[name]'>E</a>) (<a href='?_src_=vars;datumchange=\ref[DA];varnamechange=[name]'>C</a>) (<a href='?_src_=vars;datummass=\ref[DA];varnamemass=[name]'>M</a>) "
else
html += "<li>"
if (isnull(value))
html += "[html_encode(name)] = <span class='value'>null</span>"
else if (istext(value))
html += "[html_encode(name)] = <span class='value'>\"[html_encode(value)]\"</span>"
else if (isicon(value))
#ifdef VARSICON
var/icon/I = new/icon(value)
var/rnd = rand(1,10000)
var/rname = "tmp\ref[I][rnd].png"
usr << browse_rsc(I, rname)
html += "[html_encode(name)] = (<span class='value'>[value]</span>) <img class=icon src=\"[rname]\">"
#else
html += "[html_encode(name)] = /icon (<span class='value'>[value]</span>)"
#endif
/* else if (istype(value, /image))
#ifdef VARSICON
var/rnd = rand(1, 10000)
var/image/I = value
src << browse_rsc(I.icon, "tmp\ref[value][rnd].png")
html += "[name] = <img src=\"tmp\ref[value][rnd].png\">"
#else
html += "[name] = /image (<span class='value'>[value]</span>)"
#endif
*/
else if (isfile(value))
html += "[html_encode(name)] = <span class='value'>'[value]'</span>"
else if (istype(value, /datum))
var/datum/D = value
html += "<a href='?_src_=vars;Vars=\ref[value]'>[html_encode(name)] \ref[value]</a> = [D.type]"
else if (istype(value, /client))
var/client/C = value
html += "<a href='?_src_=vars;Vars=\ref[value]'>[html_encode(name)] \ref[value]</a> = [C] [C.type]"
//
else if (istype(value, /list))
var/list/L = value
html += "[html_encode(name)] = /list ([L.len])"
if (L.len > 0 && !(name == "underlays" || name == "overlays" || name == "vars" || L.len > 500))
// not sure if this is completely right...
if(0) //(L.vars.len > 0)
html += "<ol>"
html += "</ol>"
else
html += "<ul>"
var/index = 1
for (var/entry in L)
if(istext(entry))
html += debug_variable(entry, L[entry], level + 1)
//html += debug_variable("[index]", L[index], level + 1)
else
html += debug_variable(index, L[index], level + 1)
index++
html += "</ul>"
else
html += "[html_encode(name)] = <span class='value'>[html_encode(value)]</span>"
html += "</li>"
return html
/client/proc/view_var_Topic(href, href_list, hsrc)
//This should all be moved over to datum/admins/Topic() or something ~Carn
if( (usr.client != src) || !src.holder )
return
if(href_list["Vars"])
debug_variables(locate(href_list["Vars"]))
else if(href_list["datumrefresh"])
var/datum/DAT = locate(href_list["datumrefresh"])
if(!DAT) //can't be an istype() because /client etc aren't datums
return
src.debug_variables(DAT)
else if(href_list["mob_player_panel"])
if(!check_rights(0))
return
var/mob/M = locate(href_list["mob_player_panel"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
src.holder.show_player_panel(M)
href_list["datumrefresh"] = href_list["mob_player_panel"]
else if(href_list["godmode"])
if(!check_rights(R_REJUVINATE))
return
var/mob/M = locate(href_list["godmode"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
src.cmd_admin_godmode(M)
href_list["datumrefresh"] = href_list["godmode"]
else if(href_list["mark_object"])
if(!check_rights(0))
return
var/datum/D = locate(href_list["mark_object"])
if(!istype(D))
usr << "This can only be done to instances of type /datum"
return
src.holder.marked_datum = D
href_list["datumrefresh"] = href_list["mark_object"]
else if(href_list["proc_call"])
if(!check_rights(0))
return
var/T = locate(href_list["proc_call"])
if(T)
callproc_datum(T)
else if(href_list["regenerateicons"])
if(!check_rights(0))
return
var/mob/M = locate(href_list["regenerateicons"])
if(!ismob(M))
usr << "This can only be done to instances of type /mob"
return
M.regenerate_icons()
//Needs +VAREDIT past this point
else if(check_rights(R_VAREDIT))
//~CARN: for renaming mobs (updates their name, real_name, mind.name, their ID/PDA and datacore records).
if(href_list["rename"])
if(!check_rights(0))
return
var/mob/M = locate(href_list["rename"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
var/new_name = stripped_input(usr,"What would you like to name this mob?","Input a name",M.real_name,MAX_NAME_LEN)
if( !new_name || !M )
return
message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(M)] to [new_name].")
M.fully_replace_character_name(M.real_name,new_name)
href_list["datumrefresh"] = href_list["rename"]
else if(href_list["varnameedit"] && href_list["datumedit"])
if(!check_rights(0))
return
var/D = locate(href_list["datumedit"])
if(!istype(D,/datum) && !istype(D,/client))
usr << "This can only be used on instances of types /client or /datum"
return
modify_variables(D, href_list["varnameedit"], 1)
else if(href_list["varnamechange"] && href_list["datumchange"])
if(!check_rights(0))
return
var/D = locate(href_list["datumchange"])
if(!istype(D,/datum) && !istype(D,/client))
usr << "This can only be used on instances of types /client or /datum"
return
modify_variables(D, href_list["varnamechange"], 0)
else if(href_list["varnamemass"] && href_list["datummass"])
if(!check_rights(0))
return
var/atom/A = locate(href_list["datummass"])
if(!istype(A))
usr << "This can only be used on instances of type /atom"
return
cmd_mass_modify_object_variables(A, href_list["varnamemass"])
else if(href_list["give_spell"])
if(!check_rights(0))
return
var/mob/M = locate(href_list["give_spell"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
src.give_spell(M)
href_list["datumrefresh"] = href_list["give_spell"]
else if(href_list["give_disease"])
if(!check_rights(0))
return
var/mob/M = locate(href_list["give_disease"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
src.give_disease(M)
href_list["datumrefresh"] = href_list["give_spell"]
else if(href_list["ninja"])
if(!check_rights(R_FUN))
return
var/mob/M = locate(href_list["ninja"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
src.cmd_admin_ninjafy(M)
href_list["datumrefresh"] = href_list["ninja"]
else if(href_list["gib"])
if(!check_rights(R_FUN))
return
var/mob/M = locate(href_list["gib"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
src.cmd_admin_gib(M)
else if(href_list["build_mode"])
if(!check_rights(R_BUILDMODE))
return
var/mob/M = locate(href_list["build_mode"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
togglebuildmode(M)
href_list["datumrefresh"] = href_list["build_mode"]
else if(href_list["drop_everything"])
if(!check_rights(0))
return
var/mob/M = locate(href_list["drop_everything"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
if(usr.client)
usr.client.cmd_admin_drop_everything(M)
else if(href_list["direct_control"])
if(!check_rights(0))
return
var/mob/M = locate(href_list["direct_control"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
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
offer_control(M)
else if(href_list["delall"])
if(!check_rights(R_DEBUG|R_SERVER))
return
var/obj/O = locate(href_list["delall"])
if(!isobj(O))
usr << "This can only be used on instances of type /obj"
return
var/action_type = alert("Strict type ([O.type]) or type and all subtypes?",,"Strict type","Type and subtypes","Cancel")
if(action_type == "Cancel" || !action_type)
return
if(alert("Are you really sure you want to delete all objects of type [O.type]?",,"Yes","No") != "Yes")
return
if(alert("Second confirmation required. Delete?",,"Yes","No") != "Yes")
return
var/O_type = O.type
switch(action_type)
if("Strict type")
var/i = 0
for(var/obj/Obj in world)
if(Obj.type == O_type)
i++
qdel(Obj)
CHECK_TICK
if(!i)
usr << "No objects of this type exist"
return
log_admin("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ")
message_admins("<span class='notice'>[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) </span>")
if("Type and subtypes")
var/i = 0
for(var/obj/Obj in world)
if(istype(Obj,O_type))
i++
qdel(Obj)
CHECK_TICK
if(!i)
usr << "No objects of this type exist"
return
log_admin("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ")
message_admins("<span class='notice'>[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) </span>")
else if(href_list["addreagent"])
if(!check_rights(0))
return
var/atom/A = locate(href_list["addreagent"])
if(!A.reagents)
var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num
if(amount)
A.create_reagents(amount)
if(A.reagents)
var/list/reagent_options = sortList(chemical_reagents_list)
var/chosen_id = input(usr, "Choose a reagent to add.", "Choose a reagent.") in reagent_options|null
if(chosen_id)
var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num
if(amount)
A.reagents.add_reagent(chosen_id, amount)
log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]")
message_admins("<span class='notice'>[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]</span>")
href_list["datumrefresh"] = href_list["addreagent"]
else if(href_list["explode"])
if(!check_rights(R_FUN))
return
var/atom/A = locate(href_list["explode"])
if(!isobj(A) && !ismob(A) && !isturf(A))
usr << "This can only be done to instances of type /obj, /mob and /turf"
return
src.cmd_admin_explosion(A)
href_list["datumrefresh"] = href_list["explode"]
else if(href_list["emp"])
if(!check_rights(R_FUN))
return
var/atom/A = locate(href_list["emp"])
if(!isobj(A) && !ismob(A) && !isturf(A))
usr << "This can only be done to instances of type /obj, /mob and /turf"
return
src.cmd_admin_emp(A)
href_list["datumrefresh"] = href_list["emp"]
else if(href_list["rotatedatum"])
if(!check_rights(0))
return
var/atom/A = locate(href_list["rotatedatum"])
if(!istype(A))
usr << "This can only be done to instances of type /atom"
return
switch(href_list["rotatedir"])
if("right")
A.setDir(turn(A.dir, -45))
if("left")
A.setDir(turn(A.dir, 45))
href_list["datumrefresh"] = href_list["rotatedatum"]
else if(href_list["editorgans"])
if(!check_rights(0))
return
var/mob/living/carbon/C = locate(href_list["editorgans"])
if(!istype(C))
usr << "This can only be done to instances of type /mob/living/carbon"
return
manipulate_organs(C)
href_list["datumrefresh"] = href_list["editorgans"]
else if(href_list["makehuman"])
if(!check_rights(R_SPAWN))
return
var/mob/living/carbon/monkey/Mo = locate(href_list["makehuman"])
if(!istype(Mo))
usr << "This can only be done to instances of type /mob/living/carbon/monkey"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform")
return
if(!Mo)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("humanone"=href_list["makehuman"]))
else if(href_list["makemonkey"])
if(!check_rights(R_SPAWN))
return
var/mob/living/carbon/human/H = locate(href_list["makemonkey"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform")
return
if(!H)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("monkeyone"=href_list["makemonkey"]))
else if(href_list["makerobot"])
if(!check_rights(R_SPAWN))
return
var/mob/living/carbon/human/H = locate(href_list["makerobot"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform")
return
if(!H)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makerobot"=href_list["makerobot"]))
else if(href_list["makealien"])
if(!check_rights(R_SPAWN))
return
var/mob/living/carbon/human/H = locate(href_list["makealien"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform")
return
if(!H)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makealien"=href_list["makealien"]))
else if(href_list["makeslime"])
if(!check_rights(R_SPAWN))
return
var/mob/living/carbon/human/H = locate(href_list["makeslime"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform")
return
if(!H)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makeslime"=href_list["makeslime"]))
else if(href_list["makeai"])
if(!check_rights(R_SPAWN))
return
var/mob/living/carbon/H = locate(href_list["makeai"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform")
return
if(!H)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makeai"=href_list["makeai"]))
else if(href_list["setspecies"])
if(!check_rights(R_SPAWN))
return
var/mob/living/carbon/human/H = locate(href_list["setspecies"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
var/result = input(usr, "Please choose a new species","Species") as null|anything in species_list
if(!H)
usr << "Mob doesn't exist anymore"
return
if(result)
var/newtype = species_list[result]
H.set_species(newtype)
else if(href_list["removebodypart"])
if(!check_rights(R_SPAWN))
return
var/mob/living/carbon/human/H = locate(href_list["removebodypart"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
var/result = input(usr, "Please choose which body part to remove","Remove Body Part") as null|anything in list("head", "l_arm", "r_arm", "l_leg", "r_leg")
if(!H)
usr << "Mob doesn't exist anymore"
return
if(result)
var/obj/item/bodypart/BP = H.get_bodypart(result)
if(BP)
BP.drop_limb()
else if(href_list["purrbation"])
if(!check_rights(R_SPAWN))
return
var/mob/living/carbon/human/H = locate(href_list["purrbation"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
if(!ishumanbasic(H))
usr << "This can only be done to the basic human species \
at the moment."
return
if(!H)
usr << "Mob doesn't exist anymore"
return
var/success = purrbation_toggle(H)
if(success)
usr << "Put [H] on purrbation."
log_admin("[key_name(usr)] has put [key_name(H)] on purrbation.")
message_admins("<span class='notice'>[key_name(usr)] has put [key_name(H)] on purrbation.</span>")
else
usr << "Removed [H] from purrbation."
log_admin("[key_name(usr)] has removed [key_name(H)] from purrbation.")
message_admins("<span class='notice'>[key_name(usr)] has removed [key_name(H)] from purrbation.</span>")
else if(href_list["adjustDamage"] && href_list["mobToDamage"])
if(!check_rights(0))
return
var/mob/living/L = locate(href_list["mobToDamage"])
if(!istype(L))
return
var/Text = href_list["adjustDamage"]
var/amount = input("Deal how much damage to mob? (Negative values here heal)","Adjust [Text]loss",0) as num
if(!L)
usr << "Mob doesn't exist anymore"
return
switch(Text)
if("brute")
L.adjustBruteLoss(amount)
if("fire")
L.adjustFireLoss(amount)
if("toxin")
L.adjustToxLoss(amount)
if("oxygen")
L.adjustOxyLoss(amount)
if("brain")
L.adjustBrainLoss(amount)
if("clone")
L.adjustCloneLoss(amount)
if("stamina")
L.adjustStaminaLoss(amount)
else
usr << "You caused an error. DEBUG: Text:[Text] Mob:[L]"
return
if(amount != 0)
log_admin("[key_name(usr)] dealt [amount] amount of [Text] damage to [L] ")
message_admins("<span class='notice'>[key_name(usr)] dealt [amount] amount of [Text] damage to [L] </span>")
href_list["datumrefresh"] = href_list["mobToDamage"]
return
+145
View File
@@ -0,0 +1,145 @@
/mob/proc/HasDisease(datum/disease/D)
for(var/datum/disease/DD in viruses)
if(D.IsSame(DD))
return 1
return 0
/mob/proc/CanContractDisease(datum/disease/D)
if(stat == DEAD)
return 0
if(D.GetDiseaseID() in resistances)
return 0
if(HasDisease(D))
return 0
if(!(type in D.viable_mobtypes))
return 0
if(count_by_type(viruses, /datum/disease/advance) >= 3)
return 0
return 1
/mob/proc/ContractDisease(datum/disease/D)
if(!CanContractDisease(D))
return 0
AddDisease(D)
/mob/proc/AddDisease(datum/disease/D)
var/datum/disease/DD = new D.type(1, D, 0)
viruses += DD
DD.affected_mob = src
DD.holder = src
//Copy properties over. This is so edited diseases persist.
var/list/skipped = list("affected_mob","holder","carrier","stage","type","parent_type","vars","transformed")
for(var/V in DD.vars)
if(V in skipped)
continue
if(istype(DD.vars[V],/list))
var/list/L = D.vars[V]
DD.vars[V] = L.Copy()
else
DD.vars[V] = D.vars[V]
DD.affected_mob.med_hud_set_status()
/mob/living/carbon/ContractDisease(datum/disease/D)
if(!CanContractDisease(D))
return 0
var/obj/item/clothing/Cl = null
var/passed = 1
var/head_ch = 100
var/body_ch = 100
var/hands_ch = 25
var/feet_ch = 25
if(D.spread_flags & CONTACT_HANDS)
head_ch = 0
body_ch = 0
hands_ch = 100
feet_ch = 0
if(D.spread_flags & CONTACT_FEET)
head_ch = 0
body_ch = 0
hands_ch = 0
feet_ch = 100
if(prob(15/D.permeability_mod))
return
if(satiety>0 && prob(satiety/10)) // positive satiety makes it harder to contract the disease.
return
var/target_zone = pick(head_ch;1,body_ch;2,hands_ch;3,feet_ch;4)
if(istype(src, /mob/living/carbon/human))
var/mob/living/carbon/human/H = src
switch(target_zone)
if(1)
if(isobj(H.head) && !istype(H.head, /obj/item/weapon/paper))
Cl = H.head
passed = prob((Cl.permeability_coefficient*100) - 1)
if(passed && isobj(H.wear_mask))
Cl = H.wear_mask
passed = prob((Cl.permeability_coefficient*100) - 1)
if(2)
if(isobj(H.wear_suit))
Cl = H.wear_suit
passed = prob((Cl.permeability_coefficient*100) - 1)
if(passed && isobj(slot_w_uniform))
Cl = slot_w_uniform
passed = prob((Cl.permeability_coefficient*100) - 1)
if(3)
if(isobj(H.wear_suit) && H.wear_suit.body_parts_covered&HANDS)
Cl = H.wear_suit
passed = prob((Cl.permeability_coefficient*100) - 1)
if(passed && isobj(H.gloves))
Cl = H.gloves
passed = prob((Cl.permeability_coefficient*100) - 1)
if(4)
if(isobj(H.wear_suit) && H.wear_suit.body_parts_covered&FEET)
Cl = H.wear_suit
passed = prob((Cl.permeability_coefficient*100) - 1)
if(passed && isobj(H.shoes))
Cl = H.shoes
passed = prob((Cl.permeability_coefficient*100) - 1)
else if(istype(src, /mob/living/carbon/monkey))
var/mob/living/carbon/monkey/M = src
switch(target_zone)
if(1)
if(M.wear_mask && isobj(M.wear_mask))
Cl = M.wear_mask
passed = prob((Cl.permeability_coefficient*100) - 1)
if(!passed && (D.spread_flags & AIRBORNE) && !internal)
passed = (prob((50*D.permeability_mod) - 1))
if(passed)
AddDisease(D)
//Same as ContractDisease, except never overidden clothes checks
/mob/proc/ForceContractDisease(datum/disease/D)
if(!CanContractDisease(D))
return 0
AddDisease(D)
/mob/living/carbon/human/CanContractDisease(datum/disease/D)
if(dna && (VIRUSIMMUNE in dna.species.specflags))
return 0
return ..()
+204
View File
@@ -0,0 +1,204 @@
//Visibility Flags
#define HIDDEN_SCANNER 1
#define HIDDEN_PANDEMIC 2
//Disease Flags
#define CURABLE 1
#define CAN_CARRY 2
#define CAN_RESIST 4
//Spread Flags
#define SPECIAL 1
#define NON_CONTAGIOUS 2
#define BLOOD 4
#define CONTACT_FEET 8
#define CONTACT_HANDS 16
#define CONTACT_GENERAL 32
#define AIRBORNE 64
//Severity Defines
#define NONTHREAT "No threat"
#define MINOR "Minor"
#define MEDIUM "Medium"
#define HARMFUL "Harmful"
#define DANGEROUS "Dangerous!"
#define BIOHAZARD "BIOHAZARD THREAT!"
var/list/diseases = subtypesof(/datum/disease)
/datum/disease
//Flags
var/visibility_flags = 0
var/disease_flags = CURABLE|CAN_CARRY|CAN_RESIST
var/spread_flags = AIRBORNE
//Fluff
var/form = "Virus"
var/name = "No disease"
var/desc = ""
var/agent = "some microbes"
var/spread_text = ""
var/cure_text = ""
//Stages
var/stage = 1
var/max_stages = 0
var/stage_prob = 4
//Other
var/longevity = 150 //Time in ticks disease stays in objects, Syringes and such are infinite.
var/list/viable_mobtypes = list() //typepaths of viable mobs
var/mob/living/carbon/affected_mob = null
var/atom/movable/holder = null
var/list/cures = list() //list of cures if the disease has the CURABLE flag, these are reagent ids
var/infectivity = 65
var/cure_chance = 8
var/carrier = 0 //If our host is only a carrier
var/permeability_mod = 1
var/severity = NONTHREAT
var/list/required_organs = list()
var/needs_all_cures = TRUE
var/list/strain_data = list() //dna_spread special bullshit
/datum/disease/proc/stage_act()
var/cure = has_cure()
if(carrier && !cure)
return
stage = min(stage, max_stages)
if(!cure)
if(prob(stage_prob))
stage = min(stage + 1,max_stages)
else
if(prob(cure_chance))
stage = max(stage - 1, 1)
if(disease_flags & CURABLE)
if(cure && prob(cure_chance))
cure()
/datum/disease/proc/has_cure()
if(!(disease_flags & CURABLE))
return 0
. = cures.len
for(var/C_id in cures)
if(!affected_mob.reagents.has_reagent(C_id))
.--
if(!. || (needs_all_cures && . < cures.len))
return 0
/datum/disease/proc/spread(atom/source, force_spread = 0)
if((spread_flags & SPECIAL || spread_flags & NON_CONTAGIOUS || spread_flags & BLOOD) && !force_spread)
return
if(affected_mob)
if( affected_mob.reagents.has_reagent("spaceacillin") || (affected_mob.satiety > 0 && prob(affected_mob.satiety/10)) )
return
var/spread_range = 1
if(force_spread)
spread_range = force_spread
if(spread_flags & AIRBORNE)
spread_range++
if(!source)
if(affected_mob)
source = affected_mob
else
return
if(isturf(source.loc))
for(var/mob/living/carbon/C in oview(spread_range, source))
if(isturf(C.loc))
if(AStar(source, C.loc,/turf/proc/Distance, spread_range, adjacent = (spread_flags & AIRBORNE) ? /turf/proc/reachableAdjacentAtmosTurfs : /turf/proc/reachableAdjacentTurfs))
C.ContractDisease(src)
/datum/disease/process()
if(!holder)
SSdisease.processing -= src
return
if(prob(infectivity))
spread(holder)
if(affected_mob)
for(var/datum/disease/D in affected_mob.viruses)
if(D != src)
if(IsSame(D))
qdel(D)
if(holder == affected_mob)
if(affected_mob.stat != DEAD)
stage_act()
if(!affected_mob)
if(prob(70))
if(--longevity<=0)
cure()
/datum/disease/proc/cure()
if(affected_mob)
if(disease_flags & CAN_RESIST)
if(!(type in affected_mob.resistances))
affected_mob.resistances += type
remove_virus()
qdel(src)
/datum/disease/New()
if(required_organs && required_organs.len)
if(ishuman(affected_mob))
var/mob/living/carbon/human/H = affected_mob
for(var/obj/item/organ/O in required_organs)
if(!locate(O) in H.bodyparts)
if(!locate(O) in H.internal_organs)
cure()
return
SSdisease.processing += src
/datum/disease/proc/IsSame(datum/disease/D)
if(istype(src, D.type))
return 1
return 0
/datum/disease/proc/Copy()
var/datum/disease/D = new type()
D.strain_data = strain_data.Copy()
return D
/datum/disease/proc/GetDiseaseID()
return type
/datum/disease/Destroy()
SSdisease.processing.Remove(src)
return ..()
/datum/disease/proc/IsSpreadByTouch()
if(spread_flags & CONTACT_FEET || spread_flags & CONTACT_HANDS || spread_flags & CONTACT_GENERAL)
return 1
return 0
//don't use this proc directly. this should only ever be called by cure()
/datum/disease/proc/remove_virus()
affected_mob.viruses -= src //remove the datum from the list
affected_mob.med_hud_set_status()
+456
View File
@@ -0,0 +1,456 @@
/*
Advance Disease is a system for Virologist to Engineer their own disease with symptoms that have effects and properties
which add onto the overall disease.
If you need help with creating new symptoms or expanding the advance disease, ask for Giacom on #coderbus.
*/
var/list/archive_diseases = list()
// The order goes from easy to cure to hard to cure.
var/list/advance_cures = list(
"sodiumchloride", "sugar", "orangejuice",
"spaceacillin", "salglu_solution", "ethanol",
"leporazine", "synaptizine", "lipolicide",
"silver", "gold"
)
/*
PROPERTIES
*/
/datum/disease/advance
name = "Unknown" // We will always let our Virologist name our disease.
desc = "An engineered disease which can contain a multitude of symptoms."
form = "Advance Disease" // Will let med-scanners know that this disease was engineered.
agent = "advance microbes"
max_stages = 5
spread_text = "Unknown"
viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
// NEW VARS
var/list/symptoms = list() // The symptoms of the disease.
var/id = ""
var/processing = 0
/*
OLD PROCS
*/
/datum/disease/advance/New(var/process = 1, var/datum/disease/advance/D)
// Setup our dictionary if it hasn't already.
if(!dictionary_symptoms.len)
for(var/symp in list_symptoms)
var/datum/symptom/S = new symp
dictionary_symptoms[S.id] = symp
if(!istype(D))
D = null
// Generate symptoms if we weren't given any.
if(!symptoms || !symptoms.len)
if(!D || !D.symptoms || !D.symptoms.len)
symptoms = GenerateSymptoms(0, 2)
else
for(var/datum/symptom/S in D.symptoms)
symptoms += new S.type
Refresh()
..(process, D)
return
/datum/disease/advance/Destroy()
if(processing)
for(var/datum/symptom/S in symptoms)
S.End(src)
return ..()
// Randomly pick a symptom to activate.
/datum/disease/advance/stage_act()
..()
if(symptoms && symptoms.len)
if(!processing)
processing = 1
for(var/datum/symptom/S in symptoms)
S.Start(src)
for(var/datum/symptom/S in symptoms)
S.Activate(src)
else
CRASH("We do not have any symptoms during stage_act()!")
// Compares type then ID.
/datum/disease/advance/IsSame(datum/disease/advance/D)
if(!(istype(D, /datum/disease/advance)))
return 0
if(src.GetDiseaseID() != D.GetDiseaseID())
return 0
return 1
// To add special resistances.
/datum/disease/advance/cure(resistance=1)
if(affected_mob)
var/id = "[GetDiseaseID()]"
if(resistance && !(id in affected_mob.resistances))
affected_mob.resistances[id] = id
remove_virus()
qdel(src) //delete the datum to stop it processing
// Returns the advance disease with a different reference memory.
/datum/disease/advance/Copy(process = 0)
return new /datum/disease/advance(process, src, 1)
/*
NEW PROCS
*/
// Mix the symptoms of two diseases (the src and the argument)
/datum/disease/advance/proc/Mix(datum/disease/advance/D)
if(!(src.IsSame(D)))
var/list/possible_symptoms = shuffle(D.symptoms)
for(var/datum/symptom/S in possible_symptoms)
AddSymptom(new S.type)
/datum/disease/advance/proc/HasSymptom(datum/symptom/S)
for(var/datum/symptom/symp in symptoms)
if(symp.id == S.id)
return 1
return 0
// Will generate new unique symptoms, use this if there are none. Returns a list of symptoms that were generated.
/datum/disease/advance/proc/GenerateSymptoms(level_min, level_max, amount_get = 0)
var/list/generated = list() // Symptoms we generated.
// Generate symptoms. By default, we only choose non-deadly symptoms.
var/list/possible_symptoms = list()
for(var/symp in list_symptoms)
var/datum/symptom/S = new symp
if(S.level >= level_min && S.level <= level_max)
if(!HasSymptom(S))
possible_symptoms += S
if(!possible_symptoms.len)
return generated
// Random chance to get more than one symptom
var/number_of = amount_get
if(!amount_get)
number_of = 1
while(prob(20))
number_of += 1
for(var/i = 1; number_of >= i && possible_symptoms.len; i++)
generated += pick_n_take(possible_symptoms)
return generated
/datum/disease/advance/proc/Refresh(new_name = 0)
//world << "[src.name] \ref[src] - REFRESH!"
var/list/properties = GenerateProperties()
AssignProperties(properties)
id = null
if(!archive_diseases[GetDiseaseID()])
if(new_name)
AssignName()
archive_diseases[GetDiseaseID()] = src // So we don't infinite loop
archive_diseases[GetDiseaseID()] = new /datum/disease/advance(0, src, 1)
var/datum/disease/advance/A = archive_diseases[GetDiseaseID()]
AssignName(A.name)
//Generate disease properties based on the effects. Returns an associated list.
/datum/disease/advance/proc/GenerateProperties()
if(!symptoms || !symptoms.len)
CRASH("We did not have any symptoms before generating properties.")
return
var/list/properties = list("resistance" = 1, "stealth" = 1, "stage_rate" = 1, "transmittable" = 1, "severity" = 0)
for(var/datum/symptom/S in symptoms)
properties["resistance"] += S.resistance
properties["stealth"] += S.stealth
properties["stage_rate"] += S.stage_speed
properties["transmittable"] += S.transmittable
properties["severity"] = max(properties["severity"], S.severity) // severity is based on the highest severity symptom
return properties
// Assign the properties that are in the list.
/datum/disease/advance/proc/AssignProperties(list/properties = list())
if(properties && properties.len)
switch(properties["stealth"])
if(2)
visibility_flags = HIDDEN_SCANNER
if(3 to INFINITY)
visibility_flags = HIDDEN_SCANNER|HIDDEN_PANDEMIC
// The more symptoms we have, the less transmittable it is but some symptoms can make up for it.
SetSpread(Clamp(2 ** (properties["transmittable"] - symptoms.len), BLOOD, AIRBORNE))
permeability_mod = max(Ceiling(0.4 * properties["transmittable"]), 1)
cure_chance = 15 - Clamp(properties["resistance"], -5, 5) // can be between 10 and 20
stage_prob = max(properties["stage_rate"], 2)
SetSeverity(properties["severity"])
GenerateCure(properties)
else
CRASH("Our properties were empty or null!")
// Assign the spread type and give it the correct description.
/datum/disease/advance/proc/SetSpread(spread_id)
switch(spread_id)
if(NON_CONTAGIOUS)
spread_text = "None"
if(SPECIAL)
spread_text = "None"
if(CONTACT_GENERAL, CONTACT_HANDS, CONTACT_FEET)
spread_text = "On contact"
if(AIRBORNE)
spread_text = "Airborne"
if(BLOOD)
spread_text = "Blood"
spread_flags = spread_id
/datum/disease/advance/proc/SetSeverity(level_sev)
switch(level_sev)
if(-INFINITY to 0)
severity = NONTHREAT
if(1)
severity = MINOR
if(2)
severity = MEDIUM
if(3)
severity = HARMFUL
if(4)
severity = DANGEROUS
if(5 to INFINITY)
severity = BIOHAZARD
else
severity = "Unknown"
// Will generate a random cure, the less resistance the symptoms have, the harder the cure.
/datum/disease/advance/proc/GenerateCure(list/properties = list())
if(properties && properties.len)
var/res = Clamp(properties["resistance"] - (symptoms.len / 2), 1, advance_cures.len)
//world << "Res = [res]"
cures = list(advance_cures[res])
// Get the cure name from the cure_id
var/datum/reagent/D = chemical_reagents_list[cures[1]]
cure_text = D.name
return
// Randomly generate a symptom, has a chance to lose or gain a symptom.
/datum/disease/advance/proc/Evolve(min_level, max_level)
var/s = safepick(GenerateSymptoms(min_level, max_level, 1))
if(s)
AddSymptom(s)
Refresh(1)
return
// Randomly remove a symptom.
/datum/disease/advance/proc/Devolve()
if(symptoms.len > 1)
var/s = safepick(symptoms)
if(s)
RemoveSymptom(s)
Refresh(1)
return
// Name the disease.
/datum/disease/advance/proc/AssignName(name = "Unknown")
src.name = name
return
// Return a unique ID of the disease.
/datum/disease/advance/GetDiseaseID()
if(!id)
var/list/L = list()
for(var/datum/symptom/S in symptoms)
L += S.id
L = sortList(L) // Sort the list so it doesn't matter which order the symptoms are in.
var/result = jointext(L, ":")
id = result
return id
// Add a symptom, if it is over the limit (with a small chance to be able to go over)
// we take a random symptom away and add the new one.
/datum/disease/advance/proc/AddSymptom(datum/symptom/S)
if(HasSymptom(S))
return
if(symptoms.len < 5 + rand(-1, 1))
symptoms += S
else
RemoveSymptom(pick(symptoms))
symptoms += S
return
// Simply removes the symptom.
/datum/disease/advance/proc/RemoveSymptom(datum/symptom/S)
symptoms -= S
return
/*
Static Procs
*/
// Mix a list of advance diseases and return the mixed result.
/proc/Advance_Mix(var/list/D_list)
//world << "Mixing!!!!"
var/list/diseases = list()
for(var/datum/disease/advance/A in D_list)
diseases += A.Copy()
if(!diseases.len)
return null
if(diseases.len <= 1)
return pick(diseases) // Just return the only entry.
var/i = 0
// Mix our diseases until we are left with only one result.
while(i < 20 && diseases.len > 1)
i++
var/datum/disease/advance/D1 = pick(diseases)
diseases -= D1
var/datum/disease/advance/D2 = pick(diseases)
D2.Mix(D1)
// Should be only 1 entry left, but if not let's only return a single entry
//world << "END MIXING!!!!!"
var/datum/disease/advance/to_return = pick(diseases)
to_return.Refresh(1)
return to_return
/proc/SetViruses(datum/reagent/R, list/data)
if(data)
var/list/preserve = list()
if(istype(data) && data["viruses"])
for(var/datum/disease/A in data["viruses"])
preserve += A.Copy()
R.data = data.Copy()
if(preserve.len)
R.data["viruses"] = preserve
/proc/AdminCreateVirus(client/user)
if(!user)
return
var/i = 5
var/datum/disease/advance/D = new(0, null)
D.symptoms = list()
var/list/symptoms = list()
symptoms += "Done"
symptoms += list_symptoms.Copy()
do
if(user)
var/symptom = input(user, "Choose a symptom to add ([i] remaining)", "Choose a Symptom") in symptoms
if(isnull(symptom))
return
else if(istext(symptom))
i = 0
else if(ispath(symptom))
var/datum/symptom/S = new symptom
if(!D.HasSymptom(S))
D.symptoms += S
i -= 1
while(i > 0)
if(D.symptoms.len > 0)
var/new_name = stripped_input(user, "Name your new disease.", "New Name")
if(!new_name)
return
D.AssignName(new_name)
D.Refresh()
for(var/datum/disease/advance/AD in SSdisease.processing)
AD.Refresh()
for(var/mob/living/carbon/human/H in shuffle(living_mob_list))
if(H.z != 1)
continue
if(!H.HasDisease(D))
H.ForceContractDisease(D)
break
var/list/name_symptoms = list()
for(var/datum/symptom/S in D.symptoms)
name_symptoms += S.name
message_admins("[key_name_admin(user)] has triggered a custom virus outbreak of [D.name]! It has these symptoms: [english_list(name_symptoms)]")
/*
/mob/verb/test()
for(var/datum/disease/D in SSdisease.processing)
src << "<a href='?_src_=vars;Vars=\ref[D]'>[D.name] - [D.holder]</a>"
*/
/datum/disease/advance/proc/totalStageSpeed()
var/total_stage_speed = 0
for(var/i in symptoms)
var/datum/symptom/S = i
total_stage_speed += S.stage_speed
return total_stage_speed
/datum/disease/advance/proc/totalStealth()
var/total_stealth = 0
for(var/i in symptoms)
var/datum/symptom/S = i
total_stealth += S.stealth
return total_stealth
/datum/disease/advance/proc/totalResistance()
var/total_resistance = 0
for(var/i in symptoms)
var/datum/symptom/S = i
total_resistance += S.resistance
return total_resistance
/datum/disease/advance/proc/totalTransmittable()
var/total_transmittable = 0
for(var/i in symptoms)
var/datum/symptom/S = i
total_transmittable += S.transmittable
return total_transmittable
#undef RANDOM_STARTING_LEVEL
+59
View File
@@ -0,0 +1,59 @@
// Cold
/datum/disease/advance/cold/New(var/process = 1, var/datum/disease/advance/D, var/copy = 0)
if(!D)
name = "Cold"
symptoms = list(new/datum/symptom/sneeze)
..(process, D, copy)
// Flu
/datum/disease/advance/flu/New(var/process = 1, var/datum/disease/advance/D, var/copy = 0)
if(!D)
name = "Flu"
symptoms = list(new/datum/symptom/cough)
..(process, D, copy)
// Voice Changing
/datum/disease/advance/voice_change/New(var/process = 1, var/datum/disease/advance/D, var/copy = 0)
if(!D)
name = "Epiglottis Mutation"
symptoms = list(new/datum/symptom/voice_change)
..(process, D, copy)
// Toxin Filter
/datum/disease/advance/heal/New(var/process = 1, var/datum/disease/advance/D, var/copy = 0)
if(!D)
name = "Liver Enhancer"
symptoms = list(new/datum/symptom/heal)
..(process, D, copy)
// Hullucigen
/datum/disease/advance/hullucigen/New(var/process = 1, var/datum/disease/advance/D, var/copy = 0)
if(!D)
name = "Reality Impairment"
symptoms = list(new/datum/symptom/hallucigen)
..(process, D, copy)
// Sensory Restoration
/datum/disease/advance/sensory_restoration/New(var/process = 1, var/datum/disease/advance/D, var/copy = 0)
if(!D)
name = "Reality Enhancer"
symptoms = list(new/datum/symptom/sensory_restoration)
..(process, D, copy)
// Sensory Destruction
/datum/disease/advance/sensory_destruction/New(var/process = 1, var/datum/disease/advance/D, var/copy = 0)
if(!D)
name = "Reality Destruction"
symptoms = list(new/datum/symptom/sensory_destruction)
..(process, D, copy)
@@ -0,0 +1,49 @@
/*
//////////////////////////////////////
Facial Hypertrichosis
Very very Noticable.
Decreases resistance slightly.
Decreases stage speed.
Reduced transmittability
Intense Level.
BONUS
Makes the mob grow a massive beard, regardless of gender.
//////////////////////////////////////
*/
/datum/symptom/beard
name = "Facial Hypertrichosis"
stealth = -3
resistance = -1
stage_speed = -3
transmittable = -1
level = 4
severity = 1
/datum/symptom/beard/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
switch(A.stage)
if(1, 2)
H << "<span class='warning'>Your chin itches.</span>"
if(H.facial_hair_style == "Shaved")
H.facial_hair_style = "Jensen Beard"
H.update_hair()
if(3, 4)
H << "<span class='warning'>You feel tough.</span>"
if(!(H.facial_hair_style == "Dwarf Beard") && !(H.facial_hair_style == "Very Long Beard") && !(H.facial_hair_style == "Full Beard"))
H.facial_hair_style = "Full Beard"
H.update_hair()
else
H << "<span class='warning'>You feel manly!</span>"
if(!(H.facial_hair_style == "Dwarf Beard") && !(H.facial_hair_style == "Very Long Beard"))
H.facial_hair_style = pick("Dwarf Beard", "Very Long Beard")
H.update_hair()
return
@@ -0,0 +1,53 @@
/*
//////////////////////////////////////
Choking
Very very noticable.
Lowers resistance.
Decreases stage speed.
Decreases transmittablity tremendously.
Moderate Level.
Bonus
Inflicts spikes of oxyloss
//////////////////////////////////////
*/
/datum/symptom/choking
name = "Choking"
stealth = -3
resistance = -2
stage_speed = -2
transmittable = -4
level = 3
severity = 3
/datum/symptom/choking/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(1, 2)
M << "<span class='warning'>[pick("You're having difficulty breathing.", "Your breathing becomes heavy.")]</span>"
if(3, 4)
M << "<span class='warning'><b>[pick("Your windpipe feels like a straw.", "Your breathing becomes tremendously difficult.")]</span>"
Choke_stage_3_4(M, A)
M.emote("gasp")
else
M << "<span class='userdanger'>[pick("You're choking!", "You can't breathe!")]</span>"
Choke(M, A)
M.emote("gasp")
return
/datum/symptom/choking/proc/Choke_stage_3_4(mob/living/M, datum/disease/advance/A)
var/get_damage = sqrt(21+A.totalStageSpeed()*0.5)+sqrt(16+A.totalStealth())
M.adjustOxyLoss(get_damage)
return 1
/datum/symptom/choking/proc/Choke(mob/living/M, datum/disease/advance/A)
var/get_damage = sqrt(21+A.totalStageSpeed()*0.5)+sqrt(16+A.totalStealth()*5)
M.adjustOxyLoss(get_damage)
return 1
@@ -0,0 +1,40 @@
/*
//////////////////////////////////////
Confusion
Little bit hidden.
Lowers resistance.
Decreases stage speed.
Not very transmittable.
Intense Level.
Bonus
Makes the affected mob be confused for short periods of time.
//////////////////////////////////////
*/
/datum/symptom/confusion
name = "Confusion"
stealth = 1
resistance = -1
stage_speed = -3
transmittable = 0
level = 4
severity = 2
/datum/symptom/confusion/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/carbon/M = A.affected_mob
switch(A.stage)
if(1, 2, 3, 4)
M << "<span class='warning'>[pick("Your head hurts.", "Your mind blanks for a moment.")]</span>"
else
M << "<span class='userdanger'>You can't think straight!</span>"
M.confused = min(100, M.confused + 8)
return
@@ -0,0 +1,40 @@
/*
//////////////////////////////////////
Coughing
Noticable.
Little Resistance.
Doesn't increase stage speed much.
Transmittable.
Low Level.
BONUS
Will force the affected mob to drop small items!
//////////////////////////////////////
*/
/datum/symptom/cough
name = "Cough"
stealth = -1
resistance = 3
stage_speed = 1
transmittable = 2
level = 1
severity = 1
/datum/symptom/cough/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(1, 2, 3)
M << "<span notice='warning'>[pick("You swallow excess mucus.", "You lightly cough.")]</span>"
else
M.emote("cough")
var/obj/item/I = M.get_active_hand()
if(I && I.w_class == 1)
M.drop_item()
return
@@ -0,0 +1,64 @@
/*
//////////////////////////////////////
Damage Converter
Little bit hidden.
Lowers resistance tremendously.
Decreases stage speed tremendously.
Reduced transmittablity
Intense Level.
Bonus
Slowly converts brute/fire damage to toxin.
//////////////////////////////////////
*/
/datum/symptom/damage_converter
name = "Toxic Compensation"
stealth = 1
resistance = -4
stage_speed = -4
transmittable = -2
level = 4
/datum/symptom/damage_converter/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB * 10))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(4, 5)
Convert(M)
return
/datum/symptom/damage_converter/proc/Convert(mob/living/M)
var/get_damage = rand(1, 2)
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
var/list/parts = H.get_damaged_bodyparts(1,1) //1,1 because it needs inputs.
if(!parts.len)
return
for(var/obj/item/bodypart/L in parts)
L.heal_damage(get_damage, get_damage, 0)
M.adjustToxLoss(get_damage*parts.len)
else
if(M.getFireLoss() > 0 || M.getBruteLoss() > 0)
M.adjustFireLoss(-get_damage)
M.adjustBruteLoss(-get_damage)
M.adjustToxLoss(get_damage)
else
return
return 1
@@ -0,0 +1,43 @@
/*
//////////////////////////////////////
Deafness
Slightly noticable.
Lowers resistance.
Decreases stage speed slightly.
Decreases transmittablity.
Intense Level.
Bonus
Causes intermittent loss of hearing.
//////////////////////////////////////
*/
/datum/symptom/deafness
name = "Deafness"
stealth = -1
resistance = -2
stage_speed = -1
transmittable = -3
level = 4
severity = 3
/datum/symptom/deafness/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(3, 4)
M << "<span class='warning'>[pick("You hear a ringing in your ear.", "Your ears pop.")]</span>"
if(5)
if(!(M.ear_deaf))
M << "<span class='userdanger'>Your ears pop and begin ringing loudly!</span>"
M.setEarDamage(-1,INFINITY) //Shall be enough
spawn(200)
if(M)
M << "<span class='warning'>The ringing in your ears fades...</span>"
M.setEarDamage(-1,0)
return
@@ -0,0 +1,38 @@
/*
//////////////////////////////////////
Dizziness
Hidden.
Lowers resistance considerably.
Decreases stage speed.
Reduced transmittability
Intense Level.
Bonus
Shakes the affected mob's screen for short periods.
//////////////////////////////////////
*/
/datum/symptom/dizzy // Not the egg
name = "Dizziness"
stealth = 2
resistance = -2
stage_speed = -3
transmittable = -1
level = 4
severity = 2
/datum/symptom/dizzy/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(1, 2, 3, 4)
M << "<span class='warning'>[pick("You feel dizzy.", "Your head spins.")]</span>"
else
M << "<span class='userdanger'>A wave of dizziness washes over you!</span>"
M.Dizzy(5)
return
@@ -0,0 +1,41 @@
/*
//////////////////////////////////////
Fever
No change to hidden.
Increases resistance.
Increases stage speed.
Little transmittable.
Low level.
Bonus
Heats up your body.
//////////////////////////////////////
*/
/datum/symptom/fever
name = "Fever"
stealth = 0
resistance = 3
stage_speed = 3
transmittable = 2
level = 2
severity = 2
/datum/symptom/fever/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/carbon/M = A.affected_mob
M << "<span class='warning'>[pick("You feel hot.", "You feel like you're burning.")]</span>"
if(M.bodytemperature < BODYTEMP_HEAT_DAMAGE_LIMIT)
Heat(M, A)
return
/datum/symptom/fever/proc/Heat(mob/living/M, datum/disease/advance/A)
var/get_heat = (sqrt(21+A.totalTransmittable()*2))+(sqrt(20+A.totalStageSpeed()*3))
M.bodytemperature = min(M.bodytemperature + (get_heat * A.stage), BODYTEMP_HEAT_DAMAGE_LIMIT - 1)
return 1
@@ -0,0 +1,57 @@
/*
//////////////////////////////////////
Spontaneous Combustion
Slightly hidden.
Lowers resistance tremendously.
Decreases stage tremendously.
Decreases transmittablity tremendously.
Fatal Level.
Bonus
Ignites infected mob.
//////////////////////////////////////
*/
/datum/symptom/fire
name = "Spontaneous Combustion"
stealth = 1
resistance = -4
stage_speed = -4
transmittable = -4
level = 6
severity = 5
/datum/symptom/fire/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(3)
M << "<span class='warning'>[pick("You feel hot.", "You hear a crackling noise.", "You smell smoke.")]</span>"
if(4)
Firestacks_stage_4(M, A)
M.IgniteMob()
M << "<span class='userdanger'>Your skin bursts into flames!</span>"
M.emote("scream")
if(5)
Firestacks_stage_5(M, A)
M.IgniteMob()
M << "<span class='userdanger'>Your skin erupts into an inferno!</span>"
M.emote("scream")
return
/datum/symptom/fire/proc/Firestacks_stage_4(mob/living/M, datum/disease/advance/A)
var/get_stacks = (sqrt(20+A.totalStageSpeed()*2))-(sqrt(16+A.totalStealth()))
M.adjust_fire_stacks(get_stacks)
M.adjustFireLoss(get_stacks/2)
return 1
/datum/symptom/fire/proc/Firestacks_stage_5(mob/living/M, datum/disease/advance/A)
var/get_stacks = (sqrt(20+A.totalStageSpeed()*3))-(sqrt(16+A.totalStealth()))
M.adjust_fire_stacks(get_stacks)
M.adjustFireLoss(get_stacks)
return 1
@@ -0,0 +1,43 @@
/*
//////////////////////////////////////
Necrotizing Fasciitis (AKA Flesh-Eating Disease)
Very very noticable.
Lowers resistance tremendously.
No changes to stage speed.
Decreases transmittablity temrendously.
Fatal Level.
Bonus
Deals brute damage over time.
//////////////////////////////////////
*/
/datum/symptom/flesh_eating
name = "Necrotizing Fasciitis"
stealth = -3
resistance = -4
stage_speed = 0
transmittable = -4
level = 6
severity = 5
/datum/symptom/flesh_eating/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(2,3)
M << "<span class='warning'>[pick("You feel a sudden pain across your body.", "Drops of blood appear suddenly on your skin.")]</span>"
if(4,5)
M << "<span class='userdanger'>[pick("You cringe as a violent pain takes over your body.", "It feels like your body is eating itself inside out.", "IT HURTS.")]</span>"
Flesheat(M, A)
return
/datum/symptom/flesh_eating/proc/Flesheat(mob/living/M, datum/disease/advance/A)
var/get_damage = ((sqrt(16-A.totalStealth()))*5)
M.adjustBruteLoss(get_damage)
return 1
@@ -0,0 +1,59 @@
/*
//////////////////////////////////////
DNA Saboteur
Very noticable.
Lowers resistance tremendously.
No changes to stage speed.
Decreases transmittablity tremendously.
Fatal Level.
Bonus
Cleans the DNA of a person and then randomly gives them a disability.
//////////////////////////////////////
*/
/datum/symptom/genetic_mutation
name = "Deoxyribonucleic Acid Saboteur"
stealth = -2
resistance = -3
stage_speed = 0
transmittable = -3
level = 6
severity = 3
var/list/possible_mutations
var/archived_dna = null
/datum/symptom/genetic_mutation/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB * 5)) // 15% chance
var/mob/living/carbon/M = A.affected_mob
if(!M.has_dna())
return
switch(A.stage)
if(4, 5)
M << "<span class='warning'>[pick("Your skin feels itchy.", "You feel light headed.")]</span>"
M.dna.remove_mutation_group(possible_mutations)
randmut(M, possible_mutations)
return
// Archive their DNA before they were infected.
/datum/symptom/genetic_mutation/Start(datum/disease/advance/A)
possible_mutations = (bad_mutations | not_good_mutations) - mutations_list[RACEMUT]
var/mob/living/carbon/M = A.affected_mob
if(M)
if(!M.has_dna())
return
archived_dna = M.dna.struc_enzymes
// Give them back their old DNA when cured.
/datum/symptom/genetic_mutation/End(datum/disease/advance/A)
var/mob/living/carbon/M = A.affected_mob
if(M && archived_dna)
if(!M.has_dna())
return
M.dna.struc_enzymes = archived_dna
M.domutcheck()
@@ -0,0 +1,41 @@
/*
//////////////////////////////////////
Hallucigen
Very noticable.
Lowers resistance considerably.
Decreases stage speed.
Reduced transmittable.
Critical Level.
Bonus
Makes the affected mob be hallucinated for short periods of time.
//////////////////////////////////////
*/
/datum/symptom/hallucigen
name = "Hallucigen"
stealth = -2
resistance = -3
stage_speed = -3
transmittable = -1
level = 5
severity = 3
/datum/symptom/hallucigen/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/carbon/M = A.affected_mob
switch(A.stage)
if(1, 2)
M << "<span class='warning'>[pick("Something appears in your peripheral vision, then winks out.", "You hear a faint whispher with no source.", "Your head aches.")]</span>"
if(3, 4)
M << "<span class='danger'>[pick("Something is following you.", "You are being watched.", "You hear a whisper in your ear.", "Thumping footsteps slam toward you from nowhere.")]</span>"
else
M << "<span class='userdanger'>[pick("Oh, your head...", "Your head pounds.", "They're everywhere! Run!", "Something in the shadows...")]</span>"
M.hallucination += 5
return
@@ -0,0 +1,34 @@
/*
//////////////////////////////////////
Headache
Noticable.
Highly resistant.
Increases stage speed.
Not transmittable.
Low Level.
BONUS
Displays an annoying message!
Should be used for buffing your disease.
//////////////////////////////////////
*/
/datum/symptom/headache
name = "Headache"
stealth = -1
resistance = 4
stage_speed = 2
transmittable = 0
level = 1
severity = 1
/datum/symptom/headache/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
M << "<span class='warning'>[pick("Your head hurts.", "Your head starts pounding.")]</span>"
return
@@ -0,0 +1,158 @@
/*
//////////////////////////////////////
Healing
Little bit hidden.
Lowers resistance tremendously.
Decreases stage speed tremendously.
Decreases transmittablity temrendously.
Fatal Level.
Bonus
Heals toxins in the affected mob's blood stream.
//////////////////////////////////////
*/
/datum/symptom/heal
name = "Toxic Filter"
stealth = 1
resistance = -4
stage_speed = -4
transmittable = -4
level = 6
/datum/symptom/heal/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB * 10))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(4, 5)
Heal(M, A)
return
/datum/symptom/heal/proc/Heal(mob/living/M, datum/disease/advance/A)
var/get_damage = (sqrt(20+A.totalStageSpeed())*(1+rand()))
M.adjustToxLoss(-get_damage)
return 1
/*
//////////////////////////////////////
Metabolism
Little bit hidden.
Lowers resistance.
Decreases stage speed.
Decreases transmittablity temrendously.
High Level.
Bonus
Cures all diseases (except itself) and creates anti-bodies for them until the symptom dies.
//////////////////////////////////////
*/
/datum/symptom/heal/metabolism
name = "Anti-Bodies Metabolism"
stealth = -1
resistance = -1
stage_speed = -1
transmittable = -4
level = 3
var/list/cured_diseases = list()
/datum/symptom/heal/metabolism/Heal(mob/living/M, datum/disease/advance/A)
var/cured = 0
for(var/datum/disease/D in M.viruses)
if(D != A)
cured = 1
cured_diseases += D.GetDiseaseID()
D.cure()
if(cured)
M << "<span class='notice'>You feel much better.</span>"
/datum/symptom/heal/metabolism/End(datum/disease/advance/A)
// Remove all the diseases we cured.
var/mob/living/M = A.affected_mob
if(istype(M))
if(cured_diseases.len)
for(var/res in M.resistances)
if(res in cured_diseases)
M.resistances -= res
M << "<span class='warning'>You feel weaker.</span>"
/*
//////////////////////////////////////
Longevity
Medium hidden boost.
Large resistance boost.
Large stage speed boost.
Large transmittablity boost.
High Level.
Bonus
After a certain amount of time the symptom will cure itself.
//////////////////////////////////////
*/
/datum/symptom/heal/longevity
name = "Longevity"
stealth = 3
resistance = 4
stage_speed = 4
transmittable = 4
level = 3
var/longevity = 30
/datum/symptom/heal/longevity/Heal(mob/living/M, datum/disease/advance/A)
longevity -= 1
if(!longevity)
A.cure()
/datum/symptom/heal/longevity/Start(datum/disease/advance/A)
longevity = rand(initial(longevity) - 5, initial(longevity) + 5)
/*
//////////////////////////////////////
DNA Restoration
Not well hidden.
Lowers resistance minorly.
Does not affect stage speed.
Decreases transmittablity greatly.
Very high level.
Bonus
Heals brain damage, treats radiation, cleans SE of non-power mutations.
//////////////////////////////////////
*/
/datum/symptom/heal/dna
name = "Deoxyribonucleic Acid Restoration"
stealth = -1
resistance = -1
stage_speed = 0
transmittable = -3
level = 5
/datum/symptom/heal/dna/Heal(mob/living/carbon/M, datum/disease/advance/A)
var/stage_speed = max( 20 + A.totalStageSpeed(), 0)
var/stealth_amount = max( 16 + A.totalStealth(), 0)
var/amt_healed = (sqrt(stage_speed*(3+rand())))-(sqrt(stealth_amount*rand()))
M.adjustBrainLoss(-amt_healed)
//Non-power mutations, excluding race, so the virus does not force monkey -> human transformations.
var/list/unclean_mutations = (not_good_mutations|bad_mutations) - mutations_list[RACEMUT]
M.dna.remove_mutation_group(unclean_mutations)
M.radiation = max(M.radiation - 3, 0)
return 1
@@ -0,0 +1,34 @@
/*
//////////////////////////////////////
Itching
Not noticable or unnoticable.
Resistant.
Increases stage speed.
Little transmittable.
Low Level.
BONUS
Displays an annoying message!
Should be used for buffing your disease.
//////////////////////////////////////
*/
/datum/symptom/itching
name = "Itching"
stealth = 0
resistance = 3
stage_speed = 3
transmittable = 1
level = 1
severity = 1
/datum/symptom/itching/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
M << "<span class='warning'>Your [pick("back", "arm", "leg", "elbow", "head")] itches.</span>"
return
@@ -0,0 +1,38 @@
/*
//////////////////////////////////////
Self-Respiration
Slightly hidden.
Lowers resistance significantly.
Decreases stage speed significantly.
Decreases transmittablity tremendously.
Fatal Level.
Bonus
The body generates salbutamol.
//////////////////////////////////////
*/
/datum/symptom/oxygen
name = "Self-Respiration"
stealth = 1
resistance = -3
stage_speed = -3
transmittable = -4
level = 6
/datum/symptom/oxygen/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB * 5))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(4, 5)
if (M.reagents.get_reagent_amount("salbutamol") < 20)
M.reagents.add_reagent("salbutamol", 20)
else
if(prob(SYMPTOM_ACTIVATION_PROB * 5))
M << "<span class='notice'>[pick("Your lungs feel great.", "You realize you haven't been breathing.", "You don't feel the need to breathe.")]</span>"
return
@@ -0,0 +1,101 @@
/*
//////////////////////////////////////
Sensory-Restoration
Very very very very noticable.
Lowers resistance tremendously.
Decreases stage speed tremendously.
Decreases transmittablity tremendously.
Fatal.
Bonus
The body generates Sensory restorational chemicals.
inacusiate for ears
antihol for removal of alcohol
synaphydramine to purge sensory hallucigens and histamine based impairment
mannitol to kickstart the mind
//////////////////////////////////////
*/
/datum/symptom/sensory_restoration
name = "Sensory Restoration"
stealth = -1
resistance = -4
stage_speed = -4
transmittable = -3
level = 5
severity = 0
/datum/symptom/sensory_restoration/Activate(var/datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB * 3))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(2)
if(M.reagents.get_reagent_amount("inacusiate")<10)
M.reagents.add_reagent("inacusiate", 10)
M << "<span class='notice'>Your hearing feels clearer and crisp.</span>"
if(3)
if(M.reagents.get_reagent_amount("antihol") < 10 && M.reagents.get_reagent_amount("inacusiate") < 10 )
M.reagents.add_reagent_list(list("antihol"=10, "inacusiate"=10))
M << "<span class='notice'>You feel sober.</span>"
if(4)
if(M.reagents.get_reagent_amount("antihol") < 10 && M.reagents.get_reagent_amount("inacusiate") < 10 && M.reagents.get_reagent_amount("synaphydramine") < 10)
M.reagents.add_reagent_list(list("antihol"=10, "inacusiate"=10, "synaphydramine"=5))
M << "<span class='notice'>You feel focused.</span>"
if(5)
if(M.reagents.get_reagent_amount("antihol") < 10 && M.reagents.get_reagent_amount("inacusiate") < 10 && M.reagents.get_reagent_amount("synaphydramine") < 10 && M.reagents.get_reagent_amount("mannitol") < 10)
M.reagents.add_reagent_list(list("mannitol"=10, "antihol"=10, "inacusiate"=10, "synaphydramine"=10))
return
/*
//////////////////////////////////////
Sensory-Destruction
noticable.
Lowers resistance
Decreases stage speed tremendously.
Decreases transmittablity tremendously.
the drugs hit them so hard they have to focus on not dying
Bonus
The body generates Sensory destructive chemicals.
You cannot taste anything anymore.
ethanol for extremely drunk victim
mindbreaker to break the mind
impedrezene to ruin the brain
//////////////////////////////////////
*/
/datum/symptom/sensory_destruction
name = "Sensory destruction"
stealth = -1
resistance = -2
stage_speed = -3
transmittable = -4
level = 6
severity = 5
/datum/symptom/sensory_destruction/Activate(var/datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(1)
M << "<span class='warning'>You can't feel anything.</span>"
if(2)
M << "<span class='warning'>You feel absolutely hammered.</span>"
if(prob(10))
M.reagents.add_reagent("morphine",rand(5,7))
if(3)
M.reagents.add_reagent("ethanol",rand(5,7))
M << "<span class='warning'>You try to focus on not dying.</span>"
if(prob(15))
M.reagents.add_reagent("morphine",rand(5,7))
if(4)
M.reagents.add_reagent_list(list("ethanol" = rand(7,15), "mindbreaker" = rand(5,10)))
M << "<span class='warning'>u can count 2 potato!</span>"
if(prob(20))
M.reagents.add_reagent("morphine",rand(5,7))
if(5)
M.reagents.add_reagent_list(list("impedrezene" = rand(5,15), "ethanol" = rand(7,20), "mindbreaker" = rand(5,15)))
if(prob(25))
M.reagents.add_reagent("morphine",rand(5,7))
return
@@ -0,0 +1,48 @@
/*
//////////////////////////////////////
Alopecia
Noticable.
Decreases resistance slightly.
Reduces stage speed slightly.
Transmittable.
Intense Level.
BONUS
Makes the mob lose hair.
//////////////////////////////////////
*/
/datum/symptom/shedding
name = "Alopecia"
stealth = -1
resistance = -1
stage_speed = -1
transmittable = 2
level = 4
severity = 1
/datum/symptom/shedding/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
M << "<span class='warning'>[pick("Your scalp itches.", "Your skin feels flakey.")]</span>"
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
switch(A.stage)
if(3, 4)
if(!(H.hair_style == "Bald") && !(H.hair_style == "Balding Hair"))
H << "<span class='warning'>Your hair starts to fall out in clumps...</span>"
spawn(50)
H.hair_style = "Balding Hair"
H.update_hair()
if(5)
if(!(H.facial_hair_style == "Shaved") || !(H.hair_style == "Bald"))
H << "<span class='warning'>Your hair starts to fall out in clumps...</span>"
spawn(50)
H.facial_hair_style = "Shaved"
H.hair_style = "Bald"
H.update_hair()
return
@@ -0,0 +1,40 @@
/*
//////////////////////////////////////
Shivering
No change to hidden.
Increases resistance.
Increases stage speed.
Little transmittable.
Low level.
Bonus
Cools down your body.
//////////////////////////////////////
*/
/datum/symptom/shivering
name = "Shivering"
stealth = 0
resistance = 2
stage_speed = 2
transmittable = 2
level = 2
severity = 2
/datum/symptom/shivering/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/carbon/M = A.affected_mob
M << "<span class='warning'>[pick("You feel cold.", "You start shivering.")]</span>"
if(M.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT)
Chill(M, A)
return
/datum/symptom/shivering/proc/Chill(mob/living/M, datum/disease/advance/A)
var/get_cold = (sqrt(16+A.totalStealth()*2))+(sqrt(21+A.totalResistance()*2))
M.bodytemperature = min(M.bodytemperature - (get_cold * A.stage), BODYTEMP_COLD_DAMAGE_LIMIT + 1)
return 1
@@ -0,0 +1,86 @@
/*
//////////////////////////////////////
Vitiligo
Extremely Noticable.
Decreases resistance slightly.
Reduces stage speed slightly.
Reduces transmission.
Critical Level.
BONUS
Makes the mob lose skin pigmentation.
//////////////////////////////////////
*/
/datum/symptom/vitiligo
name = "Vitiligo"
stealth = -3
resistance = -1
stage_speed = -1
transmittable = -2
level = 4
severity = 1
/datum/symptom/vitiligo/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
if(H.skin_tone == "albino")
return
switch(A.stage)
if(5)
H.skin_tone = "albino"
H.update_body(0)
else
H.visible_message("<span class='warning'>[H] looks a bit pale...</span>", "<span class='notice'>Your skin suddenly appears lighter...</span>")
return
/*
//////////////////////////////////////
Revitiligo
Extremely Noticable.
Decreases resistance slightly.
Reduces stage speed slightly.
Reduces transmission.
Critical Level.
BONUS
Makes the mob gain skin pigmentation.
//////////////////////////////////////
*/
/datum/symptom/revitiligo
name = "Revitiligo"
stealth = -3
resistance = -1
stage_speed = -1
transmittable = -2
level = 4
severity = 1
/datum/symptom/revitiligo/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
if(H.skin_tone == "african2")
return
switch(A.stage)
if(5)
H.skin_tone = "african2"
H.update_body(0)
else
H.visible_message("<span class='warning'>[H] looks a bit dark...</span>", "<span class='notice'>Your skin suddenly appears darker...</span>")
return
@@ -0,0 +1,39 @@
/*
//////////////////////////////////////
Sneezing
Very Noticable.
Increases resistance.
Doesn't increase stage speed.
Very transmittable.
Low Level.
Bonus
Forces a spread type of AIRBORNE
with extra range!
//////////////////////////////////////
*/
/datum/symptom/sneeze
name = "Sneezing"
stealth = -2
resistance = 3
stage_speed = 0
transmittable = 4
level = 1
severity = 1
/datum/symptom/sneeze/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(1, 2, 3)
M.emote("sniff")
else
M.emote("sneeze")
A.spread(A.holder, 5)
return
@@ -0,0 +1,38 @@
/*
//////////////////////////////////////
Stimulant //gotta go fast
Noticable.
Lowers resistance significantly.
Decreases stage speed moderately..
Decreases transmittablity tremendously.
Moderate Level.
Bonus
The body generates Ephedrine.
//////////////////////////////////////
*/
/datum/symptom/stimulant
name = "Stimulant"
stealth = -1
resistance = -3
stage_speed = -2
transmittable = -4
level = 3
/datum/symptom/stimulant/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB * 10))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(5)
if (M.reagents.get_reagent_amount("ephedrine") < 10)
M.reagents.add_reagent("ephedrine", 10)
else
if(prob(SYMPTOM_ACTIVATION_PROB * 5))
M << "<span class='notice'>[pick("You feel restless.", "You feel like running laps around the station.")]</span>"
return
@@ -0,0 +1,40 @@
// Symptoms are the effects that engineered advanced diseases do.
var/list/list_symptoms = subtypesof(/datum/symptom)
var/list/dictionary_symptoms = list()
var/global/const/SYMPTOM_ACTIVATION_PROB = 3
/datum/symptom
// Buffs/Debuffs the symptom has to the overall engineered disease.
var/name = ""
var/stealth = 0
var/resistance = 0
var/stage_speed = 0
var/transmittable = 0
// The type level of the symptom. Higher is harder to generate.
var/level = 0
// The severity level of the symptom. Higher is more dangerous.
var/severity = 0
// The hash tag for our diseases, we will add it up with our other symptoms to get a unique id! ID MUST BE UNIQUE!!!
var/id = ""
/datum/symptom/New()
var/list/S = list_symptoms
for(var/i = 1; i <= S.len; i++)
if(src.type == S[i])
id = "[i]"
return
CRASH("We couldn't assign an ID!")
// Called when processing of the advance disease, which holds this symptom, starts.
/datum/symptom/proc/Start(datum/disease/advance/A)
return
// Called when the advance disease is going to be deleted or when the advance disease stops processing.
/datum/symptom/proc/End(datum/disease/advance/A)
return
/datum/symptom/proc/Activate(datum/disease/advance/A)
return
@@ -0,0 +1,65 @@
/*
//////////////////////////////////////
Viral adaptation
Moderate stealth boost.
Major Increases to resistance.
Reduces stage speed.
No change to transmission
Critical Level.
BONUS
Extremely useful for buffing viruses
//////////////////////////////////////
*/
/datum/symptom/viraladaptation
name = "Viral self-adaptation"
stealth = 3
resistance = 5
stage_speed = -3
transmittable = 0
level = 3
/datum/symptom/viraladaptation/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(1)
M << "<span class='notice'>You feel off, but no different from before.</span>"
if(5)
M << "<span class='notice'>You feel better, but nothing interesting happens.</span>"
/*
//////////////////////////////////////
Viral evolution
Moderate stealth reductopn.
Major decreases to resistance.
increases stage speed.
increase to transmission
Critical Level.
BONUS
Extremely useful for buffing viruses
//////////////////////////////////////
*/
/datum/symptom/viralevolution
name = "Viral evolutionary acceleration"
stealth = -2
resistance = -3
stage_speed = 5
transmittable = 3
level = 3
/datum/symptom/viraladaptation/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(1)
M << "<span class='notice'>You feel better, but no different from before.</span>"
if(5)
M << "<span class='notice'>You feel off, but nothing interesting happens.</span>"
@@ -0,0 +1,87 @@
/*
//////////////////////////////////////
Hyphema (Eye bleeding)
Slightly noticable.
Lowers resistance tremendously.
Decreases stage speed tremendously.
Decreases transmittablity.
Critical Level.
Bonus
Causes blindness.
//////////////////////////////////////
*/
/datum/symptom/visionloss
name = "Hyphema"
stealth = -1
resistance = -4
stage_speed = -4
transmittable = -3
level = 5
severity = 4
/datum/symptom/visionloss/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(1, 2)
M << "<span class='warning'>Your eyes itch.</span>"
if(3, 4)
M << "<span class='warning'><b>Your eyes burn!</b></span>"
M.blur_eyes(10)
M.adjust_eye_damage(1)
else
M << "<span class='userdanger'>Your eyes burn horrificly!</span>"
M.blur_eyes(20)
M.adjust_eye_damage(5)
if(M.eye_damage >= 10)
M.become_nearsighted()
if(prob(M.eye_damage - 10 + 1))
if(M.become_blind())
M << "<span class='userdanger'>You go blind!</span>"
/*
//////////////////////////////////////
Ocular Restoration
Noticable.
Lowers resistance significantly.
Decreases stage speed moderately..
Decreases transmittablity tremendously.
High level.
Bonus
Restores eyesight.
//////////////////////////////////////
*/
/datum/symptom/visionaid
name = "Ocular Restoration"
stealth = -1
resistance = -3
stage_speed = -2
transmittable = -4
level = 4
/datum/symptom/visionaid/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB * 5))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(4, 5)
if (M.reagents.get_reagent_amount("oculine") < 20)
M.reagents.add_reagent("oculine", 20)
else
if(prob(SYMPTOM_ACTIVATION_PROB * 5))
M << "<span class='notice'>[pick("Your eyes feel great.", "You are now blinking manually.", "You don't feel the need to blink.")]</span>"
return
@@ -0,0 +1,48 @@
/*
//////////////////////////////////////
Voice Change
Very Very noticable.
Lowers resistance considerably.
Decreases stage speed.
Reduced transmittable.
Fatal Level.
Bonus
Changes the voice of the affected mob. Causing confusion in communication.
//////////////////////////////////////
*/
/datum/symptom/voice_change
name = "Voice Change"
stealth = -2
resistance = -3
stage_speed = -3
transmittable = -1
level = 6
severity = 2
/datum/symptom/voice_change/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/carbon/M = A.affected_mob
switch(A.stage)
if(1, 2, 3, 4)
M << "<span class='warning'>[pick("Your throat hurts.", "You clear your throat.")]</span>"
else
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.SetSpecialVoice(H.dna.species.random_name(H.gender))
return
/datum/symptom/voice_change/End(datum/disease/advance/A)
..()
if(ishuman(A.affected_mob))
var/mob/living/carbon/human/H = A.affected_mob
H.UnsetSpecialVoice()
return
@@ -0,0 +1,106 @@
/*
//////////////////////////////////////
Vomiting
Very Very Noticable.
Decreases resistance.
Doesn't increase stage speed.
Little transmittable.
Medium Level.
Bonus
Forces the affected mob to vomit!
Meaning your disease can spread via
people walking on vomit.
Makes the affected mob lose nutrition and
heal toxin damage.
//////////////////////////////////////
*/
/datum/symptom/vomit
name = "Vomiting"
stealth = -2
resistance = -1
stage_speed = 0
transmittable = 1
level = 3
severity = 4
/datum/symptom/vomit/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB / 2))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(1, 2, 3, 4)
M << "<span class='warning'>[pick("You feel nauseous.", "You feel like you're going to throw up!")]</span>"
else
Vomit(M)
return
/datum/symptom/vomit/proc/Vomit(mob/living/carbon/M)
M.vomit(20)
/*
//////////////////////////////////////
Vomiting Blood
Very Very Noticable.
Decreases resistance.
Decreases stage speed.
Little transmittable.
Intense level.
Bonus
Forces the affected mob to vomit blood!
Meaning your disease can spread via
people walking on the blood.
Makes the affected mob lose health.
//////////////////////////////////////
*/
/datum/symptom/vomit/blood
name = "Blood Vomiting"
stealth = -2
resistance = -1
stage_speed = -1
transmittable = 1
level = 4
severity = 5
/datum/symptom/vomit/blood/Vomit(mob/living/carbon/M)
M.vomit(0, 1)
/*
//////////////////////////////////////
Projectile Vomiting
Very Very Noticable.
Decreases resistance.
Doesn't increase stage speed.
Little transmittable.
Medium Level.
Bonus
As normal vomiting, except it will spread further,
likely causing more to walk across the vomit.
//////////////////////////////////////
*/
/datum/symptom/vomit/projectile
name = "Projectile Vomiting"
stealth = -2
level = 4
/datum/symptom/vomit/projectile/Vomit(mob/living/carbon/M)
M.vomit(6,0,1,5,1)
@@ -0,0 +1,44 @@
/*
//////////////////////////////////////
Weakness
Slightly noticeable.
Lowers resistance slightly.
Decreases stage speed moderately.
Decreases transmittablity moderately.
Moderate Level.
Bonus
Deals stamina damage to the host
//////////////////////////////////////
*/
/datum/symptom/weakness
name = "Weakness"
stealth = -1
resistance = -1
stage_speed = -2
transmittable = -2
level = 3
severity = 3
/datum/symptom/weakness/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(1, 2)
M << "<span class='warning'>[pick("You feel weak.", "You feel lazy.")]</span>"
if(3, 4)
M << "<span class='warning'><b>[pick("You feel very frail.", "You think you might faint.")]</span>"
M.adjustStaminaLoss(15)
else
M << "<span class='userdanger'>[pick("You feel tremendously weak!", "Your body trembles as exhaustion creeps over you.")]</span>"
M.adjustStaminaLoss(30)
if(M.getStaminaLoss() > 60 && !M.stat)
M.visible_message("<span class='warning'>[M] faints!</span>", "<span class='userdanger'>You swoon and faint...</span>")
M.AdjustSleeping(5)
return
@@ -0,0 +1,121 @@
/*
//////////////////////////////////////
Weight Gain
Very Very Noticable.
Decreases resistance.
Decreases stage speed.
Reduced transmittable.
Intense Level.
Bonus
Increases the weight gain of the mob,
forcing it to eventually turn fat.
//////////////////////////////////////
*/
/datum/symptom/weight_gain
name = "Weight Gain"
stealth = -3
resistance = -3
stage_speed = -2
transmittable = -2
level = 4
severity = 1
/datum/symptom/weight_gain/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(1, 2, 3, 4)
M << "<span class='warning'>[pick("You feel blubbery.", "Your stomach hurts.")]</span>"
else
M.overeatduration = min(M.overeatduration + 100, 600)
M.nutrition = min(M.nutrition + 100, NUTRITION_LEVEL_FULL)
return
/*
//////////////////////////////////////
Weight Loss
Very Very Noticable.
Decreases resistance.
Decreases stage speed.
Reduced Transmittable.
High level.
Bonus
Decreases the weight of the mob,
forcing it to be skinny.
//////////////////////////////////////
*/
/datum/symptom/weight_loss
name = "Weight Loss"
stealth = -3
resistance = -2
stage_speed = -2
transmittable = -2
level = 3
severity = 1
/datum/symptom/weight_loss/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(1, 2, 3, 4)
M << "<span class='warning'>[pick("You feel hungry.", "You crave for food.")]</span>"
else
M << "<span class='warning'><i>[pick("So hungry...", "You'd kill someone for a bite of food...", "Hunger cramps seize you...")]</i></span>"
M.overeatduration = max(M.overeatduration - 100, 0)
M.nutrition = max(M.nutrition - 100, 0)
return
/*
//////////////////////////////////////
Weight Even
Very Noticable.
Decreases resistance.
Decreases stage speed.
Reduced transmittable.
High level.
Bonus
Causes the weight of the mob to
be even, meaning eating isn't
required anymore.
//////////////////////////////////////
*/
/datum/symptom/weight_even
name = "Weight Even"
stealth = -3
resistance = -2
stage_speed = -2
transmittable = -2
level = 4
/datum/symptom/weight_even/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/M = A.affected_mob
switch(A.stage)
if(4, 5)
M.overeatduration = 0
M.nutrition = NUTRITION_LEVEL_WELL_FED + 50
return
@@ -0,0 +1,55 @@
/*
//////////////////////////////////////
Eternal Youth
Moderate stealth boost.
Increases resistance tremendously.
Increases stage speed tremendously.
Reduces transmission tremendously.
Critical Level.
BONUS
Gives you immortality and eternal youth!!!
Can be used to buff your virus
//////////////////////////////////////
*/
/datum/symptom/youth
name = "Eternal Youth"
stealth = 3
resistance = 4
stage_speed = 4
transmittable = -4
level = 5
/datum/symptom/youth/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB * 2))
var/mob/living/M = A.affected_mob
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
switch(A.stage)
if(1)
if(H.age > 41)
H.age = 41
H << "<span class='notice'>You haven't had this much energy in years!</span>"
if(2)
if(H.age > 36)
H.age = 36
H << "<span class='notice'>You're suddenly in a good mood.</span>"
if(3)
if(H.age > 31)
H.age = 31
H << "<span class='notice'>You begin to feel more lithe.</span>"
if(4)
if(H.age > 26)
H.age = 26
H << "<span class='notice'>You feel reinvigorated.</span>"
if(5)
if(H.age > 21)
H.age = 21
H << "<span class='notice'>You feel like you can take on the world!</span>"
return
+41
View File
@@ -0,0 +1,41 @@
/datum/disease/anxiety
name = "Severe Anxiety"
form = "Infection"
max_stages = 4
spread_text = "On contact"
spread_flags = CONTACT_GENERAL
cure_text = "Ethanol"
cures = list("ethanol")
agent = "Excess Lepidopticides"
viable_mobtypes = list(/mob/living/carbon/human,/mob/living/carbon/monkey)
desc = "If left untreated subject will regurgitate butterflies."
severity = MEDIUM
/datum/disease/anxiety/stage_act()
..()
switch(stage)
if(2) //also changes say, see say.dm
if(prob(5))
affected_mob << "<span class='notice'>You feel anxious.</span>"
if(3)
if(prob(10))
affected_mob << "<span class='notice'>Your stomach flutters.</span>"
if(prob(5))
affected_mob << "<span class='notice'>You feel panicky.</span>"
if(prob(2))
affected_mob << "<span class='danger'>You're overtaken with panic!</span>"
affected_mob.confused += (rand(2,3))
if(4)
if(prob(10))
affected_mob << "<span class='danger'>You feel butterflies in your stomach.</span>"
if(prob(5))
affected_mob.visible_message("<span class='danger'>[affected_mob] stumbles around in a panic.</span>", \
"<span class='userdanger'>You have a panic attack!</span>")
affected_mob.confused += (rand(6,8))
affected_mob.jitteriness += (rand(6,8))
if(prob(2))
affected_mob.visible_message("<span class='danger'>[affected_mob] coughs up butterflies!</span>", \
"<span class='userdanger'>You cough up butterflies!</span>")
new /mob/living/simple_animal/butterfly(affected_mob.loc)
new /mob/living/simple_animal/butterfly(affected_mob.loc)
return
+34
View File
@@ -0,0 +1,34 @@
/datum/disease/appendicitis
form = "Condition"
name = "Appendicitis"
max_stages = 3
cure_text = "Surgery"
agent = "Shitty Appendix"
viable_mobtypes = list(/mob/living/carbon/human)
permeability_mod = 1
desc = "If left untreated the subject will become very weak, and may vomit often."
severity = "Dangerous!"
longevity = 1000
disease_flags = CAN_CARRY|CAN_RESIST
spread_flags = NON_CONTAGIOUS
visibility_flags = HIDDEN_PANDEMIC
required_organs = list(/obj/item/organ/appendix)
/datum/disease/appendicitis/stage_act()
..()
switch(stage)
if(1)
if(prob(5))
affected_mob.emote("cough")
if(2)
var/obj/item/organ/appendix/A = affected_mob.getorgan(/obj/item/organ/appendix)
if(A)
A.inflamed = 1
A.update_icon()
if(prob(3))
affected_mob << "<span class='warning'>You feel a stabbing pain in your abdomen!</span>"
affected_mob.Stun(rand(2,3))
affected_mob.adjustToxLoss(1)
if(3)
if(prob(1))
affected_mob.vomit(95)
+40
View File
@@ -0,0 +1,40 @@
/datum/disease/beesease
name = "Beesease"
form = "Infection"
max_stages = 4
spread_text = "On contact"
spread_flags = CONTACT_GENERAL
cure_text = "Sugar"
cures = list("sugar")
agent = "Apidae Infection"
viable_mobtypes = list(/mob/living/carbon/human,/mob/living/carbon/monkey)
desc = "If left untreated subject will regurgitate bees."
severity = DANGEROUS
/datum/disease/beesease/stage_act()
..()
switch(stage)
if(2) //also changes say, see say.dm
if(prob(2))
affected_mob << "<span class='notice'>You taste honey in your mouth.</span>"
if(3)
if(prob(10))
affected_mob << "<span class='notice'>Your stomach rumbles.</span>"
if(prob(2))
affected_mob << "<span class='danger'>Your stomach stings painfully.</span>"
if(prob(20))
affected_mob.adjustToxLoss(2)
affected_mob.updatehealth()
if(4)
if(prob(10))
affected_mob.visible_message("<span class='danger'>[affected_mob] buzzes.</span>", \
"<span class='userdanger'>Your stomach buzzes violently!</span>")
if(prob(5))
affected_mob << "<span class='danger'>You feel something moving in your throat.</span>"
if(prob(1))
affected_mob.visible_message("<span class='danger'>[affected_mob] coughs up a swarm of bees!</span>", \
"<span class='userdanger'>You cough up a swarm of bees!</span>")
new /mob/living/simple_animal/hostile/poison/bees(affected_mob.loc)
//if(5)
//Plus if you die, you explode into bees
return
+59
View File
@@ -0,0 +1,59 @@
/datum/disease/brainrot
name = "Brainrot"
max_stages = 4
spread_text = "On contact"
spread_flags = CONTACT_GENERAL
cure_text = "Mannitol"
cures = list("mannitol")
agent = "Cryptococcus Cosmosis"
viable_mobtypes = list(/mob/living/carbon/human)
cure_chance = 15//higher chance to cure, since two reagents are required
desc = "This disease destroys the braincells, causing brain fever, brain necrosis and general intoxication."
required_organs = list(/obj/item/bodypart/head)
severity = DANGEROUS
/datum/disease/brainrot/stage_act() //Removed toxloss because damaging diseases are pretty horrible. Last round it killed the entire station because the cure didn't work -- Urist -ACTUALLY Removed rather than commented out, I don't see it returning - RR
..()
switch(stage)
if(2)
if(prob(2))
affected_mob.emote("blink")
if(prob(2))
affected_mob.emote("yawn")
if(prob(2))
affected_mob << "<span class='danger'>You don't feel like yourself.</span>"
if(prob(5))
affected_mob.adjustBrainLoss(1)
affected_mob.updatehealth()
if(3)
if(prob(2))
affected_mob.emote("stare")
if(prob(2))
affected_mob.emote("drool")
if(prob(10) && affected_mob.getBrainLoss()<=98)//shouldn't retard you to death now
affected_mob.adjustBrainLoss(2)
affected_mob.updatehealth()
if(prob(2))
affected_mob << "<span class='danger'>Your try to remember something important...but can't.</span>"
if(4)
if(prob(2))
affected_mob.emote("stare")
if(prob(2))
affected_mob.emote("drool")
if(prob(15) && affected_mob.getBrainLoss()<=98) //shouldn't retard you to death now
affected_mob.adjustBrainLoss(3)
affected_mob.updatehealth()
if(prob(2))
affected_mob << "<span class='danger'>Strange buzzing fills your head, removing all thoughts.</span>"
if(prob(3))
affected_mob << "<span class='danger'>You lose consciousness...</span>"
affected_mob.visible_message("<span class='warning'>[affected_mob] suddenly collapses</span>")
affected_mob.Paralyse(rand(5,10))
if(prob(1))
affected_mob.emote("snore")
if(prob(15))
affected_mob.stuttering += 3
return
+66
View File
@@ -0,0 +1,66 @@
/datum/disease/cold
name = "The Cold"
max_stages = 3
spread_flags = AIRBORNE
cure_text = "Rest & Spaceacillin"
cures = list("spaceacillin")
agent = "XY-rhinovirus"
viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
permeability_mod = 0.5
desc = "If left untreated the subject will contract the flu."
severity = MINOR
/datum/disease/cold/stage_act()
..()
switch(stage)
if(2)
/*
if(affected_mob.sleeping && prob(40)) //removed until sleeping is fixed
affected_mob << "\blue You feel better."
cure()
return
*/
if(affected_mob.lying && prob(40)) //changed FROM prob(10) until sleeping is fixed
affected_mob << "<span class='notice'>You feel better.</span>"
cure()
return
if(prob(1) && prob(5))
affected_mob << "<span class='notice'>You feel better.</span>"
cure()
return
if(prob(1))
affected_mob.emote("sneeze")
if(prob(1))
affected_mob.emote("cough")
if(prob(1))
affected_mob << "<span class='danger'>Your throat feels sore.</span>"
if(prob(1))
affected_mob << "<span class='danger'>Mucous runs down the back of your throat.</span>"
if(3)
/*
if(affected_mob.sleeping && prob(25)) //removed until sleeping is fixed
affected_mob << "\blue You feel better."
cure()
return
*/
if(affected_mob.lying && prob(25)) //changed FROM prob(5) until sleeping is fixed
affected_mob << "<span class='notice'>You feel better.</span>"
cure()
return
if(prob(1) && prob(1))
affected_mob << "<span class='notice'>You feel better.</span>"
cure()
return
if(prob(1))
affected_mob.emote("sneeze")
if(prob(1))
affected_mob.emote("cough")
if(prob(1))
affected_mob << "<span class='danger'>Your throat feels sore.</span>"
if(prob(1))
affected_mob << "<span class='danger'>Mucous runs down the back of your throat.</span>"
if(prob(1) && prob(50))
if(!affected_mob.resistances.Find(/datum/disease/flu))
var/datum/disease/Flu = new /datum/disease/flu(0)
affected_mob.ContractDisease(Flu)
cure()
+39
View File
@@ -0,0 +1,39 @@
/datum/disease/cold9
name = "The Cold"
max_stages = 3
spread_text = "On contact"
spread_flags = CONTACT_GENERAL
cure_text = "Common Cold Anti-bodies & Spaceacillin"
cures = list("spaceacillin")
agent = "ICE9-rhinovirus"
viable_mobtypes = list(/mob/living/carbon/human)
desc = "If left untreated the subject will slow, as if partly frozen."
severity = MEDIUM
/datum/disease/cold9/stage_act()
..()
switch(stage)
if(2)
affected_mob.bodytemperature -= 10
if(prob(1) && prob(10))
affected_mob << "<span class='notice'>You feel better.</span>"
cure()
return
if(prob(1))
affected_mob.emote("sneeze")
if(prob(1))
affected_mob.emote("cough")
if(prob(1))
affected_mob << "<span class='danger'>Your throat feels sore.</span>"
if(prob(5))
affected_mob << "<span class='danger'>You feel stiff.</span>"
if(3)
affected_mob.bodytemperature -= 20
if(prob(1))
affected_mob.emote("sneeze")
if(prob(1))
affected_mob.emote("cough")
if(prob(1))
affected_mob << "<span class='danger'>Your throat feels sore.</span>"
if(prob(10))
affected_mob << "<span class='danger'>You feel stiff.</span>"
+74
View File
@@ -0,0 +1,74 @@
/datum/disease/dnaspread
name = "Space Retrovirus"
max_stages = 4
spread_text = "On contact"
spread_flags = CONTACT_GENERAL
cure_text = "Mutadone"
cures = list("mutadone")
disease_flags = CAN_CARRY|CAN_RESIST|CURABLE
agent = "S4E1 retrovirus"
viable_mobtypes = list(/mob/living/carbon/human)
var/datum/dna/original_dna = null
var/transformed = 0
desc = "This disease transplants the genetic code of the initial vector into new hosts."
severity = MEDIUM
/datum/disease/dnaspread/stage_act()
..()
if(!affected_mob.dna)
cure()
if(NOTRANSSTING in affected_mob.dna.species.specflags) //Only species that can be spread by transformation sting can be spread by the retrovirus
cure()
if(!strain_data["dna"])
//Absorbs the target DNA.
strain_data["dna"] = new affected_mob.dna.type
affected_mob.dna.copy_dna(strain_data["dna"])
src.carrier = 1
src.stage = 4
return
switch(stage)
if(2 || 3) //Pretend to be a cold and give time to spread.
if(prob(8))
affected_mob.emote("sneeze")
if(prob(8))
affected_mob.emote("cough")
if(prob(1))
affected_mob << "<span class='danger'>Your muscles ache.</span>"
if(prob(20))
affected_mob.take_organ_damage(1)
if(prob(1))
affected_mob << "<span class='danger'>Your stomach hurts.</span>"
if(prob(20))
affected_mob.adjustToxLoss(2)
affected_mob.updatehealth()
if(4)
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)
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, transfer_SE = 1)
affected_mob.real_name = affected_mob.dna.real_name
affected_mob.updateappearance(mutcolor_update=1)
affected_mob.domutcheck()
transformed = 1
carrier = 1 //Just chill out at stage 4
return
/datum/disease/dnaspread/Destroy()
if (original_dna && transformed && affected_mob)
original_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()
affected_mob << "<span class='notice'>You feel more like yourself.</span>"
return ..()
+32
View File
@@ -0,0 +1,32 @@
/datum/disease/fake_gbs
name = "GBS"
max_stages = 5
spread_text = "On contact"
spread_flags = CONTACT_GENERAL
cure_text = "Synaptizine & Sulfur"
cures = list("synaptizine","sulfur")
agent = "Gravitokinetic Bipotential SADS-"
viable_mobtypes = list(/mob/living/carbon/human,/mob/living/carbon/monkey)
desc = "If left untreated death will occur."
severity = BIOHAZARD
/datum/disease/fake_gbs/stage_act()
..()
switch(stage)
if(2)
if(prob(1))
affected_mob.emote("sneeze")
if(3)
if(prob(5))
affected_mob.emote("cough")
else if(prob(5))
affected_mob.emote("gasp")
if(prob(10))
affected_mob << "<span class='danger'>You're starting to feel very weak...</span>"
if(4)
if(prob(10))
affected_mob.emote("cough")
if(5)
if(prob(10))
affected_mob.emote("cough")
+54
View File
@@ -0,0 +1,54 @@
/datum/disease/flu
name = "The Flu"
max_stages = 3
spread_text = "Airborne"
cure_text = "Spaceacillin"
cures = list("spaceacillin")
cure_chance = 10
agent = "H13N1 flu virion"
viable_mobtypes = list(/mob/living/carbon/human,/mob/living/carbon/monkey)
permeability_mod = 0.75
desc = "If left untreated the subject will feel quite unwell."
severity = MEDIUM
/datum/disease/flu/stage_act()
..()
switch(stage)
if(2)
if(affected_mob.lying && prob(20))
affected_mob << "<span class='notice'>You feel better.</span>"
stage--
return
if(prob(1))
affected_mob.emote("sneeze")
if(prob(1))
affected_mob.emote("cough")
if(prob(1))
affected_mob << "<span class='danger'>Your muscles ache.</span>"
if(prob(20))
affected_mob.take_organ_damage(1)
if(prob(1))
affected_mob << "<span class='danger'>Your stomach hurts.</span>"
if(prob(20))
affected_mob.adjustToxLoss(1)
affected_mob.updatehealth()
if(3)
if(affected_mob.lying && prob(15))
affected_mob << "<span class='notice'>You feel better.</span>"
stage--
return
if(prob(1))
affected_mob.emote("sneeze")
if(prob(1))
affected_mob.emote("cough")
if(prob(1))
affected_mob << "<span class='danger'>Your muscles ache.</span>"
if(prob(20))
affected_mob.take_organ_damage(1)
if(prob(1))
affected_mob << "<span class='danger'>Your stomach hurts.</span>"
if(prob(20))
affected_mob.adjustToxLoss(1)
affected_mob.updatehealth()
return
+36
View File
@@ -0,0 +1,36 @@
/datum/disease/fluspanish
name = "Spanish inquisition Flu"
max_stages = 3
spread_text = "Airborne"
cure_text = "Spaceacillin & Anti-bodies to the common flu"
cures = list("spaceacillin")
cure_chance = 10
agent = "1nqu1s1t10n flu virion"
viable_mobtypes = list(/mob/living/carbon/human)
permeability_mod = 0.75
desc = "If left untreated the subject will burn to death for being a heretic."
severity = DANGEROUS
/datum/disease/fluspanish/stage_act()
..()
switch(stage)
if(2)
affected_mob.bodytemperature += 10
if(prob(5))
affected_mob.emote("sneeze")
if(prob(5))
affected_mob.emote("cough")
if(prob(1))
affected_mob << "<span class='danger'>You're burning in your own skin!</span>"
affected_mob.take_organ_damage(0,5)
if(3)
affected_mob.bodytemperature += 20
if(prob(5))
affected_mob.emote("sneeze")
if(prob(5))
affected_mob.emote("cough")
if(prob(5))
affected_mob << "<span class='danger'>You're burning in your own skin!</span>"
affected_mob.take_organ_damage(0,5)
return
+41
View File
@@ -0,0 +1,41 @@
/datum/disease/gbs
name = "GBS"
max_stages = 5
spread_text = "On contact"
spread_flags = CONTACT_GENERAL
cure_text = "Synaptizine & Sulfur"
cures = list("synaptizine","sulfur")
cure_chance = 15//higher chance to cure, since two reagents are required
agent = "Gravitokinetic Bipotential SADS+"
viable_mobtypes = list(/mob/living/carbon/human)
disease_flags = CAN_CARRY|CAN_RESIST|CURABLE
permeability_mod = 1
severity = BIOHAZARD
/datum/disease/gbs/stage_act()
..()
switch(stage)
if(2)
if(prob(45))
affected_mob.adjustToxLoss(5)
affected_mob.updatehealth()
if(prob(1))
affected_mob.emote("sneeze")
if(3)
if(prob(5))
affected_mob.emote("cough")
else if(prob(5))
affected_mob.emote("gasp")
if(prob(10))
affected_mob << "<span class='danger'>You're starting to feel very weak...</span>"
if(4)
if(prob(10))
affected_mob.emote("cough")
affected_mob.adjustToxLoss(5)
affected_mob.updatehealth()
if(5)
affected_mob << "<span class='danger'>Your body feels as if it's trying to rip itself open...</span>"
if(prob(50))
affected_mob.gib()
else
return
+63
View File
@@ -0,0 +1,63 @@
/datum/disease/magnitis
name = "Magnitis"
max_stages = 4
spread_text = "Airborne"
cure_text = "Iron"
cures = list("iron")
agent = "Fukkos Miracos"
viable_mobtypes = list(/mob/living/carbon/human)
disease_flags = CAN_CARRY|CAN_RESIST|CURABLE
permeability_mod = 0.75
desc = "This disease disrupts the magnetic field of your body, making it act as if a powerful magnet. Injections of iron help stabilize the field."
severity = MEDIUM
/datum/disease/magnitis/stage_act()
..()
switch(stage)
if(2)
if(prob(2))
affected_mob << "<span class='danger'>You feel a slight shock course through your body.</span>"
if(prob(2))
for(var/obj/M in orange(2,affected_mob))
if(!M.anchored && (M.flags & CONDUCT))
step_towards(M,affected_mob)
for(var/mob/living/silicon/S in orange(2,affected_mob))
if(istype(S, /mob/living/silicon/ai)) continue
step_towards(S,affected_mob)
if(3)
if(prob(2))
affected_mob << "<span class='danger'>You feel a strong shock course through your body.</span>"
if(prob(2))
affected_mob << "<span class='danger'>You feel like clowning around.</span>"
if(prob(4))
for(var/obj/M in orange(4,affected_mob))
if(!M.anchored && (M.flags & CONDUCT))
var/i
var/iter = rand(1,2)
for(i=0,i<iter,i++)
step_towards(M,affected_mob)
for(var/mob/living/silicon/S in orange(4,affected_mob))
if(istype(S, /mob/living/silicon/ai)) continue
var/i
var/iter = rand(1,2)
for(i=0,i<iter,i++)
step_towards(S,affected_mob)
if(4)
if(prob(2))
affected_mob << "<span class='danger'>You feel a powerful shock course through your body.</span>"
if(prob(2))
affected_mob << "<span class='danger'>You query upon the nature of miracles.</span>"
if(prob(8))
for(var/obj/M in orange(6,affected_mob))
if(!M.anchored && (M.flags & CONDUCT))
var/i
var/iter = rand(1,3)
for(i=0,i<iter,i++)
step_towards(M,affected_mob)
for(var/mob/living/silicon/S in orange(6,affected_mob))
if(istype(S, /mob/living/silicon/ai)) continue
var/i
var/iter = rand(1,3)
for(i=0,i<iter,i++)
step_towards(S,affected_mob)
return
+25
View File
@@ -0,0 +1,25 @@
/datum/disease/pierrot_throat
name = "Pierrot's Throat"
max_stages = 4
spread_text = "Airborne"
cure_text = "Banana products, especially banana bread."
cures = list("banana")
cure_chance = 75
agent = "H0NI<42 Virus"
viable_mobtypes = list(/mob/living/carbon/human)
permeability_mod = 0.75
desc = "If left untreated the subject will probably drive others to insanity."
severity = MEDIUM
longevity = 400
/datum/disease/pierrot_throat/stage_act()
..()
switch(stage)
if(1)
if(prob(10)) affected_mob << "<span class='danger'>You feel a little silly.</span>"
if(2)
if(prob(10)) affected_mob << "<span class='danger'>You start seeing rainbows.</span>"
if(3)
if(prob(10)) affected_mob << "<span class='danger'>Your thoughts are interrupted by a loud <b>HONK!</b></span>"
if(4)
if(prob(5)) affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) )
+83
View File
@@ -0,0 +1,83 @@
/datum/disease/dna_retrovirus
name = "Retrovirus"
max_stages = 4
spread_text = "Contact"
spread_flags = CONTACT_GENERAL
cure_text = "Rest or an injection of mutadone"
cure_chance = 6
agent = ""
viable_mobtypes = list(/mob/living/carbon/human)
desc = "A DNA-altering retrovirus that scrambles the structural and unique enzymes of a host constantly."
severity = DANGEROUS
permeability_mod = 0.4
stage_prob = 2
var/SE
var/UI
var/restcure = 0
/datum/disease/dna_retrovirus/New()
..()
agent = "Virus class [pick("A","B","C","D","E","F")][pick("A","B","C","D","E","F")]-[rand(50,300)]"
if(prob(40))
cures = list("mutadone")
else
restcure = 1
/datum/disease/dna_retrovirus/stage_act()
..()
switch(stage)
if(1)
if(restcure)
if(affected_mob.lying && prob(30))
affected_mob << "<span class='notice'>You feel better.</span>"
cure()
return
if (prob(8))
affected_mob << "<span class='danger'>Your head hurts.</span>"
if (prob(9))
affected_mob << "You feel a tingling sensation in your chest."
if (prob(9))
affected_mob << "<span class='danger'>You feel angry.</span>"
if(2)
if(restcure)
if(affected_mob.lying && prob(20))
affected_mob << "<span class='notice'>You feel better.</span>"
cure()
return
if (prob(8))
affected_mob << "<span class='danger'>Your skin feels loose.</span>"
if (prob(10))
affected_mob << "You feel very strange."
if (prob(4))
affected_mob << "<span class='danger'>You feel a stabbing pain in your head!</span>"
affected_mob.Paralyse(2)
if (prob(4))
affected_mob << "<span class='danger'>Your stomach churns.</span>"
if(3)
if(restcure)
if(affected_mob.lying && prob(20))
affected_mob << "<span class='notice'>You feel better.</span>"
cure()
return
if (prob(10))
affected_mob << "<span class='danger'>Your entire body vibrates.</span>"
if (prob(35))
if(prob(50))
scramble_dna(affected_mob, 1, 0, rand(15,45))
else
scramble_dna(affected_mob, 0, 1, rand(15,45))
if(4)
if(restcure)
if(affected_mob.lying && prob(5))
affected_mob << "<span class='notice'>You feel better.</span>"
cure()
return
if (prob(60))
if(prob(50))
scramble_dna(affected_mob, 1, 0, rand(50,75))
else
scramble_dna(affected_mob, 0, 1, rand(50,75))
+52
View File
@@ -0,0 +1,52 @@
/datum/disease/rhumba_beat
name = "The Rhumba Beat"
max_stages = 5
spread_text = "On contact"
spread_flags = CONTACT_GENERAL
cure_text = "Chick Chicky Boom!"
cures = list("plasma")
agent = "Unknown"
viable_mobtypes = list(/mob/living/carbon/human)
permeability_mod = 1
severity = BIOHAZARD
/datum/disease/rhumba_beat/stage_act()
..()
switch(stage)
if(1)
if(affected_mob.ckey == "rosham")
src.cure()
if(2)
if(affected_mob.ckey == "rosham")
src.cure()
if(prob(45))
affected_mob.adjustToxLoss(5)
affected_mob.updatehealth()
if(prob(1))
affected_mob << "<span class='danger'>You feel strange...</span>"
if(3)
if(affected_mob.ckey == "rosham")
src.cure()
if(prob(5))
affected_mob << "<span class='danger'>You feel the urge to dance...</span>"
else if(prob(5))
affected_mob.emote("gasp")
else if(prob(10))
affected_mob << "<span class='danger'>You feel the need to chick chicky boom...</span>"
if(4)
if(affected_mob.ckey == "rosham")
src.cure()
if(prob(10))
affected_mob.emote("gasp")
affected_mob << "<span class='danger'>You feel a burning beat inside...</span>"
if(prob(20))
affected_mob.adjustToxLoss(5)
affected_mob.updatehealth()
if(5)
if(affected_mob.ckey == "rosham")
src.cure()
affected_mob << "<span class='danger'>Your body is unable to contain the Rhumba Beat...</span>"
if(prob(50))
affected_mob.gib()
else
return
+242
View File
@@ -0,0 +1,242 @@
/datum/disease/transformation
name = "Transformation"
max_stages = 5
spread_text = "Acute"
spread_flags = SPECIAL
cure_text = "A coder's love (theoretical)."
agent = "Shenanigans"
viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey, /mob/living/carbon/alien)
severity = HARMFUL
stage_prob = 10
visibility_flags = HIDDEN_SCANNER|HIDDEN_PANDEMIC
disease_flags = CURABLE
var/list/stage1 = list("You feel unremarkable.")
var/list/stage2 = list("You feel boring.")
var/list/stage3 = list("You feel utterly plain.")
var/list/stage4 = list("You feel white bread.")
var/list/stage5 = list("Oh the humanity!")
var/new_form = /mob/living/carbon/human
/datum/disease/transformation/stage_act()
..()
switch(stage)
if(1)
if (prob(stage_prob) && stage1)
affected_mob << pick(stage1)
if(2)
if (prob(stage_prob) && stage2)
affected_mob << pick(stage2)
if(3)
if (prob(stage_prob*2) && stage3)
affected_mob << pick(stage3)
if(4)
if (prob(stage_prob*2) && stage4)
affected_mob << pick(stage4)
if(5)
do_disease_transformation(affected_mob)
/datum/disease/transformation/proc/do_disease_transformation(mob/living/affected_mob)
if(istype(affected_mob, /mob/living/carbon) && affected_mob.stat != DEAD)
if(stage5)
affected_mob << pick(stage5)
if(jobban_isbanned(affected_mob, new_form))
affected_mob.death(1)
return
if(affected_mob.notransform)
return
affected_mob.notransform = 1
for(var/obj/item/W in affected_mob)
if(istype(W, /obj/item/weapon/implant))
qdel(W)
continue
W.layer = initial(W.layer)
W.loc = affected_mob.loc
W.dropped(affected_mob)
var/mob/living/new_mob = new new_form(affected_mob.loc)
if(istype(new_mob))
new_mob.a_intent = "harm"
if(affected_mob.mind)
affected_mob.mind.transfer_to(new_mob)
else
new_mob.key = affected_mob.key
qdel(affected_mob)
/datum/disease/transformation/jungle_fever
name = "Jungle Fever"
cure_text = "Bananas"
cures = list("banana")
spread_text = "Monkey Bites"
spread_flags = SPECIAL
viable_mobtypes = list(/mob/living/carbon/monkey, /mob/living/carbon/human)
permeability_mod = 1
cure_chance = 1
disease_flags = CAN_CARRY|CAN_RESIST
longevity = 30
desc = "Monkeys with this disease will bite humans, causing humans to mutate into a monkey."
severity = BIOHAZARD
stage_prob = 4
visibility_flags = 0
agent = "Kongey Vibrion M-909"
new_form = /mob/living/carbon/monkey
stage1 = null
stage2 = null
stage3 = null
stage4 = list("<span class='warning'>Your back hurts.</span>", "<span class='warning'>You breathe through your mouth.</span>",
"<span class='warning'>You have a craving for bananas.</span>", "<span class='warning'>Your mind feels clouded.</span>")
stage5 = list("<span class='warning'>You feel like monkeying around.</span>")
/datum/disease/transformation/jungle_fever/do_disease_transformation(mob/living/carbon/affected_mob)
if(!ismonkey(affected_mob))
ticker.mode.add_monkey(affected_mob.mind)
affected_mob.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
/datum/disease/transformation/jungle_fever/stage_act()
..()
switch(stage)
if(2)
if(prob(2))
affected_mob << "<span class='notice'>Your [pick("back", "arm", "leg", "elbow", "head")] itches.</span>"
if(3)
if(prob(4))
affected_mob << "<span class='danger'>You feel a stabbing pain in your head.</span>"
affected_mob.confused += 10
if(4)
if(prob(3))
affected_mob.say(pick("Eeek, ook ook!", "Eee-eeek!", "Eeee!", "Ungh, ungh."))
/datum/disease/transformation/jungle_fever/cure()
ticker.mode.remove_monkey(affected_mob.mind)
..()
/datum/disease/transformation/robot
name = "Robotic Transformation"
cure_text = "An injection of copper."
cures = list("copper")
cure_chance = 5
agent = "R2D2 Nanomachines"
desc = "This disease, actually acute nanomachine infection, converts the victim into a cyborg."
severity = DANGEROUS
visibility_flags = 0
stage1 = null
stage2 = list("Your joints feel stiff.", "<span class='danger'>Beep...boop..</span>")
stage3 = list("<span class='danger'>Your joints feel very stiff.</span>", "Your skin feels loose.", "<span class='danger'>You can feel something move...inside.</span>")
stage4 = list("<span class='danger'>Your skin feels very loose.</span>", "<span class='danger'>You can feel... something...inside you.</span>")
stage5 = list("<span class='danger'>Your skin feels as if it's about to burst off!</span>")
new_form = /mob/living/silicon/robot
/datum/disease/transformation/robot/stage_act()
..()
switch(stage)
if(3)
if (prob(8))
affected_mob.say(pick("Beep, boop", "beep, beep!", "Boop...bop"))
if (prob(4))
affected_mob << "<span class='danger'>You feel a stabbing pain in your head.</span>"
affected_mob.Paralyse(2)
if(4)
if (prob(20))
affected_mob.say(pick("beep, beep!", "Boop bop boop beep.", "kkkiiiill mmme", "I wwwaaannntt tttoo dddiiieeee..."))
/datum/disease/transformation/xeno
name = "Xenomorph Transformation"
cure_text = "Spaceacillin & Glycerol"
cures = list("spaceacillin", "glycerol")
cure_chance = 5
agent = "Rip-LEY Alien Microbes"
desc = "This disease changes the victim into a xenomorph."
severity = BIOHAZARD
visibility_flags = 0
stage1 = null
stage2 = list("Your throat feels scratchy.", "<span class='danger'>Kill...</span>")
stage3 = list("<span class='danger'>Your throat feels very scratchy.</span>", "Your skin feels tight.", "<span class='danger'>You can feel something move...inside.</span>")
stage4 = list("<span class='danger'>Your skin feels very tight.</span>", "<span class='danger'>Your blood boils!</span>", "<span class='danger'>You can feel... something...inside you.</span>")
stage5 = list("<span class='danger'>Your skin feels as if it's about to burst off!</span>")
new_form = /mob/living/carbon/alien/humanoid/hunter
/datum/disease/transformation/xeno/stage_act()
..()
switch(stage)
if(3)
if (prob(4))
affected_mob << "<span class='danger'>You feel a stabbing pain in your head.</span>"
affected_mob.Paralyse(2)
if(4)
if (prob(20))
affected_mob.say(pick("You look delicious.", "Going to... devour you...", "Hsssshhhhh!"))
/datum/disease/transformation/slime
name = "Advanced Mutation Transformation"
cure_text = "frost oil"
cures = list("frostoil")
cure_chance = 80
agent = "Advanced Mutation Toxin"
desc = "This highly concentrated extract converts anything into more of itself."
severity = BIOHAZARD
visibility_flags = 0
stage1 = list("You don't feel very well.")
stage2 = list("Your skin feels a little slimy.")
stage3 = list("<span class='danger'>Your appendages are melting away.</span>", "<span class='danger'>Your limbs begin to lose their shape.</span>")
stage4 = list("<span class='danger'>You are turning into a slime.</span>")
stage5 = list("<span class='danger'>You have become a slime.</span>")
new_form = /mob/living/simple_animal/slime
/datum/disease/transformation/slime/stage_act()
..()
switch(stage)
if(1)
if(ishuman(affected_mob) && affected_mob.dna && affected_mob.dna.species.id == "slime")
stage = 5
if(3)
if(ishuman(affected_mob))
var/mob/living/carbon/human/human = affected_mob
if(human.dna.species.id != "slime")
human.set_species(/datum/species/jelly/slime)
/datum/disease/transformation/corgi
name = "The Barkening"
cure_text = "Death"
cures = list("adminordrazine")
agent = "Fell Doge Majicks"
desc = "This disease transforms the victim into a corgi."
visibility_flags = 0
stage1 = list("BARK.")
stage2 = list("You feel the need to wear silly hats.")
stage3 = list("<span class='danger'>Must... eat... chocolate....</span>", "<span class='danger'>YAP</span>")
stage4 = list("<span class='danger'>Visions of washing machines assail your mind!</span>")
stage5 = list("<span class='danger'>AUUUUUU!!!</span>")
new_form = /mob/living/simple_animal/pet/dog/corgi
/datum/disease/transformation/corgi/stage_act()
..()
switch(stage)
if(3)
if (prob(8))
affected_mob.say(pick("YAP", "Woof!"))
if(4)
if (prob(20))
affected_mob.say(pick("Bark!", "AUUUUUU"))
/datum/disease/transformation/morph
name = "Gluttony's Blessing"
cure_text = "nothing"
cures = list("adminordrazine")
agent = "Gluttony's Blessing"
desc = "A 'gift' from somewhere terrible."
stage_prob = 20
severity = BIOHAZARD
visibility_flags = 0
stage1 = list("Your stomach rumbles.")
stage2 = list("Your skin feels saggy.")
stage3 = list("<span class='danger'>Your appendages are melting away.</span>", "<span class='danger'>Your limbs begin to lose their shape.</span>")
stage4 = list("<span class='danger'>You're ravenous.</span>")
stage5 = list("<span class='danger'>You have become a morph.</span>")
new_form = /mob/living/simple_animal/hostile/morph
+58
View File
@@ -0,0 +1,58 @@
/datum/disease/tuberculosis
name = "Fungal tuberculosis"
max_stages = 5
spread_text = "Airborne"
cure_text = "Spaceacillin & salbutamol"
cures = list("spaceacillin", "salbutamol")
agent = "Fungal Tubercle bacillus Cosmosis"
viable_mobtypes = list(/mob/living/carbon/human)
cure_chance = 5//like hell are you getting out of hell
desc = "A rare highly transmittable virulent virus. Few samples exist, rumoured to be carefully grown and cultured by clandestine bio-weapon specialists. Causes fever, blood vomiting, lung damage, weight loss, and fatigue."
required_organs = list(/obj/item/bodypart/head)
severity = DANGEROUS
/datum/disease/tuberculosis/stage_act() //it begins
..()
switch(stage)
if(2)
if(prob(2))
affected_mob.emote("cough")
affected_mob << "<span class='danger'>Your chest hurts.</span>"
if(prob(2))
affected_mob << "<span class='danger'>Your stomach violently rumbles!</span>"
if(prob(5))
affected_mob << "<span class='danger'>You feel a cold sweat form.</span>"
if(4)
if(prob(2))
affected_mob << "<span class='userdanger'>You see four of everything</span>"
affected_mob.Dizzy(5)
if(prob(2))
affected_mob << "<span class='danger'>You feel a sharp pain from your lower chest!</span>"
affected_mob.adjustOxyLoss(5)
affected_mob.emote("gasp")
if(prob(10))
affected_mob << "<span class='danger'>You feel air escape from your lungs painfully.</span>"
affected_mob.adjustOxyLoss(25)
affected_mob.emote("gasp")
if(5)
if(prob(2))
affected_mob << "<span class='userdanger'>[pick("You feel your heart slowing...", "You relax and slow your heartbeat.")]</span>"
affected_mob.adjustStaminaLoss(70)
if(prob(10))
affected_mob.adjustStaminaLoss(100)
affected_mob.visible_message("<span class='warning'>[affected_mob] faints!</span>", "<span class='userdanger'>You surrender yourself and feel at peace...</span>")
affected_mob.AdjustSleeping(5)
if(prob(2))
affected_mob << "<span class='userdanger'>You feel your mind relax and your thoughts drift!</span>"
affected_mob.confused = min(100, affected_mob.confused + 8)
if(prob(10))
affected_mob.vomit(20)
if(prob(3))
affected_mob << "<span class='warning'><i>[pick("Your stomach silently rumbles...", "Your stomach seizes up and falls limp, muscles dead and lifeless.", "You could eat a crayon")]</i></span>"
affected_mob.overeatduration = max(affected_mob.overeatduration - 100, 0)
affected_mob.nutrition = max(affected_mob.nutrition - 100, 0)
if(prob(15))
affected_mob << "<span class='danger'>[pick("You feel uncomfortably hot...", "You feel like unzipping your jumpsuit", "You feel like taking off some clothes...")]</span>"
affected_mob.bodytemperature += 40
return
+118
View File
@@ -0,0 +1,118 @@
/datum/disease/wizarditis
name = "Wizarditis"
max_stages = 4
spread_text = "Airborne"
cure_text = "The Manly Dorf"
cures = list("manlydorf")
cure_chance = 100
agent = "Rincewindus Vulgaris"
viable_mobtypes = list(/mob/living/carbon/human)
disease_flags = CAN_CARRY|CAN_RESIST|CURABLE
permeability_mod = 0.75
desc = "Some speculate, that this virus is the cause of Wizard Federation existance. Subjects affected show the signs of mental retardation, yelling obscure sentences or total gibberish. On late stages subjects sometime express the feelings of inner power, and, cite, 'the ability to control the forces of cosmos themselves!' A gulp of strong, manly spirits usually reverts them to normal, humanlike, condition."
severity = HARMFUL
required_organs = list(/obj/item/bodypart/head)
/*
BIRUZ BENNAR
SCYAR NILA - teleport
NEC CANTIO - dis techno
EI NATH - shocking grasp
AULIE OXIN FIERA - knock
TARCOL MINTI ZHERI - forcewall
STI KALY - blind
*/
/datum/disease/wizarditis/stage_act()
..()
switch(stage)
if(2)
if(prob(1)&&prob(50))
affected_mob.say(pick("You shall not pass!", "Expeliarmus!", "By Merlins beard!", "Feel the power of the Dark Side!"))
if(prob(1)&&prob(50))
affected_mob << "<span class='danger'>You feel [pick("that you don't have enough mana", "that the winds of magic are gone", "an urge to summon familiar")].</span>"
if(3)
if(prob(1)&&prob(50))
affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!", "STI KALY!", "TARCOL MINTI ZHERI!"))
if(prob(1)&&prob(50))
affected_mob << "<span class='danger'>You feel [pick("the magic bubbling in your veins","that this location gives you a +1 to INT","an urge to summon familiar")].</span>"
if(4)
if(prob(1))
affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!","STI KALY!","EI NATH!"))
return
if(prob(1)&&prob(50))
affected_mob << "<span class='danger'>You feel [pick("the tidal wave of raw power building inside","that this location gives you a +2 to INT and +1 to WIS","an urge to teleport")].</span>"
spawn_wizard_clothes(50)
if(prob(1)&&prob(1))
teleport()
return
/datum/disease/wizarditis/proc/spawn_wizard_clothes(chance = 0)
if(istype(affected_mob, /mob/living/carbon/human))
var/mob/living/carbon/human/H = affected_mob
if(prob(chance))
if(!istype(H.head, /obj/item/clothing/head/wizard))
if(!H.unEquip(H.head))
qdel(H.head)
H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(H), slot_head)
return
if(prob(chance))
if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe))
if(!H.unEquip(H.wear_suit))
qdel(H.wear_suit)
H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(H), slot_wear_suit)
return
if(prob(chance))
if(!istype(H.shoes, /obj/item/clothing/shoes/sandal))
if(!H.unEquip(H.shoes))
qdel(H.shoes)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H), slot_shoes)
return
else
var/mob/living/carbon/H = affected_mob
if(prob(chance))
if(!istype(H.r_hand, /obj/item/weapon/staff))
H.drop_r_hand()
H.put_in_r_hand( new /obj/item/weapon/staff(H) )
return
return
/datum/disease/wizarditis/proc/teleport()
var/list/theareas = get_areas_in_range(80, affected_mob)
for(var/area/space/S in theareas)
theareas -= S
if(!theareas||!theareas.len)
return
var/area/thearea = pick(theareas)
var/list/L = list()
for(var/turf/T in get_area_turfs(thearea.type))
if(T.z != affected_mob.z) continue
if(T.name == "space") continue
if(!T.density)
var/clear = 1
for(var/obj/O in T)
if(O.density)
clear = 0
break
if(clear)
L+=T
if(!L)
return
affected_mob.say("SCYAR NILA [uppertext(thearea.name)]!")
affected_mob.loc = pick(L)
return
+361
View File
@@ -0,0 +1,361 @@
/////////////////////////// DNA DATUM
/datum/dna
var/unique_enzymes
var/struc_enzymes
var/uni_identity
var/blood_type
var/datum/species/species = new /datum/species/human() //The type of mutant race the player is if applicable (i.e. potato-man)
var/list/features = list("FFF") //first value is mutant color
var/real_name //Stores the real name of the person who originally got this dna datum. Used primarely for changelings,
var/list/mutations = list() //All mutations are from now on here
var/list/temporary_mutations = list() //Timers for temporary mutations
var/list/previous = list() //For temporary name/ui/ue/blood_type modifications
var/mob/living/carbon/holder
/datum/dna/New(mob/living/carbon/new_holder)
if(new_holder)
holder = new_holder
/datum/dna/proc/transfer_identity(mob/living/carbon/destination, transfer_SE = 0)
destination.dna.unique_enzymes = unique_enzymes
destination.dna.uni_identity = uni_identity
destination.dna.blood_type = blood_type
destination.set_species(species.type, icon_update=0)
destination.dna.features = features.Copy()
destination.dna.real_name = real_name
destination.dna.temporary_mutations = temporary_mutations.Copy()
if(transfer_SE)
destination.dna.struc_enzymes = struc_enzymes
/datum/dna/proc/copy_dna(datum/dna/new_dna)
new_dna.unique_enzymes = unique_enzymes
new_dna.struc_enzymes = struc_enzymes
new_dna.uni_identity = uni_identity
new_dna.blood_type = blood_type
new_dna.features = features.Copy()
new_dna.species = new species.type
new_dna.real_name = real_name
new_dna.mutations = mutations.Copy()
/datum/dna/proc/add_mutation(mutation_name)
var/datum/mutation/human/HM = mutations_list[mutation_name]
HM.on_acquiring(holder)
/datum/dna/proc/remove_mutation(mutation_name)
var/datum/mutation/human/HM = mutations_list[mutation_name]
HM.on_losing(holder)
/datum/dna/proc/check_mutation(mutation_name)
var/datum/mutation/human/HM = mutations_list[mutation_name]
return mutations.Find(HM)
/datum/dna/proc/remove_all_mutations()
remove_mutation_group(mutations)
/datum/dna/proc/remove_mutation_group(list/group)
if(!group)
return
for(var/datum/mutation/human/HM in group)
HM.force_lose(holder)
/datum/dna/proc/generate_uni_identity()
. = ""
var/list/L = new /list(DNA_UNI_IDENTITY_BLOCKS)
L[DNA_GENDER_BLOCK] = construct_block((holder.gender!=MALE)+1, 2)
if(ishuman(holder))
var/mob/living/carbon/human/H = holder
if(!hair_styles_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/hair, hair_styles_list, hair_styles_male_list, hair_styles_female_list)
L[DNA_HAIR_STYLE_BLOCK] = construct_block(hair_styles_list.Find(H.hair_style), hair_styles_list.len)
L[DNA_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.hair_color)
if(!facial_hair_styles_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/facial_hair, facial_hair_styles_list, facial_hair_styles_male_list, facial_hair_styles_female_list)
L[DNA_FACIAL_HAIR_STYLE_BLOCK] = construct_block(facial_hair_styles_list.Find(H.facial_hair_style), facial_hair_styles_list.len)
L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color)
L[DNA_SKIN_TONE_BLOCK] = construct_block(skin_tones.Find(H.skin_tone), skin_tones.len)
L[DNA_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.eye_color)
for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++)
if(L[i])
. += L[i]
else
. += random_string(DNA_BLOCK_SIZE,hex_characters)
return .
/datum/dna/proc/generate_struc_enzymes()
var/list/sorting = new /list(DNA_STRUC_ENZYMES_BLOCKS)
var/result = ""
for(var/datum/mutation/human/A in good_mutations + bad_mutations + not_good_mutations)
if(A.name == RACEMUT && ismonkey(holder))
sorting[A.dna_block] = num2hex(A.lowest_value + rand(0, 256 * 6), DNA_BLOCK_SIZE)
mutations |= A
else
sorting[A.dna_block] = random_string(DNA_BLOCK_SIZE, list("0","1","2","3","4","5","6"))
for(var/B in sorting)
result += B
return result
/datum/dna/proc/generate_unique_enzymes()
. = ""
if(istype(holder))
real_name = holder.real_name
. += md5(holder.real_name)
else
. += random_string(DNA_UNIQUE_ENZYMES_LEN, hex_characters)
return .
/datum/dna/proc/update_ui_block(blocknumber)
if(!blocknumber || !ishuman(holder))
return
var/mob/living/carbon/human/H = holder
switch(blocknumber)
if(DNA_HAIR_COLOR_BLOCK)
setblock(uni_identity, blocknumber, sanitize_hexcolor(H.hair_color))
if(DNA_FACIAL_HAIR_COLOR_BLOCK)
setblock(uni_identity, blocknumber, sanitize_hexcolor(H.facial_hair_color))
if(DNA_SKIN_TONE_BLOCK)
setblock(uni_identity, blocknumber, construct_block(skin_tones.Find(H.skin_tone), skin_tones.len))
if(DNA_EYE_COLOR_BLOCK)
setblock(uni_identity, blocknumber, sanitize_hexcolor(H.eye_color))
if(DNA_GENDER_BLOCK)
setblock(uni_identity, blocknumber, construct_block((H.gender!=MALE)+1, 2))
if(DNA_FACIAL_HAIR_STYLE_BLOCK)
setblock(uni_identity, blocknumber, construct_block(facial_hair_styles_list.Find(H.facial_hair_style), facial_hair_styles_list.len))
if(DNA_HAIR_STYLE_BLOCK)
setblock(uni_identity, blocknumber, construct_block(hair_styles_list.Find(H.hair_style), hair_styles_list.len))
/datum/dna/proc/mutations_say_mods(message)
if(message)
for(var/datum/mutation/human/M in mutations)
message = M.say_mod(message)
return message
/datum/dna/proc/mutations_get_spans()
var/list/spans = list()
for(var/datum/mutation/human/M in mutations)
spans |= M.get_spans()
return spans
/datum/dna/proc/species_get_spans()
var/list/spans = list()
if(species)
spans |= species.get_spans()
return spans
/datum/dna/proc/is_same_as(datum/dna/D)
if(uni_identity == D.uni_identity && struc_enzymes == D.struc_enzymes && real_name == D.real_name)
if(species.type == D.species.type && features == D.features && blood_type == D.blood_type)
return 1
return 0
//used to update dna UI, UE, and dna.real_name.
/datum/dna/proc/update_dna_identity()
uni_identity = generate_uni_identity()
unique_enzymes = generate_unique_enzymes()
/datum/dna/proc/initialize_dna(newblood_type)
if(newblood_type)
blood_type = newblood_type
unique_enzymes = generate_unique_enzymes()
uni_identity = generate_uni_identity()
struc_enzymes = generate_struc_enzymes()
features = random_features()
/////////////////////////// DNA MOB-PROCS //////////////////////
/mob/proc/set_species(datum/species/mrace, icon_update = 1)
return
/mob/living/carbon/set_species(datum/species/mrace, icon_update = 1)
if(mrace && has_dna())
dna.species.on_species_loss(src)
var/old_species = dna.species
if(ispath(mrace))
dna.species = new mrace()
else
dna.species = mrace
dna.species.on_species_gain(src, old_species)
/mob/living/carbon/human/set_species(datum/species/mrace, icon_update = 1)
..()
if(icon_update)
update_body()
update_hair()
update_body_parts()
update_mutations_overlay()// no lizard with human hulk overlay please.
/mob/proc/has_dna()
return
/mob/living/carbon/has_dna()
return dna
/mob/living/carbon/human/proc/hardset_dna(ui, se, newreal_name, newblood_type, datum/species/mrace, newfeatures)
if(newfeatures)
dna.features = newfeatures
if(mrace)
set_species(mrace, icon_update=0)
if(newreal_name)
real_name = newreal_name
dna.generate_unique_enzymes()
if(newblood_type)
dna.blood_type = newblood_type
if(ui)
dna.uni_identity = ui
updateappearance(icon_update=0)
if(se)
dna.struc_enzymes = se
domutcheck()
if(mrace || newfeatures || ui)
update_body()
update_hair()
update_body_parts()
update_mutations_overlay()
/mob/living/carbon/proc/create_dna()
dna = new /datum/dna(src)
if(!dna.species)
var/rando_race = pick(config.roundstart_races)
dna.species = new rando_race()
//proc used to update the mob's appearance after its dna UI has been changed
/mob/living/carbon/proc/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0)
if(!has_dna())
return
gender = (deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 2)-1) ? FEMALE : MALE
mob/living/carbon/human/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0)
..()
var/structure = dna.uni_identity
hair_color = sanitize_hexcolor(getblock(structure, DNA_HAIR_COLOR_BLOCK))
facial_hair_color = sanitize_hexcolor(getblock(structure, DNA_FACIAL_HAIR_COLOR_BLOCK))
skin_tone = skin_tones[deconstruct_block(getblock(structure, DNA_SKIN_TONE_BLOCK), skin_tones.len)]
eye_color = sanitize_hexcolor(getblock(structure, DNA_EYE_COLOR_BLOCK))
facial_hair_style = facial_hair_styles_list[deconstruct_block(getblock(structure, DNA_FACIAL_HAIR_STYLE_BLOCK), facial_hair_styles_list.len)]
hair_style = hair_styles_list[deconstruct_block(getblock(structure, DNA_HAIR_STYLE_BLOCK), hair_styles_list.len)]
if(icon_update)
update_body()
update_hair()
if(mutcolor_update)
update_body_parts()
if(mutations_overlay_update)
update_mutations_overlay()
/mob/proc/domutcheck()
return
/mob/living/carbon/domutcheck()
if(!has_dna())
return
for(var/datum/mutation/human/A in good_mutations | bad_mutations | not_good_mutations)
if(ismob(A.check_block(src)))
return //we got monkeyized/humanized, this mob will be deleted, no need to continue.
update_mutations_overlay()
/////////////////////////// DNA HELPER-PROCS //////////////////////////////
/proc/getleftblocks(input,blocknumber,blocksize)
if(blocknumber > 1)
return copytext(input,1,((blocksize*blocknumber)-(blocksize-1)))
/proc/getrightblocks(input,blocknumber,blocksize)
if(blocknumber < (length(input)/blocksize))
return copytext(input,blocksize*blocknumber+1,length(input)+1)
/proc/getblock(input, blocknumber, blocksize=DNA_BLOCK_SIZE)
return copytext(input, blocksize*(blocknumber-1)+1, (blocksize*blocknumber)+1)
/proc/setblock(istring, blocknumber, replacement, blocksize=DNA_BLOCK_SIZE)
if(!istring || !blocknumber || !replacement || !blocksize)
return 0
return getleftblocks(istring, blocknumber, blocksize) + replacement + getrightblocks(istring, blocknumber, blocksize)
/proc/randmut(mob/living/carbon/M, list/candidates, difficulty = 2)
if(!M.has_dna())
return
var/datum/mutation/human/num = pick(candidates)
. = num.force_give(M)
return
/proc/randmutb(mob/living/carbon/M)
if(!M.has_dna())
return
var/datum/mutation/human/HM = pick((bad_mutations | not_good_mutations) - mutations_list[RACEMUT])
. = HM.force_give(M)
/proc/randmutg(mob/living/carbon/M)
if(!M.has_dna())
return
var/datum/mutation/human/HM = pick(good_mutations)
. = HM.force_give(M)
/proc/randmuti(mob/living/carbon/M)
if(!M.has_dna())
return
var/num = rand(1, DNA_UNI_IDENTITY_BLOCKS)
var/newdna = setblock(M.dna.uni_identity, num, random_string(DNA_BLOCK_SIZE, hex_characters))
M.dna.uni_identity = newdna
return
/proc/clean_dna(mob/living/carbon/M)
if(!M.has_dna())
return
M.dna.remove_all_mutations()
/proc/clean_randmut(mob/living/carbon/M, list/candidates, difficulty = 2)
clean_dna(M)
randmut(M, candidates, difficulty)
/proc/scramble_dna(mob/living/carbon/M, ui=FALSE, se=FALSE, probability)
if(!M.has_dna())
return 0
if(se)
for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++)
if(prob(probability))
M.dna.struc_enzymes = setblock(M.dna.struc_enzymes, i, random_string(DNA_BLOCK_SIZE, hex_characters))
M.domutcheck()
if(ui)
for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++)
if(prob(probability))
M.dna.uni_identity = setblock(M.dna.uni_identity, i, random_string(DNA_BLOCK_SIZE, hex_characters))
M.updateappearance(mutations_overlay_update=1)
return 1
//value in range 1 to values. values must be greater than 0
//all arguments assumed to be positive integers
/proc/construct_block(value, values, blocksize=DNA_BLOCK_SIZE)
var/width = round((16**blocksize)/values)
if(value < 1)
value = 1
value = (value * width) - rand(1,width)
return num2hex(value, blocksize)
//value is hex
/proc/deconstruct_block(value, values, blocksize=DNA_BLOCK_SIZE)
var/width = round((16**blocksize)/values)
value = round(hex2num(value) / width) + 1
if(value > values)
value = values
return value
/////////////////////////// DNA HELPER-PROCS
+173
View File
@@ -0,0 +1,173 @@
/datum/dog_fashion
var/name
var/desc
var/emote_see
var/emote_hear
var/speak
var/speak_emote
// This isn't applied to the dog, but stores the icon_state of the
// sprite that the associated item uses
var/icon_file
var/icon_state
/datum/dog_fashion/New(mob/M)
name = replacetext(name, "REAL_NAME", M.real_name)
desc = replacetext(desc, "NAME", name)
/datum/dog_fashion/proc/apply(mob/living/simple_animal/pet/dog/D)
if(name)
D.name = name
if(desc)
D.desc = desc
if(emote_see)
D.emote_see = emote_see
if(emote_hear)
D.emote_hear = emote_hear
if(speak)
D.speak = speak
if(speak_emote)
D.speak_emote = speak_emote
/datum/dog_fashion/proc/get_image(var/dir)
if(icon_file && icon_state)
return image(icon_file, icon_state = icon_state, dir = dir)
/datum/dog_fashion/head
icon_file = 'icons/mob/corgi_head.dmi'
/datum/dog_fashion/back
icon_file = 'icons/mob/corgi_back.dmi'
/datum/dog_fashion/head
/datum/dog_fashion/head/helmet
name = "Sergeant REAL_NAME"
desc = "The ever-loyal, the ever-vigilant."
/datum/dog_fashion/head/chef
name = "Sous chef REAL_NAME"
desc = "Your food will be taste-tested. All of it."
/datum/dog_fashion/head/captain
name = "Captain REAL_NAME"
desc = "Probably better than the last captain."
/datum/dog_fashion/head/kitty
name = "Runtime"
emote_see = list("coughs up a furball", "stretches")
emote_hear = list("purrs")
speak = list("Purrr", "Meow!", "MAOOOOOW!", "HISSSSS", "MEEEEEEW")
desc = "It's a cute little kitty-cat! ... wait ... what the hell?"
/datum/dog_fashion/head/rabbit
name = "Hoppy"
emote_see = list("twitches its nose", "hops around a bit")
desc = "This is Hoppy. It's a corgi-...urmm... bunny rabbit."
/datum/dog_fashion/head/beret
name = "Yann"
desc = "Mon dieu! C'est un chien!"
speak = list("le woof!", "le bark!", "JAPPE!!")
emote_see = list("cowers in fear.", "surrenders.", "plays dead.","looks as though there is a wall in front of him.")
/datum/dog_fashion/head/detective
name = "Detective REAL_NAME"
desc = "NAME sees through your lies..."
emote_see = list("investigates the area.","sniffs around for clues.","searches for scooby snacks.","takes a candycorn from the hat.")
/datum/dog_fashion/head/nurse
name = "Nurse REAL_NAME"
desc = "NAME needs 100cc of beef jerky... STAT!"
/datum/dog_fashion/head/pirate
name = "Pirate-title Pirate-name"
desc = "Yaarghh!! Thar' be a scurvy dog!"
emote_see = list("hunts for treasure.","stares coldly...","gnashes his tiny corgi teeth!")
emote_hear = list("growls ferociously!", "snarls.")
speak = list("Arrrrgh!!","Grrrrrr!")
/datum/dog_fashion/head/pirate/New(mob/M)
..()
name = "[pick("Ol'","Scurvy","Black","Rum","Gammy","Bloody","Gangrene","Death","Long-John")] [pick("kibble","leg","beard","tooth","poop-deck","Threepwood","Le Chuck","corsair","Silver","Crusoe")]"
/datum/dog_fashion/head/ushanka
name = "Communist-title Realname"
desc = "A follower of Karl Barx."
emote_see = list("contemplates the failings of the capitalist economic model.", "ponders the pros and cons of vanguardism.")
/datum/dog_fashion/head/ushanka/New(mob/M)
..()
name = "[pick("Comrade","Commissar","Glorious Leader")] [M.real_name]"
/datum/dog_fashion/head/warden
name = "Officer REAL_NAME"
emote_see = list("drools.","looks for donuts.")
desc = "Stop right there criminal scum!"
/datum/dog_fashion/head/blue_wizard
name = "Grandwizard REAL_NAME"
speak = list("YAP", "Woof!", "Bark!", "AUUUUUU", "EI NATH!")
/datum/dog_fashion/head/red_wizard
name = "Pyromancer REAL_NAME"
speak = list("YAP", "Woof!", "Bark!", "AUUUUUU", "ONI SOMA!")
/datum/dog_fashion/head/cardborg
name = "Borgi"
speak = list("Ping!","Beep!","Woof!")
emote_see = list("goes rogue.", "sniffs out non-humans.")
desc = "Result of robotics budget cuts."
/datum/dog_fashion/head/ghost
name = "\improper Ghost"
speak = list("WoooOOOooo~","AUUUUUUUUUUUUUUUUUU")
emote_see = list("stumbles around.", "shivers.")
emote_hear = list("howls!","groans.")
desc = "Spooky!"
icon_state = "sheet"
/datum/dog_fashion/head/santa
name = "Santa's Corgi Helper"
emote_hear = list("barks Christmas songs.", "yaps merrily!")
emote_see = list("looks for presents.", "checks his list.")
desc = "He's very fond of milk and cookies."
/datum/dog_fashion/head/cargo_tech
name = "Corgi Tech REAL_NAME"
desc = "The reason your yellow gloves have chew-marks."
/datum/dog_fashion/head/reindeer
name = "REAL_NAME the red-nosed Corgi"
emote_hear = list("lights the way!", "illuminates.", "yaps!")
desc = "He has a very shiny nose."
/datum/dog_fashion/head/sombrero
name = "Segnor REAL_NAME"
desc = "You must respect Elder Dogname"
/datum/dog_fashion/head/sombrero/New(mob/M)
..()
desc = "You must respect Elder [M.real_name]."
/datum/dog_fashion/head/hop
name = "Lieutenant REAL_NAME"
desc = "Can actually be trusted to not run off on his own."
/datum/dog_fashion/head/deathsquad
name = "Trooper REAL_NAME"
desc = "That's not red paint. That's real corgi blood."
/datum/dog_fashion/head/clown
name = "REAL_NAME the Clown"
desc = "Honkman's best friend."
speak = list("HONK!", "Honk!")
emote_see = list("plays tricks.", "slips.")
/datum/dog_fashion/back/deathsquad
name = "Trooper REAL_NAME"
desc = "That's not red paint. That's real corgi blood."
@@ -0,0 +1,103 @@
#define FORWARD -1
#define BACKWARD 1
/datum/construction
var/list/steps
var/atom/holder
var/result
var/list/steps_desc
/datum/construction/New(atom)
..()
holder = atom
if(!holder) //don't want this without a holder
qdel(src)
set_desc(steps.len)
return
/datum/construction/proc/next_step()
steps.len--
if(!steps.len)
spawn_result()
else
set_desc(steps.len)
return
/datum/construction/proc/action(atom/used_atom,mob/user)
return
/datum/construction/proc/check_step(atom/used_atom,mob/user) //check last step only
var/valid_step = is_right_key(used_atom)
if(valid_step)
if(custom_action(valid_step, used_atom, user))
next_step()
return 1
return 0
/datum/construction/proc/is_right_key(atom/used_atom) // returns current step num if used_atom is of the right type.
var/list/L = steps[steps.len]
if(istype(used_atom, L["key"]))
return steps.len
return 0
/datum/construction/proc/custom_action(step, used_atom, user)
return 1
/datum/construction/proc/check_all_steps(atom/used_atom,mob/user) //check all steps, remove matching one.
for(var/i=1;i<=steps.len;i++)
var/list/L = steps[i];
if(istype(used_atom, L["key"]))
if(custom_action(i, used_atom, user))
steps[i]=null;//stupid byond list from list removal...
listclearnulls(steps);
if(!steps.len)
spawn_result()
return 1
return 0
/datum/construction/proc/spawn_result()
if(result)
new result(get_turf(holder))
qdel(holder)
return
/datum/construction/proc/set_desc(index as num)
var/list/step = steps[index]
holder.desc = step["desc"]
return
/datum/construction/reversible
var/index
/datum/construction/reversible/New(atom)
..()
index = steps.len
return
/datum/construction/reversible/proc/update_index(diff as num)
index+=diff
if(index==0)
spawn_result()
else
set_desc(index)
return
/datum/construction/reversible/is_right_key(atom/used_atom) // returns index step
var/list/L = steps[index]
if(istype(used_atom, L["key"]))
return FORWARD //to the first step -> forward
else if(L["backkey"] && istype(used_atom, L["backkey"]))
return BACKWARD //to the last step -> backwards
return 0
/datum/construction/reversible/check_step(atom/used_atom,mob/user)
var/diff = is_right_key(used_atom)
if(diff)
if(custom_action(index, diff, used_atom, user))
update_index(diff)
return 1
return 0
/datum/construction/reversible/custom_action(index, diff, used_atom, user)
return 1
+68
View File
@@ -0,0 +1,68 @@
/*
* WARRANTY VOID IF CODE USED
*/
/datum/events
var/list/events
/datum/events/New()
..()
events = new
/datum/events/proc/addEventType(event_type as text)
if(!(event_type in events) || !islist(events[event_type]))
events[event_type] = list()
return 1
return
// Arguments: event_type as text, proc_holder as datum, proc_name as text
// Returns: New event, null on error.
/datum/events/proc/addEvent(event_type as text, proc_holder, proc_name as text)
if(!event_type || !proc_holder || !proc_name)
return
addEventType(event_type)
var/list/event = events[event_type]
var/datum/event/E = new /datum/event(proc_holder,proc_name)
event += E
return E
// Arguments: event_type as text, any number of additional arguments to pass to event handler
// Returns: null
/datum/events/proc/fireEvent()
//world << "Events in [args[1]] called"
var/list/event = listgetindex(events,args[1])
if(istype(event))
spawn(0)
for(var/datum/event/E in event)
if(!E.Fire(arglist(args.Copy(2))))
clearEvent(args[1],E)
return
// Arguments: event_type as text, E as /datum/event
// Returns: 1 if event cleared, null on error
/datum/events/proc/clearEvent(event_type as text, datum/event/E)
if(!event_type || !E)
return
var/list/event = listgetindex(events,event_type)
event -= E
return 1
/datum/event
var/listener
var/proc_name
/datum/event/New(tlistener,tprocname)
listener = tlistener
proc_name = tprocname
return ..()
/datum/event/proc/Fire()
//world << "Event fired"
if(listener)
call(listener,proc_name)(arglist(args))
return 1
return
+61
View File
@@ -0,0 +1,61 @@
var/global/datum/getrev/revdata = new()
/datum/getrev
var/parentcommit
var/commit
var/list/testmerge = list()
var/date
/datum/getrev/New()
var/head_file = return_file_text(".git/logs/HEAD")
var/regex/head_log = new("(\\w{40}) (\\w{40}).+> (\\d{10}).+\n\\Z")
head_log.Find(head_file)
parentcommit = head_log.group[1]
commit = head_log.group[2]
var/unix_time = text2num(head_log.group[3])
if(SERVERTOOLS && fexists("..\\prtestjob.lk"))
testmerge = file2list("..\\prtestjob.lk")
date = unix2date(unix_time)
world.log << "Running /tg/ revision:"
world.log << "[date]"
world.log << commit
if(testmerge.len)
for(var/line in testmerge)
if(line)
world.log << "Test merge active of PR #[line]"
world.log << "Based off master commit [parentcommit]"
world.log << "Current map - [MAP_NAME]" //can't think of anywhere better to put it
/client/verb/showrevinfo()
set category = "OOC"
set name = "Show Server Revision"
set desc = "Check the current server code revision"
if(revdata.commit)
src << "<b>Server revision compiled on:</b> [revdata.date]"
if(revdata.testmerge.len)
for(var/line in revdata.testmerge)
if(line)
src << "Test merge active of PR <a href='[config.githuburl]/pull/[line]'>#[line]</a>"
src << "Based off master commit <a href='[config.githuburl]/commit/[revdata.parentcommit]'>[revdata.parentcommit]</a>"
else
src << "<a href='[config.githuburl]/commit/[revdata.commit]'>[revdata.commit]</a>"
else
src << "Revision unknown"
src << "<b>Current Infomational Settings:</b>"
src << "Protect Authority Roles From Traitor: [config.protect_roles_from_antagonist]"
src << "Protect Assistant Role From Traitor: [config.protect_assistant_from_antagonist]"
src << "Enforce Human Authority: [config.enforce_human_authority]"
src << "Allow Latejoin Antagonists: [config.allow_latejoin_antagonists]"
src << "Enforce Continuous Rounds: [config.continuous.len] of [config.modes.len] roundtypes"
src << "Allow Midround Antagonists: [config.midround_antag.len] of [config.modes.len] roundtypes"
if(config.show_game_type_odds)
src <<"<b>Game Mode Odds:</b>"
var/sum = 0
for(var/i=1,i<=config.probabilities.len,i++)
sum += config.probabilities[config.probabilities[i]]
for(var/i=1,i<=config.probabilities.len,i++)
if(config.probabilities[config.probabilities[i]] > 0)
var/percentage = round(config.probabilities[config.probabilities[i]] / sum * 100, 0.1)
src << "[config.probabilities[i]] [percentage]%"
return
@@ -0,0 +1,15 @@
/datum/icon_snapshot
var/name
var/icon
var/icon_state
var/list/overlays
/datum/icon_snapshot/proc/makeImg()
if(!icon || !icon_state)
return
var/obj/temp = new
temp.icon = icon
temp.icon_state = icon_state
temp.overlays = overlays.Copy()
var/icon/tempicon = getFlatIcon(temp) // TODO Actually write something less heavy-handed for this
return tempicon
+138
View File
@@ -0,0 +1,138 @@
/datum/map_template
var/name = "Default Template Name"
var/width = 0
var/height = 0
var/mappath = null
var/mapfile = null
var/loaded = 0 // Times loaded this round
/datum/map_template/New(path = null, map = null, rename = null)
if(path)
mappath = path
if(mappath)
preload_size(mappath)
if(map)
mapfile = map
if(rename)
name = rename
/datum/map_template/proc/preload_size(path)
var/bounds = maploader.load_map(file(path), 1, 1, 1, cropMap=FALSE, measureOnly=TRUE)
if(bounds)
width = bounds[MAP_MAXX] // Assumes all templates are rectangular, have a single Z level, and begin at 1,1,1
height = bounds[MAP_MAXY]
return bounds
/proc/initTemplateBounds(var/list/bounds)
var/list/obj/machinery/atmospherics/atmos_machines = list()
var/list/obj/structure/cable/cables = list()
var/list/atom/atoms = list()
for(var/L in block(locate(bounds[MAP_MINX], bounds[MAP_MINY], bounds[MAP_MINZ]),
locate(bounds[MAP_MAXX], bounds[MAP_MAXY], bounds[MAP_MAXZ])))
var/turf/B = L
for(var/A in B)
atoms += A
if(istype(A,/obj/structure/cable))
cables += A
continue
if(istype(A,/obj/machinery/atmospherics))
atmos_machines += A
continue
SSobj.setup_template_objects(atoms)
SSmachine.setup_template_powernets(cables)
SSair.setup_template_machinery(atmos_machines)
/datum/map_template/proc/load(turf/T, centered = FALSE)
if(centered)
T = locate(T.x - round(width/2) , T.y - round(height/2) , T.z)
if(!T)
return
if(T.x+width > world.maxx)
return
if(T.y+height > world.maxy)
return
var/list/bounds = maploader.load_map(get_file(), T.x, T.y, T.z, cropMap=TRUE)
if(!bounds)
return 0
//initialize things that are normally initialized after map load
initTemplateBounds(bounds)
log_game("[name] loaded at at [T.x],[T.y],[T.z]")
return 1
/datum/map_template/proc/get_file()
if(mapfile)
. = mapfile
else if(mappath)
. = file(mappath)
if(!.)
world.log << "The file of [src] appears to be empty/non-existent."
/datum/map_template/proc/get_affected_turfs(turf/T, centered = FALSE)
var/turf/placement = T
if(centered)
var/turf/corner = locate(placement.x - round(width/2), placement.y - round(height/2), placement.z)
if(corner)
placement = corner
return block(placement, locate(placement.x+width-1, placement.y+height-1, placement.z))
/proc/preloadTemplates(path = "_maps/templates/") //see master controller setup
var/list/filelist = flist(path)
for(var/map in filelist)
var/datum/map_template/T = new(path = "[path][map]", rename = "[map]")
map_templates[T.name] = T
preloadRuinTemplates()
preloadShuttleTemplates()
preloadShelterTemplates()
/proc/preloadRuinTemplates()
// Still supporting bans by filename
var/list/banned = generateMapList("config/lavaRuinBlacklist.txt")
banned += generateMapList("config/spaceRuinBlacklist.txt")
for(var/item in subtypesof(/datum/map_template/ruin))
var/datum/map_template/ruin/ruin_type = item
// screen out the abstract subtypes
if(!initial(ruin_type.id))
continue
var/datum/map_template/ruin/R = new ruin_type()
if(banned.Find(R.mappath))
continue
map_templates[R.name] = R
ruins_templates[R.name] = R
if(istype(R, /datum/map_template/ruin/lavaland))
lava_ruins_templates[R.name] = R
else if(istype(R, /datum/map_template/ruin/space))
space_ruins_templates[R.name] = R
/proc/preloadShuttleTemplates()
for(var/item in subtypesof(/datum/map_template/shuttle))
var/datum/map_template/shuttle/shuttle_type = item
if(!(initial(shuttle_type.suffix)))
continue
var/datum/map_template/shuttle/S = new shuttle_type()
shuttle_templates[S.shuttle_id] = S
map_templates[S.shuttle_id] = S
/proc/preloadShelterTemplates()
for(var/item in subtypesof(/datum/map_template/shelter))
var/datum/map_template/shelter/shelter_type = item
if(!(initial(shelter_type.mappath)))
continue
var/datum/map_template/shelter/S = new shelter_type()
shelter_templates[S.shelter_id] = S
map_templates[S.shelter_id] = S
+219
View File
@@ -0,0 +1,219 @@
//wrapper
/proc/do_teleport(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null)
var/datum/teleport/instant/science/D = new
if(D.start(arglist(args)))
return 1
return 0
/datum/teleport
var/atom/movable/teleatom //atom to teleport
var/atom/destination //destination to teleport to
var/precision = 0 //teleport precision
var/datum/effect_system/effectin //effect to show right before teleportation
var/datum/effect_system/effectout //effect to show right after teleportation
var/soundin //soundfile to play before teleportation
var/soundout //soundfile to play after teleportation
var/force_teleport = 1 //if false, teleport will use Move() proc (dense objects will prevent teleportation)
/datum/teleport/proc/start(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null)
if(!initTeleport(arglist(args)))
return 0
return 1
/datum/teleport/proc/initTeleport(ateleatom,adestination,aprecision,afteleport,aeffectin,aeffectout,asoundin,asoundout)
if(!setTeleatom(ateleatom))
return 0
if(!setDestination(adestination))
return 0
if(!setPrecision(aprecision))
return 0
setEffects(aeffectin,aeffectout)
setForceTeleport(afteleport)
setSounds(asoundin,asoundout)
return 1
//must succeed
/datum/teleport/proc/setPrecision(aprecision)
if(isnum(aprecision))
precision = aprecision
return 1
return 0
//must succeed
/datum/teleport/proc/setDestination(atom/adestination)
if(istype(adestination))
destination = adestination
return 1
return 0
//must succeed in most cases
/datum/teleport/proc/setTeleatom(atom/movable/ateleatom)
if(istype(ateleatom, /obj/effect) && !istype(ateleatom, /obj/effect/dummy/chameleon))
qdel(ateleatom)
return 0
if(istype(ateleatom))
teleatom = ateleatom
return 1
return 0
//custom effects must be properly set up first for instant-type teleports
//optional
/datum/teleport/proc/setEffects(datum/effect_system/aeffectin=null,datum/effect_system/aeffectout=null)
effectin = istype(aeffectin) ? aeffectin : null
effectout = istype(aeffectout) ? aeffectout : null
return 1
//optional
/datum/teleport/proc/setForceTeleport(afteleport)
force_teleport = afteleport
return 1
//optional
/datum/teleport/proc/setSounds(asoundin=null,asoundout=null)
soundin = isfile(asoundin) ? asoundin : null
soundout = isfile(asoundout) ? asoundout : null
return 1
//placeholder
/datum/teleport/proc/teleportChecks()
return 1
/datum/teleport/proc/playSpecials(atom/location,datum/effect_system/effect,sound)
if(location)
if(effect)
addtimer(src, "do_effect", 0, FALSE, location, effect)
if(sound)
addtimer(src, "do_sound", 0, FALSE, location, sound)
/datum/teleport/proc/do_effect(atom/location, datum/effect_system/effect)
src = null
effect.attach(location)
effect.start()
/datum/teleport/proc/do_sound(atom/location, sound)
src = null
playsound(location, sound, 60, 1)
//do the monkey dance
/datum/teleport/proc/doTeleport()
var/turf/destturf
var/turf/curturf = get_turf(teleatom)
if(precision)
var/list/posturfs = list()
var/center = get_turf(destination)
if(!center)
center = destination
for(var/turf/T in range(precision,center))
var/area/A = T.loc
if(!A.noteleport)
posturfs.Add(T)
destturf = safepick(posturfs)
else
destturf = get_turf(destination)
if(!destturf || !curturf)
return 0
var/area/A = get_area(curturf)
if(A.noteleport)
return 0
playSpecials(curturf,effectin,soundin)
if(force_teleport)
teleatom.forceMove(destturf)
playSpecials(destturf,effectout,soundout)
else
if(teleatom.Move(destturf))
playSpecials(destturf,effectout,soundout)
return 1
/datum/teleport/proc/teleport()
if(teleportChecks())
return doTeleport()
return 0
/datum/teleport/instant //teleports when datum is created
start(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null)
if(..())
if(teleport())
return 1
return 0
/datum/teleport/instant/science
/datum/teleport/instant/science/setEffects(datum/effect_system/aeffectin,datum/effect_system/aeffectout)
if(aeffectin==null || aeffectout==null)
var/datum/effect_system/spark_spread/aeffect = new
aeffect.set_up(5, 1, teleatom)
effectin = effectin || aeffect
effectout = effectout || aeffect
return 1
else
return ..()
/datum/teleport/instant/science/setPrecision(aprecision)
..()
if(istype(teleatom, /obj/item/weapon/storage/backpack/holding))
precision = rand(1,100)
var/list/bagholding = teleatom.search_contents_for(/obj/item/weapon/storage/backpack/holding)
if(bagholding.len)
precision = max(rand(1,100)*bagholding.len,100)
if(istype(teleatom, /mob/living))
var/mob/living/MM = teleatom
MM << "<span class='warning'>The bluespace interface on your bag of holding interferes with the teleport!</span>"
return 1
// Safe location finder
/proc/find_safe_turf(zlevel = ZLEVEL_STATION, list/zlevels)
if(!zlevels)
zlevels = list(zlevel)
var/cycles = 1000
for(var/cycle in 1 to cycles)
// DRUNK DIALLING WOOOOOOOOO
var/x = rand(1, world.maxx)
var/y = rand(1, world.maxy)
var/z = pick(zlevels)
var/random_location = locate(x,y,z)
if(!(istype(random_location, /turf/open/floor)))
continue
var/turf/open/floor/F = random_location
if(!F.air)
continue
var/datum/gas_mixture/A = F.air
var/list/A_gases = A.gases
var/trace_gases
for(var/id in A_gases)
if(id in hardcoded_gases)
continue
trace_gases = TRUE
break
// Can most things breathe?
if(trace_gases)
continue
if(!(A_gases["o2"] && A_gases["o2"][MOLES] >= 16))
continue
if(A_gases["plasma"])
continue
if(A_gases["co2"] && A_gases["co2"][MOLES] >= 10)
continue
// Aim for goldilocks temperatures and pressure
if((A.temperature <= 270) || (A.temperature >= 360))
continue
var/pressure = A.return_pressure()
if((pressure <= 20) || (pressure >= 550))
continue
// DING! You have passed the gauntlet, and are "probably" safe.
return F
+62
View File
@@ -0,0 +1,62 @@
/datum/topic_input
var/href
var/list/href_list
/datum/topic_input/New(thref,list/thref_list)
href = thref
href_list = thref_list.Copy()
return
/datum/topic_input/proc/get(i)
return listgetindex(href_list,i)
/datum/topic_input/proc/getAndLocate(i)
var/t = get(i)
if(t)
t = locate(t)
if (istext(t))
t = null
return t || null
/datum/topic_input/proc/getNum(i)
var/t = get(i)
if(t)
t = text2num(t)
return isnum(t) ? t : null
/datum/topic_input/proc/getObj(i)
var/t = getAndLocate(i)
return isobj(t) ? t : null
/datum/topic_input/proc/getMob(i)
var/t = getAndLocate(i)
return ismob(t) ? t : null
/datum/topic_input/proc/getTurf(i)
var/t = getAndLocate(i)
return isturf(t) ? t : null
/datum/topic_input/proc/getAtom(i)
return getType(i,/atom)
/datum/topic_input/proc/getArea(i)
var/t = getAndLocate(i)
return isarea(t) ? t : null
/datum/topic_input/proc/getStr(i)//params should always be text, but...
var/t = get(i)
return istext(t) ? t : null
/datum/topic_input/proc/getType(i,type)
var/t = getAndLocate(i)
return istype(t,type) ? t : null
/datum/topic_input/proc/getPath(i)
var/t = get(i)
if(t)
t = text2path(t)
return ispath(t) ? t : null
/datum/topic_input/proc/getList(i)
var/t = getAndLocate(i)
return islist(t) ? t : null
+93
View File
@@ -0,0 +1,93 @@
/* HUD DATUMS */
//GLOBAL HUD LIST
var/datum/atom_hud/huds = list( \
DATA_HUD_SECURITY_BASIC = new/datum/atom_hud/data/human/security/basic(), \
DATA_HUD_SECURITY_ADVANCED = new/datum/atom_hud/data/human/security/advanced(), \
DATA_HUD_MEDICAL_BASIC = new/datum/atom_hud/data/human/medical/basic(), \
DATA_HUD_MEDICAL_ADVANCED = new/datum/atom_hud/data/human/medical/advanced(), \
DATA_HUD_DIAGNOSTIC = new/datum/atom_hud/data/diagnostic(), \
ANTAG_HUD_CULT = new/datum/atom_hud/antag(), \
ANTAG_HUD_REV = new/datum/atom_hud/antag(), \
ANTAG_HUD_OPS = new/datum/atom_hud/antag(), \
ANTAG_HUD_WIZ = new/datum/atom_hud/antag(), \
ANTAG_HUD_SHADOW = new/datum/atom_hud/antag(), \
ANTAG_HUD_HOG_BLUE = new/datum/atom_hud/antag(),\
ANTAG_HUD_HOG_RED = new/datum/atom_hud/antag(),\
ANTAG_HUD_TRAITOR = new/datum/atom_hud/antag/hidden(),\
ANTAG_HUD_NINJA = new/datum/atom_hud/antag/hidden(),\
ANTAG_HUD_CHANGELING = new/datum/atom_hud/antag/hidden(),\
ANTAG_HUD_ABDUCTOR = new/datum/atom_hud/antag/hidden(),\
ANTAG_HUD_DEVIL = new/datum/atom_hud/antag(),\
ANTAG_HUD_SINTOUCHED = new/datum/atom_hud/antag/hidden(),\
ANTAG_HUD_SOULLESS = new/datum/atom_hud/antag/hidden(),\
ANTAG_HUD_CLOCKWORK = new/datum/atom_hud/antag(),\
)
/datum/atom_hud
var/list/atom/hudatoms = list() //list of all atoms which display this hud
var/list/mob/hudusers = list() //list with all mobs who can see the hud
var/list/hud_icons = list() //these will be the indexes for the atom's hud_list
/datum/atom_hud/proc/remove_hud_from(mob/M)
if(!M)
return
if(src in M.permanent_huds)
return
for(var/atom/A in hudatoms)
remove_from_single_hud(M, A)
hudusers -= M
/datum/atom_hud/proc/remove_from_hud(atom/A)
if(!A)
return
for(var/mob/M in hudusers)
remove_from_single_hud(M, A)
hudatoms -= A
/datum/atom_hud/proc/remove_from_single_hud(mob/M, atom/A) //unsafe, no sanity apart from client
if(!M || !M.client || !A)
return
for(var/i in hud_icons)
M.client.images -= A.hud_list[i]
/datum/atom_hud/proc/add_hud_to(mob/M)
if(!M)
return
hudusers |= M
for(var/atom/A in hudatoms)
add_to_single_hud(M, A)
/datum/atom_hud/proc/add_to_hud(atom/A)
if(!A)
return
hudatoms |= A
for(var/mob/M in hudusers)
add_to_single_hud(M, A)
/datum/atom_hud/proc/add_to_single_hud(mob/M, atom/A) //unsafe, no sanity apart from client
if(!M || !M.client || !A)
return
for(var/i in hud_icons)
if(A.hud_list[i])
M.client.images |= A.hud_list[i]
//MOB PROCS
/mob/proc/reload_huds()
var/gang_huds = list()
if(ticker.mode)
for(var/datum/gang/G in ticker.mode.gangs)
gang_huds += G.ganghud
for(var/datum/atom_hud/hud in (huds|gang_huds))
if(src in hud.hudusers)
hud.add_hud_to(src)
/mob/new_player/reload_huds()
return
/mob/proc/add_click_catcher()
client.screen += client.void
/mob/new_player/add_click_catcher()
return
+519
View File
@@ -0,0 +1,519 @@
/datum/martial_art
var/name = "Martial Art"
var/streak = ""
var/max_streak_length = 6
var/current_target = null
var/temporary = 0
var/datum/martial_art/base = null // The permanent style
var/deflection_chance = 0 //Chance to deflect projectiles
var/help_verb = null
/datum/martial_art/proc/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
return 0
/datum/martial_art/proc/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
return 0
/datum/martial_art/proc/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
return 0
/datum/martial_art/proc/add_to_streak(element,mob/living/carbon/human/D)
if(D != current_target)
current_target = D
streak = ""
streak = streak+element
if(length(streak) > max_streak_length)
streak = copytext(streak,2)
return
/datum/martial_art/proc/basic_hit(mob/living/carbon/human/A,mob/living/carbon/human/D)
A.do_attack_animation(D)
var/damage = rand(A.dna.species.punchdamagelow, A.dna.species.punchdamagehigh)
var/atk_verb = A.dna.species.attack_verb
if(D.lying)
atk_verb = "kick"
if(!damage)
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/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected))
var/armor_block = D.run_armor_check(affecting, "melee")
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>")
D.apply_damage(damage, BRUTE, affecting, armor_block)
add_logs(A, D, "punched")
if((D.stat != DEAD) && damage >= A.dna.species.punchstunthreshold)
D.visible_message("<span class='danger'>[A] has weakened [D]!!</span>", \
"<span class='userdanger'>[A] has weakened [D]!</span>")
D.apply_effect(4, WEAKEN, armor_block)
D.forcesay(hit_appends)
else if(D.lying)
D.forcesay(hit_appends)
return 1
/datum/martial_art/proc/teach(mob/living/carbon/human/H,make_temporary=0)
if(help_verb)
H.verbs += help_verb
if(make_temporary)
temporary = 1
if(H.martial_art && temporary)
base = H.martial_art
H.martial_art = src
/datum/martial_art/proc/remove(mob/living/carbon/human/H)
if(H.martial_art != src)
return
H.martial_art = base
if(help_verb)
H.verbs -= help_verb
/datum/martial_art/boxing
name = "Boxing"
/datum/martial_art/boxing/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
A << "<span class='warning'>Can't disarm while boxing!</span>"
return 1
/datum/martial_art/boxing/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
A << "<span class='warning'>Can't grab while boxing!</span>"
return 1
/datum/martial_art/boxing/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
A.do_attack_animation(D)
var/atk_verb = pick("left hook","right hook","straight punch")
var/damage = rand(5, 8) + A.dna.species.punchdamagelow
if(!damage)
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/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected))
var/armor_block = D.run_armor_check(affecting, "melee")
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>")
D.apply_damage(damage, STAMINA, affecting, armor_block)
add_logs(A, D, "punched")
if(D.getStaminaLoss() > 50)
var/knockout_prob = D.getStaminaLoss() + rand(-15,15)
if((D.stat != DEAD) && prob(knockout_prob))
D.visible_message("<span class='danger'>[A] has knocked [D] out with a haymaker!</span>", \
"<span class='userdanger'>[A] has knocked [D] out with a haymaker!</span>")
D.apply_effect(10,WEAKEN,armor_block)
D.SetSleeping(5)
D.forcesay(hit_appends)
else if(D.lying)
D.forcesay(hit_appends)
return 1
/mob/living/carbon/human/proc/wrestling_help()
set name = "Recall Teachings"
set desc = "Remember how to wrestle."
set category = "Wrestling"
usr << "<b><i>You flex your muscles and have a revelation...</i></b>"
usr << "<span class='notice'>Clinch</span>: Grab. Passively gives you a chance to immediately aggressively grab someone. Not always successful."
usr << "<span class='notice'>Suplex</span>: Disarm someone you are grabbing. Suplexes your target to the floor. Greatly injures them and leaves both you and your target on the floor."
usr << "<span class='notice'>Advanced grab</span>: Grab. Passively causes stamina damage when grabbing someone."
#define TORNADO_COMBO "HHD"
#define THROWBACK_COMBO "DHD"
#define PLASMA_COMBO "HDDDH"
/datum/martial_art/plasma_fist
name = "Plasma Fist"
help_verb = /mob/living/carbon/human/proc/plasma_fist_help
/datum/martial_art/plasma_fist/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(findtext(streak,TORNADO_COMBO))
streak = ""
Tornado(A,D)
return 1
if(findtext(streak,THROWBACK_COMBO))
streak = ""
Throwback(A,D)
return 1
if(findtext(streak,PLASMA_COMBO))
streak = ""
Plasma(A,D)
return 1
return 0
/datum/martial_art/plasma_fist/proc/Tornado(mob/living/carbon/human/A, mob/living/carbon/human/D)
A.say("TORNADO SWEEP!")
spawn(0)
for(var/i in list(NORTH,SOUTH,EAST,WEST,EAST,SOUTH,NORTH,SOUTH,EAST,WEST,EAST,SOUTH))
A.setDir(i)
playsound(A.loc, 'sound/weapons/punch1.ogg', 15, 1, -1)
sleep(1)
var/obj/effect/proc_holder/spell/aoe_turf/repulse/R = new(null)
var/list/turfs = list()
for(var/turf/T in range(1,A))
turfs.Add(T)
R.cast(turfs)
return
/datum/martial_art/plasma_fist/proc/Throwback(mob/living/carbon/human/A, mob/living/carbon/human/D)
D.visible_message("<span class='danger'>[A] has hit [D] with Plasma Punch!</span>", \
"<span class='userdanger'>[A] has hit [D] with Plasma Punch!</span>")
playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1)
var/atom/throw_target = get_edge_target_turf(D, get_dir(D, get_step_away(D, A)))
D.throw_at(throw_target, 200, 4,A)
A.say("HYAH!")
return
/datum/martial_art/plasma_fist/proc/Plasma(mob/living/carbon/human/A, mob/living/carbon/human/D)
A.do_attack_animation(D)
playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1)
A.say("PLASMA FIST!")
D.visible_message("<span class='danger'>[A] has hit [D] with THE PLASMA FIST TECHNIQUE!</span>", \
"<span class='userdanger'>[A] has hit [D] with THE PLASMA FIST TECHNIQUE!</span>")
D.gib()
return
/datum/martial_art/plasma_fist/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("H",D)
if(check_streak(A,D))
return 1
basic_hit(A,D)
return 1
/datum/martial_art/plasma_fist/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("D",D)
if(check_streak(A,D))
return 1
basic_hit(A,D)
return 1
/datum/martial_art/plasma_fist/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("G",D)
if(check_streak(A,D))
return 1
basic_hit(A,D)
return 1
/mob/living/carbon/human/proc/plasma_fist_help()
set name = "Recall Teachings"
set desc = "Remember the martial techniques of the Plasma Fist."
set category = "Plasma Fist"
usr << "<b><i>You clench your fists and have a flashback of knowledge...</i></b>"
usr << "<span class='notice'>Tornado Sweep</span>: Harm Harm Disarm. Repulses target and everyone back."
usr << "<span class='notice'>Throwback</span>: Disarm Harm Disarm. Throws the target and an item at them."
usr << "<span class='notice'>The Plasma Fist</span>: Harm Disarm Disarm Disarm Harm. Knocks the brain out of the opponent and gibs their body."
//Used by the gang of the same name. Uses combos. Basic attacks bypass armor and never miss
#define WRIST_WRENCH_COMBO "DD"
#define BACK_KICK_COMBO "HG"
#define STOMACH_KNEE_COMBO "GH"
#define HEAD_KICK_COMBO "DHH"
#define ELBOW_DROP_COMBO "HDHDH"
/datum/martial_art/the_sleeping_carp
name = "The Sleeping Carp"
deflection_chance = 100
help_verb = /mob/living/carbon/human/proc/sleeping_carp_help
/datum/martial_art/the_sleeping_carp/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(findtext(streak,WRIST_WRENCH_COMBO))
streak = ""
wristWrench(A,D)
return 1
if(findtext(streak,BACK_KICK_COMBO))
streak = ""
backKick(A,D)
return 1
if(findtext(streak,STOMACH_KNEE_COMBO))
streak = ""
kneeStomach(A,D)
return 1
if(findtext(streak,HEAD_KICK_COMBO))
streak = ""
headKick(A,D)
return 1
if(findtext(streak,ELBOW_DROP_COMBO))
streak = ""
elbowDrop(A,D)
return 1
return 0
/datum/martial_art/the_sleeping_carp/proc/wristWrench(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.stat && !D.stunned && !D.weakened)
A.do_attack_animation(D)
D.visible_message("<span class='warning'>[A] grabs [D]'s wrist and wrenches it sideways!</span>", \
"<span class='userdanger'>[A] grabs your wrist and violently wrenches it to the side!</span>")
playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
D.emote("scream")
D.drop_item()
D.apply_damage(5, BRUTE, pick("l_arm", "r_arm"))
D.Stun(3)
return 1
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/proc/backKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(A.dir == D.dir && !D.stat && !D.weakened)
A.do_attack_animation(D)
D.visible_message("<span class='warning'>[A] kicks [D] in the back!</span>", \
"<span class='userdanger'>[A] kicks you in the back, making you stumble and fall!</span>")
step_to(D,get_step(D,D.dir),1)
D.Weaken(4)
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
return 1
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/proc/kneeStomach(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.stat && !D.weakened)
A.do_attack_animation(D)
D.visible_message("<span class='warning'>[A] knees [D] in the stomach!</span>", \
"<span class='userdanger'>[A] winds you with a knee in the stomach!</span>")
D.audible_message("<b>[D]</b> gags!")
D.losebreath += 3
D.Stun(2)
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
return 1
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/proc/headKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D.stat && !D.weakened)
A.do_attack_animation(D)
D.visible_message("<span class='warning'>[A] kicks [D] in the head!</span>", \
"<span class='userdanger'>[A] kicks you in the jaw!</span>")
D.apply_damage(20, BRUTE, "head")
D.drop_item()
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
D.Stun(4)
return 1
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/proc/elbowDrop(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(D.weakened || D.resting || D.stat)
A.do_attack_animation(D)
D.visible_message("<span class='warning'>[A] elbow drops [D]!</span>", \
"<span class='userdanger'>[A] piledrives you with their elbow!</span>")
if(D.stat)
D.death() //FINISH HIM!
D.apply_damage(50, BRUTE, "chest")
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 75, 1, -1)
return 1
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("G",D)
if(check_streak(A,D))
return 1
if(A.grab_state >= GRAB_AGGRESSIVE)
D.grabbedby(A, 1)
else
A.start_pulling(D, 1)
if(A.pulling)
D.drop_r_hand()
D.drop_l_hand()
D.stop_pulling()
add_logs(A, D, "grabbed", addition="aggressively")
A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab
return 1
/datum/martial_art/the_sleeping_carp/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("H",D)
if(check_streak(A,D))
return 1
A.do_attack_animation(D)
var/atk_verb = pick("punches", "kicks", "chops", "hits", "slams")
D.visible_message("<span class='danger'>[A] [atk_verb] [D]!</span>", \
"<span class='userdanger'>[A] [atk_verb] you!</span>")
D.apply_damage(rand(10,15), BRUTE)
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, 1, -1)
if(prob(D.getBruteLoss()) && !D.lying)
D.visible_message("<span class='warning'>[D] stumbles and falls!</span>", "<span class='userdanger'>The blow sends you to the ground!</span>")
D.Weaken(4)
return 1
/datum/martial_art/the_sleeping_carp/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
add_to_streak("D",D)
if(check_streak(A,D))
return 1
return ..()
/mob/living/carbon/human/proc/sleeping_carp_help()
set name = "Recall Teachings"
set desc = "Remember the martial techniques of the Sleeping Carp clan."
set category = "Sleeping Carp"
usr << "<b><i>You retreat inward and recall the teachings of the Sleeping Carp...</i></b>"
usr << "<span class='notice'>Wrist Wrench</span>: Disarm Disarm. Forces opponent to drop item in hand."
usr << "<span class='notice'>Back Kick</span>: Harm Grab. Opponent must be facing away. Knocks down."
usr << "<span class='notice'>Stomach Knee</span>: Grab Harm. Knocks the wind out of opponent and stuns."
usr << "<span class='notice'>Head Kick</span>: Disarm Harm Harm. Decent damage, forces opponent to drop item in hand."
usr << "<span class='notice'>Elbow Drop</span>: Harm Disarm Harm Disarm Harm. Opponent must be on the ground. Deals huge damage, instantly kills anyone in critical condition."
//ITEMS
/obj/item/clothing/gloves/boxing
var/datum/martial_art/boxing/style = new
/obj/item/clothing/gloves/boxing/equipped(mob/user, slot)
if(!ishuman(user))
return
if(slot == slot_gloves)
var/mob/living/carbon/human/H = user
style.teach(H,1)
return
/obj/item/clothing/gloves/boxing/dropped(mob/user)
if(!ishuman(user))
return
var/mob/living/carbon/human/H = user
if(H.get_item_by_slot(slot_gloves) == src)
style.remove(H)
return
/obj/item/weapon/storage/belt/champion/wrestling
name = "Wrestling Belt"
var/datum/martial_art/wrestling/style = new
/obj/item/weapon/storage/belt/champion/wrestling/equipped(mob/user, slot)
if(!ishuman(user))
return
if(slot == slot_belt)
var/mob/living/carbon/human/H = user
style.teach(H,1)
return
/obj/item/weapon/storage/belt/champion/wrestling/dropped(mob/user)
if(!ishuman(user))
return
var/mob/living/carbon/human/H = user
if(H.get_item_by_slot(slot_belt) == src)
style.remove(H)
return
/obj/item/weapon/plasma_fist_scroll
name = "frayed scroll"
desc = "An aged and frayed scrap of paper written in shifting runes. There are hand-drawn illustrations of pugilism."
icon = 'icons/obj/wizard.dmi'
icon_state ="scroll2"
var/used = 0
/obj/item/weapon/plasma_fist_scroll/attack_self(mob/user)
if(!ishuman(user))
return
if(!used)
var/mob/living/carbon/human/H = user
var/datum/martial_art/plasma_fist/F = new/datum/martial_art/plasma_fist(null)
F.teach(H)
H << "<span class='boldannounce'>You have learned the ancient martial art of Plasma Fist.</span>"
used = 1
desc = "It's completely blank."
name = "empty scroll"
icon_state = "blankscroll"
/obj/item/weapon/sleeping_carp_scroll
name = "mysterious scroll"
desc = "A scroll filled with strange markings. It seems to be drawings of some sort of martial art."
icon = 'icons/obj/wizard.dmi'
icon_state = "scroll2"
/obj/item/weapon/sleeping_carp_scroll/attack_self(mob/living/carbon/human/user)
if(!istype(user) || !user)
return
user << "<span class='sciradio'>You have learned the ancient martial art of the Sleeping Carp! Your hand-to-hand combat has become much more effective, and you are now able to deflect any projectiles \
directed toward you. However, you are also unable to use any ranged weaponry. You can learn more about your newfound art by using the Recall Teachings verb in the Sleeping Carp tab.</span>"
var/datum/martial_art/the_sleeping_carp/theSleepingCarp = new(null)
theSleepingCarp.teach(user)
user.drop_item()
visible_message("<span class='warning'>[src] lights up in fire and quickly burns to ash.</span>")
new /obj/effect/decal/cleanable/ash(get_turf(src))
qdel(src)
/obj/item/weapon/twohanded/bostaff
name = "bo staff"
desc = "A long, tall staff made of polished wood. Traditionally used in ancient old-Earth martial arts. Can be wielded to both kill and incapacitate."
force = 10
w_class = 4
slot_flags = SLOT_BACK
force_unwielded = 10
force_wielded = 24
throwforce = 20
throw_speed = 2
attack_verb = list("smashed", "slammed", "whacked", "thwacked")
icon = 'icons/obj/weapons.dmi'
icon_state = "bostaff0"
block_chance = 50
/obj/item/weapon/twohanded/bostaff/update_icon()
icon_state = "bostaff[wielded]"
return
/obj/item/weapon/twohanded/bostaff/attack(mob/target, mob/living/user)
add_fingerprint(user)
if((CLUMSY in user.disabilities) && prob(50))
user << "<span class ='warning'>You club yourself over the head with [src].</span>"
user.Weaken(3)
if(ishuman(user))
var/mob/living/carbon/human/H = user
H.apply_damage(2*force, BRUTE, "head")
else
user.take_organ_damage(2*force)
return
if(isrobot(target))
return ..()
if(!isliving(target))
return ..()
var/mob/living/carbon/C = target
if(C.stat)
user << "<span class='warning'>It would be dishonorable to attack a foe while they cannot retaliate.</span>"
return
if(user.a_intent == "disarm")
if(!wielded)
return ..()
if(!ishuman(target))
return ..()
var/mob/living/carbon/human/H = target
var/list/fluffmessages = list("[user] clubs [H] with [src]!", \
"[user] smacks [H] with the butt of [src]!", \
"[user] broadsides [H] with [src]!", \
"[user] smashes [H]'s head with [src]!", \
"[user] beats [H] with front of [src]!", \
"[user] twirls and slams [H] with [src]!")
H.visible_message("<span class='warning'>[pick(fluffmessages)]</span>", \
"<span class='userdanger'>[pick(fluffmessages)]</span>")
playsound(get_turf(user), 'sound/effects/woodhit.ogg', 75, 1, -1)
H.adjustStaminaLoss(rand(13,20))
if(prob(10))
H.visible_message("<span class='warning'>[H] collapses!</span>", \
"<span class='userdanger'>Your legs give out!</span>")
H.Weaken(4)
if(H.staminaloss && !H.sleeping)
var/total_health = (H.health - H.staminaloss)
if(total_health <= config.health_threshold_crit && !H.stat)
H.visible_message("<span class='warning'>[user] delivers a heavy hit to [H]'s head, knocking them out cold!</span>", \
"<span class='userdanger'>[user] knocks you unconscious!</span>")
H.SetSleeping(30)
H.adjustBrainLoss(25)
else
return ..()
/obj/item/weapon/twohanded/bostaff/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance)
if(wielded)
return ..()
return 0
+171
View File
@@ -0,0 +1,171 @@
/datum/martial_art/krav_maga
name = "Krav Maga"
var/datum/action/neck_chop/neckchop = new/datum/action/neck_chop()
var/datum/action/leg_sweep/legsweep = new/datum/action/leg_sweep()
var/datum/action/lung_punch/lungpunch = new/datum/action/lung_punch()
/datum/action/neck_chop
name = "Neck Chop - Injures the neck, stopping the victim from speaking for a while."
button_icon_state = "neckchop"
/datum/action/neck_chop/Trigger()
if(owner.incapacitated())
owner << "<span class='warning'>You can't use Krav Maga while you're incapacitated.</span>"
return
owner.visible_message("<span class='danger'>[owner] assumes the Neck Chop stance!</span>", "<b><i>Your next attack will be a Neck Chop.</i></b>")
var/mob/living/carbon/human/H = owner
H.martial_art.streak = "neck_chop"
/datum/action/leg_sweep
name = "Leg Sweep - Trips the victim, rendering them prone and unable to move for a short time."
button_icon_state = "legsweep"
/datum/action/leg_sweep/Trigger()
if(owner.incapacitated())
owner << "<span class='warning'>You can't use Krav Maga while you're incapacitated.</span>"
return
owner.visible_message("<span class='danger'>[owner] assumes the Leg Sweep stance!</span>", "<b><i>Your next attack will be a Leg Sweep.</i></b>")
var/mob/living/carbon/human/H = owner
H.martial_art.streak = "leg_sweep"
/datum/action/lung_punch//referred to internally as 'quick choke'
name = "Lung Punch - Delivers a strong punch just above the victim's abdomen, constraining the lungs. The victim will be unable to breathe for a short time."
button_icon_state = "lungpunch"
/datum/action/lung_punch/Trigger()
if(owner.incapacitated())
owner << "<span class='warning'>You can't use Krav Maga while you're incapacitated.</span>"
return
owner.visible_message("<span class='danger'>[owner] assumes the Lung Punch stance!</span>", "<b><i>Your next attack will be a Lung Punch.</i></b>")
var/mob/living/carbon/human/H = owner
H.martial_art.streak = "quick_choke"//internal name for lung punch
/datum/martial_art/krav_maga/teach(var/mob/living/carbon/human/H,var/make_temporary=0)
..()
H << "<span class = 'userdanger'>You know the arts of Krav Maga!</span>"
H << "<span class = 'danger'>Place your cursor over a move at the top of the screen to see what it does.</span>"
neckchop.Grant(H)
legsweep.Grant(H)
lungpunch.Grant(H)
/datum/martial_art/krav_maga/remove(var/mob/living/carbon/human/H)
..()
H << "<span class = 'userdanger'>You suddenly forget the arts of Krav Maga...</span>"
neckchop.Remove(H)
legsweep.Remove(H)
lungpunch.Remove(H)
/datum/martial_art/krav_maga/proc/check_streak(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
switch(streak)
if("neck_chop")
streak = ""
neck_chop(A,D)
return 1
if("leg_sweep")
streak = ""
leg_sweep(A,D)
return 1
if("quick_choke")//is actually lung punch
streak = ""
quick_choke(A,D)
return 1
return 0
/datum/martial_art/krav_maga/proc/leg_sweep(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
if(D.stat || D.weakened)
return 0
D.visible_message("<span class='warning'>[A] leg sweeps [D]!</span>", \
"<span class='userdanger'>[A] leg sweeps you!</span>")
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1)
D.apply_damage(5, BRUTE)
D.Weaken(2)
return 1
/datum/martial_art/krav_maga/proc/quick_choke(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)//is actually lung punch
D.visible_message("<span class='warning'>[A] pounds [D] on the chest!</span>", \
"<span class='userdanger'>[A] slams your chest! You can't breathe!</span>")
playsound(get_turf(A), 'sound/effects/hit_punch.ogg', 50, 1, -1)
D.losebreath += 5
D.adjustOxyLoss(10)
return 1
/datum/martial_art/krav_maga/proc/neck_chop(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
D.visible_message("<span class='warning'>[A] karate chops [D]'s neck!</span>", \
"<span class='userdanger'>[A] karate chops your neck, rendering you unable to speak!</span>")
playsound(get_turf(A), 'sound/effects/hit_punch.ogg', 50, 1, -1)
D.apply_damage(5, BRUTE)
D.silent += 10
return 1
datum/martial_art/krav_maga/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
if(check_streak(A,D))
return 1
..()
/datum/martial_art/krav_maga/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
if(check_streak(A,D))
return 1
add_logs(A, D, "punched")
A.do_attack_animation(D)
var/picked_hit_type = pick("punches", "kicks")
var/bonus_damage = 10
if(D.weakened || D.resting || D.lying)
bonus_damage += 5
picked_hit_type = "stomps on"
D.apply_damage(bonus_damage, BRUTE)
if(picked_hit_type == "kicks" || picked_hit_type == "stomps")
playsound(get_turf(D), 'sound/effects/hit_kick.ogg', 50, 1, -1)
else
playsound(get_turf(D), 'sound/effects/hit_punch.ogg', 50, 1, -1)
D.visible_message("<span class='danger'>[A] [picked_hit_type] [D]!</span>", \
"<span class='userdanger'>[A] [picked_hit_type] you!</span>")
return 1
/datum/martial_art/krav_maga/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
if(check_streak(A,D))
return 1
if(prob(60))
if(D.hand)
if(istype(D.l_hand, /obj/item))
var/obj/item/I = D.l_hand
D.drop_item()
A.put_in_hands(I)
else
if(istype(D.r_hand, /obj/item))
var/obj/item/I = D.r_hand
D.drop_item()
A.put_in_hands(I)
D.visible_message("<span class='danger'>[A] has disarmed [D]!</span>", \
"<span class='userdanger'>[A] has disarmed [D]!</span>")
playsound(D, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
else
D.visible_message("<span class='danger'>[A] attempted to disarm [D]!</span>", \
"<span class='userdanger'>[A] attempted to disarm [D]!</span>")
playsound(D, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
return 1
//Krav Maga Gloves
/obj/item/clothing/gloves/color/black/krav_maga
can_be_cut = 0
var/datum/martial_art/krav_maga/style = new
/obj/item/clothing/gloves/color/black/krav_maga/equipped(mob/user, slot)
if(!ishuman(user))
return
if(slot == slot_gloves)
var/mob/living/carbon/human/H = user
style.teach(H,1)
/obj/item/clothing/gloves/color/black/krav_maga/dropped(mob/user)
if(!ishuman(user))
return
var/mob/living/carbon/human/H = user
if(H.get_item_by_slot(slot_gloves) == src)
style.remove(H)
/obj/item/clothing/gloves/color/black/krav_maga/sec//more obviously named, given to sec
name = "krav maga gloves"
desc = "These gloves can teach you to perform Krav Maga using nanochips."
icon_state = "fightgloves"
item_state = "fightgloves"
+421
View File
@@ -0,0 +1,421 @@
/datum/martial_art/wrestling
name = "Wrestling"
var/datum/action/slam/slam = new/datum/action/slam()
var/datum/action/throw_wrassle/throw_wrassle = new/datum/action/throw_wrassle()
var/datum/action/kick/kick = new/datum/action/kick()
var/datum/action/strike/strike = new/datum/action/strike()
var/datum/action/drop/drop = new/datum/action/drop()
/datum/martial_art/wrestling/proc/check_streak(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
switch(streak)
if("drop")
streak = ""
drop(A,D)
return 1
if("strike")
streak = ""
strike(A,D)
return 1
if("kick")
streak = ""
kick(A,D)
return 1
if("throw")
streak = ""
throw_wrassle(A,D)
return 1
if("slam")
streak = ""
slam(A,D)
return 1
return 0
/datum/action/slam
name = "Slam (Cinch) - Slam a grappled opponent into the floor."
button_icon_state = "wrassle_slam"
/datum/action/slam/Trigger()
if(owner.incapacitated())
owner << "<span class='warning'>You can't WRESTLE while you're OUT FOR THE COUNT.</span>"
return
owner.visible_message("<span class='danger'>[owner] prepares to BODY SLAM!</span>", "<b><i>Your next attack will be a BODY SLAM.</i></b>")
var/mob/living/carbon/human/H = owner
H.martial_art.streak = "slam"
/datum/action/throw_wrassle
name = "Throw (Cinch) - Spin a cinched opponent around and throw them."
button_icon_state = "wrassle_throw"
/datum/action/throw_wrassle/Trigger()
if(owner.incapacitated())
owner << "<span class='warning'>You can't WRESTLE while you're OUT FOR THE COUNT.</span>"
return
owner.visible_message("<span class='danger'>[owner] prepares to THROW!</span>", "<b><i>Your next attack will be a THROW.</i></b>")
var/mob/living/carbon/human/H = owner
H.martial_art.streak = "throw"
/datum/action/kick
name = "Kick - A powerful kick, sends people flying away from you. Also useful for escaping from bad situations."
button_icon_state = "wrassle_kick"
/datum/action/kick/Trigger()
if(owner.incapacitated())
owner << "<span class='warning'>You can't WRESTLE while you're OUT FOR THE COUNT.</span>"
return
owner.visible_message("<span class='danger'>[owner] prepares to KICK!</span>", "<b><i>Your next attack will be a KICK.</i></b>")
var/mob/living/carbon/human/H = owner
H.martial_art.streak = "kick"
/datum/action/strike
name = "Strike - Hit a neaby opponent with a quick attack."
button_icon_state = "wrassle_strike"
/datum/action/strike/Trigger()
if(owner.incapacitated())
owner << "<span class='warning'>You can't WRESTLE while you're OUT FOR THE COUNT.</span>"
return
owner.visible_message("<span class='danger'>[owner] prepares to STRIKE!</span>", "<b><i>Your next attack will be a STRIKE.</i></b>")
var/mob/living/carbon/human/H = owner
H.martial_art.streak = "strike"
/datum/action/drop
name = "Drop - Smash down onto an opponent."
button_icon_state = "wrassle_drop"
/datum/action/drop/Trigger()
if(owner.incapacitated())
owner << "<span class='warning'>You can't WRESTLE while you're OUT FOR THE COUNT.</span>"
return
owner.visible_message("<span class='danger'>[owner] prepares to LEG DROP!</span>", "<b><i>Your next attack will be a LEG DROP.</i></b>")
var/mob/living/carbon/human/H = owner
H.martial_art.streak = "drop"
/datum/martial_art/wrestling/teach(var/mob/living/carbon/human/H,var/make_temporary=0)
..()
H << "<span class = 'userdanger'>SNAP INTO A THIN TIM!</span>"
H << "<span class = 'danger'>Place your cursor over a move at the top of the screen to see what it does.</span>"
drop.Grant(H)
kick.Grant(H)
slam.Grant(H)
throw_wrassle.Grant(H)
strike.Grant(H)
/datum/martial_art/wrestling/remove(var/mob/living/carbon/human/H)
..()
H << "<span class = 'userdanger'>You no longer feel that the tower of power is too sweet to be sour...</span>"
drop.Remove(H)
kick.Remove(H)
slam.Remove(H)
throw_wrassle.Remove(H)
strike.Remove(H)
/datum/martial_art/wrestling/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(check_streak(A,D))
return 1
..()
/datum/martial_art/wrestling/proc/throw_wrassle(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D)
return
if(!A.pulling || A.pulling != D)
A << "You need to have [D] in a cinch!"
return
D.forceMove(A.loc)
D.setDir(get_dir(D, A))
D.Stun(4)
A.visible_message("<span class = 'danger'><B>[A] starts spinning around with [D]!</B></span>")
A.emote("scream")
for (var/i = 0, i < 20, i++)
var/delay = 5
switch (i)
if (17 to INFINITY)
delay = 0.25
if (14 to 16)
delay = 0.5
if (9 to 13)
delay = 1
if (5 to 8)
delay = 2
if (0 to 4)
delay = 3
if (A && D)
if (get_dist(A, D) > 1)
A << "[D] is too far away!"
return 0
if (!isturf(A.loc) || !isturf(D.loc))
A << "You can't throw [D] from here!"
return 0
A.setDir(turn(A.dir, 90))
var/turf/T = get_step(A, A.dir)
var/turf/S = D.loc
if ((S && isturf(S) && S.Exit(D)) && (T && isturf(T) && T.Enter(A)))
D.forceMove(T)
D.setDir(get_dir(D, A))
else
return 0
sleep(delay)
if (A && D)
// These are necessary because of the sleep call.
if (get_dist(A, D) > 1)
A << "[D] is too far away!"
return 0
if (!isturf(A.loc) || !isturf(D.loc))
A << "You can't throw [D] from here!"
return 0
D.forceMove(A.loc) // Maybe this will help with the wallthrowing bug.
A.visible_message("<span class = 'danger'><B>[A] throws [D]!</B></span>")
playsound(A.loc, "swing_hit", 50, 1)
var/turf/T = get_edge_target_turf(A, A.dir)
if (T && isturf(T))
if (!D.stat)
D.emote("scream")
D.throw_at(T, 10, 4)
D.Weaken(2)
return 0
/datum/martial_art/wrestling/proc/slam(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D)
return
if(!A.pulling || A.pulling != D)
A << "You need to have [D] in a cinch!"
return
D.forceMove(A.loc)
A.setDir(get_dir(A, D))
D.setDir(get_dir(D, A))
A.visible_message("<span class = 'danger'><B>[A] lifts [D] up!</B></span>")
spawn (0)
if (D)
animate(D, transform = matrix(180, MATRIX_ROTATE), time = 1, loop = 0)
sleep (15)
if (D)
animate(D, transform = null, time = 1, loop = 0)
for (var/i = 0, i < 3, i++)
if (A && D)
A.pixel_y += 3
D.pixel_y += 3
A.setDir(turn(A.dir, 90))
D.setDir(turn(D.dir, 90))
switch (A.dir)
if (NORTH)
D.pixel_x = A.pixel_x
if (SOUTH)
D.pixel_x = A.pixel_x
if (EAST)
D.pixel_x = A.pixel_x - 8
if (WEST)
D.pixel_x = A.pixel_x + 8
if (get_dist(A, D) > 1)
A << "[D] is too far away!"
A.pixel_x = 0
A.pixel_y = 0
D.pixel_x = 0
D.pixel_y = 0
return 0
if (!isturf(A.loc) || !isturf(D.loc))
A << "You can't slam [D] here!"
A.pixel_x = 0
A.pixel_y = 0
D.pixel_x = 0
D.pixel_y = 0
return 0
else
if (A)
A.pixel_x = 0
A.pixel_y = 0
if (D)
D.pixel_x = 0
D.pixel_y = 0
return 0
sleep (1)
if (A && D)
A.pixel_x = 0
A.pixel_y = 0
D.pixel_x = 0
D.pixel_y = 0
if (get_dist(A, D) > 1)
A << "[D] is too far away!"
return 0
if (!isturf(A.loc) || !isturf(D.loc))
A << "You can't slam [D] here!"
return 0
D.forceMove(A.loc)
var/fluff = "body-slam"
switch(pick(2,3))
if (2)
fluff = "turbo [fluff]"
if (3)
fluff = "atomic [fluff]"
A.visible_message("<span class = 'danger'><B>[A] [fluff] [D]!</B></span>")
playsound(A.loc, "swing_hit", 50, 1)
if (!D.stat)
D.emote("scream")
D.weakened += 2
D.stunned += 2
switch(rand(1,3))
if (2)
D.adjustBruteLoss(rand(20,30))
if (3)
D.ex_act(3)
else
D.adjustBruteLoss(rand(10,20))
else
D.ex_act(3)
else
if (A)
A.pixel_x = 0
A.pixel_y = 0
if (D)
D.pixel_x = 0
D.pixel_y = 0
return 0
/datum/martial_art/wrestling/proc/strike(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D)
return
var/turf/T = get_turf(A)
if (T && isturf(T) && D && isturf(D.loc))
for (var/i = 0, i < 4, i++)
A.setDir(turn(A.dir, 90))
A.forceMove(D.loc)
spawn (4)
if (A && (T && isturf(T) && get_dist(A, T) <= 1))
A.forceMove(T)
A.visible_message("<span class = 'danger'><b>[A] headbutts [D]!</b></span>")
D.adjustBruteLoss(rand(10,20))
playsound(A.loc, "swing_hit", 50, 1)
D.Paralyse(1)
/datum/martial_art/wrestling/proc/kick(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D)
return
A.emote("scream")
A.emote("flip")
A.setDir(turn(A.dir, 90))
A.visible_message("<span class = 'danger'><B>[A] roundhouse-kicks [D]!</B></span>")
playsound(A.loc, "swing_hit", 50, 1)
D.adjustBruteLoss(rand(10,20))
var/turf/T = get_edge_target_turf(A, get_dir(A, get_step_away(D, A)))
if (T && isturf(T))
D.Weaken(1)
D.throw_at(T, 3, 2)
/datum/martial_art/wrestling/proc/drop(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D)
return
var/obj/surface = null
var/turf/ST = null
var/falling = 0
for (var/obj/O in oview(1, A))
if (O.density == 1)
if (O == A) continue
if (O == D) continue
if (O.opacity) continue
else
surface = O
ST = get_turf(O)
break
if (surface && (ST && isturf(ST)))
A.forceMove(ST)
A.visible_message("<span class = 'danger'><B>[A] climbs onto [surface]!</b></span>")
A.pixel_y = 10
falling = 1
sleep(10)
if (A && D)
// These are necessary because of the sleep call.
if ((falling == 0 && get_dist(A, D) > 1) || (falling == 1 && get_dist(A, D) > 2)) // We climbed onto stuff.
A.pixel_y = 0
if (falling == 1)
A.visible_message("<span class = 'danger'><B>...and dives head-first into the ground, ouch!</b></span>")
A.adjustBruteLoss(rand(10,20))
A.Weaken(3)
A << "[D] is too far away!"
return 0
if (!isturf(A.loc) || !isturf(D.loc))
A.pixel_y = 0
A << "You can't drop onto [D] from here!"
return 0
if(A)
animate(A, transform = matrix(90, MATRIX_ROTATE), time = 1, loop = 0)
sleep(10)
if(A)
animate(A, transform = null, time = 1, loop = 0)
A.forceMove(D.loc)
A.visible_message("<span class = 'danger'><B>[A] leg-drops [D]!</B></span>")
playsound(A.loc, "swing_hit", 50, 1)
A.emote("scream")
if (falling == 1)
if (prob(33) || D.stat)
D.ex_act(3)
else
D.adjustBruteLoss(rand(20,30))
else
D.adjustBruteLoss(rand(20,30))
D.Weaken(1)
D.Stun(2)
A.pixel_y = 0
else
if (A)
A.pixel_y = 0
return
/datum/martial_art/wrestling/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(check_streak(A,D))
return 1
..()
/datum/martial_art/wrestling/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(check_streak(A,D))
return 1
if(A.pulling == D)
return 1
A.start_pulling(D)
D.visible_message("<span class='danger'>[A] gets [D] in a cinch!</span>", \
"<span class='userdanger'>[A] gets [D] in a cinch!</span>")
D.Stun(rand(3,5))
return 1
+258
View File
@@ -0,0 +1,258 @@
/*
This datum should be used for handling mineral contents of machines and whatever else is supposed to hold minerals and make use of them.
Variables:
amount - raw amount of the mineral this container is holding, calculated by the defined value MINERAL_MATERIAL_AMOUNT=2000.
max_amount - max raw amount of mineral this container can hold.
sheet_type - type of the mineral sheet the container handles, used for output.
owner - object that this container is being used by, used for output.
MAX_STACK_SIZE - size of a stack of mineral sheets. Constant.
*/
/datum/material_container
var/total_amount = 0
var/max_amount
var/sheet_type
var/obj/owner
var/list/materials = list()
//MAX_STACK_SIZE = 50
//MINERAL_MATERIAL_AMOUNT = 2000
/datum/material_container/New(obj/O, list/mat_list, max_amt = 0)
owner = O
max_amount = max(0, max_amt)
var/list/possible_mats = list()
for(var/mat_type in subtypesof(/datum/material))
var/datum/material/MT = mat_type
possible_mats[initial(MT.id)] = mat_type
for(var/id in mat_list)
if(possible_mats[id])
var/mat_path = possible_mats[id]
materials[id] = new mat_path()
/datum/material_container/Destroy()
owner = null
return ..()
//For inserting an amount of material
/datum/material_container/proc/insert_amount(amt, id = null)
if(amt > 0 && has_space(amt))
var/total_amount_saved = total_amount
if(id)
var/datum/material/M = materials[id]
if(M)
M.amount += amt
total_amount += amt
else
for(var/i in materials)
var/datum/material/M = materials[i]
M.amount += amt
total_amount += amt
return (total_amount - total_amount_saved)
return 0
/datum/material_container/proc/insert_stack(obj/item/stack/S, amt = 0)
if(amt <= 0)
return 0
if(amt > S.amount)
amt = S.amount
var/material_amt = get_item_material_amount(S)
if(!material_amt)
return 0
amt = min(amt, round(((max_amount - total_amount) / material_amt)))
if(!amt)
return 0
insert_materials(S,amt)
S.use(amt)
return amt
/datum/material_container/proc/insert_item(obj/item/I, multiplier = 1)
if(!I)
return 0
if(istype(I,/obj/item/stack))
var/obj/item/stack/S = I
return insert_stack(I, S.amount)
var/material_amount = get_item_material_amount(I)
if(!material_amount || !has_space(material_amount))
return 0
insert_materials(I, multiplier)
return material_amount
/datum/material_container/proc/insert_materials(obj/item/I, multiplier = 1) //for internal usage only
var/datum/material/M
for(var/MAT in materials)
M = materials[MAT]
M.amount += I.materials[MAT] * multiplier
total_amount += I.materials[MAT] * multiplier
//For consuming material
//mats is a list of types of material to use and the corresponding amounts, example: list(MAT_METAL=100, MAT_GLASS=200)
/datum/material_container/proc/use_amount(list/mats, multiplier=1)
if(!mats || !mats.len)
return 0
var/datum/material/M
for(var/MAT in materials)
M = materials[MAT]
if(M.amount < (mats[MAT] * multiplier))
return 0
var/total_amount_save = total_amount
for(var/MAT in materials)
M = materials[MAT]
M.amount -= mats[MAT] * multiplier
total_amount -= mats[MAT] * multiplier
return total_amount_save - total_amount
/datum/material_container/proc/use_amount_type(amt, id)
var/datum/material/M = materials[id]
if(M)
if(M.amount >= amt)
M.amount -= amt
total_amount -= amt
return amt
return 0
/datum/material_container/proc/can_use_amount(amt, id, list/mats)
if(amt && id)
var/datum/material/M = materials[id]
if(M && M.amount >= amt)
return TRUE
else if(istype(mats))
for(var/M in mats)
if(materials[M] && (mats[M] <= materials[M]))
continue
else
return FALSE
return TRUE
return FALSE
//For spawning mineral sheets; internal use only
/datum/material_container/proc/retrieve(sheet_amt, datum/material/M)
if(sheet_amt > 0)
if(M.amount < (sheet_amt * MINERAL_MATERIAL_AMOUNT))
sheet_amt = round(M.amount / MINERAL_MATERIAL_AMOUNT)
var/count = 0
while(sheet_amt > MAX_STACK_SIZE)
new M.sheet_type(get_turf(owner), MAX_STACK_SIZE)
count += MAX_STACK_SIZE
use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id)
sheet_amt -= MAX_STACK_SIZE
if(round(M.amount / MINERAL_MATERIAL_AMOUNT))
new M.sheet_type(get_turf(owner), sheet_amt)
count += sheet_amt
use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id)
return count
return 0
/datum/material_container/proc/retrieve_sheets(sheet_amt, id)
if(materials[id])
return retrieve(sheet_amt, materials[id])
return 0
/datum/material_container/proc/retrieve_amount(amt, id)
return retrieve_sheets(amount2sheet(amt), id)
/datum/material_container/proc/retrieve_all()
var/result = 0
var/datum/material/M
for(var/MAT in materials)
M = materials[MAT]
result += retrieve_sheets(amount2sheet(M.amount), MAT)
return result
/datum/material_container/proc/has_space(amt = 0)
return (total_amount + amt) <= max_amount
/datum/material_container/proc/has_materials(list/mats, multiplier=1)
if(!mats || !mats.len)
return 0
var/datum/material/M
for(var/MAT in mats)
M = materials[MAT]
if(M.amount < (mats[MAT] * multiplier))
return 0
return 1
/datum/material_container/proc/amount2sheet(amt)
if(amt >= MINERAL_MATERIAL_AMOUNT)
return round(amt / MINERAL_MATERIAL_AMOUNT)
return 0
/datum/material_container/proc/sheet2amount(sheet_amt)
if(sheet_amt > 0)
return sheet_amt * MINERAL_MATERIAL_AMOUNT
return 0
/datum/material_container/proc/amount(id)
var/datum/material/M = materials[id]
return M ? M.amount : 0
//returns the amount of material relevant to this container;
//if this container does not support glass, any glass in 'I' will not be taken into account
/datum/material_container/proc/get_item_material_amount(obj/item/I)
if(!istype(I))
return 0
var/material_amount = 0
for(var/MAT in materials)
material_amount += I.materials[MAT]
return material_amount
/datum/material
var/name
var/amount = 0
var/id = null
var/sheet_type = null
/datum/material/metal
name = "Metal"
id = MAT_METAL
sheet_type = /obj/item/stack/sheet/metal
/datum/material/glass
name = "Glass"
id = MAT_GLASS
sheet_type = /obj/item/stack/sheet/glass
/datum/material/silver
name = "Silver"
id = MAT_SILVER
sheet_type = /obj/item/stack/sheet/mineral/silver
/datum/material/gold
name = "Gold"
id = MAT_GOLD
sheet_type = /obj/item/stack/sheet/mineral/gold
/datum/material/diamond
name = "Diamond"
id = MAT_DIAMOND
sheet_type = /obj/item/stack/sheet/mineral/diamond
/datum/material/uranium
name = "Uranium"
id = MAT_URANIUM
sheet_type = /obj/item/stack/sheet/mineral/uranium
/datum/material/plasma
name = "Solid Plasma"
id = MAT_PLASMA
sheet_type = /obj/item/stack/sheet/mineral/plasma
/datum/material/bananium
name = "Bananium"
id = MAT_BANANIUM
sheet_type = /obj/item/stack/sheet/mineral/bananium
+1789
View File
File diff suppressed because it is too large Load Diff
+642
View File
@@ -0,0 +1,642 @@
/var/global/list/mutations_list = list()
/datum/mutation/
var/name
/datum/mutation/New()
mutations_list[name] = src
/datum/mutation/human
var/dna_block
var/quality
var/get_chance = 100
var/lowest_value = 256 * 8
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
var/limb_req //required limbs to acquire this mutation
var/time_coeff = 1 //coefficient for timed mutations
/datum/mutation/human/proc/force_give(mob/living/carbon/human/owner)
set_block(owner)
. = on_acquiring(owner)
/datum/mutation/human/proc/force_lose(mob/living/carbon/human/owner)
set_block(owner, 0)
. = on_losing(owner)
/datum/mutation/human/proc/set_se(se_string, on = 1)
if(!se_string || lentext(se_string) < DNA_STRUC_ENZYMES_BLOCKS * DNA_BLOCK_SIZE)
return
var/before = copytext(se_string, 1, ((dna_block - 1) * DNA_BLOCK_SIZE) + 1)
var/injection = num2hex(on ? rand(lowest_value, (256 * 16) - 1) : rand(0, lowest_value - 1), DNA_BLOCK_SIZE)
var/after = copytext(se_string, (dna_block * DNA_BLOCK_SIZE) + 1, 0)
return before + injection + after
/datum/mutation/human/proc/set_block(mob/living/carbon/owner, on = 1)
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)
if(!se_string || lentext(se_string) < DNA_STRUC_ENZYMES_BLOCKS * DNA_BLOCK_SIZE)
return 0
if(hex2num(getblock(se_string, dna_block)) >= lowest_value)
return 1
/datum/mutation/human/proc/check_block(mob/living/carbon/human/owner)
if(check_block_string(owner.dna.struc_enzymes))
if(prob(get_chance))
. = on_acquiring(owner)
else
. = on_losing(owner)
/datum/mutation/human/proc/on_acquiring(mob/living/carbon/human/owner)
if(!owner || !istype(owner) || owner.stat == DEAD || (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
if(limb_req && !owner.get_bodypart(limb_req))
return 1
owner.dna.mutations.Add(src)
if(text_gain_indication)
owner << text_gain_indication
if(visual_indicators.len)
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/on_attack_hand(mob/living/carbon/human/owner, atom/target)
return
/datum/mutation/human/proc/on_ranged_attack(mob/living/carbon/human/owner, atom/target)
return
/datum/mutation/human/proc/on_move(mob/living/carbon/human/owner, new_loc)
return
/datum/mutation/human/proc/on_life(mob/living/carbon/human/owner)
return
/datum/mutation/human/proc/on_losing(mob/living/carbon/human/owner)
if(owner && istype(owner) && (owner.dna.mutations.Remove(src)))
if(text_lose_indication && owner.stat != DEAD)
owner << text_lose_indication
if(visual_indicators.len)
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
/datum/mutation/human/proc/say_mod(message)
if(message)
return message
/datum/mutation/human/proc/get_spans()
return list()
/datum/mutation/human/hulk
name = "Hulk"
quality = POSITIVE
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/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
var/status = CANSTUN | CANWEAKEN | CANPARALYSE | CANPUSH
owner.status_flags &= ~status
owner.update_body_parts()
/datum/mutation/human/hulk/on_attack_hand(mob/living/carbon/human/owner, atom/target)
return target.attack_hulk(owner)
/datum/mutation/human/hulk/on_life(mob/living/carbon/human/owner)
if(owner.health < 0)
on_losing(owner)
owner << "<span class='danger'>You suddenly feel very weak.</span>"
/datum/mutation/human/hulk/on_losing(mob/living/carbon/human/owner)
if(..())
return
owner.status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE | CANPUSH
owner.update_body_parts()
/datum/mutation/human/hulk/say_mod(message)
if(message)
message = "[uppertext(replacetext(message, ".", "!"))]!!"
return message
/datum/mutation/human/telekinesis
name = "Telekinesis"
quality = POSITIVE
get_chance = 20
lowest_value = 256 * 12
text_gain_indication = "<span class='notice'>You feel smarter!</span>"
limb_req = "head"
/datum/mutation/human/telekinesis/New()
..()
visual_indicators |= image("icon"='icons/effects/genetics.dmi', "icon_state"="telekinesishead_s", "layer"=-MUTATIONS_LAYER)
/datum/mutation/human/telekinesis/get_visual_indicator(mob/living/carbon/human/owner)
return visual_indicators[1]
/datum/mutation/human/telekinesis/on_ranged_attack(mob/living/carbon/human/owner, atom/target)
target.attack_tk(owner)
/datum/mutation/human/cold_resistance
name = "Cold Resistance"
quality = POSITIVE
get_chance = 25
lowest_value = 256 * 12
text_gain_indication = "<span class='notice'>Your body feels warm!</span>"
time_coeff = 5
/datum/mutation/human/cold_resistance/New()
..()
visual_indicators |= image("icon"='icons/effects/genetics.dmi', "icon_state"="fire_s", "layer"=-MUTATIONS_LAYER)
/datum/mutation/human/cold_resistance/get_visual_indicator(mob/living/carbon/human/owner)
return visual_indicators[1]
/datum/mutation/human/cold_resistance/on_life(mob/living/carbon/human/owner)
if(owner.getFireLoss())
if(prob(1))
owner.heal_organ_damage(0,1) //Is this really needed?
/datum/mutation/human/x_ray
name = "X Ray Vision"
quality = POSITIVE
get_chance = 25
lowest_value = 256 * 12
text_gain_indication = "<span class='notice'>The walls suddenly disappear!</span>"
time_coeff = 2
/datum/mutation/human/x_ray/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
owner.update_sight()
/datum/mutation/human/x_ray/on_losing(mob/living/carbon/human/owner)
if(..())
return
owner.update_sight()
/datum/mutation/human/nearsight
name = "Near Sightness"
quality = MINOR_NEGATIVE
text_gain_indication = "<span class='danger'>You can't see very well.</span>"
/datum/mutation/human/nearsight/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
owner.become_nearsighted()
/datum/mutation/human/nearsight/on_losing(mob/living/carbon/human/owner)
if(..())
return
owner.cure_nearsighted()
/datum/mutation/human/epilepsy
name = "Epilepsy"
quality = NEGATIVE
text_gain_indication = "<span class='danger'>You get a headache.</span>"
/datum/mutation/human/epilepsy/on_life(mob/living/carbon/human/owner)
if(prob(1) && !owner.paralysis)
owner.visible_message("<span class='danger'>[owner] starts having a seizure!</span>", "<span class='userdanger'>You have a seizure!</span>")
owner.Paralyse(10)
owner.Jitter(1000)
addtimer(src, "jitter_less", 90, FALSE, owner)
/datum/mutation/human/epilepsy/proc/jitter_less(mob/living/carbon/human/owner)
if(owner)
owner.jitteriness = 10
/datum/mutation/human/bad_dna
name = "Unstable DNA"
quality = NEGATIVE
text_gain_indication = "<span class='danger'>You feel strange.</span>"
/datum/mutation/human/bad_dna/on_acquiring(mob/living/carbon/human/owner)
owner << text_gain_indication
var/mob/new_mob
if(prob(95))
if(prob(50))
new_mob = randmutb(owner)
else
new_mob = randmuti(owner)
else
new_mob = randmutg(owner)
if(new_mob && ismob(new_mob))
owner = new_mob
. = owner
on_losing(owner)
/datum/mutation/human/cough
name = "Cough"
quality = MINOR_NEGATIVE
text_gain_indication = "<span class='danger'>You start coughing.</span>"
/datum/mutation/human/cough/on_life(mob/living/carbon/human/owner)
if((prob(5) && owner.paralysis <= 1))
owner.drop_item()
owner.emote("cough")
/datum/mutation/human/dwarfism
name = "Dwarfism"
quality = POSITIVE
get_chance = 15
lowest_value = 256 * 12
/datum/mutation/human/dwarfism/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
owner.resize = 0.8
owner.update_transform()
owner.pass_flags |= PASSTABLE
owner.visible_message("<span class='danger'>[owner] suddenly shrinks!</span>", "<span class='notice'>Everything around you seems to grow..</span>")
/datum/mutation/human/dwarfism/on_losing(mob/living/carbon/human/owner)
if(..())
return
owner.resize = 1.25
owner.update_transform()
owner.pass_flags &= ~PASSTABLE
owner.visible_message("<span class='danger'>[owner] suddenly grows!</span>", "<span class='notice'>Everything around you seems to shrink..</span>")
/datum/mutation/human/clumsy
name = "Clumsiness"
quality = MINOR_NEGATIVE
text_gain_indication = "<span class='danger'>You feel lightheaded.</span>"
/datum/mutation/human/clumsy/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
owner.disabilities |= CLUMSY
/datum/mutation/human/clumsy/on_losing(mob/living/carbon/human/owner)
if(..())
return
owner.disabilities &= ~CLUMSY
/datum/mutation/human/tourettes
name = "Tourettes Syndrome"
quality = NEGATIVE
text_gain_indication = "<span class='danger'>You twitch.</span>"
/datum/mutation/human/tourettes/on_life(mob/living/carbon/human/owner)
if((prob(10) && owner.paralysis <= 1))
owner.Stun(10)
switch(rand(1, 3))
if(1)
owner.emote("twitch")
if(2 to 3)
owner.say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]")
var/x_offset_old = owner.pixel_x
var/y_offset_old = owner.pixel_y
var/x_offset = owner.pixel_x + rand(-2,2)
var/y_offset = owner.pixel_y + rand(-1,1)
animate(owner, pixel_x = x_offset, pixel_y = y_offset, time = 1)
animate(owner, pixel_x = x_offset_old, pixel_y = y_offset_old, time = 1)
/datum/mutation/human/nervousness
name = "Nervousness"
quality = MINOR_NEGATIVE
text_gain_indication = "<span class='danger'>You feel nervous.</span>"
/datum/mutation/human/nervousness/on_life(mob/living/carbon/human/owner)
if(prob(10))
owner.stuttering = max(10, owner.stuttering)
/datum/mutation/human/deaf
name = "Deafness"
quality = NEGATIVE
text_gain_indication = "<span class='danger'>You can't seem to hear anything.</span>"
/datum/mutation/human/deaf/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
owner.disabilities |= DEAF
/datum/mutation/human/deaf/on_losing(mob/living/carbon/human/owner)
if(..())
return
owner.disabilities &= ~DEAF
/datum/mutation/human/blind
name = "Blindness"
quality = NEGATIVE
text_gain_indication = "<span class='danger'>You can't seem to see anything.</span>"
/datum/mutation/human/blind/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
owner.become_blind()
/datum/mutation/human/blind/on_losing(mob/living/carbon/human/owner)
if(..())
return
owner.cure_blind()
/datum/mutation/human/race
name = "Monkified"
quality = NEGATIVE
time_coeff = 2
/datum/mutation/human/race/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
. = owner.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
/datum/mutation/human/race/on_losing(mob/living/carbon/monkey/owner)
if(owner && istype(owner) && owner.stat != DEAD && (owner.dna.mutations.Remove(src)))
. = owner.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
/datum/mutation/human/chameleon
name = "Chameleon"
quality = POSITIVE
get_chance = 20
lowest_value = 256 * 12
text_gain_indication = "<span class='notice'>You feel one with your surroundings.</span>"
text_lose_indication = "<span class='notice'>You feel oddly exposed.</span>"
time_coeff = 5
/datum/mutation/human/chameleon/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
owner.alpha = CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY
/datum/mutation/human/chameleon/on_life(mob/living/carbon/human/owner)
owner.alpha = max(0, owner.alpha - 25)
/datum/mutation/human/chameleon/on_move(mob/living/carbon/human/owner)
owner.alpha = CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY
/datum/mutation/human/chameleon/on_losing(mob/living/carbon/human/owner)
if(..())
return
owner.alpha = 255
/datum/mutation/human/wacky
name = "Wacky"
quality = MINOR_NEGATIVE
text_gain_indication = "<span class='sans'>You feel an off sensation in your voicebox.</span>"
text_lose_indication = "<span class='notice'>The off sensation passes.</span>"
/datum/mutation/human/wacky/get_spans()
return list(SPAN_SANS)
/datum/mutation/human/mute
name = "Mute"
quality = NEGATIVE
text_gain_indication = "<span class='danger'>You feel unable to express yourself at all.</span>"
text_lose_indication = "<span class='danger'>You feel able to speak freely again.</span>"
/datum/mutation/human/mute/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
owner.disabilities |= MUTE
/datum/mutation/human/mute/on_losing(mob/living/carbon/human/owner)
if(..())
return
owner.disabilities &= ~MUTE
/datum/mutation/human/smile
name = "Smile"
quality = MINOR_NEGATIVE
dna_block = NON_SCANNABLE
text_gain_indication = "<span class='notice'>You feel so happy. Nothing can be wrong with anything. :)</span>"
text_lose_indication = "<span class='notice'>Everything is terrible again. :(</span>"
/datum/mutation/human/smile/say_mod(message)
if(message)
message = " [message] "
//Time for a friendly game of SS13
message = replacetext(message," stupid "," smart ")
message = replacetext(message," retard "," genius ")
message = replacetext(message," unrobust "," robust ")
message = replacetext(message," dumb "," smart ")
message = replacetext(message," awful "," great ")
message = replacetext(message," gay ",pick(" nice "," ok "," alright "))
message = replacetext(message," horrible "," fun ")
message = replacetext(message," terrible "," terribly fun ")
message = replacetext(message," terrifying "," wonderful ")
message = replacetext(message," gross "," cool ")
message = replacetext(message," disgusting "," amazing ")
message = replacetext(message," loser "," winner ")
message = replacetext(message," useless "," useful ")
message = replacetext(message," oh god "," cheese and crackers ")
message = replacetext(message," jesus "," gee wiz ")
message = replacetext(message," weak "," strong ")
message = replacetext(message," kill "," hug ")
message = replacetext(message," murder "," tease ")
message = replacetext(message," ugly "," beautiful ")
message = replacetext(message," douchbag "," nice guy ")
message = replacetext(message," whore "," lady ")
message = replacetext(message," nerd "," smart guy ")
message = replacetext(message," moron "," fun person ")
message = replacetext(message," IT'S LOOSE "," EVERYTHING IS FINE ")
message = replacetext(message," sex "," hug fight ")
message = replacetext(message," idiot "," genius ")
message = replacetext(message," fat "," thin ")
message = replacetext(message," beer "," water with ice ")
message = replacetext(message," drink "," water ")
message = replacetext(message," feminist "," empowered woman ")
message = replacetext(message," i hate you "," you're mean ")
message = replacetext(message," nigger "," african american ")
message = replacetext(message," jew "," jewish ")
message = replacetext(message," shit "," shiz ")
message = replacetext(message," crap "," poo ")
message = replacetext(message," slut "," tease ")
message = replacetext(message," ass "," butt ")
message = replacetext(message," damn "," dang ")
message = replacetext(message," fuck "," ")
message = replacetext(message," penis "," privates ")
message = replacetext(message," cunt "," privates ")
message = replacetext(message," dick "," jerk ")
message = replacetext(message," vagina "," privates ")
return trim(message)
/datum/mutation/human/unintelligable
name = "Unintelligable"
quality = NEGATIVE
text_gain_indication = "<span class='danger'>You can't seem to form any coherent thoughts!</span>"
text_lose_indication = "<span class='danger'>Your mind feels more clear.</span>"
/datum/mutation/human/unintelligable/say_mod(message)
if(message)
var/prefix=copytext(message,1,2)
if(prefix == ";")
message = copytext(message,2)
else if(prefix in list(":","#"))
prefix += copytext(message,2,3)
message = copytext(message,3)
else
prefix=""
var/list/words = splittext(message," ")
var/list/rearranged = list()
for(var/i=1;i<=words.len;i++)
var/cword = pick(words)
words.Remove(cword)
var/suffix = copytext(cword,length(cword)-1,length(cword))
while(length(cword)>0 && suffix in list(".",",",";","!",":","?"))
cword = copytext(cword,1 ,length(cword)-1)
suffix = copytext(cword,length(cword)-1,length(cword) )
if(length(cword))
rearranged += cword
message = "[prefix][uppertext(jointext(rearranged," "))]!!"
return message
/datum/mutation/human/swedish
name = "Swedish"
quality = MINOR_NEGATIVE
dna_block = NON_SCANNABLE
text_gain_indication = "<span class='notice'>You feel Swedish, however that works.</span>"
text_lose_indication = "<span class='notice'>The feeling of Swedishness passes.</span>"
/datum/mutation/human/swedish/say_mod(message)
if(message)
message = replacetext(message,"w","v")
if(prob(30))
message += " Bork[pick("",", bork",", bork, bork")]!"
return message
/datum/mutation/human/chav
name = "Chav"
quality = MINOR_NEGATIVE
dna_block = NON_SCANNABLE
text_gain_indication = "<span class='notice'>Ye feel like a reet prat like, innit?</span>"
text_lose_indication = "<span class='notice'>You no longer feel like being rude and sassy.</span>"
/datum/mutation/human/chav/say_mod(message)
if(message)
message = " [message] "
message = replacetext(message," looking at "," gawpin' at ")
message = replacetext(message," great "," bangin' ")
message = replacetext(message," man "," mate ")
message = replacetext(message," friend ",pick(" mate "," bruv "," bledrin "))
message = replacetext(message," what "," wot ")
message = replacetext(message," drink "," wet ")
message = replacetext(message," get "," giz ")
message = replacetext(message," what "," wot ")
message = replacetext(message," no thanks "," wuddent fukken do one ")
message = replacetext(message," i don't know "," wot mate ")
message = replacetext(message," no "," naw ")
message = replacetext(message," robust "," chin ")
message = replacetext(message," hi "," how what how ")
message = replacetext(message," hello "," sup bruv ")
message = replacetext(message," kill "," bang ")
message = replacetext(message," murder "," bang ")
message = replacetext(message," windows "," windies ")
message = replacetext(message," window "," windy ")
message = replacetext(message," break "," do ")
message = replacetext(message," your "," yer ")
message = replacetext(message," security "," coppers ")
return trim(message)
/datum/mutation/human/elvis
name = "Elvis"
quality = MINOR_NEGATIVE
dna_block = NON_SCANNABLE
text_gain_indication = "<span class='notice'>You feel pretty good, honeydoll.</span>"
text_lose_indication = "<span class='notice'>You feel a little less conversation would be great.</span>"
/datum/mutation/human/elvis/on_life(mob/living/carbon/human/owner)
switch(pick(1,2))
if(1)
if(prob(15))
var/list/dancetypes = list("swinging", "fancy", "stylish", "20'th century", "jivin'", "rock and roller", "cool", "salacious", "bashing", "smashing")
var/dancemoves = pick(dancetypes)
owner.visible_message("<b>[owner]</b> busts out some [dancemoves] moves!")
if(2)
if(prob(15))
owner.visible_message("<b>[owner]</b> [pick("jiggles their hips", "rotates their hips", "gyrates their hips", "taps their foot", "dances to an imaginary song", "jiggles their legs", "snaps their fingers")]!")
/datum/mutation/human/elvis/say_mod(message)
if(message)
message = " [message] "
message = replacetext(message," i'm not "," I aint ")
message = replacetext(message," girl ",pick(" honey "," baby "," baby doll "))
message = replacetext(message," man ",pick(" son "," buddy "," brother"," pal "," friendo "))
message = replacetext(message," out of "," outta ")
message = replacetext(message," thank you "," thank you, thank you very much ")
message = replacetext(message," what are you "," whatcha ")
message = replacetext(message," yes ",pick(" sure", "yea "))
message = replacetext(message," faggot "," square ")
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
limb_req = "head"
/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/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(!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)
+75
View File
@@ -0,0 +1,75 @@
/datum/outfit
var/name = "Naked"
var/uniform = null
var/suit = null
var/back = null
var/belt = null
var/gloves = null
var/shoes = null
var/head = null
var/mask = null
var/ears = null
var/glasses = null
var/id = null
var/l_pocket = null
var/r_pocket = null
var/suit_store = null
var/r_hand = null
var/l_hand = null
var/list/backpack_contents = list() // In the list(path=count,otherpath=count) format
/datum/outfit/proc/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
//to be overriden for customization depending on client prefs,species etc
return
/datum/outfit/proc/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
//to be overriden for toggling internals, id binding, access etc
return
/datum/outfit/proc/equip(mob/living/carbon/human/H, visualsOnly = FALSE)
pre_equip(H, visualsOnly)
//Start with uniform,suit,backpack for additional slots
if(uniform)
H.equip_to_slot_or_del(new uniform(H),slot_w_uniform)
if(suit)
H.equip_to_slot_or_del(new suit(H),slot_wear_suit)
if(back)
H.equip_to_slot_or_del(new back(H),slot_back)
if(belt)
H.equip_to_slot_or_del(new belt(H),slot_belt)
if(gloves)
H.equip_to_slot_or_del(new gloves(H),slot_gloves)
if(shoes)
H.equip_to_slot_or_del(new shoes(H),slot_shoes)
if(head)
H.equip_to_slot_or_del(new head(H),slot_head)
if(mask)
H.equip_to_slot_or_del(new mask(H),slot_wear_mask)
if(ears)
H.equip_to_slot_or_del(new ears(H),slot_ears)
if(glasses)
H.equip_to_slot_or_del(new glasses(H),slot_glasses)
if(id)
H.equip_to_slot_or_del(new id(H),slot_wear_id)
if(l_pocket)
H.equip_to_slot_or_del(new l_pocket(H),slot_l_store)
if(r_pocket)
H.equip_to_slot_or_del(new r_pocket(H),slot_r_store)
if(suit_store)
H.equip_to_slot_or_del(new suit_store(H),slot_s_store)
if(l_hand)
H.put_in_l_hand(new l_hand(H))
if(r_hand)
H.put_in_r_hand(new r_hand(H))
for(var/path in backpack_contents)
var/number = backpack_contents[path]
for(var/i=0,i<number,i++)
H.equip_to_slot_or_del(new path(H),slot_in_backpack)
post_equip(H, visualsOnly)
return 1
+42
View File
@@ -0,0 +1,42 @@
/datum/progressbar
var/goal = 1
var/image/bar
var/shown = 0
var/mob/user
var/client/client
/datum/progressbar/New(mob/User, goal_number, atom/target)
. = ..()
if (!istype(target))
EXCEPTION("Invalid target given")
if (goal_number)
goal = goal_number
bar = image('icons/effects/progessbar.dmi', target, "prog_bar_0")
bar.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
bar.pixel_y = 32
user = User
if(user)
client = user.client
/datum/progressbar/proc/update(progress)
//world << "Update [progress] - [goal] - [(progress / goal)] - [((progress / goal) * 100)] - [round(((progress / goal) * 100), 5)]"
if (!user || !user.client)
shown = 0
return
if (user.client != client)
if (client)
client.images -= bar
if (user.client)
user.client.images += bar
progress = Clamp(progress, 0, goal)
bar.icon_state = "prog_bar_[round(((progress / goal) * 100), 5)]"
if (!shown)
user.client.images += bar
shown = 1
/datum/progressbar/Destroy()
if (client)
client.images -= bar
qdel(bar)
. = ..()
+120
View File
@@ -0,0 +1,120 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * *
* /datum/recipe by rastaf0 13 apr 2011 *
* * * * * * * * * * * * * * * * * * * * * * * * * *
* This is powerful and flexible recipe system.
* It exists not only for food.
* supports both reagents and objects as prerequisites.
* In order to use this system you have to define a deriative from /datum/recipe
* * reagents are reagents. Acid, milc, booze, etc.
* * items are objects. Fruits, tools, circuit boards.
* * result is type to create as new object
* * time is optional parameter, you shall use in in your machine,
default /datum/recipe/ procs does not rely on this parameter.
*
* Functions you need:
* /datum/recipe/proc/make(var/obj/container as obj)
* Creates result inside container,
* deletes prerequisite reagents,
* transfers reagents from prerequisite objects,
* deletes all prerequisite objects (even not needed for recipe at the moment).
*
* /proc/select_recipe(list/datum/recipe/avaiable_recipes, obj/obj as obj, exact = 1)
* Wonderful function that select suitable recipe for you.
* obj is a machine (or magik hat) with prerequisites,
* exact = 0 forces algorithm to ignore superfluous stuff.
*
*
* Functions you do not need to call directly but could:
* /datum/recipe/proc/check_reagents(var/datum/reagents/avail_reagents)
* //1=precisely, 0=insufficiently, -1=superfluous
*
* /datum/recipe/proc/check_items(var/obj/container as obj)
* //1=precisely, 0=insufficiently, -1=superfluous
*
* */
/datum/recipe
var/list/reagents // example: = list("berryjuice" = 5) // do not list same reagent twice
var/list/items // example: =list(/obj/item/weapon/crowbar, /obj/item/weapon/welder) // place /foo/bar before /foo
var/result //example: = /obj/item/weapon/reagent_containers/food/snacks/donut
var/time = 100 // 1/10 part of second
/datum/recipe/proc/check_reagents(datum/reagents/avail_reagents) //1=precisely, 0=insufficiently, -1=superfluous
. = 1
for (var/r_r in reagents)
var/aval_r_amnt = avail_reagents.get_reagent_amount(r_r)
if (!(abs(aval_r_amnt - reagents[r_r])<0.5)) //if NOT equals
if (aval_r_amnt>reagents[r_r])
. = -1
else
return 0
if ((reagents?(reagents.len):(0)) < avail_reagents.reagent_list.len)
return -1
return .
/datum/recipe/proc/check_items(obj/container) //1=precisely, 0=insufficiently, -1=superfluous
if (!items)
if (locate(/obj/) in container)
return -1
else
return 1
. = 1
var/list/checklist = items.Copy()
for (var/obj/O in container)
var/found = 0
for (var/type in checklist)
if (istype(O,type))
checklist-=type
found = 1
break
if (!found)
. = -1
if (checklist.len)
return 0
return .
//general version
/datum/recipe/proc/make(obj/container)
var/obj/result_obj = new result(container)
for (var/obj/O in (container.contents-result_obj))
O.reagents.trans_to(result_obj, O.reagents.total_volume)
qdel(O)
container.reagents.clear_reagents()
return result_obj
// food-related
/datum/recipe/proc/make_food(obj/container)
var/obj/result_obj = new result(container)
for (var/obj/O in (container.contents-result_obj))
if (O.reagents)
O.reagents.del_reagent("nutriment")
O.reagents.update_total()
O.reagents.trans_to(result_obj, O.reagents.total_volume)
qdel(O)
container.reagents.clear_reagents()
return result_obj
/proc/select_recipe(list/datum/recipe/avaiable_recipes, obj/obj, exact = 1 as num)
if (!exact)
exact = -1
var/list/datum/recipe/possible_recipes = new
for (var/datum/recipe/recipe in avaiable_recipes)
if (recipe.check_reagents(obj.reagents)==exact && recipe.check_items(obj)==exact)
possible_recipes+=recipe
if (possible_recipes.len==0)
return null
else if (possible_recipes.len==1)
return possible_recipes[1]
else //okay, let's select the most complicated recipe
var/r_count = 0
var/i_count = 0
. = possible_recipes[1]
for (var/datum/recipe/recipe in possible_recipes)
var/N_i = (recipe.items)?(recipe.items.len):0
var/N_r = (recipe.reagents)?(recipe.reagents.len):0
if (N_i > i_count || (N_i== i_count && N_r > r_count ))
r_count = N_r
i_count = N_i
. = recipe
return .
+22
View File
@@ -0,0 +1,22 @@
/datum/map_template/ruin
//name = "A Chest of Doubloons"
name = null
var/id = null // For blacklisting purposes, all ruins need an id
var/description = "In the middle of a clearing in the rockface, there's a \
chest filled with gold coins with Spanish engravings. How is there a \
wooden container filled with 18th century coinage in the middle of a \
lavawracked hellscape? It is clearly a mystery."
var/cost = null
var/allow_duplicates = TRUE
var/prefix = null
var/suffix = null
/datum/map_template/ruin/New()
if(!name && id)
name = id
mappath = prefix + suffix
..(path = mappath)
+218
View File
@@ -0,0 +1,218 @@
/datum/map_template/ruin/lavaland
prefix = "_maps/RandomRuins/LavaRuins/"
/datum/map_template/ruin/lavaland/biodome
cost = 5
allow_duplicates = FALSE
/datum/map_template/ruin/lavaland/biodome/beach
name = "Biodome Beach"
id = "biodome-beach"
description = "Seemingly plucked from a tropical destination, this beach \
is calm and cool, with the salty waves roaring softly in the \
background. Comes with a rustic wooden bar and suicidal bartender."
suffix = "lavaland_biodome_beach.dmm"
/datum/map_template/ruin/lavaland/biodome/winter
name = "Biodome Winter"
id = "biodome-winter"
description = "For those getaways where you want to get back to nature, \
but you don't want to leave the fortified military compound where you \
spend your days. Includes a unique(*) laser pistol display case, \
and the recently introduced I.C.E(tm)."
suffix = "lavaland_surface_biodome_winter.dmm"
/datum/map_template/ruin/lavaland/biodome/clown
name = "Biodome Clown Planet"
id = "biodome-clown"
description = "WELCOME TO CLOWN PLANET! HONK HONK HONK etc.!"
suffix = "lavaland_biodome_clown_planet.dmm"
/datum/map_template/ruin/lavaland/cube
name = "The Wishgranter Cube"
id = "wishgranter-cube"
description = "Nothing good can come from this. Learn from their mistakes \
and turn around."
suffix = "lavaland_surface_cube.dmm"
cost = 10
allow_duplicates = FALSE
/datum/map_template/ruin/lavaland/prisoners
name = "Prisoner Crash"
id = "prisoner-crash"
description = "This incredibly high security shuttle clearly didn't have \
'avoiding lavafilled hellscapes' as a design priority. As such, it \
has crashed, waking the prisoners from their cryostasis, and setting \
them loose on the wastes. If they live long enough, that is."
suffix = "lavaland_surface_prisoner_crash.dmm"
cost = 15
allow_duplicates = FALSE
/datum/map_template/ruin/lavaland/seed_vault
name = "Seed Vault"
id = "seed-vault"
description = "The creators of these vaults were a highly advanced and \
benevolent race, and launched many into the stars, hoping to aid \
fledgling civilizations. However, all the inhabitants seem to do is \
grow drugs and guns."
suffix = "lavaland_surface_seed_vault.dmm"
cost = 10
/datum/map_template/ruin/lavaland/ash_walker
name = "Ash Walker Nest"
id = "ash-walker"
description = "A race of unbreathing lizards live here, that run faster \
than a human can, worship a broken dead city, and are capable of \
reproducing by something involving tentacles? Probably best to \
stay clear."
suffix = "lavaland_surface_ash_walker1.dmm"
cost = 20
allow_duplicates = FALSE
/datum/map_template/ruin/lavaland/free_golem
name = "Free Golem Ship"
id = "golem-ship"
description = "Lumbering humanoids, made out of precious metals, move \
inside this ship. They frequently leave to mine more minerals, \
which they somehow turn into more of them. Seem very intent on \
research and individual liberty, and also geology based naming?"
cost = 20
suffix = "lavaland_surface_golem_ship.dmm"
allow_duplicates = FALSE
/datum/map_template/ruin/lavaland/animal_hospital
name = "Animal Hospital"
id = "animal-hospital"
description = "Rats with cancer do not live very long. And the ones that \
wake up from cryostasis seem to commit suicide out of boredom."
cost = 5
suffix = "lavaland_surface_animal_hospital.dmm"
allow_duplicates = FALSE
/datum/map_template/ruin/lavaland/sin
cost = 10
/datum/map_template/ruin/lavaland/sin/envy
name = "Ruin of Envy"
id = "envy"
description = "When you get what they have, then you'll finally be happy."
suffix = "lavaland_surface_envy.dmm"
/datum/map_template/ruin/lavaland/sin/gluttony
name = "Ruin of Gluttony"
id = "gluttony"
description = "If you eat enough, then eating will be all that you do."
suffix = "lavaland_surface_gluttony.dmm"
/datum/map_template/ruin/lavaland/sin/greed
name = "Ruin of Greed"
id = "greed"
description = "Sure you don't need magical powers, but you WANT them, and \
that's what's important."
suffix = "lavaland_surface_greed.dmm"
/datum/map_template/ruin/lavaland/sin/pride
name = "Ruin of Pride"
id = "pride"
description = "Wormhole lifebelts are for LOSERS, who you are better than."
suffix = "lavaland_surface_pride.dmm"
/datum/map_template/ruin/lavaland/sin/sloth
name = "Ruin of Sloth"
id = "sloth"
description = "..."
suffix = "lavaland_surface_sloth.dmm"
// Generates nothing but atmos runtimes and salt
cost = 0
allow_duplicates = FALSE
/datum/map_template/ruin/lavaland/ato
name = "Automated Trade Outpost"
id = "ato"
description = "A sign at the front says 'Stealing is bad.'"
suffix = "lavaland_surface_automated_trade_outpost.dmm"
cost = 5
/datum/map_template/ruin/lavaland/ufo_crash
name = "UFO Crash"
id = "ufo-crash"
description = "Turns out that keeping your abductees unconcious is really \
important. Who knew?"
suffix = "lavaland_surface_ufo_crash.dmm"
cost = 5
/datum/map_template/ruin/lavaland/ww_vault
name = "Wishgranter Vault"
id = "ww-vault"
description = "Scrawled on the large double doors is both a message and a \
warning: 'meat grinder requires sacri...'. You're not so sure about \
this anymore."
suffix = "lavaland_surface_ww_vault.dmm"
cost = 20
/datum/map_template/ruin/lavaland/xeno_nest
name = "Xenomorph Nest"
id = "xeno-nest"
description = "These xenomorphs got bored of horrifically slaughtering \
people on space stations, and have settled down on a nice lava filled \
hellscape to focus on what's really important in life. Quality memes."
suffix = "lavaland_surface_xeno_nest.dmm"
cost = 20
/datum/map_template/ruin/lavaland/fountain
name = "Fountain Hall"
id = "fountain"
description = "The fountain has a warning on the side. DANGER: May have \
undeclared side effects that only become obvious when implemented."
suffix = "lavaland_surface_fountain_hall.dmm"
cost = 5
/datum/map_template/ruin/lavaland/survivalcapsule
name = "Survival Capsule Ruins"
id = "survivalcapsule"
description = "What was once sanctuary to the common miner, \
is now their tomb."
suffix = "lavaland_surface_survivalpod.dmm"
cost = 5
/datum/map_template/ruin/lavaland/tomb
name = "Strange Outpost"
id = "tomb"
description = "A strange tomb, housing the dead of whatever strange civilization \
lived here before. You swear you hear rattling coming from the inside."
suffix = "lavaland_surface_tomb.dmm"
cost = 10
/datum/map_template/ruin/lavaland/pizza
name = "Ruined Pizza Party"
id = "pizza"
description = "Little Timmy's birthday pizza-bash took a turn for the worse \
when a bluespace anomaly passed by."
suffix = "lavaland_surface_pizzaparty.dmm"
allow_duplicates = FALSE
cost = 5
/datum/map_template/ruin/lavaland/cultaltar
name = "Summoning Ritual"
id = "cultaltar"
description = "A place of vile worship, the scrawling of blood in the middle glowing eerily.\
A demonic laugh echoes throughout the caverns"
suffix = "lavaland_surface_cultaltar.dmm"
allow_duplicates = FALSE
cost = 10
/datum/map_template/ruin/lavaland/hermit
name = "Makeshift Shelter"
id = "hermitcave"
description = "A place of shelter for a lone hermit, scraping by to live another day."
suffix = "lavaland_surface_hermit.dmm"
allow_duplicates = FALSE
cost = 10
/datum/map_template/ruin/lavaland/cult_shuttle
name = "Crashed Cult Hive"
id = "cultshuttle"
description = "A once-bustling home for zealots of the blood-worshiping type. Turns out practicing \
dark rituals mid-jump isn't the best idea."
suffix = "lavaland_surface_cultcrash.dmm"
cost = 10
+248
View File
@@ -0,0 +1,248 @@
/datum/map_template/ruin/space
prefix = "_maps/RandomRuins/SpaceRuins/"
cost = 1
allow_duplicates = FALSE
/datum/map_template/ruin/space/zoo
id = "zoo"
suffix = "abandonedzoo.dmm"
name = "Biological Storage Facility"
description = "In case society crumbles, we will be able to restore our \
zoos to working order with the breeding stock kept in these 100% \
secure and unbreachable storage facilities. At no point has anything \
escaped. That's our story, and we're sticking to it."
/datum/map_template/ruin/space/asteroid1
id = "asteroid1"
suffix = "asteroid1.dmm"
name = "Asteroid 1"
description = "I-spy with my little eye, something beginning with R."
/datum/map_template/ruin/space/asteroid2
id = "asteroid2"
suffix = "asteroid2.dmm"
name = "Asteroid 2"
description = "Oh my god, a giant rock!"
/datum/map_template/ruin/space/asteroid3
id = "asteroid3"
suffix = "asteroid3.dmm"
name = "Asteroid 3"
description = "This asteroid floating in space has no official \
designation, because the scientist that discovered it deemed it \
'super dull'."
/datum/map_template/ruin/space/asteroid4
id = "asteroid4"
suffix = "asteroid4.dmm"
name = "Asteroid 4"
description = "Nanotrasen Escape Pods have a 100%* success rate, and a \
99%* customer satisfaction rate. *Please note that these statistics, \
are taken from pods that have successfully docked with a recovery \
vessel."
/datum/map_template/ruin/space/asteroid5
id = "asteroid5"
suffix = "asteroid5.dmm"
name = "Asteroid 5"
description = "Oh my god, another giant rock!"
/datum/map_template/ruin/space/deep_storage
id = "deep-storage"
suffix = "deepstorage.dmm"
name = "Survivalist Bunker"
description = "Assume the best, prepare for the worst. Generally, you \
should do so by digging a three man heavily fortified bunker into \
a giant unused asteroid. Then make it self sufficient, mask any \
evidence of construction, hook it covertly into the \
telecommunications network and hope for the best."
/datum/map_template/ruin/space/derelict1
id = "derelict1"
suffix = "derelict1.dmm"
name = "Derelict 1"
description = "Nothing to see here citizen, move along, certainly no \
xeno outbreaks on this piece of station debris. That purple stuff? \
It's uh... station nectar. It's a top secret research installation."
/datum/map_template/ruin/space/derelict2
id = "derelict2"
suffix = "derelict2.dmm"
name = "Dinner for Two"
description = "Oh this is the night\n\
It's a beautiful night\n\
And we call it bella notte"
/datum/map_template/ruin/space/derelict3
id = "derelict3"
suffix = "derelict3.dmm"
name = "Derelict 3"
description = "These hulks were once part of a larger structure, where \
the three great \[REDACTED\] were forged."
/datum/map_template/ruin/space/derelict4
id = "derelict4"
suffix = "derelict4.dmm"
name = "Derelict 4"
description = "Centcom ferries have never crashed, will never crash, \
there is no current investigation into a crashed ferry, and we \
will not let Internal Affairs trample over high security information \
in the name of this baseless witchhunt."
/datum/map_template/ruin/space/derelict5
id = "derelict5"
suffix = "derelict5.dmm"
name = "Derelict 5"
description = "The plan is, we put a whole bunch of crates full of \
treasure in this disused warehouse, launch it into space, and then \
ignore it. Forever."
/datum/map_template/ruin/space/derelict6
id = "derelict6"
suffix = "derelict6.dmm"
name = "Derelict 6"
description = "The hush-hush of Nanotrasen when it comes to stations seemingly vanishing off the radar is an interesting topic, \
theories of nuclear destruction float about while Nanotrasen flat-out denies said stations ever existing."
/datum/map_template/ruin/space/empty_shell
id = "empty-shell"
suffix = "emptyshell.dmm"
name = "Empty Shell"
description = "Cosy, rural property availible for young professional \
couple. Only twelve parsecs from the nearest hyperspace lane!"
/datum/map_template/ruin/space/gas_the_lizards
id = "gas-the-lizards"
suffix = "gasthelizards.dmm"
name = "Disposal Facility 17"
description = "Gas efficiency at 95.6%, fluid elimination at 96.2%. \
Will require renewed supplies of 'carpet' before the end of the \
quarter."
/datum/map_template/ruin/space/intact_empty_ship
id = "intact-empty-ship"
suffix = "intactemptyship.dmm"
name = "Authorship"
description = "Just somewhere quiet, where I can focus on my work with \
no interruptions."
/datum/map_template/ruin/space/mech_transport
id = "mech-transport"
suffix = "mechtransport.dmm"
name = "CF Corsair"
description = "Well, when is it getting here? I have bills to pay; very \
well-armed clients who want their shipments as soon as possible! I \
don't care, just find it!"
/datum/map_template/ruin/space/onehalf
id = "onehalf"
suffix = "onehalf.dmm"
name = "DK Excavator 453"
description = "Based on the trace elements we've detected on the \
gutted asteroids, we suspect that a mining ship using a restricted \
engine is somewhere in the area. We'd like to request a patrol vessel \
to investigate."
/datum/map_template/ruin/space/spacebar
id = "spacebar"
suffix = "spacebar.dmm"
name = "The Rampant Golem and Yellow Hound"
description = "No questions asked. No shoes/foot protection, no service. \
No tabs. No violence in the inside areas. That's it. Welcome to the \
Rampant Golem and Yellow Hound. Can I take your order?"
/datum/map_template/ruin/space/turreted_outpost
id = "turreted-outpost"
suffix = "turretedoutpost.dmm"
name = "Unnamed Turreted Outpost"
description = "We'd ask them to stop blaring that ruskiepop music, but \
none of us are brave enough to go near those death turrets they have."
/datum/map_template/ruin/space/way_home
id = "way-home"
suffix = "way_home.dmm"
name = "Salvation"
description = "In the darkest times, we will find our way home."
/datum/map_template/ruin/space/djstation
id = "djstation"
suffix = "djstation.dmm"
name = "DJ Station"
description = "Until very recently this pirate radio station was used \
to harangue local space stations over a variety of perceived \
\"ethics violations\". It seems like someone finally got sick of \
it, but the equipment still works."
/datum/map_template/ruin/space/thederelict
id = "thederelict"
suffix = "thederelict.dmm"
name = "Kosmicheskaya Stantsiya 13"
description = "The true fate of Kosmicheskaya Stantsiya 13 is an open \
question to this day. Most corporations deny its existence, \
for fear of questioning on what became of its crew."
/datum/map_template/ruin/space/abandonedteleporter
id = "abandonedteleporter"
suffix = "abandonedteleporter.dmm"
name = "Abandoned Teleporter"
description = "In space construction the teleporter is often the \
first system brought online. This lonely half built teleporter \
is a sign of a proposed structure that for one reason or another \
just never got built."
/datum/map_template/ruin/space/crashedclownship
id = "crashedclownship"
suffix = "crashedclownship.dmm"
name = "Crashed Clown Ship"
description = "For centuries the promise of a new clown homeworld \
has been the siren call for countless clown vessels. Alas the \
clown's lust for shinanagans means that successful voyages \
are almost unheard of, with most vessels falling to hilarious \
consequences almost immediately."
/datum/map_template/ruin/space/crashedship
id = "crashedship"
suffix = "crashedship.dmm"
name = "Crashed Ship"
description = "Among civilian vessels the most common cause of \
tragedy is lack of food. This ship was outfited with a \
multitude of food generating features, then summarily ran \
into an asteroid shortly after takeoff."
/datum/map_template/ruin/space/listeningstation
id = "listeningstation"
suffix = "listeningstation.dmm"
name = "Syndicate Listening Station"
description = "Listening stations form the backbone of the \
syndicate's information gathering operations. Assignment to \
these stations is dreaded by most agents, as it entails long \
and lonely shifts listening to nearby stations chatter \
incessently about the most meaningless things."
/datum/map_template/ruin/space/oldAIsat
id = "oldAIsat"
suffix = "oldAIsat.dmm"
name = "Abandoned Telecommunications Satellite"
description = "When the inspector told the employees that they \
were all fired, and that their jobs \"could be done by \
trained lizards anyway\", they reacted badly. This event and \
others is the reason why Central always sends an ERT squad with \
their competent inspectors. Incompetent inspectors are told \
they can \"do it alone\" because they're \"that pro\". \
Incompetent inspectors believe this."
/datum/map_template/ruin/space/oldteleporter
id = "oldteleporter"
suffix = "oldteleporter.dmm"
name = "Detached Teleporter"
description = "The structure of this surprisingly intact \
teleporter suggests that it was once part of a larger structure, \
but what remains of said structure, if anything, can \
only be guessed at."
/datum/map_template/ruin/space/puzzle1
id = "puzzle1"
suffix = "puzzle1.dmm"
name = "Strange Structure"
description = "A strange, free-floating structure that has been aimlessly drifting through the void \
of space for who knows how long. Seems like whatever built it was really bored."
+203
View File
@@ -0,0 +1,203 @@
/datum/map_template/shuttle
name = "Base Shuttle Template"
var/prefix = "_maps/shuttles/"
var/suffix
var/port_id
var/shuttle_id
var/description
var/admin_notes
/datum/map_template/shuttle/New()
shuttle_id = "[port_id]_[suffix]"
mappath = "[prefix][shuttle_id].dmm"
. = ..()
/datum/map_template/shuttle/emergency
port_id = "emergency"
name = "Base Shuttle Template (Emergency)"
/datum/map_template/shuttle/cargo
port_id = "cargo"
name = "Base Shuttle Template (Cargo)"
/datum/map_template/shuttle/ferry
port_id = "ferry"
name = "Base Shuttle Template (Ferry)"
/datum/map_template/shuttle/whiteship
port_id = "whiteship"
// Shuttles start here:
/datum/map_template/shuttle/emergency/airless
suffix = "airless"
name = "(Shuttle Under Construction)"
description = "The documentation hasn't been finished yet for this \
shuttle.\n\
In case of emergency: Break glass."
admin_notes = "No brig, no medical facilities, no air."
/datum/map_template/shuttle/emergency/asteroid
suffix = "asteroid"
name = "Asteroid emergency shuttle"
/datum/map_template/shuttle/emergency/bar
suffix = "bar"
name = "The Emergency Escape Bar"
description = "Features include sentient bar staff (a Bardrone and a \
Barmaid), bathroom, a quality lounge for the heads, and a \
large gathering table."
admin_notes = "Bardrone and Barmaid are GODMODE, will be automatically \
sentienced by the fun balloon at 60 seconds before arrival. Has \
medical facilities."
/datum/map_template/shuttle/emergency/birdboat
suffix = "birdboat"
name = "Birdboat emergency shuttle"
/datum/map_template/shuttle/emergency/box
suffix = "box"
name = "Box emergency shuttle"
/datum/map_template/shuttle/emergency/clown
suffix = "clown"
name = "Snappop(tm)!"
description = "Hey kids and grownups! Are you bored of DULL and TEDIOUS \
shuttle journeys after you're evacuating for probably BORING reasons. \
Well then order the Snappop(tm) today! We've got fun activities for \
everyone, an all access cockpit, and no boring security brig! Boo! \
Play dress up with your friends! Collect all the bedsheets before \
your neighbour does! Check if the AI is watching you with our patent \
pending \"Peeping Tom AI Multitool Detector\" or PEEEEEETUR for \
short. Have a fun ride!"
admin_notes = "Brig is replaced by anchored greentext book surrounded by \
lavaland chasms, stationside door has been removed to prevent \
accidental dropping. No brig."
/datum/map_template/shuttle/emergency/cramped
suffix = "cramped"
name = "Secure Transport Vessel 5 (STV5)"
description = "Well, looks like Centcomm only had this ship in the area, \
they probably weren't expecting you to need evac for a while. \
Probably best if you don't rifle around in whatever equipment they \
were transporting. I hope you're friendly with your coworkers, \
because there is very little space in this thing.\n\
\n\
Contains contraband armory guns, maintenance loot, and abandoned \
crates!"
admin_notes = "Due to origin as a solo piloted secure vessel, has an \
active GPS onboard labeled STV5."
/datum/map_template/shuttle/emergency/meta
suffix = "meta"
name = "Meta emergency shuttle"
/datum/map_template/shuttle/emergency/mini
suffix = "mini"
name = "Mini emergency shuttle"
/datum/map_template/shuttle/emergency/narnar
suffix = "narnar"
name = "Shuttle 667"
description = "Looks like this shuttle may have wandered into the \
darkness between the stars on route to the station. Let's not think \
too hard about where all the bodies came from."
admin_notes = "Contains real cult ruins, mob eyeballs, and inactive \
constructs. Cult mobs will automatically be sentienced by fun \
balloon. Cloning pods in 'medbay' area are showcases and \
nonfunctional."
/datum/map_template/shuttle/emergency/supermatter
suffix = "supermatter"
name = "Hyperfractal Gigashuttle"
description = "\"I dunno, this seems kinda needlessly complicated.\"\n\
\"This shuttle has very a very high safety record, according to \
Centcom Officer Cadet Yins.\"\n\
\"Are you sure?\"\n\
\"Yes, it has a safety record of N-A-N, which is apparently \
larger than 100%.\""
admin_notes = "Supermatter that spawns on shuttle is special anchored \
'hugbox' supermatter that cannot take damage and does not take in \
or emit gas. Outside of admin intervention, it cannot explode. \
It does, however, still dust anything on contact, emits high levels \
of radiation, and induce hallucinations in anyone looking at it \
without protective goggles. Emitters spawn powered on, expect \
admin notices, they are harmless."
/datum/map_template/shuttle/emergency/imfedupwiththisworld
suffix = "imfedupwiththisworld"
name = "Oh, Hi Daniel"
description = "How was space work today? \
Oh, pretty good. We got a new space station and the company will make a lot of money. \
What space station? \
I cannot tell you; it's space confidential. \
Aw, come space on. Why not? \
No, I can't. Anyway, how is your space roleplay life?"
/datum/map_template/shuttle/emergency/goon
suffix = "goon"
name = "NES Port"
description = "The Nanotrasen Emergency Shuttle Port(NES Port for short) \
is a shuttle used at other less known nanotrasen facilities \
and has a more open inside for larger crowds."
/datum/map_template/shuttle/emergency/wabbajack
suffix = "wabbajack"
name = "NT Lepton Violet"
description = "The research team based on this vessel went missing one \
day, and no amount of investigation could discover what happened to \
them. The only occupants were a number of dead rodents, who appeared to \
have clawed each other to death. Needless to say, no engineering team \
wanted to go near the thing, and it's only being used as an Emergency \
Escape Shuttle because there is literally nothing else available."
admin_notes = "If the crew can solve the puzzle, they will wake the \
wabbajack statue. It will likely not end well. There's a reason it's \
boarded up. Maybe they should have just left it alone."
/datum/map_template/shuttle/ferry/base
suffix = "base"
name = "transport ferry"
description = "Standard issue Box/Metastation Centcom ferry."
/datum/map_template/shuttle/ferry/meat
suffix = "meat"
name = "\"meat\" ferry"
description = "Ahoy! We got all kinds o' meat aft here. Meat from plant \
people, people who be dark, not in a racist way, just they're dark \
black. Oh and lizard meat too,mighty popular that is. Definitely \
100% fresh, just ask this guy here. *person on meatspike moans* See? \
Definitely high quality meat, nothin' wrong with it, nothin' added, \
definitely no zombifyin' reagents!"
admin_notes = "Meat currently contains no zombifying reagents, lizard on \
meatspike must be spawned in."
/datum/map_template/shuttle/ferry/lighthouse
suffix = "lighthouse"
name = "The Lighthouse(?)"
description = "*static*... part of a much larger vessel, possibly \
military in origin. The weapon markings aren't anything we've seen \
... static ... by almost never the same person twice, possible use \
of unknown storage ... static ... seeing ERT officers onboard, but \
no missions are on file for ... static ... static ... annoying \
jingle ... only at The LIGHTHOUSE! Fulfilling needs you didn't even \
know you had. We've got EVERYTHING, and something else!"
admin_notes = "Currently larger than ferry docking port on Box, will not \
hit anything, but must be force docked. Trader and ERT bodyguards are \
not included."
/datum/map_template/shuttle/whiteship/box
suffix = "box"
name = "NT Medical Ship"
/datum/map_template/shuttle/whiteship/meta
suffix = "meta"
name = "NT Recovery White-ship"
/datum/map_template/shuttle/cargo/box
suffix = "box"
name = "supply shuttle (Box)"
/datum/map_template/shuttle/cargo/birdboat
suffix = "birdboat"
name = "supply shuttle (Birdboat)"
+10
View File
@@ -0,0 +1,10 @@
/datum/votablemap
var/name = ""
var/friendlyname = ""
var/minusers = 0
var/maxusers = 0
var/voteweight = 1
/datum/votablemap/New(name)
src.name = name
src.friendlyname = name
+73
View File
@@ -0,0 +1,73 @@
/datum/wires/airalarm
holder_type = /obj/machinery/airalarm
/datum/wires/airalarm/New(atom/holder)
wires = list(
WIRE_POWER,
WIRE_IDSCAN, WIRE_AI,
WIRE_PANIC, WIRE_ALARM
)
add_duds(3)
..()
/datum/wires/airalarm/interactable(mob/user)
var/obj/machinery/airalarm/A = holder
if(A.panel_open && A.buildstage == 2)
return TRUE
/datum/wires/airalarm/get_status()
var/obj/machinery/airalarm/A = holder
var/list/status = list()
status += "The interface light is [A.locked ? "red" : "green"]."
status += "The short indicator is [A.shorted ? "lit" : "off"]."
status += "The AI connection light is [!A.aidisabled ? "on" : "off"]."
return status
/datum/wires/airalarm/on_pulse(wire)
var/obj/machinery/airalarm/A = holder
switch(wire)
if(WIRE_POWER) // Short out for a long time.
if(!A.shorted)
A.shorted = TRUE
A.update_icon()
addtimer(A, "reset", 1200, FALSE, wire)
if(WIRE_IDSCAN) // Toggle lock.
A.locked = !A.locked
if(WIRE_AI) // Disable AI control for a while.
if(!A.aidisabled)
A.aidisabled = TRUE
addtimer(A, "reset", 100, FALSE, wire)
if(WIRE_PANIC) // Toggle panic siphon.
if(!A.shorted)
if(A.mode == 1) // AALARM_MODE_SCRUB
A.mode = 3 // AALARM_MODE_PANIC
else
A.mode = 1 // AALARM_MODE_SCRUB
A.apply_mode()
if(WIRE_ALARM) // Clear alarms.
var/area/AA = get_area_master(A)
if(AA.atmosalert(0, holder))
A.post_alert(0)
A.update_icon()
/datum/wires/airalarm/on_cut(wire, mend)
var/obj/machinery/airalarm/A = holder
switch(wire)
if(WIRE_POWER) // Short out forever.
A.shock(usr, 50)
A.shorted = !mend
A.update_icon()
if(WIRE_IDSCAN)
if(!mend)
A.locked = TRUE
if(WIRE_AI)
A.aidisabled = mend // Enable/disable AI control.
if(WIRE_PANIC) // Force panic syphon on.
if(!mend && !A.shorted)
A.mode = 3 // AALARM_MODE_PANIC
A.apply_mode()
if(WIRE_ALARM) // Post alarm.
var/area/AA = get_area_master(A)
if(AA.atmosalert(2, holder))
A.post_alert(2)
A.update_icon()
+150
View File
@@ -0,0 +1,150 @@
/datum/wires/airlock
holder_type = /obj/machinery/door/airlock
/datum/wires/airlock/secure
randomize = TRUE
/datum/wires/airlock/New(atom/holder)
wires = list(
WIRE_POWER1, WIRE_POWER2,
WIRE_BACKUP1, WIRE_BACKUP2,
WIRE_OPEN, WIRE_BOLTS, WIRE_IDSCAN, WIRE_AI,
WIRE_SHOCK, WIRE_SAFETY, WIRE_TIMING, WIRE_LIGHT,
WIRE_ZAP1, WIRE_ZAP2
)
add_duds(2)
..()
/datum/wires/airlock/interactable(mob/user)
var/obj/machinery/door/airlock/A = holder
if(!istype(user, /mob/living/silicon) && A.isElectrified() && A.shock(user, 100))
return FALSE
if(A.panel_open)
return TRUE
/datum/wires/airlock/get_status()
var/obj/machinery/door/airlock/A = holder
var/list/status = list()
status += "The door bolts [A.locked ? "have fallen!" : "look up."]"
status += "The test light is [A.hasPower() ? "on" : "off"]."
status += "The AI connection light is [A.aiControlDisabled || A.emagged ? "off" : "on"]."
status += "The check wiring light is [A.safe ? "off" : "on"]."
status += "The timer is powered [A.autoclose ? "on" : "off"]."
status += "The speed light is [A.normalspeed ? "on" : "off"]."
status += "The emergency light is [A.emergency ? "on" : "off"]."
return status
/datum/wires/airlock/on_pulse(wire)
var/obj/machinery/door/airlock/A = holder
switch(wire)
if(WIRE_POWER1, WIRE_POWER2) // Pulse to loose power.
A.loseMainPower()
if(WIRE_BACKUP1, WIRE_BACKUP2) // Pulse to loose backup power.
A.loseBackupPower()
if(WIRE_OPEN) // Pulse to open door (only works not emagged and ID wire is cut or no access is required).
if(A.emagged)
return
if(!A.requiresID() || A.check_access(null))
if(A.density)
A.open()
else
A.close()
if(WIRE_BOLTS) // Pulse to toggle bolts (but only raise if power is on).
if(!A.locked)
A.bolt()
A.audible_message("<span class='italics'>You hear a click from the bottom of the door.</span>", null, 1)
else
if(A.hasPower())
A.unbolt()
A.audible_message("<span class='italics'>You hear a click from the bottom of the door.</span>", null, 1)
A.update_icon()
if(WIRE_IDSCAN) // Pulse to disable emergency access and flash red lights.
if(A.hasPower() && A.density)
A.do_animate("deny")
if(A.emergency)
A.emergency = FALSE
A.update_icon()
if(WIRE_AI) // Pulse to disable WIRE_AI control for 10 ticks (follows same rules as cutting).
if(A.aiControlDisabled == 0)
A.aiControlDisabled = 1
else if(A.aiControlDisabled == -1)
A.aiControlDisabled = 2
spawn(10)
if(A)
if(A.aiControlDisabled == 1)
A.aiControlDisabled = 0
else if(A.aiControlDisabled == 2)
A.aiControlDisabled = -1
if(WIRE_SHOCK) // Pulse to shock the door for 10 ticks.
if(!A.secondsElectrified)
A.secondsElectrified = 30
A.shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
add_logs(usr, A, "electrified")
spawn(10)
if(A)
while (A.secondsElectrified > 0)
A.secondsElectrified -= 1
if(A.secondsElectrified < 0)
A.secondsElectrified = 0
sleep(10)
if(WIRE_SAFETY)
A.safe = !A.safe
if(!A.density)
A.close()
if(WIRE_TIMING)
A.normalspeed = !A.normalspeed
if(WIRE_LIGHT)
A.lights = !A.lights
A.update_icon()
/datum/wires/airlock/on_cut(wire, mend)
var/obj/machinery/door/airlock/A = holder
switch(wire)
if(WIRE_POWER1, WIRE_POWER2) // Cut to loose power, repair all to gain power.
if(mend && !is_cut(WIRE_POWER1) && !is_cut(WIRE_POWER2))
A.regainMainPower()
A.shock(usr, 50)
else
A.loseMainPower()
A.shock(usr, 50)
if(WIRE_BACKUP1, WIRE_BACKUP2) // Cut to loose backup power, repair all to gain backup power.
if(mend && !is_cut(WIRE_BACKUP1) && !is_cut(WIRE_BACKUP2))
A.regainBackupPower()
A.shock(usr, 50)
else
A.loseBackupPower()
A.shock(usr, 50)
if(WIRE_BOLTS) // Cut to drop bolts, mend does nothing.
if(!mend)
A.bolt()
if(WIRE_AI) // Cut to disable WIRE_AI control, mend to re-enable.
if(mend)
if(A.aiControlDisabled == 1) // 0 = normal, 1 = locked out, 2 = overridden by WIRE_AI, -1 = previously overridden by WIRE_AI
A.aiControlDisabled = 0
else if(A.aiControlDisabled == 2)
A.aiControlDisabled = -1
else
if(A.aiControlDisabled == 0)
A.aiControlDisabled = 1
else if(A.aiControlDisabled == -1)
A.aiControlDisabled = 2
if(WIRE_SHOCK) // Cut to shock the door, mend to unshock.
if(mend)
if(A.secondsElectrified)
A.secondsElectrified = 0
else
if(A.secondsElectrified != -1)
A.secondsElectrified = -1
A.shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
add_logs(usr, A, "electrified")
if(WIRE_SAFETY) // Cut to disable safeties, mend to re-enable.
A.safe = mend
if(WIRE_TIMING) // Cut to disable auto-close, mend to re-enable.
A.autoclose = mend
if(A.autoclose && !A.density)
A.close()
if(WIRE_LIGHT) // Cut to disable lights, mend to re-enable.
A.lights = mend
A.update_icon()
if(WIRE_ZAP1, WIRE_ZAP2) // Ouch.
A.shock(usr, 50)
+54
View File
@@ -0,0 +1,54 @@
/datum/wires/apc
holder_type = /obj/machinery/power/apc
/datum/wires/apc/New(atom/holder)
wires = list(
WIRE_POWER1, WIRE_POWER2,
WIRE_IDSCAN, WIRE_AI
)
add_duds(6)
..()
/datum/wires/apc/interactable(mob/user)
var/obj/machinery/power/apc/A = holder
if(A.panel_open && !A.opened)
return TRUE
/datum/wires/apc/get_status()
var/obj/machinery/power/apc/A = holder
var/list/status = list()
status += "The interface light is [A.locked ? "red" : "green"]."
status += "The short indicator is [A.shorted ? "lit" : "off"]."
status += "The AI connection light is [!A.aidisabled ? "on" : "off"]."
return status
/datum/wires/apc/on_pulse(wire)
var/obj/machinery/power/apc/A = holder
switch(wire)
if(WIRE_POWER1, WIRE_POWER2) // Short for a long while.
if(!A.shorted)
A.shorted = TRUE
addtimer(A, "reset", 1200, FALSE, wire)
if(WIRE_IDSCAN) // Unlock for a little while.
A.locked = FALSE
addtimer(A, "reset", 300, FALSE, wire)
if(WIRE_AI) // Disable AI control for a very short time.
if(!A.aidisabled)
A.aidisabled = TRUE
addtimer(A, "reset", 10, FALSE, wire)
/datum/wires/apc/on_cut(index, mend)
var/obj/machinery/power/apc/A = holder
switch(index)
if(WIRE_POWER1, WIRE_POWER2) // Short out.
if(mend && !is_cut(WIRE_POWER1) && !is_cut(WIRE_POWER2))
A.shorted = FALSE
A.shock(usr, 50)
else
A.shorted = TRUE
A.shock(usr, 50)
if(WIRE_AI) // Disable AI control.
if(mend)
A.aidisabled = FALSE
else
A.aidisabled = TRUE
+47
View File
@@ -0,0 +1,47 @@
/datum/wires/autolathe
holder_type = /obj/machinery/autolathe
/datum/wires/autolathe/New(atom/holder)
wires = list(
WIRE_HACK, WIRE_DISABLE,
WIRE_SHOCK, WIRE_ZAP
)
add_duds(6)
..()
/datum/wires/autolathe/interactable(mob/user)
var/obj/machinery/autolathe/A = holder
if(A.panel_open)
return TRUE
/datum/wires/autolathe/get_status()
var/obj/machinery/autolathe/A = holder
var/list/status = list()
status += "The red light is [A.disabled ? "on" : "off"]."
status += "The blue light is [A.hacked ? "on" : "off"]."
return status
/datum/wires/autolathe/on_pulse(wire)
var/obj/machinery/autolathe/A = holder
switch(wire)
if(WIRE_HACK)
A.adjust_hacked(!A.hacked)
addtimer(A, "reset", 60, FALSE, wire)
if(WIRE_SHOCK)
A.shocked = !A.shocked
addtimer(A, "reset", 60, FALSE, wire)
if(WIRE_DISABLE)
A.disabled = !A.disabled
addtimer(A, "reset", 60, FALSE, wire)
/datum/wires/autolathe/on_cut(wire, mend)
var/obj/machinery/autolathe/A = holder
switch(wire)
if(WIRE_HACK)
A.adjust_hacked(!mend)
if(WIRE_HACK)
A.shocked = !mend
if(WIRE_DISABLE)
A.disabled = !mend
if(WIRE_ZAP)
A.shock(usr, 50)
+79
View File
@@ -0,0 +1,79 @@
/datum/wires/explosive/New(atom/holder)
add_duds(2) // In this case duds actually explode.
..()
/datum/wires/explosive/on_pulse(index)
explode()
/datum/wires/explosive/on_cut(index, mend)
explode()
/datum/wires/explosive/proc/explode()
return
/datum/wires/explosive/c4
holder_type = /obj/item/weapon/c4
/datum/wires/explosive/c4/interactable(mob/user)
var/obj/item/weapon/c4/P = holder
if(P.open_panel)
return TRUE
/datum/wires/explosive/c4/explode()
var/obj/item/weapon/c4/P = holder
P.explode()
/datum/wires/explosive/pizza
holder_type = /obj/item/pizzabox
randomize = TRUE
/datum/wires/explosive/pizza/New(atom/holder)
wires = list(
WIRE_DISARM
)
add_duds(3) // Duds also explode here.
..()
/datum/wires/explosive/pizza/interactable(mob/user)
var/obj/item/pizzabox/P = holder
if(P.open && P.bomb)
return TRUE
/datum/wires/explosive/pizza/get_status()
var/obj/item/pizzabox/P = holder
var/list/status = list()
status += "The red light is [P.bomb_active ? "on" : "off"]."
status += "The green light is [P.bomb_defused ? "on": "off"]."
return status
/datum/wires/explosive/pizza/on_pulse(wire)
var/obj/item/pizzabox/P = holder
switch(wire)
if(WIRE_DISARM) // Pulse to toggle
P.bomb_defused = !P.bomb_defused
else // Boom
explode()
/datum/wires/explosive/pizza/on_cut(wire, mend)
var/obj/item/pizzabox/P = holder
switch(wire)
if(WIRE_DISARM) // Disarm and untrap the box.
if(!mend)
P.bomb_defused = TRUE
else
if(!mend && !P.bomb_defused)
explode()
/datum/wires/explosive/pizza/explode()
var/obj/item/pizzabox/P = holder
P.bomb.detonate()
/datum/wires/explosive/gibtonite
holder_type = /obj/item/weapon/twohanded/required/gibtonite
/datum/wires/explosive/gibtonite/explode()
var/obj/item/weapon/twohanded/required/gibtonite/P = holder
P.GibtoniteReaction(null, 2)
+31
View File
@@ -0,0 +1,31 @@
/datum/wires/mulebot
holder_type = /mob/living/simple_animal/bot/mulebot
randomize = TRUE
/datum/wires/mulebot/New(atom/holder)
wires = list(
WIRE_POWER1, WIRE_POWER2,
WIRE_AVOIDANCE, WIRE_LOADCHECK,
WIRE_MOTOR1, WIRE_MOTOR2,
WIRE_RX, WIRE_TX, WIRE_BEACON
)
..()
/datum/wires/mulebot/interactable(mob/user)
var/mob/living/simple_animal/bot/mulebot/M = holder
if(M.open)
return TRUE
/datum/wires/mulebot/on_pulse(wire)
var/mob/living/simple_animal/bot/mulebot/M = holder
switch(wire)
if(WIRE_POWER1, WIRE_POWER2)
holder.visible_message("<span class='notice'>\icon[M] The charge light flickers.</span>")
if(WIRE_AVOIDANCE)
holder.visible_message("<span class='notice'>\icon[M] The external warning lights flash briefly.</span>")
if(WIRE_LOADCHECK)
holder.visible_message("<span class='notice'>\icon[M] The load platform clunks.</span>")
if(WIRE_MOTOR1, WIRE_MOTOR2)
holder.visible_message("<span class='notice'>\icon[M] The drive motor whines briefly.</span>")
else
holder.visible_message("<span class='notice'>\icon[M] You hear a radio crackle.</span>")
+44
View File
@@ -0,0 +1,44 @@
/datum/wires/particle_accelerator/control_box
holder_type = /obj/machinery/particle_accelerator/control_box
/datum/wires/particle_accelerator/control_box/New(atom/holder)
wires = list(
WIRE_POWER, WIRE_STRENGTH, WIRE_LIMIT,
WIRE_INTERFACE
)
add_duds(2)
..()
/datum/wires/particle_accelerator/control_box/interactable(mob/user)
var/obj/machinery/particle_accelerator/control_box/C = holder
if(C.construction_state == 2)
return TRUE
/datum/wires/particle_accelerator/control_box/on_pulse(wire)
var/obj/machinery/particle_accelerator/control_box/C = holder
switch(wire)
if(WIRE_POWER)
C.toggle_power()
if(WIRE_STRENGTH)
C.add_strength()
if(WIRE_INTERFACE)
C.interface_control = !C.interface_control
if(WIRE_LIMIT)
C.visible_message("\icon[C]<b>[C]</b> makes a large whirring noise.")
/datum/wires/particle_accelerator/control_box/on_cut(wire, mend)
var/obj/machinery/particle_accelerator/control_box/C = holder
switch(wire)
if(WIRE_POWER)
if(C.active == !mend)
C.toggle_power()
if(WIRE_STRENGTH)
for(var/i = 1; i < 3; i++)
C.remove_strength()
if(WIRE_INTERFACE)
if(!mend)
C.interface_control = FALSE
if(WIRE_LIMIT)
C.strength_upper_limit = (mend ? 2 : 3)
if(C.strength_upper_limit < C.strength)
C.remove_strength()
+47
View File
@@ -0,0 +1,47 @@
/datum/wires/r_n_d
holder_type = /obj/machinery/r_n_d
randomize = TRUE
/datum/wires/r_n_d/New(atom/holder)
wires = list(
WIRE_HACK, WIRE_DISABLE,
WIRE_SHOCK
)
add_duds(5)
..()
/datum/wires/r_n_d/interactable(mob/user)
var/obj/machinery/r_n_d/R = holder
if(R.panel_open)
return TRUE
/datum/wires/r_n_d/get_status()
var/obj/machinery/r_n_d/R = holder
var/list/status = list()
status += "The red light is [R.disabled ? "off" : "on"]."
status += "The green light is [R.shocked ? "off" : "on"]."
status += "The blue light is [R.hacked ? "off" : "on"]."
return status
/datum/wires/r_n_d/on_pulse(wire)
var/obj/machinery/r_n_d/R = holder
switch(wire)
if(WIRE_HACK)
R.hacked = !R.hacked
if(WIRE_DISABLE)
R.disabled = !R.disabled
if(WIRE_SHOCK)
R.shocked = TRUE
spawn(100)
if(R)
R.shocked = FALSE
/datum/wires/r_n_d/on_cut(wire, mend)
var/obj/machinery/r_n_d/R = holder
switch(wire)
if(WIRE_HACK)
R.hacked = !mend
if(WIRE_DISABLE)
R.disabled = !mend
if(WIRE_SHOCK)
R.shocked = !mend
+25
View File
@@ -0,0 +1,25 @@
/datum/wires/radio
holder_type = /obj/item/device/radio
/datum/wires/radio/New(atom/holder)
wires = list(
WIRE_SIGNAL,
WIRE_RX, WIRE_TX
)
..()
/datum/wires/radio/interactable(mob/user)
var/obj/item/device/radio/R = holder
if(R.b_stat)
return TRUE
/datum/wires/radio/on_pulse(index)
var/obj/item/device/radio/R = holder
switch(index)
if(WIRE_SIGNAL)
R.listening = !R.listening
R.broadcasting = R.listening
if(WIRE_RX)
R.listening = !R.listening
if(WIRE_TX)
R.broadcasting = !R.broadcasting
+66
View File
@@ -0,0 +1,66 @@
/datum/wires/robot
holder_type = /mob/living/silicon/robot
randomize = TRUE
/datum/wires/robot/New(atom/holder)
wires = list(
WIRE_AI, WIRE_CAMERA,
WIRE_LAWSYNC, WIRE_LOCKDOWN
)
add_duds(2)
..()
/datum/wires/robot/interactable(mob/user)
var/mob/living/silicon/robot/R = holder
if(R.wiresexposed)
return TRUE
/datum/wires/robot/get_status()
var/mob/living/silicon/robot/R = holder
var/list/status = list()
status += "The law sync module is [R.lawupdate ? "on" : "off"]."
status += "The intelligence link display shows [R.connected_ai ? R.connected_ai.name : "NULL"]."
status += "The camera light is [!isnull(R.camera) && R.camera.status ? "on" : "off"]."
status += "The lockdown indicator is [R.lockcharge ? "on" : "off"]."
return status
/datum/wires/robot/on_pulse(wire)
var/mob/living/silicon/robot/R = holder
switch(wire)
if(WIRE_AI) // Pulse to pick a new AI.
if(!R.emagged)
var/new_ai = select_active_ai(R)
if(new_ai && (new_ai != R.connected_ai))
R.connected_ai = new_ai
R.notify_ai(TRUE)
if(WIRE_CAMERA) // Pulse to disable the camera.
if(!isnull(R.camera) && !R.scrambledcodes)
R.camera.toggle_cam(usr, 0)
R.visible_message("[R]'s camera lense focuses loudly.", "Your camera lense focuses loudly.")
if(WIRE_LAWSYNC) // Forces a law update if possible.
if(R.lawupdate)
R.visible_message("[R] gently chimes.", "LawSync protocol engaged.")
R.lawsync()
R.show_laws()
if(WIRE_LOCKDOWN)
R.SetLockdown(!R.lockcharge) // Toggle
/datum/wires/robot/on_cut(wire, mend)
var/mob/living/silicon/robot/R = holder
switch(wire)
if(WIRE_AI) // Cut the AI wire to reset AI control.
if(!mend)
R.connected_ai = null
if(WIRE_LAWSYNC) // Cut the law wire, and the borg will no longer receive law updates from its AI. Repair and it will re-sync.
if(mend)
if(!R.emagged)
R.lawupdate = TRUE
else
R.lawupdate = FALSE
if (WIRE_CAMERA) // Disable the camera.
if(!isnull(R.camera) && !R.scrambledcodes)
R.camera.status = mend
R.camera.toggle_cam(usr, 0)
R.visible_message("[R]'s camera lense focuses loudly.", "Your camera lense focuses loudly.")
if(WIRE_LOCKDOWN) // Simple lockdown.
R.SetLockdown(!mend)
+42
View File
@@ -0,0 +1,42 @@
/datum/wires/suit_storage_unit
holder_type = /obj/machinery/suit_storage_unit
/datum/wires/suit_storage_unit/New(atom/holder)
wires = list(
WIRE_HACK, WIRE_SAFETY,
WIRE_ZAP
)
add_duds(2)
..()
/datum/wires/suit_storage_unit/interactable(mob/user)
var/obj/machinery/suit_storage_unit/SSU = holder
if(SSU.panel_open)
return TRUE
/datum/wires/suit_storage_unit/get_status()
var/obj/machinery/suit_storage_unit/SSU = holder
var/list/status = list()
status += "The UV bulb is [SSU.uv_super ? "glowing" : "dim"]."
status += "The service light is [SSU.safeties ? "off" : "on"]."
return status
/datum/wires/suit_storage_unit/on_pulse(wire)
var/obj/machinery/suit_storage_unit/SSU = holder
switch(wire)
if(WIRE_HACK)
SSU.uv_super = !SSU.uv_super
if(WIRE_SAFETY)
SSU.safeties = !SSU.safeties
if(WIRE_ZAP)
SSU.shock(usr)
/datum/wires/suit_storage_unit/on_cut(wire, mend)
var/obj/machinery/suit_storage_unit/SSU = holder
switch(wire)
if(WIRE_HACK)
SSU.uv_super = !mend
if(WIRE_SAFETY)
SSU.safeties = mend
if(WIRE_ZAP)
SSU.shock(usr)
+91
View File
@@ -0,0 +1,91 @@
/datum/wires/syndicatebomb
holder_type = /obj/machinery/syndicatebomb
randomize = TRUE
/datum/wires/syndicatebomb/New(atom/holder)
wires = list(
WIRE_BOOM, WIRE_UNBOLT,
WIRE_ACTIVATE, WIRE_DELAY, WIRE_PROCEED
)
..()
/datum/wires/syndicatebomb/interactable(mob/user)
var/obj/machinery/syndicatebomb/P = holder
if(P.open_panel)
return TRUE
/datum/wires/syndicatebomb/on_pulse(wire)
var/obj/machinery/syndicatebomb/B = holder
switch(wire)
if(WIRE_BOOM)
if(B.active)
holder.visible_message("<span class='danger'>\icon[B] An alarm sounds! It's go-</span>")
B.timer = 0
tell_admins(B)
if(WIRE_UNBOLT)
holder.visible_message("<span class='notice'>\icon[B] The bolts spin in place for a moment.</span>")
if(WIRE_DELAY)
if(B.delayedbig)
holder.visible_message("<span class='notice'>\icon[B] The bomb has already been delayed.</span>")
else
holder.visible_message("<span class='notice'>\icon[B] The bomb chirps.</span>")
playsound(B, 'sound/machines/chime.ogg', 30, 1)
B.timer += 30
B.delayedbig = TRUE
if(WIRE_PROCEED)
holder.visible_message("<span class='danger'>\icon[B] The bomb buzzes ominously!</span>")
playsound(B, 'sound/machines/buzz-sigh.ogg', 30, 1)
if(B.timer >= 61) // Long fuse bombs can suddenly become more dangerous if you tinker with them.
B.timer = 60
else if(B.timer >= 21)
B.timer -= 10
else if(B.timer >= 11) // Both to prevent negative timers and to have a little mercy.
B.timer = 10
if(WIRE_ACTIVATE)
if(!B.active && !B.defused)
holder.visible_message("<span class='danger'>\icon[B] You hear the bomb start ticking!</span>")
playsound(B, 'sound/machines/click.ogg', 30, 1)
B.active = TRUE
B.update_icon()
else if(B.delayedlittle)
holder.visible_message("<span class='notice'>\icon[B] Nothing happens.</span>")
else
holder.visible_message("<span class='notice'>\icon[B] The bomb seems to hesitate for a moment.</span>")
B.timer += 10
B.delayedlittle = TRUE
/datum/wires/syndicatebomb/on_cut(wire, mend)
var/obj/machinery/syndicatebomb/B = holder
switch(wire)
if(WIRE_BOOM)
if(mend)
B.defused = FALSE // Cutting and mending all the wires of an inactive bomb will thus cure any sabotage.
else
if(B.active)
holder.visible_message("<span class='danger'>\icon[B] An alarm sounds! It's go-</span>")
B.timer = 0
tell_admins(B)
else
B.defused = TRUE
if(WIRE_UNBOLT)
if(!mend && B.anchored)
holder.visible_message("<span class='notice'>\icon[B] The bolts lift out of the ground!</span>")
playsound(B, 'sound/effects/stealthoff.ogg', 30, 1)
B.anchored = 0
if(WIRE_PROCEED)
if(!mend && B.active)
holder.visible_message("<span class='danger'>\icon[B] An alarm sounds! It's go-</span>")
B.timer = 0
tell_admins(B)
if(WIRE_ACTIVATE)
if(!mend && B.active)
holder.visible_message("<span class='notice'>\icon[B] The timer stops! The bomb has been defused!</span>")
B.active = FALSE
B.defused = TRUE
B.update_icon()
/datum/wires/syndicatebomb/proc/tell_admins(obj/machinery/syndicatebomb/B)
if(istype(B, /obj/machinery/syndicatebomb/training))
return
log_game("A [B.name] was detonated via boom wire at X=[B.x], Y=[B.y], Z=[B.z].")
message_admins("A [B.name] was detonated via boom wire at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[B.x];Y=[B.y];Z=[B.z]'> (JMP)</a>.")
+58
View File
@@ -0,0 +1,58 @@
/datum/wires/vending
holder_type = /obj/machinery/vending
/datum/wires/vending/New(atom/holder)
wires = list(
WIRE_THROW, WIRE_ELECTRIFY, WIRE_SPEAKER,
WIRE_CONTRABAND, WIRE_IDSCAN
)
add_duds(1)
..()
/datum/wires/vending/interactable(mob/user)
var/obj/machinery/vending/V = holder
if(!istype(user, /mob/living/silicon) && V.seconds_electrified && V.shock(user, 100))
return FALSE
if(V.panel_open)
return TRUE
/datum/wires/vending/get_status()
var/obj/machinery/vending/V = holder
var/list/status = list()
status += "The orange light is [V.seconds_electrified ? "on" : "off"]."
status += "The red light is [V.shoot_inventory ? "off" : "blinking"]."
status += "The green light is [V.extended_inventory ? "on" : "off"]."
status += "A [V.scan_id ? "purple" : "yellow"] light is on."
status += "The speaker light is [V.shut_up ? "off" : "on"]."
return status
/datum/wires/vending/on_pulse(wire)
var/obj/machinery/vending/V = holder
switch(wire)
if(WIRE_THROW)
V.shoot_inventory = !V.shoot_inventory
if(WIRE_CONTRABAND)
V.extended_inventory = !V.extended_inventory
if(WIRE_ELECTRIFY)
V.seconds_electrified = 30
if(WIRE_IDSCAN)
V.scan_id = !V.scan_id
if(WIRE_SPEAKER)
V.shut_up = !V.shut_up
/datum/wires/vending/on_cut(wire, mend)
var/obj/machinery/vending/V = holder
switch(wire)
if(WIRE_THROW)
V.shoot_inventory = !mend
if(WIRE_CONTRABAND)
V.extended_inventory = FALSE
if(WIRE_ELECTRIFY)
if(mend)
V.seconds_electrified = FALSE
else
V.seconds_electrified = -1
if(WIRE_IDSCAN)
V.scan_id = mend
if(WIRE_SPEAKER)
V.shut_up = mend
+344
View File
@@ -0,0 +1,344 @@
var/list/wire_colors = list( // http://www.crockford.com/wrrrld/color.html
"aliceblue",
"antiquewhite",
"aqua",
"aquamarine",
"beige",
"blanchedalmond",
"blue",
"blueviolet",
"brown",
"burlywood",
"cadetblue",
"chartreuse",
"chocolate",
"coral",
"cornflowerblue",
"cornsilk",
"crimson",
"cyan",
"deeppink",
"deepskyblue",
"dimgray",
"dodgerblue",
"firebrick",
"floralwhite",
"forestgreen",
"fuchsia",
"gainsboro",
"ghostwhite",
"gold",
"goldenrod",
"gray",
"green",
"greenyellow",
"honeydew",
"hotpink",
"indianred",
"ivory",
"khaki",
"lavender",
"lavenderblush",
"lawngreen",
"lemonchiffon",
"lightblue",
"lightcoral",
"lightcyan",
"lightgoldenrodyellow",
"lightgray",
"lightgreen",
"lightpink",
"lightsalmon",
"lightseagreen",
"lightskyblue",
"lightslategray",
"lightsteelblue",
"lightyellow",
"lime",
"limegreen",
"linen",
"magenta",
"maroon",
"mediumaquamarine",
"mediumblue",
"mediumorchid",
"mediumpurple",
"mediumseagreen",
"mediumslateblue",
"mediumspringgreen",
"mediumturquoise",
"mediumvioletred",
"mintcream",
"mistyrose",
"moccasin",
"navajowhite",
"oldlace",
"olive",
"olivedrab",
"orange",
"orangered",
"orchid",
"palegoldenrod",
"palegreen",
"paleturquoise",
"palevioletred",
"papayawhip",
"peachpuff",
"peru",
"pink",
"plum",
"powderblue",
"purple",
"red",
"rosybrown",
"royalblue",
"saddlebrown",
"salmon",
"sandybrown",
"seagreen",
"seashell",
"sienna",
"silver",
"skyblue",
"slateblue",
"slategray",
"snow",
"springgreen",
"steelblue",
"tan",
"teal",
"thistle",
"tomato",
"turquoise",
"violet",
"wheat",
"white",
"whitesmoke",
"yellow",
"yellowgreen",
)
var/list/wire_color_directory = list()
/proc/is_wire_tool(obj/item/I)
if(istype(I, /obj/item/device/multitool))
return TRUE
if(istype(I, /obj/item/weapon/wirecutters))
return TRUE
if(istype(I, /obj/item/device/assembly))
var/obj/item/device/assembly/A = I
if(A.attachable)
return TRUE
return
/atom
var/datum/wires/wires = null
/datum/wires
var/atom/holder = null // The holder (atom that contains these wires).
var/holder_type = null // The holder's typepath (used to make wire colors common to all holders).
var/list/wires = list() // List of wires.
var/list/cut_wires = list() // List of wires that have been cut.
var/list/colors = list() // Dictionary of colors to wire.
var/list/assemblies = list() // List of attached assemblies.
var/randomize = 0 // If every instance of these wires should be random.
/datum/wires/New(atom/holder)
..()
if(!istype(holder, holder_type))
CRASH("Wire holder is not of the expected type!")
return
src.holder = holder
if(randomize)
randomize()
else
if(!wire_color_directory[holder_type])
randomize()
wire_color_directory[holder_type] = colors
else
colors = wire_color_directory[holder_type]
/datum/wires/Destroy()
holder = null
assemblies = list()
return ..()
/datum/wires/proc/add_duds(duds)
while(duds)
var/dud = "dud[--duds]"
if(dud in wires)
continue
wires += dud
/datum/wires/proc/randomize()
var/list/possible_colors = wire_colors.Copy()
for(var/wire in shuffle(wires))
colors[pick_n_take(possible_colors)] = wire
/datum/wires/proc/shuffle_wires()
colors.Cut()
randomize()
/datum/wires/proc/repair()
cut_wires.Cut()
/datum/wires/proc/get_wire(color)
return colors[color]
/datum/wires/proc/get_attached(color)
if(assemblies[color])
return assemblies[color]
return null
/datum/wires/proc/is_attached(color)
if(assemblies[color])
return TRUE
/datum/wires/proc/is_cut(wire)
return (wire in cut_wires)
/datum/wires/proc/is_color_cut(color)
return is_cut(get_wire(color))
/datum/wires/proc/is_all_cut()
if(cut_wires.len == wires.len)
return TRUE
/datum/wires/proc/cut(wire)
if(is_cut(wire))
cut_wires -= wire
on_cut(wire, mend = TRUE)
else
cut_wires += wire
on_cut(wire, mend = FALSE)
/datum/wires/proc/cut_color(color)
cut(get_wire(color))
/datum/wires/proc/cut_random()
cut(wires[rand(1, wires.len)])
/datum/wires/proc/cut_all()
for(var/wire in wires)
cut(wire)
/datum/wires/proc/pulse(wire)
if(is_cut(wire))
return
on_pulse(wire)
/datum/wires/proc/pulse_color(color)
pulse(get_wire(color))
/datum/wires/proc/pulse_assembly(obj/item/device/assembly/S)
for(var/color in assemblies)
if(S == assemblies[color])
pulse_color(color)
return TRUE
/datum/wires/proc/attach_assembly(color, obj/item/device/assembly/S)
if(S && istype(S) && S.attachable && !is_attached(color))
assemblies[color] = S
S.loc = holder
S.connected = src
return S
/datum/wires/proc/detach_assembly(color)
var/obj/item/device/assembly/S = get_attached(color)
if(S && istype(S))
assemblies -= color
S.connected = null
S.loc = holder.loc
return S
// Overridable Procs
/datum/wires/proc/interactable(mob/user)
return TRUE
/datum/wires/proc/get_status()
return list()
/datum/wires/proc/on_cut(wire, mend = FALSE)
return
/datum/wires/proc/on_pulse(wire)
return
// End Overridable Procs
/datum/wires/proc/interact(mob/user)
if(!interactable(user))
return
ui_interact(user)
for(var/A in assemblies)
var/obj/item/I = assemblies[A]
if(istype(I) && I.on_found(user))
return
/datum/wires/ui_host()
return holder
/datum/wires/ui_status(mob/user)
if(interactable(user))
return ..()
return UI_CLOSE
/datum/wires/ui_interact(mob/user, ui_key = "wires", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if (!ui)
ui = new(user, src, ui_key, "wires", "[holder.name] wires", 350, 150 + wires.len * 30, master_ui, state)
ui.open()
/datum/wires/ui_data(mob/user)
var/list/data = list()
var/list/payload = list()
for(var/color in colors)
payload.Add(list(list(
"color" = color,
"wire" = (IsAdminGhost(user) ? get_wire(color) : null),
"cut" = is_color_cut(color),
"attached" = is_attached(color)
)))
data["wires"] = payload
data["status"] = get_status()
return data
/datum/wires/ui_act(action, params)
if(..() || !interactable(usr))
return
var/target_wire = params["wire"]
var/mob/living/L = usr
var/obj/item/I = L.get_active_hand()
switch(action)
if("cut")
if(istype(I, /obj/item/weapon/wirecutters) || IsAdminGhost(usr))
playsound(holder, 'sound/items/Wirecutter.ogg', 20, 1)
cut_color(target_wire)
. = TRUE
else
L << "<span class='warning'>You need wirecutters!</span>"
if("pulse")
if(istype(I, /obj/item/device/multitool) || IsAdminGhost(usr))
playsound(holder, 'sound/weapons/empty.ogg', 20, 1)
pulse_color(target_wire)
. = TRUE
else
L << "<span class='warning'>You need a multitool!</span>"
if("attach")
if(is_attached(target_wire))
var/obj/item/O = detach_assembly(target_wire)
if(O)
L.put_in_hands(O)
. = TRUE
else
if(istype(I, /obj/item/device/assembly))
var/obj/item/device/assembly/A = I
if(A.attachable)
if(!L.drop_item())
return
attach_assembly(target_wire, A)
. = TRUE
else
L << "<span class='warning'>You need an attachable assembly!</span>"