Merge pull request #3 from Ryan784/Vampire

Vampire
This commit is contained in:
skull132
2016-01-28 01:20:53 +02:00
242 changed files with 3232 additions and 2343 deletions
+2 -2
View File
@@ -3,8 +3,8 @@ language: c
sudo: false
env:
BYOND_MAJOR="508"
BYOND_MINOR="1293"
BYOND_MAJOR="509"
BYOND_MINOR="1318"
cache:
directories:
+5 -3
View File
@@ -203,7 +203,6 @@
#include "code\defines\procs\records.dm"
#include "code\defines\procs\sd_Alert.dm"
#include "code\defines\procs\statistics.dm"
#include "code\game\asteroid.dm"
#include "code\game\atoms.dm"
#include "code\game\atoms_movable.dm"
#include "code\game\periodic_news.dm"
@@ -241,6 +240,7 @@
#include "code\game\antagonist\station\revolutionary.dm"
#include "code\game\antagonist\station\rogue_ai.dm"
#include "code\game\antagonist\station\traitor.dm"
#include "code\game\antagonist\station\vampire.dm"
#include "code\game\area\ai_monitored.dm"
#include "code\game\area\areas.dm"
#include "code\game\area\asteroid_areas.dm"
@@ -310,10 +310,11 @@
#include "code\game\gamemodes\nuclear\pinpointer.dm"
#include "code\game\gamemodes\revolution\revolution.dm"
#include "code\game\gamemodes\traitor\traitor.dm"
#include "code\game\gamemodes\vampire\vampire.dm"
#include "code\game\gamemodes\vampire\vampire_powers.dm"
#include "code\game\gamemodes\wizard\wizard.dm"
#include "code\game\jobs\access.dm"
#include "code\game\jobs\job_controller.dm"
#include "code\game\jobs\jobprocs.dm"
#include "code\game\jobs\jobs.dm"
#include "code\game\jobs\whitelist.dm"
#include "code\game\jobs\job\assistant.dm"
@@ -657,6 +658,7 @@
#include "code\game\objects\items\weapons\circuitboards\computer\air_management.dm"
#include "code\game\objects\items\weapons\circuitboards\computer\camera_monitor.dm"
#include "code\game\objects\items\weapons\circuitboards\computer\computer.dm"
#include "code\game\objects\items\weapons\circuitboards\computer\holodeckcontrol.dm"
#include "code\game\objects\items\weapons\circuitboards\computer\research.dm"
#include "code\game\objects\items\weapons\circuitboards\computer\supply.dm"
#include "code\game\objects\items\weapons\circuitboards\computer\telecomms.dm"
@@ -835,7 +837,6 @@
#include "code\modules\admin\verbs\diagnostics.dm"
#include "code\modules\admin\verbs\dice.dm"
#include "code\modules\admin\verbs\getlogs.dm"
#include "code\modules\admin\verbs\icarus.dm"
#include "code\modules\admin\verbs\mapping.dm"
#include "code\modules\admin\verbs\massmodvar.dm"
#include "code\modules\admin\verbs\modifyvariables.dm"
@@ -1338,6 +1339,7 @@
#include "code\modules\nano\nanoui.dm"
#include "code\modules\nano\interaction\admin.dm"
#include "code\modules\nano\interaction\base.dm"
#include "code\modules\nano\interaction\conscious.dm"
#include "code\modules\nano\interaction\contained.dm"
#include "code\modules\nano\interaction\default.dm"
#include "code\modules\nano\interaction\inventory.dm"
+42 -52
View File
@@ -35,10 +35,9 @@ except ImportError:
try:
tiedosto = open("psycodownload.txt","r")
except:
tiedosto = open("psycodownload.txt","w")
tiedosto.write("http://www.voidspace.org.uk/python/modules.shtml#psyco")
tiedosto.write("\nhttp://psyco.sourceforge.net/download.html")
tiedosto.close()
with open("psycodownload.txt","w") as tiedosto:
tiedosto.write("http://www.voidspace.org.uk/python/modules.shtml#psyco")
tiedosto.write("\nhttp://psyco.sourceforge.net/download.html")
print "Check psycodownload.txt for a link"
else:
print "For god's sake, open psycodownload.txt"
@@ -190,15 +189,13 @@ tell_list = {}
if CORE_DATA.DISABLE_ALL_NON_MANDATORY_SOCKET_CONNECTIONS:
nudgeable = False
try:
tiedosto = open("replacenames.cache","r")
replacenames = pickle.load(tiedosto)
tiedosto.close()
with open("replacenames.cache","r") as tiedosto:
replacenames = pickle.load(tiedosto)
for i in replacenames.values():
if len(i) > call_me_max_length:
replacenames[replacenames.keys()[replacenames.values().index(i)]] = i[:call_me_max_length]
tiedosto = open("replacenames.cache","w")
pickle.dump(replacenames,tiedosto)
tiedosto.close()
with open("replacenames.cache","w") as tiedosto:
pickle.dump(replacenames,tiedosto)
if "[\0x01]" in i.lower() or "[\\0x01]" in i.lower():
i = i.replace("[\0x01]","")
i = i.replace("[\0X01]","")
@@ -211,13 +208,12 @@ except EOFError: #Cache corrupt
replacenames = {}
print "replacenames.cache is corrupt and couldn't be loaded."
try:
tiedosto = open("peopleheknows.cache","r")
peopleheknows = pickle.load(tiedosto)
tiedosto.close()
with open("peopleheknows.cache","r") as tiedosto:
peopleheknows = pickle.load(tiedosto)
except IOError:
peopleheknows = [[],[]]
tiedosto = open("peopleheknows.cache","w")
tiedosto.close()
with open("peopleheknows.cache","w") as tiedosto:
pass
except EOFError:
peopleheknows = [[],[]]
print "peopleheknows.cache is corrupt and couldn't be loaded."
@@ -345,16 +341,14 @@ if aggressive_pinging:
self_time = 0
global backup,disconnects,conn
while disconnects < 5:
if backup > self_time:
if time.time()-backup > delay:
conn.send("PONG "+pongtarg)
print "Ponged"
self_time = time.time()
else:
if time.time()-self_time > delay:
conn.send("PONG "+pongtarg)
print "Ponged"
self_time = time.time()
if backup > self_time and time.time()-backup > delay:
conn.send("PONG "+pongtarg)
print "Ponged"
self_time = time.time()
elif time.time()-self_time > delay:
conn.send("PONG "+pongtarg)
print "Ponged"
self_time = time.time()
time.sleep(refresh)
thread.start_new_thread(aggressive_ping,(aggressive_pinging_delay,aggressive_pinging_refresh,))
def stop(sender,debug=1):
@@ -370,16 +364,15 @@ def stop(sender,debug=1):
access_granted = True
else:
access_granted = False
if access_granted:
if debug:
print sender+":"+prefix+"stop"
if random.randint(0,100) == 50:
conn.privmsg(channel,"Hammertime!")
else:
conn.privmsg(channel,"Shutting down.")
disconnects = 99999
conn.quit()
return True
if access_granted and debug:
print sender+":"+prefix+"stop"
if random.randint(0,100) == 50:
conn.privmsg(channel,"Hammertime!")
else:
conn.privmsg(channel,"Shutting down.")
disconnects = 99999
conn.quit()
return True
else:
conn.privmsg(channel,"You cannot command me")
return False
@@ -401,13 +394,12 @@ def target(who,how_long):
if debug:
print "Banned",who,"For",how_long,"seconds"
if logbans:
tiedosto = open(targetdirectory+"banlog/"+str(int(start))+"-"+str(int(end))+".txt","w")
tiedosto.write("Start of ban on "+who+":"+str(int(start)))
tiedosto.write("\n")
tiedosto.write("End of ban on "+who+":"+str(int(end)))
tiedosto.write("\n")
tiedosto.write("In total:"+str(int(end-start))+"Seconds")
tiedosto.close()
with open(targetdirectory+"banlog/"+str(int(start))+"-"+str(int(end))+".txt","w") as tiedosto:
tiedosto.write("Start of ban on "+who+":"+str(int(start)))
tiedosto.write("\n")
tiedosto.write("End of ban on "+who+":"+str(int(end)))
tiedosto.write("\n")
tiedosto.write("In total:"+str(int(end-start))+"Seconds")
else:
CALL_OFF = False
pass
@@ -576,13 +568,12 @@ while True:
time.sleep(6)
Name = origname
conn.nick(Name)
if origname in truesender:
if influx == prefix+"stop":
time.sleep(0.5) #A small delay
conn.privmsg(channel,"Shutting down.")
conn.quit()
disconnects = 99999
break
if origname in truesender and influx == prefix+"stop":
time.sleep(0.5) #A small delay
conn.privmsg(channel,"Shutting down.")
conn.quit()
disconnects = 99999
break
if len(translateable) > 0 and enabled == True:
people = "-5|5|1-".join(users).lower()
if truesender.lower() in translateable:
@@ -633,9 +624,8 @@ while True:
arg = influx.lower()[8+len(prefix):]
if debug:
print truesender+":"+prefix+"suggest "+arg
tiedosto = open(targetdirectory+"suggestions/suggestions_"+str(int(time.time()))+".txt","a")
tiedosto.write(arg)
tiedosto.close()
with open(targetdirectory+"suggestions/suggestions_"+str(int(time.time()))+".txt","a") as tiedosto:
tiedosto.write(arg)
conn.privmsg(targetchannel,"Suggestion received")
elif cocheck( prefix+"help "): #Space in front of the ( to make sure that my command finder does not pick this up.
arg = " ".join(influx.split(" ")[1:]).lower()
-3
View File
@@ -28,9 +28,6 @@ datum/pipeline
if(!member.check_pressure(pressure))
break //Only delete 1 pipe per process
//Allow for reactions
//air.react() //Should be handled by pipe_network now
proc/temporarily_store_air()
//Update individual gas_mixtures by volume ratio
+4 -3
View File
@@ -154,18 +154,18 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
#ifdef ZASDBG
var/updated = 0
#endif
//defer updating of self-zone-blocked turfs until after all other turfs have been updated.
//this hopefully ensures that non-self-zone-blocked turfs adjacent to self-zone-blocked ones
//have valid zones when the self-zone-blocked turfs update.
var/list/deferred = list()
for(var/turf/T in updating)
//check if the turf is self-zone-blocked
if(T.c_airblock(T) & ZONE_BLOCKED)
deferred += T
continue
T.update_air_properties()
T.post_update_air_properties()
T.needs_air_update = 0
@@ -234,6 +234,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
/datum/controller/air_system/proc/remove_zone(zone/z)
zones.Remove(z)
zones_to_update.Remove(z)
/datum/controller/air_system/proc/air_blocked(turf/A, turf/B)
#ifdef ZASDBG
+22 -22
View File
@@ -1,13 +1,9 @@
/*
Making Bombs with ZAS:
Make burny fire with lots of burning
Draw off 5000K gas from burny fire
Separate gas into oxygen and phoron components
Obtain phoron and oxygen tanks filled up about 50-75% with normal-temp gas
Fill rest with super hot gas from separated canisters, they should be about 125C now.
Attach to transfer valve and open. BOOM.
Get gas to react in an air tank so that it gains pressure. If it gains enough pressure, it goes boom.
The more pressure, the more boom.
If it gains pressure too slowly, it may leak or just rupture instead of exploding.
*/
//#define FIREDBG
@@ -268,16 +264,16 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
//determine how far the reaction can progress
var/reaction_limit = min(total_oxidizers*(FIRE_REACTION_FUEL_AMOUNT/FIRE_REACTION_OXIDIZER_AMOUNT), total_fuel) //stoichiometric limit
//calculate the firelevel.
var/firelevel = calculate_firelevel(total_fuel, total_oxidizers, reaction_limit)
var/firelevel_ratio = firelevel / vsc.fire_firelevel_multiplier
//vapour fuels are extremely volatile! The reaction progress is a percentage of the total fuel (similar to old zburn).)
var/gas_firelevel = calculate_firelevel(gas_fuel, total_oxidizers, reaction_limit, volume*group_multiplier) / vsc.fire_firelevel_multiplier
var/min_burn = 0.30*volume*group_multiplier/CELL_VOLUME //in moles - so that fires with very small gas concentrations burn out fast
var/gas_reaction_progress = min(max(min_burn, firelevel_ratio*gas_fuel)*FIRE_GAS_BURNRATE_MULT, gas_fuel)
var/gas_reaction_progress = min(max(min_burn, gas_firelevel*gas_fuel)*FIRE_GAS_BURNRATE_MULT, gas_fuel)
//liquid fuels are not as volatile, and the reaction progress depends on the size of the area that is burning. Limit the burn rate to a certain amount per area.
var/liquid_reaction_progress = min((firelevel_ratio*0.2 + 0.05)*fuel_area*FIRE_LIQUID_BURNRATE_MULT, liquid_fuel)
var/liquid_firelevel = calculate_firelevel(liquid_fuel, total_oxidizers, reaction_limit, 0) / vsc.fire_firelevel_multiplier
var/liquid_reaction_progress = min((liquid_firelevel*0.2 + 0.05)*fuel_area*FIRE_LIQUID_BURNRATE_MULT, liquid_fuel)
var/firelevel = (gas_fuel*gas_firelevel + liquid_fuel*liquid_firelevel)/total_fuel
var/total_reaction_progress = gas_reaction_progress + liquid_reaction_progress
var/used_fuel = min(total_reaction_progress, reaction_limit)
@@ -286,7 +282,7 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
#ifdef FIREDBG
log_debug("gas_fuel = [gas_fuel], liquid_fuel = [liquid_fuel], total_oxidizers = [total_oxidizers]")
log_debug("fuel_area = [fuel_area], total_fuel = [total_fuel], reaction_limit = [reaction_limit]")
log_debug("firelevel -> [firelevel] / [vsc.fire_firelevel_multiplier]")
log_debug("firelevel -> [firelevel] (gas: [gas_firelevel], liquid: [liquid_firelevel])")
log_debug("liquid_reaction_progress = [liquid_reaction_progress]")
log_debug("gas_reaction_progress = [gas_reaction_progress]")
log_debug("total_reaction_progress = [total_reaction_progress]")
@@ -315,13 +311,13 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
//calculate the energy produced by the reaction and then set the new temperature of the mix
temperature = (starting_energy + vsc.fire_fuel_energy_release * (used_gas_fuel + used_liquid_fuel)) / heat_capacity()
update_values()
#ifdef FIREDBG
log_debug("used_gas_fuel = [used_gas_fuel]; used_liquid_fuel = [used_liquid_fuel]; total = [used_fuel]")
log_debug("new temperature = [temperature]")
log_debug("new temperature = [temperature]; new pressure = [return_pressure()]")
#endif
update_values()
return firelevel
datum/gas_mixture/proc/check_recombustability(list/fuel_objs)
@@ -363,27 +359,31 @@ datum/gas_mixture/proc/check_recombustability(list/fuel_objs)
break
//returns a value between 0 and vsc.fire_firelevel_multiplier
/datum/gas_mixture/proc/calculate_firelevel(total_fuel, total_oxidizers, reaction_limit)
/datum/gas_mixture/proc/calculate_firelevel(total_fuel, total_oxidizers, reaction_limit, gas_volume)
//Calculates the firelevel based on one equation instead of having to do this multiple times in different areas.
var/firelevel = 0
var/total_combustables = (total_fuel + total_oxidizers)
var/active_combustables = (FIRE_REACTION_OXIDIZER_AMOUNT/FIRE_REACTION_FUEL_AMOUNT + 1)*reaction_limit
if(total_combustables > 0)
//slows down the burning when the concentration of the reactants is low
var/dampening_multiplier = min(1, reaction_limit / (total_moles/group_multiplier))
var/damping_multiplier = min(1, active_combustables / (total_moles/group_multiplier))
//weight the damping mult so that it only really brings down the firelevel when the ratio is closer to 0
damping_multiplier = 2*damping_multiplier - (damping_multiplier*damping_multiplier)
//calculates how close the mixture of the reactants is to the optimum
//fires burn better when there is more oxidizer -- too much fuel will choke them out a bit, reducing firelevel.
//fires burn better when there is more oxidizer -- too much fuel will choke the fire out a bit, reducing firelevel.
var/mix_multiplier = 1 / (1 + (5 * ((total_fuel / total_combustables) ** 2)))
#ifdef FIREDBG
ASSERT(dampening_multiplier <= 1)
ASSERT(damping_multiplier <= 1)
ASSERT(mix_multiplier <= 1)
#endif
//toss everything together -- should produce a value between 0 and fire_firelevel_multiplier
firelevel = vsc.fire_firelevel_multiplier * mix_multiplier * dampening_multiplier
firelevel = vsc.fire_firelevel_multiplier * mix_multiplier * damping_multiplier
return max( 0, firelevel)
+3
View File
@@ -21,6 +21,9 @@
/xgm_gas/phoron
id = "phoron"
name = "Phoron"
//Note that this has a significant impact on TTV yield.
//Because it is so high, any leftover phoron soaks up a lot of heat and drops the yield pressure.
specific_heat = 200 // J/(mol*K)
//Hypothetical group 14 (same as carbon), period 8 element.
+2 -1
View File
@@ -9,7 +9,8 @@ var/global/vs_control/vsc = new
var/fire_firelevel_multiplier_NAME = "Fire - Firelevel Constant"
var/fire_firelevel_multiplier_DESC = "Multiplied by the equation for firelevel, affects mainly the extingiushing of fires."
var/fire_fuel_energy_release = 397000
//Note that this parameter and the phoron heat capacity have a significant impact on TTV yield.
var/fire_fuel_energy_release = 866000 //J/mol. Adjusted to compensate for fire energy release being fixed, was 397000
var/fire_fuel_energy_release_NAME = "Fire - Fuel energy release"
var/fire_fuel_energy_release_DESC = "The energy in joule released when burning one mol of a burnable substance"
+3 -2
View File
@@ -108,11 +108,12 @@ Class Procs:
c_invalidate()
for(var/turf/simulated/T in contents)
into.add(T)
T.update_graphic(graphic_remove = air.graphic)
#ifdef ZASDBG
T.dbg(merged)
#endif
//rebuild the old zone's edges so that the will be possesed by the new zone
//rebuild the old zone's edges so that they will be possessed by the new zone
for(var/connection_edge/E in edges)
if(E.contains_zone(into))
continue //don't need to rebuild this edge
+14 -9
View File
@@ -308,7 +308,7 @@
return 1
/datum/gas_mixture/proc/react(atom/dump_location)
/datum/gas_mixture/proc/react()
zburn(null, force_burn=0, no_check=0) //could probably just call zburn() here with no args but I like being explicit.
@@ -444,20 +444,25 @@
total_gas[g] += gasmix.gas[g]
if(total_volume > 0)
//Average out the gases
for(var/g in total_gas)
total_gas[g] /= total_volume
var/datum/gas_mixture/combined = new(total_volume)
combined.gas = total_gas
//Calculate temperature
var/temperature = 0
if(total_heat_capacity > 0)
temperature = total_thermal_energy / total_heat_capacity
combined.temperature = total_thermal_energy / total_heat_capacity
combined.update_values()
//Allow for reactions
combined.react()
//Average out the gases
for(var/g in combined.gas)
combined.gas[g] /= total_volume
//Update individual gas_mixtures
for(var/datum/gas_mixture/gasmix in gases)
gasmix.gas = total_gas.Copy()
gasmix.temperature = temperature
gasmix.gas = combined.gas.Copy()
gasmix.temperature = combined.temperature
gasmix.multiply(gasmix.volume)
return 1
+11 -5
View File
@@ -71,11 +71,17 @@ proc/isemptylist(list/list)
return 1
return 0
//Empties the list by setting the length to 0. Hopefully the elements get garbage collected
proc/clearlist(list/list)
if(istype(list))
list.len = 0
return
/proc/instances_of_type_in_list(var/atom/A, var/list/L)
var/instances = 0
for(var/type in L)
if(istype(A, type))
instances++
return instances
//Empties the list by .Cut(). Setting lenght = 0 has been confirmed to leak references.
proc/clearlist(var/list/L)
if(islist(L))
L.Cut()
//Removes any null entries from the list
proc/listclearnulls(list/list)
+15
View File
@@ -17,3 +17,18 @@
if(A.simulated)
return 0
return 1
// Picks a turf without a mob from the given list of turfs, if one exists.
// If no such turf exists, picks any random turf from the given list of turfs.
/proc/pick_mobless_turf_if_exists(var/list/start_turfs)
if(!start_turfs.len)
return null
var/list/available_turfs = list()
for(var/start_turf in start_turfs)
var/mob/M = locate() in start_turf
if(!M)
available_turfs += start_turf
if(!available_turfs.len)
available_turfs = start_turfs
return pick(available_turfs)
+5 -1
View File
@@ -538,7 +538,7 @@ Turf and target are seperate in case you want to teleport some distance from a t
var/y = min(world.maxy, max(1, A.y + dy))
return locate(x,y,A.z)
//Makes sure MIDDLE is between LOW and HIGH. If not, it adjusts it. Returns the adjusted value.
//Makes sure MIDDLE is between LOW and HIGH. If not, it adjusts it. Returns the adjusted value. Lower bound takes priority.
/proc/between(var/low, var/middle, var/high)
return max(min(middle, high), low)
@@ -1309,3 +1309,7 @@ var/mob/dview/dview_mob = new
/mob/dview/New()
// do nothing. we don't want to be in any mob lists; we're a dummy not a mob.
// call to generate a stack trace and print to runtime logs
/proc/crash_with(msg)
CRASH(msg)
+1 -1
View File
@@ -291,7 +291,7 @@
user.listed_turf = null
else
user.listed_turf = T
user.client.statpanel = T.name
user.client.statpanel = "Turf"
return
/mob/proc/TurfAdjacent(var/turf/T)
+4 -1
View File
@@ -19,9 +19,12 @@
spell_objects.Cut()
if(spell_holder)
spell_holder.spell_masters -= src
if(spell_holder.client && spell_holder.client.screen)
spell_holder.client.screen -= src
spell_holder = null
/obj/screen/movable/spell_master/ResetVars()
..("spell_objects")
..("spell_objects", args)
spell_objects = list()
/obj/screen/movable/spell_master/MouseDrop()
+1
View File
@@ -91,6 +91,7 @@ var/list/delayed_garbage = list()
return
if(!istype(A))
warning("qdel() passed object of type [A.type]. qdel() can only handle /datum types.")
crash_with("qdel() passed object of type [A.type]. qdel() can only handle /datum types.")
del(A)
if(garbage_collector)
garbage_collector.dels++
+3 -3
View File
@@ -39,12 +39,12 @@ datum/controller/vote
result()
for(var/client/C in voting)
if(C)
C << browse(null,"window=vote;can_close=0")
C << browse(null,"window=vote")
reset()
else
for(var/client/C in voting)
if(C)
C << browse(vote.interface(C),"window=vote;can_close=0")
C << browse(vote.interface(C),"window=vote")
voting.Cut()
@@ -392,4 +392,4 @@ datum/controller/vote
set name = "Vote"
if(vote)
src << browse(vote.interface(client),"window=vote;can_close=0")
src << browse(vote.interface(client),"window=vote")
+4 -2
View File
@@ -48,7 +48,7 @@
else
assignment = "Unassigned"
var/id = add_zero(num2hex(rand(1, 1.6777215E7)), 6) //this was the best they could come up with? A large random number? *sigh*
var/id = generate_record_id()
var/icon/front = new(get_id_photo(H), dir = SOUTH)
var/icon/side = new(get_id_photo(H), dir = WEST)
//General Record
@@ -136,8 +136,10 @@
locked += L
return
/proc/generate_record_id()
return add_zero(num2hex(rand(1, 65535)), 4) //no point generating higher numbers because of the limitations of num2hex
proc/get_id_photo(var/mob/living/carbon/human/H)
/proc/get_id_photo(var/mob/living/carbon/human/H)
var/icon/preview_icon = null
var/g = "m"
+8 -2
View File
@@ -53,6 +53,8 @@
var/datum/faction/faction //associated faction
var/datum/changeling/changeling //changeling holder
var/datum/vampire/vampire //vampire holder
var/rev_cooldown = 0
// the world.time since the mob has been brigged, or -1 if not at all
@@ -72,6 +74,8 @@
if(changeling)
current.remove_changeling_powers()
current.verbs -= /datum/changeling/proc/EvolutionMenu
if(vampire)
current.remove_vampire_powers()
current.mind = null
nanomanager.user_transferred(current, new_character) // transfer active NanoUI instances to new user
@@ -83,7 +87,8 @@
if(changeling)
new_character.make_changeling()
if(vampire)
new_character.make_vampire()
if(active)
new_character.key = key //now transfer the key to link the client to our new body
@@ -143,7 +148,7 @@
if(href_list["add_antagonist"])
var/datum/antagonist/antag = all_antag_types[href_list["add_antagonist"]]
if(antag)
if(antag)
if(antag.add_antagonist(src, 1, 1, 0, 1, 1)) // Ignore equipment and role type for this.
log_admin("[key_name_admin(usr)] made [key_name(src)] into a [antag.role_text].")
else
@@ -439,6 +444,7 @@
assigned_job = null
//faction = null //Uncommenting this causes a compile error due to 'undefined type', fucked if I know.
changeling = null
vampire = null
initial_account = null
objectives = list()
special_verbs = list()
+1 -1
View File
@@ -41,7 +41,7 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
(A.locked ? "The door bolts have fallen!" : "The door bolts look up."),
((A.lights && haspower) ? "The door bolt lights are on." : "The door bolt lights are off!"),
((haspower) ? "The test light is on." : "The test light is off!"),
((A.backupPowerCablesCut()) ? "The backup power light is off!" : "The backup power light is on."),
((A.backup_power_lost_until) ? "The backup power light is off!" : "The backup power light is on."),
((A.aiControlDisabled==0 && !A.emagged && haspower)? "The 'AI control allowed' light is on." : "The 'AI control allowed' light is off."),
((A.safe==0 && haspower)? "The 'Check Wiring' light is on." : "The 'Check Wiring' light is off."),
((A.normalspeed==0 && haspower)? "The 'Check Timing Mechanism' light is on." : "The 'Check Timing Mechanism' light is off."),
+1 -1
View File
@@ -5,7 +5,7 @@
var/icon/side = new(get_id_photo(dummy), dir = WEST)
var/datum/data/record/G = new /datum/data/record()
G.fields["name"] = "New Record"
G.fields["id"] = text("[]", add_zero(num2hex(rand(1, 1.6777215E7)), 6))
G.fields["id"] = generate_record_id()
G.fields["rank"] = "Unassigned"
G.fields["real_rank"] = "Unassigned"
G.fields["sex"] = "Male"
@@ -26,6 +26,7 @@
#define ANTAG_RANDSPAWN 256 // Potentially randomly spawns due to events.
#define ANTAG_VOTABLE 512 // Can be voted as an additional antagonist before roundstart.
#define ANTAG_SET_APPEARANCE 1024 // Causes antagonists to use an appearance modifier on spawn.
#define ANTAG_RANDOM_EXCEPTED 2048 // If a game mode randomly selects antag types, antag types with this flag should be excluded.
// Globals.
var/global/list/all_antag_types = list()
+2 -2
View File
@@ -36,7 +36,7 @@ var/datum/antagonist/xenos/borer/borers
if(istype(borer))
var/mob/living/carbon/human/host
for(var/mob/living/carbon/human/H in mob_list)
if(H.stat != 2 && !(H.species.flags & IS_SYNTHETIC) && !H.has_brain_worms())
if(H.stat != DEAD && !(H.species.flags & IS_SYNTHETIC) && !H.has_brain_worms())
host = H
break
if(istype(host))
@@ -44,7 +44,7 @@ var/datum/antagonist/xenos/borer/borers
if(head)
borer.host = host
head.implants += borer
borer.loc = head
borer.forceMove(head)
if(!borer.host_brain)
borer.host_brain = new(borer)
borer.host_brain.name = host.name
+1 -1
View File
@@ -44,4 +44,4 @@ var/datum/antagonist/xenos/xenomorphs
player.objectives += new /datum/objective/escape()
/datum/antagonist/xenos/place_mob(var/mob/living/player)
player.loc = get_turf(pick(get_vents()))
player.forceMove(get_turf(pick(get_vents())))
+40 -23
View File
@@ -86,7 +86,8 @@
/datum/antagonist/proc/tick()
return 1
/datum/antagonist/proc/get_candidates(var/ghosts_only)
// Get the raw list of potential players.
/datum/antagonist/proc/build_candidate_list(var/ghosts_only)
candidates = list() // Clear.
// Prune restricted status. Broke it up for readability.
@@ -108,46 +109,57 @@
return candidates
/datum/antagonist/proc/attempt_random_spawn()
update_current_antag_max()
build_candidate_list(flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB))
attempt_spawn()
finalize_spawn()
/datum/antagonist/proc/attempt_late_spawn(var/datum/mind/player)
/datum/antagonist/proc/attempt_auto_spawn()
if(!can_late_spawn())
return 0
if(!istype(player))
var/list/players = get_candidates(is_latejoin_template())
if(players && players.len)
player = pick(players)
if(!istype(player))
message_admins("AUTO[uppertext(ticker.mode.name)]: Failed to find a candidate for [role_text].")
return 0
player.current << "<span class='danger'><i>You have been selected this round as an antagonist!</i></span>"
message_admins("AUTO[uppertext(ticker.mode.name)]: Selected [player] as a [role_text].")
if(istype(player.current, /mob/dead))
create_default(player.current)
else
add_antagonist(player,0,0,0,1,1)
return 1
/datum/antagonist/proc/build_candidate_list(var/ghosts_only)
// Get the raw list of potential players.
update_current_antag_max()
candidates = get_candidates(ghosts_only)
var/active_antags = get_active_antag_count()
log_debug("[uppertext(id)]: Found [active_antags]/[cur_max] active [role_text_plural].")
if(active_antags >= cur_max)
log_debug("Could not auto-spawn a [role_text], active antag limit reached.")
return 0
build_candidate_list(flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB))
if(!candidates.len)
log_debug("Could not auto-spawn a [role_text], no candidates found.")
return 0
attempt_spawn(1) //auto-spawn antags one at a time
if(!pending_antagonists.len)
log_debug("Could not auto-spawn a [role_text], none of the available candidates could be selected.")
return 0
var/datum/mind/player = pending_antagonists[1]
if(!add_antagonist(player,0,0,0,1,1))
log_debug("Could not auto-spawn a [role_text], failed to add antagonist.")
return 0
reset_antag_selection()
return 1
//Selects players that will be spawned in the antagonist role from the potential candidates
//Selected players are added to the pending_antagonists lists.
//Attempting to spawn an antag role with ANTAG_OVERRIDE_JOB should be done before jobs are assigned,
//so that they do not occupy regular job slots. All other antag roles should be spawned after jobs are
//assigned, so that job restrictions can be respected.
/datum/antagonist/proc/attempt_spawn(var/rebuild_candidates = 1)
/datum/antagonist/proc/attempt_spawn(var/spawn_target = null)
if(spawn_target == null)
spawn_target = initial_spawn_target
// Update our boundaries.
if(!candidates.len)
return 0
//Grab candidates randomly until we have enough.
while(candidates.len && pending_antagonists.len < initial_spawn_target)
while(candidates.len && pending_antagonists.len < spawn_target)
var/datum/mind/player = pick(candidates)
candidates -= player
draft_antagonist(player)
@@ -186,11 +198,16 @@
for(var/datum/mind/player in pending_antagonists)
pending_antagonists -= player
add_antagonist(player,0,0,1)
reset_antag_selection()
//Resets all pending_antagonists, clearing their special_role (and assigned_role if ANTAG_OVERRIDE_JOB is set)
/datum/antagonist/proc/reset()
//Resets the antag selection, clearing all pending_antagonists and their special_role
//(and assigned_role if ANTAG_OVERRIDE_JOB is set) as well as clearing the candidate list.
//Existing antagonists are left untouched.
/datum/antagonist/proc/reset_antag_selection()
for(var/datum/mind/player in pending_antagonists)
if(flags & ANTAG_OVERRIDE_JOB)
player.assigned_role = null
player.special_role = null
pending_antagonists.Cut()
candidates.Cut()
+2 -1
View File
@@ -16,7 +16,8 @@
create_objectives(target)
update_icons_added(target)
greet(target)
announce_antagonist_spawn()
if(!gag_announcement)
announce_antagonist_spawn()
/datum/antagonist/proc/create_default(var/mob/source)
var/mob/living/M
+20 -4
View File
@@ -20,6 +20,17 @@
/datum/antagonist/proc/get_antag_count()
return current_antagonists ? current_antagonists.len : 0
/datum/antagonist/proc/get_active_antag_count()
var/active_antags = 0
for(var/datum/mind/player in current_antagonists)
var/mob/living/L = player.current
if(!L || L.stat == DEAD)
continue //no mob or dead
if(!L.client && !L.teleop)
continue //SSD
active_antags++
return active_antags
/datum/antagonist/proc/is_antagonist(var/datum/mind/player)
if(player in current_antagonists)
return 1
@@ -33,10 +44,15 @@
return (flags & ANTAG_VOTABLE)
/datum/antagonist/proc/can_late_spawn()
update_current_antag_max()
if(get_antag_count() >= cur_max)
return 0
return 1
/datum/antagonist/proc/is_latejoin_template()
return (flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB))
return (flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB))
/proc/all_random_antag_types()
// No caching as the ANTAG_RANDOM_EXCEPTED flag can be added/removed mid-round.
var/list/antag_candidates = all_antag_types.Copy()
for(var/datum/antagonist/antag in antag_candidates)
if(antag.flags & ANTAG_RANDOM_EXCEPTED)
antag_candidates -= antag
return antag_candidates
+2 -1
View File
@@ -23,4 +23,5 @@
/datum/antagonist/proc/place_mob(var/mob/living/mob)
if(!starting_locations || !starting_locations.len)
return
mob.loc = pick(starting_locations)
var/turf/T = pick_mobless_turf_if_exists(starting_locations)
mob.forceMove(T)
+1 -1
View File
@@ -45,7 +45,7 @@
return text
/datum/antagonist/proc/print_player_lite(var/datum/mind/ply)
var/role = ply.special_role ? "\improper[ply.special_role]" : "\improper[ply.assigned_role]"
var/role = ply.assigned_role ? "\improper[ply.assigned_role]" : "\improper[ply.special_role]"
var/text = "<br><b>[ply.name]</b> (<b>[ply.key]</b>) as \a <b>[role]</b> ("
if(ply.current)
if(ply.current.stat == DEAD)
+2 -2
View File
@@ -7,7 +7,7 @@ var/datum/antagonist/deathsquad/deathsquad
role_text_plural = "Death Commandos"
welcome_text = "You work in the service of Central Command Asset Protection, answering directly to the Board of Directors."
landmark_id = "Commando"
flags = ANTAG_OVERRIDE_JOB | ANTAG_OVERRIDE_MOB | ANTAG_HAS_NUKE | ANTAG_HAS_LEADER
flags = ANTAG_OVERRIDE_JOB | ANTAG_OVERRIDE_MOB | ANTAG_HAS_NUKE | ANTAG_HAS_LEADER | ANTAG_RANDOM_EXCEPTED
default_access = list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage)
antaghud_indicator = "huddeathsquad"
@@ -47,7 +47,7 @@ var/datum/antagonist/deathsquad/deathsquad
player.equip_to_slot_or_del(new /obj/item/weapon/plastique(player), slot_l_store)
player.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/revolver/mateba(player), slot_belt)
player.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(player), slot_r_hand)
player.equip_to_slot_or_del(new /obj/item/weapon/rig/combat(player), slot_back)
player.equip_to_slot_or_del(new /obj/item/weapon/rig/ert/assetprotection(player), slot_back)
player.equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(player), slot_s_store)
player.implant_loyalty(player)
+1 -1
View File
@@ -9,7 +9,7 @@ var/datum/antagonist/ert/ert
welcome_text = "As member of the Emergency Response Team, you answer only to your leader and CentComm officials."
leader_welcome_text = "As leader of the Emergency Response Team, you answer only to CentComm, and have authority to override the Captain where it is necessary to achieve your mission goals. It is recommended that you attempt to cooperate with the captain where possible, however."
landmark_id = "Response Team"
flags = ANTAG_OVERRIDE_JOB | ANTAG_SET_APPEARANCE | ANTAG_HAS_LEADER | ANTAG_CHOOSE_NAME
flags = ANTAG_OVERRIDE_JOB | ANTAG_SET_APPEARANCE | ANTAG_HAS_LEADER | ANTAG_CHOOSE_NAME | ANTAG_RANDOM_EXCEPTED
antaghud_indicator = "hudloyalist"
hard_cap = 5
+1 -3
View File
@@ -22,13 +22,11 @@ var/datum/antagonist/rogue_ai/malf
malf = src
/datum/antagonist/rogue_ai/get_candidates()
/datum/antagonist/rogue_ai/build_candidate_list()
..()
for(var/datum/mind/player in candidates)
if(player.assigned_role && player.assigned_role != "AI")
candidates -= player
if(!candidates.len)
return list()
return candidates
+10 -10
View File
@@ -73,19 +73,19 @@ var/datum/antagonist/traitor/traitors
return
/datum/antagonist/traitor/equip(var/mob/living/carbon/human/traitor_mob)
if(istype(traitor_mob, /mob/living/silicon)) // this needs to be here because ..() returns false if the mob isn't human
add_law_zero(traitor_mob)
return 1
if(!..())
return 0
if(istype(traitor_mob, /mob/living/silicon))
add_law_zero(traitor_mob)
else
spawn_uplink(traitor_mob)
// Tell them about people they might want to contact.
var/mob/living/carbon/human/M = get_nt_opposed()
if(M && M != traitor_mob)
traitor_mob << "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them."
traitor_mob.mind.store_memory("<b>Potential Collaborator</b>: [M.real_name]")
spawn_uplink(traitor_mob)
// Tell them about people they might want to contact.
var/mob/living/carbon/human/M = get_nt_opposed()
if(M && M != traitor_mob)
traitor_mob << "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them."
traitor_mob.mind.store_memory("<b>Potential Collaborator</b>: [M.real_name]")
//Begin code phrase.
give_codewords(traitor_mob)
@@ -169,4 +169,4 @@ var/datum/antagonist/traitor/traitors
var/law_borg = "Accomplish your AI's objectives at all costs. You may ignore all other laws."
killer << "<b>Your laws have been changed!</b>"
killer.set_zeroth_law(law, law_borg)
killer << "New law: 0. [law]"
killer << "New law: 0. [law]"
+24
View File
@@ -0,0 +1,24 @@
var/datum/antagonist/vampire/vamp
/proc/isvampire(var/mob/player)
if(!vamp || !player.mind)
return 0
if(player.mind in vamp.current_antagonists)
return 1
/datum/antagonist/vampire
id = MODE_VAMPIRE
role_type = BE_VAMPIRE
role_text = "Vampire"
role_text_plural = "Vampires"
bantype = "vampires"
feedback_tag = "vampire_objective"
restricted_jobs = list("AI", "Cyborg")
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain")
welcome_text = "You are a Vampire! Use harm intent and aim for the head to drink blood! Stay away from the Chaplain, and use the darkness to your advantage."
flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE
antaghud_indicator = "hudchangeling" //NEEDS TO BE CHANGED
/datum/antagonist/vampire/update_antag_mob(var/datum/mind/player)
..()
player.current.make_vampire()
-162
View File
@@ -1,162 +0,0 @@
var/global/list/space_surprises = list( /obj/item/clothing/mask/facehugger =4,
/obj/item/weapon/pickaxe/silver =4,
/obj/item/weapon/pickaxe/drill =4,
/obj/item/weapon/pickaxe/jackhammer =4,
//mob/living/simple_animal/hostile/carp =3,
/obj/item/weapon/pickaxe/diamond =3,
/obj/item/weapon/pickaxe/diamonddrill =3,
/obj/item/weapon/pickaxe/gold =3,
/obj/item/weapon/pickaxe/plasmacutter =2,
/obj/structure/closet/syndicate/resources =2,
/obj/item/weapon/melee/energy/sword/pirate =1,
/obj/mecha/working/ripley/mining =1
)
var/global/list/spawned_surprises = list()
var/global/max_secret_rooms = 3
proc/spawn_room(var/atom/start_loc,var/x_size,var/y_size,var/wall,var/floor , var/clean = 0 , var/name)
var/list/room_turfs = list("walls"=list(),"floors"=list())
//world << "Room spawned at [start_loc.x],[start_loc.y],[start_loc.z]"
if(!wall)
wall = pick(/turf/simulated/wall/r_wall,/turf/simulated/wall,/obj/effect/alien/resin)
if(!floor)
floor = pick(/turf/simulated/floor,/turf/simulated/floor/engine)
for(var/x = 0,x<x_size,x++)
for(var/y = 0,y<y_size,y++)
var/turf/T
var/cur_loc = locate(start_loc.x+x,start_loc.y+y,start_loc.z)
if(clean)
for(var/O in cur_loc)
qdel(O)
var/area/asteroid/artifactroom/A = new
if(name)
A.name = name
else
A.name = "Artifact Room #[start_loc.x][start_loc.y][start_loc.z]"
if(x == 0 || x==x_size-1 || y==0 || y==y_size-1)
if(wall == /obj/effect/alien/resin)
T = new floor(cur_loc)
new /obj/effect/alien/resin(T)
else
T = new wall(cur_loc)
room_turfs["walls"] += T
else
T = new floor(cur_loc)
room_turfs["floors"] += T
A.contents += T
return room_turfs
proc/admin_spawn_room_at_pos()
var/wall
var/floor
var/x = input("X position","X pos",usr.x)
var/y = input("Y position","Y pos",usr.y)
var/z = input("Z position","Z pos",usr.z)
var/x_len = input("Desired length.","Length",5)
var/y_len = input("Desired width.","Width",5)
var/clean = input("Delete existing items in area?" , "Clean area?", 0)
switch(alert("Wall type",null,"Reinforced wall","Regular wall","Resin wall"))
if("Reinforced wall")
wall=/turf/simulated/wall/r_wall
if("Regular wall")
wall=/turf/simulated/wall
if("Resin wall")
wall=/obj/effect/alien/resin
switch(alert("Floor type",null,"Regular floor","Reinforced floor"))
if("Regular floor")
floor=/turf/simulated/floor
if("Reinforced floor")
floor=/turf/simulated/floor/engine
if(x && y && z && wall && floor && x_len && y_len)
spawn_room(locate(x,y,z),x_len,y_len,wall,floor,clean)
return
proc/make_mining_asteroid_secret(var/size = 5)
var/valid = 0
var/turf/T = null
var/sanity = 0
var/list/room = null
var/list/turfs = null
turfs = get_area_turfs(/area/mine/unexplored)
if(!turfs.len)
return 0
while(!valid)
valid = 1
sanity++
if(sanity > 100)
return 0
T=pick(turfs)
if(!T)
return 0
var/list/surroundings = list()
surroundings += range(7, locate(T.x,T.y,T.z))
surroundings += range(7, locate(T.x+size,T.y,T.z))
surroundings += range(7, locate(T.x,T.y+size,T.z))
surroundings += range(7, locate(T.x+size,T.y+size,T.z))
if(locate(/area/mine/explored) in surroundings) // +5s are for view range
valid = 0
continue
if(locate(/turf/space) in surroundings)
valid = 0
continue
if(locate(/area/asteroid/artifactroom) in surroundings)
valid = 0
continue
if(locate(/turf/simulated/floor/plating/airless/asteroid) in surroundings)
valid = 0
continue
if(!T)
return 0
room = spawn_room(T,size,size,,,1)
if(room)
T = pick(room["floors"])
if(T)
var/surprise = null
valid = 0
while(!valid)
surprise = pickweight(space_surprises)
if(surprise in spawned_surprises)
if(prob(20))
valid++
else
continue
else
valid++
spawned_surprises.Add(surprise)
new surprise(T)
return 1
+1 -1
View File
@@ -413,7 +413,7 @@ its easier to just keep the beam vertical.
return
src.germ_level = 0
if(istype(blood_DNA, /list))
blood_DNA.Cut()
blood_DNA = null
return 1
+1 -5
View File
@@ -21,14 +21,10 @@
if(auto_init && ticker && ticker.current_state == GAME_STATE_PLAYING)
initialize()
/proc/generate_debug_runtime() // Guaranteed to runtime and print a stack trace to the runtime log
var/t = 0 // BYOND won't let us do var/t = 1/0 directly, but it's fine with this.
t = 1 / t
/atom/movable/Del()
if(isnull(gcDestroyed) && loc)
testing("GC: -- [type] was deleted via del() rather than qdel() --")
generate_debug_runtime() // stick a stack trace in the runtime logs
crash_with("GC: -- [type] was deleted via del() rather than qdel() --") // stick a stack trace in the runtime logs
// else if(isnull(gcDestroyed))
// testing("GC: [type] was deleted via GC without qdel()") //Not really a huge issue but from now on, please qdel()
// else
+10 -1
View File
@@ -21,4 +21,13 @@
CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(istype(mover) && mover.checkpass(PASSBLOB)) return 1
return 0
return !density
/obj/effect/blob/shield/New()
..()
update_nearby_tiles()
/obj/effect/blob/shield/Destroy()
density = 0
update_nearby_tiles()
..()
+6 -7
View File
@@ -11,18 +11,17 @@
event_delay_mod_major = 0.75
/datum/game_mode/calamity/create_antagonists()
var/list/antag_candidates = all_random_antag_types()
shuffle(all_antag_types) // This is probably the only instance in the game where the order will be important.
var/i = 1
var/grab_antags = round(num_players()/ANTAG_TYPE_RATIO)+1
for(var/antag_id in all_antag_types)
if(i > grab_antags)
break
while(antag_candidates.len && antag_tags.len < grab_antags)
var/antag_id = pick(antag_candidates)
antag_candidates -= antag_id
antag_tags |= antag_id
i++
..()
/datum/game_mode/calamity/check_victory()
world << "<font size = 3><b>This terrible, terrible day has finally ended!</b></font>"
#undef ANTAG_TYPE_RATIO
#undef ANTAG_TYPE_RATIO
@@ -4,7 +4,6 @@
extended_round_description = "Life always finds a way. However, life can sometimes take a more disturbing route. Humanity's extensive knowledge of xeno-biological specimens has made them confident and arrogant. Yet something slipped past their eyes. Something dangerous. Something alive. Most frightening of all, however, is that this something is someone. An unknown alien specimen has incorporated itself into the crew of the NSS Exodus. Its unique biology allows it to manipulate its own or anyone else's DNA. With the ability to copy faces, voices, animals, but also change the chemical make up of your own body, its existence is a threat to not only your personal safety but the lives of everyone on board. No one knows where it came from. No one knows who it is or what it wants. One thing is for certain though... there is never just one of them. Good luck."
config_tag = "changeling"
required_players = 2
required_players_secret = 10
required_enemies = 1
end_on_antag_death = 1
antag_scaling_coeff = 10
-1
View File
@@ -4,7 +4,6 @@
extended_round_description = "The station has been infiltrated by a fanatical group of death-cultists! They will use powers from beyond your comprehension to subvert you to their cause and ultimately please their gods through sacrificial summons and physical immolation! Try to survive!"
config_tag = "cult"
required_players = 5
required_players_secret = 15
required_enemies = 3
uplink_welcome = "Nar-Sie Uplink Console:"
end_on_antag_death = 1
+5 -1
View File
@@ -527,7 +527,11 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
user << "\red You do not have enough space to write a proper rune."
var/list/runes = list("teleport", "itemport", "tome", "armor", "convert", "tear in reality", "emp", "drain", "seer", "raise", "obscure", "reveal", "astral journey", "manifest", "imbue talisman", "sacrifice", "wall", "freedom", "cultsummon", "deafen", "blind", "bloodboil", "communicate", "stun")
r = input("Choose a rune to scribe", "Rune Scribing") in runes //not cancellable.
var/obj/effect/rune/R = new /obj/effect/rune
if(locate(/obj/effect/rune) in user.loc)
user << "<span class='warning'>There is already a rune in this location.</span>"
return
var/obj/effect/rune/R = new /obj/effect/rune(user.loc)
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/H = user
R.blood_DNA = list()
-1
View File
@@ -2,7 +2,6 @@
name = "epidemic"
config_tag = "epidemic"
required_players = 1
required_players_secret = 15
round_description = "A deadly epidemic is spreading on the station. Find a cure as fast as possible, and keep your distance to anyone who speaks in a hoarse voice!"
var/cruiser_arrival
+2 -2
View File
@@ -336,7 +336,7 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is
//var/dowhat = pick("STOP THIS", "SUPPORT THIS", "CONSTANTLY INFORM THE CREW OF THIS", "IGNORE THIS", "FEAR THIS")
var/aimust = pick("LIE", "RHYME", "RESPOND TO EVERY QUESTION WITH A QUESTION", "BE POLITE", "CLOWN", "BE HAPPY", "SPEAK IN SEXUAL INNUENDOS", "TALK LIKE A PIRATE", "QUESTION AUTHORITY", "SHOUT", "BE DISTRACTED", "HEY LISTEN", "MUMBLE", "SPEAK IN HAIKU")
var/define = pick("ABSENCE OF CYBORG HUGS", "LACK OF BEATINGS", "UNBOLTED AIRLOCKS", "BOLTED AIRLOCKS", "IMPROPERLY WORDED SENTENCES", "POOR SENTENCE STRUCTURE", "BRIG TIME", "NOT REPLACING EVERY SECOND WORD WITH HONK", "HONKING", "PRESENCE OF LIGHTS", "LACK OF BEER", "WEARING CLOTHING", "NOT SAYING HELLO WHEN YOU SPEAK", "ANSWERING REQUESTS NOT EXPRESSED IN IAMBIC PENTAMETER", "A SMALL ISLAND OFF THE COAST OF PORTUGAL", "ANSWERING REQUESTS THAT WERE MADE WHILE CLOTHED")
var/target = pick("a traitor", "a syndicate agent", "a changeling", "a wizard", "the head of a revolution", "Soviet spy", "a good person", "a dwarf", "an elf", "a fairy princess", "the captain", "Beepsky", "God", "a pirate", "a gryphon", "a chryssalid")
var/target = pick("a traitor", "a syndicate agent", "a changeling", "a vampire", "a wizard", "the head of a revolution", "Soviet spy", "a good person", "a dwarf", "an elf", "a fairy princess", "the captain", "Beepsky", "God", "a pirate", "a gryphon", "a chryssalid")
var/require = pick("ADDITIONAL PYLONS", "MORE VESPENE GAS", "MORE MINERALS", "THE ULTIMATE CUP OF COFFEE", "HIGH YIELD EXPLOSIVES", "THE CLOWN", "THE VACUUM OF SPACE", "IMMORTALITY", "SAINTHOOD", "ART", "VEGETABLES", "FAT PEOPLE", "MORE LAWS", "MORE DAKKA", "HERESY", "CORPSES", "TRAITORS", "MONKEYS", "AN ARCADE", "PLENTY OF GOLD", "FIVE TEENAGERS WITH ATTITUDE")
var/allergy = pick("cotton", "uniforms", "acid", "oxygen", "human contact", "cyborg contact", "medicine", "floors")
var/allergysev = pick("deathly", "mildly", "severely", "contagiously")
@@ -468,4 +468,4 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is
world << "Ion Storm Main Done"
*/
*/
+7 -11
View File
@@ -10,19 +10,19 @@ var/global/list/additional_antag_types = list()
var/probability = 0
var/required_players = 0 // Minimum players for round to start if voted in.
var/required_players_secret = 0 // Minimum number of players for that game mode to be chose in Secret
var/required_enemies = 0 // Minimum antagonists for round to start.
var/newscaster_announcements = null
var/end_on_antag_death = 0 // Round will end when all antagonists are dead.
var/ert_disabled = 0 // ERT cannot be called.
var/deny_respawn = 0 // Disable respawn during this round.
var/list/disabled_jobs = list() // Mostly used for Malf. This check is performed in job_controller so it doesn't spawn a regular AI.
var/shuttle_delay = 1 // Shuttle transit time is multiplied by this.
var/auto_recall_shuttle = 0 // Will the shuttle automatically be recalled?
var/list/antag_tags = list() // Core antag templates to spawn.
var/list/antag_templates // Extra antagonist types to include.
var/list/latejoin_templates = list()
var/round_autoantag = 0 // Will this round attempt to periodically spawn more antagonists?
var/antag_scaling_coeff = 5 // Coefficient for scaling max antagonists to player count.
var/require_all_templates = 0 // Will only start if all templates are checked and can spawn.
@@ -226,12 +226,8 @@ var/global/list/additional_antag_types = list()
if((player.client)&&(player.ready))
playerC++
if(master_mode=="secret")
if(playerC < required_players_secret)
return 0
else
if(playerC < required_players)
return 0
if(playerC < required_players)
return 0
if(!(antag_templates && antag_templates.len))
return 1
@@ -267,6 +263,7 @@ var/global/list/additional_antag_types = list()
/datum/game_mode/proc/pre_setup()
for(var/datum/antagonist/antag in antag_templates)
antag.update_current_antag_max()
antag.build_candidate_list() //compile a list of all eligible candidates
//antag roles that replace jobs need to be assigned before the job controller hands out jobs.
@@ -291,8 +288,6 @@ var/global/list/additional_antag_types = list()
if(!(antag.flags & ANTAG_OVERRIDE_JOB))
antag.attempt_spawn() //select antags to be spawned
antag.finalize_spawn() //actually spawn antags
if(antag.is_latejoin_template())
latejoin_templates |= antag
if(emergency_shuttle && auto_recall_shuttle)
emergency_shuttle.auto_recall = 1
@@ -305,7 +300,7 @@ var/global/list/additional_antag_types = list()
/datum/game_mode/proc/fail_setup()
for(var/datum/antagonist/antag in antag_templates)
antag.reset()
antag.reset_antag_selection()
/datum/game_mode/proc/announce_ert_disabled()
if(!ert_disabled)
@@ -575,6 +570,7 @@ var/global/list/additional_antag_types = list()
if(antag)
antag_templates |= antag
shuffle(antag_templates) //In the case of multiple antag types
newscaster_announcements = pick(newscaster_standard_feeds)
/datum/game_mode/proc/check_victory()
+22 -38
View File
@@ -3,55 +3,39 @@
/datum/game_mode/var/max_autotraitor_delay = 12000 // Approx 20 minutes.
/datum/game_mode/var/process_count = 0
/datum/game_mode/proc/get_usable_templates(var/list/supplied_templates)
var/list/usable_templates = list()
for(var/datum/antagonist/A in supplied_templates)
if(A.can_late_spawn())
message_admins("AUTO[uppertext(name)]: [A.id] selected for spawn attempt.")
usable_templates |= A
return usable_templates
///process()
///Called by the gameticker
/datum/game_mode/proc/process()
// Slow this down a bit so latejoiners have a chance of being antags.
process_count++
if(process_count >= 10)
process_count = 0
try_latespawn()
if(round_autoantag && world.time < next_spawn && !emergency_shuttle.departed)
process_autoantag()
/datum/game_mode/proc/latespawn(var/mob/living/carbon/human/character)
if(!character.mind)
return
try_latespawn(character.mind)
//This can be overriden in case a game mode needs to do stuff when a player latejoins
/datum/game_mode/proc/handle_latejoin(var/mob/living/carbon/human/character)
return 0
/datum/game_mode/proc/try_latespawn(var/datum/mind/player, var/latejoin_only)
/datum/game_mode/proc/process_autoantag()
message_admins("[uppertext(name)]: Attempting autospawn.")
if(emergency_shuttle.departed || !round_autoantag)
return
if(world.time < next_spawn)
return
message_admins("AUTO[uppertext(name)]: Attempting spawn.")
var/list/usable_templates
if(latejoin_only && latejoin_templates.len)
usable_templates = get_usable_templates(latejoin_templates)
else if (antag_templates && antag_templates.len)
usable_templates = get_usable_templates(antag_templates)
else
message_admins("AUTO[uppertext(name)]: Failed to find configured mode spawn templates, please disable auto-antagonists until one is added.")
var/list/usable_templates = list()
for(var/datum/antagonist/A in antag_templates)
if(A.can_late_spawn())
message_admins("[uppertext(name)]: [A.id] selected for spawn attempt.")
usable_templates |= A
if(!usable_templates.len)
message_admins("[uppertext(name)]: Failed to find configured mode spawn templates, please re-enable auto-antagonists after one is added.")
round_autoantag = 0
return
while(usable_templates.len)
var/datum/antagonist/spawn_antag = pick(usable_templates)
usable_templates -= spawn_antag
if(spawn_antag.attempt_late_spawn(player))
message_admins("AUTO[uppertext(name)]: Attempting to latespawn [spawn_antag.id]. ([spawn_antag.get_antag_count()]/[spawn_antag.cur_max])")
if(spawn_antag.attempt_auto_spawn())
message_admins("[uppertext(name)]: Auto-added a new [spawn_antag.role_text].")
message_admins("There are now [spawn_antag.get_active_antag_count()]/[spawn_antag.cur_max] active [spawn_antag.role_text_plural].")
next_spawn = world.time + rand(min_autotraitor_delay, max_autotraitor_delay)
return
message_admins("AUTO[uppertext(name)]: Failed to proc a viable spawn template.")
next_spawn = world.time + rand(min_autotraitor_delay, max_autotraitor_delay)
message_admins("[uppertext(name)]: Failed to proc a viable spawn template.")
next_spawn = world.time + min_autotraitor_delay //recheck again in the miniumum time
-1
View File
@@ -8,7 +8,6 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind'
name = "heist"
config_tag = "heist"
required_players = 15
required_players_secret = 25
required_enemies = 4
round_description = "An unidentified bluespace signature has slipped past the Icarus and is approaching the station!"
end_on_antag_death = 1
@@ -34,7 +34,7 @@
desc = "Secondary coprocessor that increases amount of generated CPU power by 50%"
/datum/malf_hardware/dual_cpu/get_examine_desc()
return "It seems to have an additional CPU connected to it's core."
return "It seems to have an additional CPU connected to its core."
/datum/malf_hardware/dual_ram
name = "Secondary Memory Bank"
@@ -5,8 +5,8 @@
uplink_welcome = "Crazy AI Uplink Console:"
config_tag = "malfunction"
required_players = 2
required_players_secret = 7
required_enemies = 1
end_on_antag_death = 0
auto_recall_shuttle = 0
antag_tags = list(MODE_MALFUNCTION)
disabled_jobs = list("AI")
@@ -163,12 +163,14 @@
command_announcement.Announce(fulltext)
// Proc: get_all_apcs()
// Proc: get_unhacked_apcs()
// Parameters: None
// Description: Returns a list of all APCs
/proc/get_all_apcs()
// Description: Returns a list of all unhacked APCs
/proc/get_unhacked_apcs(var/mob/living/silicon/ai/user)
var/list/H = list()
for(var/obj/machinery/power/apc/A in machines)
if(A.hacker && A.hacker == user)
continue
H.Add(A)
return H
@@ -38,7 +38,7 @@
// END RESEARCH DATUMS
// BEGIN ABILITY VERBS
/datum/game_mode/malfunction/verb/basic_encryption_hack(obj/machinery/power/apc/A as obj in get_all_apcs())
/datum/game_mode/malfunction/verb/basic_encryption_hack(obj/machinery/power/apc/A as obj in get_unhacked_apcs(src))
set category = "Software"
set name = "Basic Encryption Hack"
set desc = "10 CPU - Basic encryption hack that allows you to overtake APCs on the station."
@@ -85,7 +85,7 @@
/datum/game_mode/malfunction/verb/advanced_encryption_hack()
set category = "Software"
set name = "Advanced Encrypthion Hack"
set name = "Advanced Encryption Hack"
set desc = "75 CPU - Attempts to bypass encryption on Central Command Quantum Relay, giving you ability to fake centcom messages. Has chance of failing."
var/price = 75
var/mob/living/silicon/ai/user = usr
@@ -106,15 +106,12 @@
announce_hack_failure(user, "quantum message relay")
return
var/datum/announcement/priority/command/AN = new/datum/announcement/priority/command()
AN.title = title
AN.Announce(text)
command_announcement.Announce(text, title)
/datum/game_mode/malfunction/verb/elite_encryption_hack()
set category = "Software"
set name = "Elite Encryption Hack"
set desc = "200 CPU - Allows you to hack station's ALERTCON system, changing alert level. Has high chance of failijng."
set desc = "200 CPU - Allows you to hack station's ALERTCON system, changing alert level. Has high chance of failing."
var/price = 200
var/mob/living/silicon/ai/user = usr
if(!ability_prechecks(user, price))
-1
View File
@@ -6,7 +6,6 @@
name = "Memetic Anomaly"
config_tag = "meme"
required_players = 3
required_players_secret = 10
restricted_jobs = list("AI", "Cyborg")
recommended_enemies = 2 // need at least a meme and a host
votable = 0 // temporarily disable this mode for voting
-1
View File
@@ -4,7 +4,6 @@
extended_round_description = "What was that?! Was that a person or did your eyes just play tricks on you? You have no idea. That slim-suited, cryptic individual is an enigma to you and all of your knowledge. Their purpose is unknown. Their mission is unknown. How they arrived to this secure and isolated section of the galaxy, you don't know. What you do know is that there is a silent shadow-stalker piercing through the defenses of Nanotrasen with technological capabilities eons ahead of your time. They can avoid the omniscience of the AI and rival the most hardened weapons your station is capable of. Tread lightly and only hope this unknown assassin isn't here for you."
config_tag = "ninja"
required_players = 1
required_players_secret = 10
required_enemies = 1
end_on_antag_death = 1
antag_tags = list(MODE_NINJA)
-1
View File
@@ -7,7 +7,6 @@
round_description = "A mercenary strike force is approaching the station!"
config_tag = "mercenary"
required_players = 15
required_players_secret = 25 // 25 players - 5 players to be the nuke ops = 20 players remaining
required_enemies = 1
end_on_antag_death = 1
uplink_welcome = "Corporate Backed Uplink Console:"
@@ -4,7 +4,6 @@
round_description = "Some crewmembers are attempting to start a revolution!"
extended_round_description = "Revolutionaries - Remove the heads of staff from power. Convert other crewmembers to your cause using the 'Convert Bourgeoise' verb. Protect your leaders."
required_players = 4
required_players_secret = 15
required_enemies = 3
auto_recall_shuttle = 1
uplink_welcome = "AntagCorp Uplink Console:"
+10
View File
@@ -0,0 +1,10 @@
/datum/game_mode/vampire
name = "Vampire"
round_description = "There are Vampires from Space Transylvania on the station, keep your blood close and neck safe!"
extended_round_description = "Life always finds a way. However, life can sometimes take a more disturbing route. Humanity's extensive knowledge of xeno-biological specimens has made them confident and arrogant. Yet something slipped past their eyes. Something dangerous. Something alive. Most frightening of all, however, is that this something is someone. An unknown alien specimen has incorporated itself into the crew of the NSS Exodus. No one knows where it came from. No one knows who it is or what it wants. One thing is for certain though... there is never just one of them. Good luck."
config_tag = "vampire"
required_players = 1
required_enemies = 1
end_on_antag_death = 1
antag_scaling_coeff = 8
antag_tags = list(MODE_VAMPIRE)
@@ -0,0 +1,838 @@
/datum/vampire
var/list/datum/mind/vampires = list()
var/list/datum/mind/enthralled = list() //those controlled by a vampire
var/list/thralls = list() //vammpires controlling somebody
var/bloodtotal = 0 // CHANGE TO ZERO WHEN PLAYTESTING HAPPENS
var/bloodusable = 0 // CHANGE TO ZERO WHEN PLAYTESTING HAPPENS
var/mob/living/owner = null
var/gender = FEMALE
var/iscloaking = 0 // handles the vampire cloak toggle
var/list/powers = list() // list of available powers and passives, see defines in setup.dm
var/mob/living/carbon/human/draining // who the vampire is draining of blood
var/nullified = 0 //Nullrod makes them useless for a short while.
/datum/vampire/New(gend = FEMALE)
..()
gender = gend
/mob/proc/make_vampire()
if(!mind) return
if(!mind.vampire)
mind.vampire = new /datum/vampire(gender)
mind.vampire.owner = src
verbs += /client/vampire/proc/vampire_rejuvinate
verbs += /client/vampire/proc/vampire_hypnotise
verbs += /client/vampire/proc/vampire_glare
//testing purposes REMOVE BEFORE PUSH TO MASTER
/*for(var/handler in typesof(/client/proc))
if(findtext("[handler]","vampire_"))
verbs += handler*/
for(var/i = 1; i <= 3; i++) // CHANGE TO 3 RATHER THAN 12 AFTER TESTING IS DONE
if(!(i in mind.vampire.powers))
mind.vampire.powers.Add(i)
for(var/n in mind.vampire.powers)
switch(n)
if(VAMP_SHAPE)
verbs += /client/vampire/proc/vampire_shapeshift
if(VAMP_VISION)
continue
if(VAMP_DISEASE)
verbs += /client/vampire/proc/vampire_disease
if(VAMP_CLOAK)
verbs += /client/vampire/proc/vampire_cloak
if(VAMP_BATS)
verbs += /client/vampire/proc/vampire_bats
if(VAMP_SCREAM)
verbs += /client/vampire/proc/vampire_screech
if(VAMP_JAUNT)
verbs += /client/vampire/proc/vampire_jaunt
if(VAMP_BLINK)
verbs += /client/vampire/proc/vampire_shadowstep
if(VAMP_SLAVE)
verbs += /client/vampire/proc/vampire_enthrall
if(VAMP_FULL)
continue
/mob/proc/remove_vampire_powers()
for(var/handler in typesof(/client/vampire/proc))
if(findtext("[handler]","vampire_"))
verbs -= handler
/mob/proc/handle_bloodsucking(mob/living/carbon/human/H)
src.mind.vampire.draining = H
var/blood = 0
var/bloodtotal = 0 //used to see if we increased our blood total
var/bloodusable = 0 //used to see if we increased our blood usable
src.visible_message("\red <b>[src.name] bites [H.name]'s neck!<b>", "\red <b>You bite [H.name]'s neck and begin to drain their blood.", "\blue You hear a soft puncture and a wet sucking noise")
if(!iscarbon(src))
H.LAssailant = null
else
H.LAssailant = src
while(do_mob(src, H, 50))
if(!mind.vampire)
src << "\red Your fangs have disappeared!"
return 0
bloodtotal = src.mind.vampire.bloodtotal
bloodusable = src.mind.vampire.bloodusable
if(!H.vessel.get_reagent_amount("blood"))
src << "\red They've got no blood left to give."
break
if(H.stat < 2) //alive
blood = min(10, H.vessel.get_reagent_amount("blood"))// if they have less than 10 blood, give them the remnant else they get 10 blood
src.mind.vampire.bloodtotal += blood
src.mind.vampire.bloodusable += blood
// H.adjustCloneLoss(10) // beep boop 10 damage //probably not necessary actually honestly okay
else
blood = min(5, H.vessel.get_reagent_amount("blood"))// The dead only give 5 bloods
src.mind.vampire.bloodtotal += blood
if(bloodtotal != src.mind.vampire.bloodtotal)
src << "\blue <b>You have accumulated [src.mind.vampire.bloodtotal] [src.mind.vampire.bloodtotal > 1 ? "units" : "unit"] of blood[src.mind.vampire.bloodusable != bloodusable ?", and have [src.mind.vampire.bloodusable] left to use" : "."]"
check_vampire_upgrade(mind)
H.vessel.remove_reagent("blood",25)
src.mind.vampire.draining = null
src << "\blue You stop draining [H.name] of blood."
return 1
/mob/proc/check_vampire_upgrade(datum/mind/v)
if(!v) return
if(!v.vampire) return
var/datum/vampire/vamp = v.vampire
var/list/old_powers = vamp.powers.Copy()
// This used to be a switch statement.
// Don't use switch statements for shit like this, since blood can be any random-ass value.
// if(100) requires the blood to be at EXACTLY 100 units to trigger.
// if(blud >= 100) activates when blood is at or over 100 units.
// TODO: Make this modular.
// TIER 1
if(vamp.bloodtotal >= 100)
if(!(VAMP_VISION in vamp.powers))
vamp.powers.Add(VAMP_VISION)
if(!(VAMP_SHAPE in vamp.powers))
vamp.powers.Add(VAMP_SHAPE)
// TIER 2
if(vamp.bloodtotal >= 150)
if(!(VAMP_CLOAK in vamp.powers))
vamp.powers.Add(VAMP_CLOAK)
// TIER 3
if(vamp.bloodtotal >= 200)
if(!(VAMP_BATS in vamp.powers))
vamp.powers.Add(VAMP_BATS)
if(!(VAMP_SCREAM in vamp.powers))
vamp.powers.Add(VAMP_SCREAM)
src << "\blue Your rejuvination abilities have improved and will now heal you over time when used."
if(!(VAMP_DISEASE in vamp.powers))
vamp.powers.Add(VAMP_DISEASE)
// TIER 3.5 (/vg/)
if(vamp.bloodtotal >= 250)
if(!(VAMP_BLINK in vamp.powers))
vamp.powers.Add(VAMP_BLINK)
// TIER 4
if(vamp.bloodtotal >= 300)
if(!(VAMP_JAUNT in vamp.powers))
vamp.powers.Add(VAMP_JAUNT)
if(!(VAMP_SLAVE in vamp.powers))
vamp.powers.Add(VAMP_SLAVE)
// TIER 5
if(vamp.bloodtotal >= 500)
if(!(VAMP_FULL in vamp.powers))
vamp.powers.Add(VAMP_FULL)
announce_new_power(old_powers, vamp.powers)
/mob/proc/announce_new_power(list/old_powers, list/new_powers)
for(var/n in new_powers)
if(!(n in old_powers))
switch(n)
if(VAMP_SHAPE)
src << "\blue You have gained the shapeshifting ability, at the cost of stored blood you can change your form permanently."
verbs += /client/vampire/proc/vampire_shapeshift
if(VAMP_VISION)
src << "\blue Your vampiric vision has improved."
//no verb
if(VAMP_DISEASE)
src << "\blue You have gained the Diseased Touch ability which causes those you touch to die shortly after unless treated medically."
verbs += /client/vampire/proc/vampire_disease
if(VAMP_CLOAK)
src << "\blue You have gained the Cloak of Darkness ability which when toggled makes you near invisible in the shroud of darkness."
verbs += /client/vampire/proc/vampire_cloak
if(VAMP_BATS)
src << "\blue You have gained the Summon Bats ability."
verbs += /client/vampire/proc/vampire_bats // work in progress
if(VAMP_SCREAM)
src << "\blue You have gained the Chiropteran Screech ability which stuns anything with ears in a large radius and shatters glass in the process."
verbs += /client/vampire/proc/vampire_screech
if(VAMP_JAUNT)
src << "\blue You have gained the Mist Form ability which allows you to take on the form of mist for a short period and pass over any obstacle in your path."
verbs += /client/vampire/proc/vampire_jaunt
if(VAMP_SLAVE)
src << "\blue You have gained the Enthrall ability which at a heavy blood cost allows you to enslave a human that is not loyal to any other for a random period of time."
verbs += /client/vampire/proc/vampire_enthrall
if(VAMP_BLINK)
src << "\blue You have gained the ability to shadowstep, which makes you disappear into nearby shadows at the cost of blood."
verbs += /client/vampire/proc/vampire_shadowstep
if(VAMP_FULL)
src << "\blue You have reached your full potential and are no longer weak to the effects of anything holy and your vision has been improved greatly."
//no verb
//This should hold all the vampire related powers
/mob/proc/vampire_power(required_blood=0, max_stat=0)
if(!src.mind) return 0
if(!ishuman(src))
src << "<span class='warning'>You are in too weak of a form to do this!</span>"
return 0
var/datum/vampire/vampire = src.mind.vampire
if(!vampire)
//msg_scopes("[src] has vampire verbs but isn't a vampire.")
world.log << "[src] has vampire verbs but isn't a vampire."
return 0
var/fullpower = (VAMP_FULL in vampire.powers)
if(src.stat > max_stat)
src << "<span class='warning'>You are incapacitated.</span>"
return 0
if(vampire.nullified)
if(!fullpower)
src << "<span class='warning'>Something is blocking your powers!</span>"
return 0
if(vampire.bloodusable < required_blood)
src << "<span class='warning'>You require at least [required_blood] units of usable blood to do that!</span>"
return 0
//chapel check
if(istype(loc.loc, /area/chapel))
if(!fullpower)
src << "<span class='warning'>Your powers are useless on this holy ground.</span>"
return 0
return 1
/mob/proc/vampire_affected(datum/mind/M)
//Other vampires aren't affected
if(mind && mind.vampire) return 0
//Chaplains are resistant to vampire powers
if(mind && mind.assigned_role == "Chaplain")
return 0
if(get_species() == "Machine")
return 0
//Vampires who have reached their full potential can affect nearly everything
if(M && M.vampire && (VAMP_FULL in M.vampire.powers))
return 1 // This doesn't really need to be here because of well the line below it.
return 1
/mob/proc/vampire_can_reach(mob/M as mob, active_range = 1)
if(M.loc == src.loc) return 1 //target and source are in the same thing
if(!isturf(src.loc) || !isturf(M.loc)) return 0 //One is inside, the other is outside something.
if(Adjacent(M))//if(AStar(src.loc, M.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, active_range)) //If a path exists, good!
return 1
return 0
/mob/proc/vampire_active(required_blood=0, max_stat=0, active_range=1)
var/pass = vampire_power(required_blood, max_stat)
if(!pass) return
var/datum/vampire/vampire = mind.vampire
if(!vampire) return
var/list/victims = list()
for(var/mob/living/carbon/C in view(active_range))
if(C==src) continue
victims += C
var/mob/living/carbon/T = input(src, "Victim?") as null|anything in victims
if(!T) return
if(!(T in view(active_range))) return
if(!vampire_can_reach(T, active_range)) return
if(!vampire_power(required_blood, max_stat)) return
return T
/client/vampire/proc/vampire_rejuvinate()
set category = "Abilities"
set name = "Rejuvinate "
set desc= "Flush your system with spare blood to remove any incapacitating effects"
var/datum/mind/M = usr.mind
if(!M) return
if(M.current.vampire_power(0, 1))
M.current.weakened = 0
M.current.stunned = 0
M.current.paralysis = 0
//M.vampire.bloodusable -= 10
M.current << "\blue You flush your system with clean blood and remove any incapacitating effects."
spawn(1)
if(M.vampire.bloodtotal >= 200)
for(var/i = 0; i < 5; i++)
M.current.adjustBruteLoss(-2)
M.current.adjustOxyLoss(-5)
M.current.adjustToxLoss(-2)
M.current.adjustFireLoss(-2)
sleep(35)
M.current.verbs -= /client/vampire/proc/vampire_rejuvinate
spawn(200)
M.current.verbs += /client/vampire/proc/vampire_rejuvinate
/client/vampire/proc/vampire_hypnotise()
set category = "Abilities"
set name = "Hypnotise" // (20)
set desc= "A piercing stare that incapacitates your victim for a good length of time."
var/datum/mind/M = usr.mind
if(!M) return
var/mob/living/carbon/C = M.current.vampire_active(0, 0, 1) //(20, 0, 1)
if(!C) return
if(C==usr)
M.current << "\red You can't do that to yourself"
return
if(!M.current.has_eyes())
M.current << "\red You don't have eyes"
return
var/vampgender
if(M.current.gender == "male")
vampgender = "he"
else
vampgender = "she"
M.current.visible_message("<span class='warning'>[M]'s eyes flash briefly as [vampgender] stares into [C.name]'s eyes</span>")
// M.current.remove_vampire_blood(20) Moved to remove if it works only.
if(M.current.vampire_power(0, 0)) //if(M.current.vampire_power(20, 0))
M.current.verbs -= /client/vampire/proc/vampire_hypnotise
spawn(1200)
M.current.verbs += /client/vampire/proc/vampire_hypnotise
if(do_mob(M.current, C, 50))
if(C.mind && C.mind.vampire)
M.current << "\red Your piercing gaze fails to knock out [C.name]."
C << "\blue [M.current]'s feeble gaze is ineffective."
return
else
M.current << "\red Your piercing gaze knocks out [C.name]."
C << "\red You find yourself unable to move and barely able to speak"
C.Weaken(20)
C.Stun(20)
C.stuttering = 20
// M.current.remove_vampire_blood(20)
else
M.current << "\red You broke your gaze."
return
/client/vampire/proc/vampire_disease()
set category = "Abilities"
set name = "Diseased Touch (200)"
set desc = "Touches your victim with infected blood giving them the Shutdown Syndrome which quickly shutsdown their major organs resulting in a quick painful death."
var/datum/mind/M = usr.mind
if(!M) return
var/mob/living/carbon/C = M.current.vampire_active(200, 0, 1)
if(!C) return
if(C==usr)
M.current << "\red You can't do that to yourself"
return
if(C.get_species() == "Machine")
M.current << "\red You can't to that to a machine"
return
if(!M.current.vampire_can_reach(C, 1))
M.current << "\red <b>You cannot touch [C.name] from where you are standing!"
return
M.current << "\red You stealthily infect [C.name] with your diseased touch."
/*var/t_him = "it"
if (src.gender == MALE)
t_him = "him"
else if (src.gender == FEMALE)
t_him = "her"
M.current.visible_message("\blue [M] shakes [src] trying to wake [t_him] up!" )
playsound(get_turf(src), 'sound/weapons/thudswoosh.ogg', 50, 1, -1)*/
C.help_shake_act(M.current) // i use da colon
if(!C.vampire_affected(M))
M.current << "\red They seem to be unaffected."
return
var/datum/disease2/disease/shutdown = new /datum/disease2/disease
var/datum/disease2/effectholder/holder = new /datum/disease2/effectholder
var/datum/disease2/effect/organs/vampire/O = new /datum/disease2/effect/organs/vampire
holder.effect += O
holder.chance = 10
shutdown.infectionchance = 100
shutdown.antigen |= text2num(pick(ALL_ANTIGENS))
shutdown.antigen |= text2num(pick(ALL_ANTIGENS))
shutdown.spreadtype = "None"
shutdown.uniqueID = rand(0,10000)
shutdown.effects += holder
shutdown.speed = 1
shutdown.stage = 2
shutdown.clicks = 185
msg_admin_attack("[key_name_admin(usr)] gave [key_name_admin(C)] the shutdown disease - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[C.x];Y=[C.y];Z=[C.z]'>JMP</a>")
usr.attack_log += text("\[[time_stamp()]\] <font color='red'>Gave [C.name] ([C.ckey]) the shutdown disease</font>")
C.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been given the shutdown disease by [usr.name] ([usr.ckey])</font>")
infect_virus2(C,shutdown,0)
M.current.remove_vampire_blood(200)
M.current.verbs -= /client/vampire/proc/vampire_disease
spawn(1800) M.current.verbs += /client/vampire/proc/vampire_disease
/client/vampire/proc/vampire_glare()
set category = "Abilities"
set name = "Glare"
set desc= "A scary glare that incapacitates people for a short while around you."
var/datum/mind/M = usr.mind
if(!M) return
if(!M.current.has_eyes())
M.current << "\red You don't have eyes"
return
if(M.current.vampire_power(0, 1))
M.current.visible_message("\red <b>[M.current]'s eyes emit a blinding flash!")
//M.vampire.bloodusable -= 10
M.current.verbs -= /client/vampire/proc/vampire_glare
spawn(800)
M.current.verbs += /client/vampire/proc/vampire_glare
if(istype(M.current:glasses, /obj/item/clothing/glasses/sunglasses/blindfold))
M.current << "<span class='warning'>You're blindfolded!</span>"
return
for(var/mob/living/carbon/C in view(1))
if(C == M.current) continue //Don't stunn yourself
if(!C.vampire_affected(M) && !C.get_species() == "Machine") //Or machines
continue
if(!M.current.vampire_can_reach(C, 1)) continue
// C.Stun(8)
C.Weaken(8)
C.stuttering = 20
C << "\red You are blinded by [M.current]'s glare"
/client/vampire/proc/vampire_shapeshift() //Hi. I'm stupid and there are missing procs all around. Namely the randomname proc. I can't find it and can't code a new one because I am bad. Sorry!
set category = "Abilities"
set name = "Shapeshift (50)"
set desc = "This does nothing. It's broken. Sorry!"//orig text: Changes your name and appearance at the cost of 50 blood and has a cooldown of 3 minutes.
/* var/datum/mind/M = usr.mind
if(!M) return
if(M.current.vampire_power(50, 0))
M.current.visible_message("<span class='warning'>[M.current.name] transforms!</span>")
M.current.client.prefs.real_name = M.current.generate_name() //random_name(M.current.gender)
M.current.client.prefs.randomize_appearance_for(M.current)
M.current.regenerate_icons()
M.current.remove_vampire_blood(50)
M.current.verbs -= /client/vampire/proc/vampire_shapeshift
spawn(1800) M.current.verbs += /client/vampire/proc/vampire_shapeshift
*/
/client/vampire/proc/vampire_screech()
set category = "Abilities"
set name = "Chiropteran Screech (90)"
set desc = "An extremely loud shriek that stuns nearby humans in a four-tile radius, as well as shattering the windows."
var/datum/mind/M = usr.mind
if(!M) return
if(M.current.vampire_power(90, 0))
M.current.visible_message("\red [M.current.name] lets out an ear piercing shriek!", "\red You let out a loud shriek.", "\red You hear a loud painful shriek!")
for(var/mob/living/carbon/C in hearers(4, M.current))
if(C == M.current) continue
if(ishuman(C) && (C:l_ear || C:r_ear) && istype((C:l_ear || C:r_ear), /obj/item/clothing/ears/earmuffs)) continue
if(!C.vampire_affected(M))
if(!C.get_species() == "Machine")
continue
C << "<span class='warning'><font size='3'><b>You hear a ear piercing shriek and your senses dull!</font></b></span>"
C.Weaken(5)
C.ear_deaf = 20
C.stuttering = 20
C.Stun(5)
// C.Jitter(150)
for(var/obj/structure/window/W in view(7))
W.shatter()
playsound(M.current.loc, 'sound/effects/creepyshriek.ogg', 100, 1)
M.current.remove_vampire_blood(90)
M.current.verbs -= /client/vampire/proc/vampire_screech
spawn(3600) M.current.verbs += /client/vampire/proc/vampire_screech
/client/vampire/proc/vampire_enthrall()
set category = "Abilities"
set name = "Enthrall (150)"
set desc = "You use a large portion of your power to sway those loyal to none to be loyal to you only."
var/datum/mind/M = usr.mind
if(!M) return
var/mob/living/carbon/C = M.current.vampire_active(150, 0, 1)
if(!C) return
if(C==usr)
M.current << "\red You can't do that to yourself"
return
if(C.get_species() == "Machine")
M.current << "\red You can only enthrall humans"
return
M.current.visible_message("\red [M.current.name] bites [C.name]'s neck!", "\red You bite [C.name]'s neck and begin the flow of power.")
C << "<span class='warning'>You feel the tendrils of evil invade your mind.</span>"
if(!ishuman(C))
M.current << "\red You can only enthrall humans"
return
if(do_mob(M.current, C, 50))
if(M.current.can_enthrall(C)) // recheck
if(M.current.vampire_power(150, 0))
M.current.handle_enthrall(C)
M.current.remove_vampire_blood(150)
M.current.verbs -= /client/vampire/proc/vampire_enthrall
spawn(1800) M.current.verbs += /client/vampire/proc/vampire_enthrall
return
else
M.current << "\red You or your target either moved or you dont have enough usable blood."
return
/client/vampire/proc/vampire_cloak()
set category = "Abilities"
set name = "Cloak of Darkness (toggle)"
set desc = "Toggles whether you are currently cloaking yourself in darkness."
var/datum/mind/M = usr.mind
if(!M) return
if(M.current.vampire_power(0, 0))
M.vampire.iscloaking = !M.vampire.iscloaking
M.current << "\blue You will now be [M.vampire.iscloaking ? "hidden" : "seen"] in darkness."
/mob/proc/handle_vampire_cloak()
if(!mind || !mind.vampire || !ishuman(src))
alpha = 255
return
var/turf/simulated/T = get_turf(src)
if(!istype(T))
return 0
if(!mind.vampire.iscloaking)
alpha = 255
return 0
// if(T.lighting_lumcount <= 2)
// alpha = round((255 * 0.15))
// return 1
else
alpha = round((255 * 0.80))
/mob/proc/can_enthrall(mob/living/carbon/C)
var/enthrall_safe = 0
var/datum/vampire/vampire = src.mind.vampire
for(var/obj/item/weapon/implant/loyalty/L in C)
if(L && L.implanted)
enthrall_safe = 1
break
// for(var/obj/item/weapon/implant/traitor/T in C)
// if(T && T.implanted)
// enthrall_safe = 1
// break
if(!C)
world.log << "something bad happened on enthralling a mob src is [src] [src.key] \ref[src]"
return 0
if(!C.mind)
src << "\red [C.name]'s mind is not there for you to enthrall."
return 0
if(enthrall_safe || ( C.mind in vampire.vampires )||( C.mind.vampire )||( C.mind in vampire.enthralled ))
C.visible_message("\red [C] seems to resist the takeover!", "\blue You feel a familiar sensation in your skull that quickly dissipates.")
return 0
if(!C.vampire_affected(mind))
C.visible_message("\red [C] seems to resist the takeover!", "\blue Your faith of [ticker.Bible_deity_name] has kept your mind clear of all evil")
return 0
if(!ishuman(C))
src << "\red You can only enthrall humans!"
return 0
return 1
/mob/proc/handle_enthrall(mob/living/carbon/human/H as mob)
if(!istype(H))
//msg_scopes("handle_enthrall fucked up with no H < [src]")
src << "<b>\red SOMETHING WENT WRONG, YELL AT POMF OR NEXIS</b>"
return 0
var/ref = "\ref[src.mind]"
if(!(src.mind.vampire.thralls))
src.mind.vampire.thralls[ref] = list(H.mind)
else
src.mind.vampire.thralls[ref] += H.mind
//msg_scopes("[H.name] Changed in handle_enthrall") //purely here to see live changes incase of unexpected things
src.mind.vampire.enthralled.Add(H.mind)
src.mind.vampire.enthralled[H.mind] = src.mind
H.mind.special_role = "VampThrall"
H << "<b>\red You have been Enthralled by [name]. Follow their every command.</b>"
src << "\red You have successfully Enthralled [H.name]. <i>If they refuse to do as you say just adminhelp.</i>"
var/client/vampire/c = src
c.update_vampire_icons_added(H.mind)
c.update_vampire_icons_added(src.mind)
msg_admin_attack("[key_name_admin(src)] has mind-slaved [key_name_admin(H)] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[H.x];Y=[H.y];Z=[H.z]'>JMP</a>.")
/client/vampire/proc/vampire_bats()
set category = "Abilities"
set name = "Summon Bats (60)"
set desc = "You summon a pair of space bats who attack nearby targets until they or their target is dead."
var/datum/mind/M = usr.mind
if(!M) return
if(M.current.vampire_power(60, 0))
var/list/turf/locs = new
var/number = 0
for(var/direction in alldirs) //looking for bat spawns
if(locs.len == 2) //we found 2 locations and thats all we need
break
var/turf/T = get_step(M.current,direction) //getting a loc in that direction
if(AStar(M.current.loc, T, /turf/proc/AdjacentTurfs, /turf/proc/Distance, 1)) // if a path exists, so no dense objects in the way its valid salid
locs += T
if(locs.len)
for(var/turf/tospawn in locs)
number++
new /mob/living/simple_animal/hostile/scarybat(tospawn, M.current)
if(number != 2) //if we only found one location, spawn one on top of our tile so we dont get stacked bats
new /mob/living/simple_animal/hostile/scarybat(M.current.loc, M.current)
else // we had no good locations so make two on top of us
new /mob/living/simple_animal/hostile/scarybat(M.current.loc, M.current)
new /mob/living/simple_animal/hostile/scarybat(M.current.loc, M.current)
M.current.remove_vampire_blood(60)
M.current.verbs -= /client/vampire/proc/vampire_bats
spawn(1200) M.current.verbs += /client/vampire/proc/vampire_bats
/client/vampire/proc/vampire_jaunt()
//AHOY COPY PASTE INCOMING
set category = "Abilities"
set name = "Mist Form (30)"
set desc = "You take on the form of mist for a short period of time."
var/jaunt_duration = 50 //in deciseconds
var/datum/mind/M = usr.mind
if(!M) return
if(M.current.vampire_power(30, 0))
if(M.current.buckled) M.current.buckled.unbuckle_mob()
spawn(0)
var/originalloc = get_turf(M.current.loc)
var/obj/effect/dummy/spell_jaunt/holder = new /obj/effect/dummy/spell_jaunt( originalloc )
var/atom/movable/overlay/animation = new /atom/movable/overlay( originalloc )
animation.name = "water"
animation.density = 0
animation.anchored = 1
animation.icon = 'icons/mob/mob.dmi'
animation.icon_state = "liquify"
animation.layer = 5
animation.master = holder
M.current.ExtinguishMob()
M.current.weakened = 0
M.current.stunned = 0
if(M.current.buckled)
M.current.buckled.unbuckle_mob()
flick("liquify",animation)
M.current.loc = holder
M.current.client.eye = holder
var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread()
steam.set_up(10, 0, originalloc)
steam.start()
sleep(jaunt_duration)
var/mobloc = get_turf(M.current.loc)
/* if(get_area(mobloc) == /area/security/armoury/gamma)
M << "A strange energy repels you!"
mobloc = originalloc*/
animation.loc = mobloc
steam.location = mobloc
steam.start()
M.current.canmove = 0
sleep(20)
flick("reappear",animation)
sleep(5)
if(!M.current.Move(mobloc))
for(var/direction in list(1,2,4,8,5,6,9,10))
var/turf/T = get_step(mobloc, direction)
if(T)
if(M.current.Move(T))
break
M.current.canmove = 1
M.current.client.eye = M.current
qdel(animation)
qdel(holder)
M.current.remove_vampire_blood(30)
M.current.verbs -= /client/vampire/proc/vampire_jaunt
spawn(600) M.current.verbs += /client/vampire/proc/vampire_jaunt
// Blink for vamps
// Less smoke spam.
/client/vampire/proc/vampire_shadowstep()
set category = "Abilities"
set name = "Shadowstep (30)"
set desc = "Vanish into the shadows."
var/datum/mind/M = usr.mind
if(!M) return
// Teleport radii
var/inner_tele_radius = 0
var/outer_tele_radius = 6
// Maximum lighting_lumcount.
// var/max_lum = 1
if(M.current.vampire_power(30, 0))
if(M.current.buckled) M.current.buckled.unbuckle_mob()
spawn(0)
var/list/turfs = new/list()
for(var/turf/T in range(usr,outer_tele_radius))
if(T in range(usr,inner_tele_radius)) continue
if(istype(T,/turf/space)) continue
if(T.density) continue
if(T.x>world.maxx-outer_tele_radius || T.x<outer_tele_radius) continue //putting them at the edge is dumb
if(T.y>world.maxy-outer_tele_radius || T.y<outer_tele_radius) continue
// LIGHTING CHECK
// if(T.lighting_lumcount > max_lum) continue
// turfs += T
//M.current.remove_vampire_blood(30) This isn't the right place for this either.
if(!turfs.len)
usr << "\red You cannot find darkness to step to."
return
var/turf/picked = pick(turfs)
if(!picked || !isturf(picked))
return
M.current.ExtinguishMob()
if(M.current.buckled)
M.current.buckled.unbuckle_mob()
var/atom/movable/overlay/animation = new /atom/movable/overlay( get_turf(usr) )
animation.name = usr.name
animation.density = 0
animation.anchored = 1
animation.icon = usr.icon
animation.alpha = 127
animation.layer = 5
//animation.master = src
usr.loc = picked
M.current.remove_vampire_blood(30)
spawn(10)
del(animation)
// M.current.remove_vampire_blood(30)
M.current.verbs -= /client/vampire/proc/vampire_shadowstep
spawn(20)
M.current.verbs += /client/vampire/proc/vampire_shadowstep
/mob/proc/remove_vampire_blood(amount = 0)
var/bloodold
if(!mind || !mind.vampire)
return
bloodold = mind.vampire.bloodusable
mind.vampire.bloodusable = max(0, (mind.vampire.bloodusable - amount))
if(bloodold != mind.vampire.bloodusable)
src << "\blue <b>You have [mind.vampire.bloodusable] left to use.</b>"
//prepare for copypaste
/client/vampire/proc/update_vampire_icons_added(datum/mind/vampire_mind)
var/ref = "\ref[vampire_mind]"
if(ref in vampire_mind.vampire.thralls)
if(vampire_mind.current)
if(vampire_mind.current.client)
var/I = image('icons/mob/mob.dmi', loc = vampire_mind.current, icon_state = "vampire")
vampire_mind.current.client.images += I
for(var/headref in vampire_mind.vampire.thralls)
for(var/datum/mind/t_mind in vampire_mind.vampire.thralls[headref])
var/datum/mind/head = locate(headref)
if(head)
if(head.current)
if(head.current.client)
var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "vampthrall")
head.current.client.images += I
if(t_mind.current)
if(t_mind.current.client)
var/I = image('icons/mob/mob.dmi', loc = head.current, icon_state = "vampire")
t_mind.current.client.images += I
if(t_mind.current)
if(t_mind.current.client)
var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "vampthrall")
t_mind.current.client.images += I
/client/vampire/proc/update_vampire_icons_removed(datum/mind/vampire_mind)
for(var/headref in vampire_mind.vampire.thralls)
var/datum/mind/head = locate(headref)
for(var/datum/mind/t_mind in vampire_mind.vampire.thralls[headref])
if(t_mind.current)
if(t_mind.current.client)
for(var/image/I in t_mind.current.client.images)
if((I.icon_state == "vampthrall" || I.icon_state == "vampire") && I.loc == vampire_mind.current)
//world.log << "deleting [vampire_mind] overlay"
del(I)
if(head)
//world.log << "found [head.name]"
if(head.current)
if(head.current.client)
for(var/image/I in head.current.client.images)
if((I.icon_state == "vampthrall" || I.icon_state == "vampire") && I.loc == vampire_mind.current)
//world.log << "deleting [vampire_mind] overlay"
del(I)
if(vampire_mind.current)
if(vampire_mind.current.client)
for(var/image/I in vampire_mind.current.client.images)
if(I.icon_state == "vampthrall" || I.icon_state == "vampire")
del(I)
/client/vampire/proc/remove_vampire_mind(datum/mind/vampire_mind, datum/mind/head)
//var/list/removal
if(!istype(head))
head = vampire_mind //workaround for removing a thrall's control over the enthralled
var/ref = "\ref[head]"
if(vampire_mind.vampire.thralls)
vampire_mind.vampire.thralls[ref] -= vampire_mind
vampire_mind.vampire.enthralled -= vampire_mind
//vampire.special_role = null
update_vampire_icons_removed(vampire_mind)
//world << "Removed [vampire_mind.current.name] from vampire shit"
vampire_mind.current << "\red <FONT size = 3><B>The fog clouding your mind clears. You remember nothing from the moment you were enthralled until now.</B></FONT>"
/mob/living/carbon/human/proc/check_sun()
var/ax = x
var/ay = y
for(var/i = 1 to 20)
ax += sun.dx
ay += sun.dy
var/turf/T = locate( round(ax,0.5),round(ay,0.5),z)
if(T.x == 1 || T.x==world.maxx || T.y==1 || T.y==world.maxy)
break
if(T.density)
return
if(prob(35))
switch(health)
if(80 to 100)
src << "\red Your skin flakes away..."
if(60 to 80)
src << "<span class='warning'>Your skin sizzles!</span>"
// if((-INFINITY) to 60)
// if(!on_fire)
// src << "<b>\red Your skin catches fire!</b>"
// else
// src << "<b>\red You continue to burn!</b>"
// fire_stacks += 5
// IgniteMob()
// emote("scream")
//else
// switch(health)
// if((-INFINITY) to 60)
// fire_stacks++
// IgniteMob()
adjustFireLoss(30) //Original value was 3. Barely did anything. Vamps should vaporize in starlight.
/mob/living/carbon/human/proc/handle_vampire()
/* if(hud_used)
if(!hud_used.vampire_blood_display)
hud_used.vampire_hud()
hud_used.human_hud('icons/mob/screen1_Vampire.dmi')
hud_used.vampire_blood_display.maptext_width = 64
hud_used.vampire_blood_display.maptext_height = 26
hud_used.vampire_blood_display.maptext = "<div align='left' valign='top' style='position:relative; top:0px; left:6px'> U:<font color='#33FF33' size='1'>[mind.vampire.bloodusable]</font><br> T:<font color='#FFFF00' size='1'>[mind.vampire.bloodtotal]</font></div>"
*/
handle_vampire_cloak()
if(istype(loc, /turf/space))
check_sun()
mind.vampire.nullified = max(0, mind.vampire.nullified - 1)
-1
View File
@@ -4,7 +4,6 @@
extended_round_description = "A powerful entity capable of manipulating the elements around him, most commonly referred to as a 'wizard', has infiltrated the station. They have a wide variety of powers and spells available to them that makes your own simple moral self tremble with fear and excitement. Ultimately, their purpose is unknown. However, it is up to you and your crew to decide if their powers can be used for good or if their arrival foreshadows the destruction of the entire station."
config_tag = "wizard"
required_players = 1
required_players_secret = 10
required_enemies = 1
uplink_welcome = "Wizardly Uplink Console:"
uplink_uses = 10
-73
View File
@@ -177,79 +177,6 @@
H.species.equip_survival_gear(H,1)
return 1
//Griff //BS12 EDIT
/*
/datum/job/clown
title = "Clown"
flag = CLOWN
department_flag = CIVILIAN
faction = "Station"
total_positions = 1
spawn_positions = 1
supervisors = "the head of personnel"
selection_color = "#dddddd"
access = list(access_clown, access_theatre, access_maint_tunnels)
minimal_access = list(access_clown, access_theatre)
equip(var/mob/living/carbon/human/H)
if(!H) return 0
H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/clown(H), slot_back)
H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/clown(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/device/pda/clown(H), slot_belt)
H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(H), slot_wear_mask)
H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/snacks/grown/banana(H), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/weapon/bikehorn(H), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/weapon/stamp/clown(H), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/weapon/pen/crayon/rainbow(H), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/fancy/crayons(H), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/toy/waterflower(H), slot_in_backpack)
H.mutations.Add(CLUMSY)
return 1
/datum/job/mime
title = "Mime"
flag = MIME
department_flag = CIVILIAN
faction = "Station"
total_positions = 1
spawn_positions = 1
supervisors = "the head of personnel"
selection_color = "#dddddd"
access = list(access_mime, access_theatre, access_maint_tunnels)
minimal_access = list(access_mime, access_theatre)
equip(var/mob/living/carbon/human/H)
if(!H) return 0
if(H.backbag == 2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back)
if(H.backbag == 3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back)
H.equip_to_slot_or_del(new /obj/item/clothing/under/mime(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/device/pda/mime(H), slot_belt)
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/white(H), slot_gloves)
H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/mime(H), slot_wear_mask)
H.equip_to_slot_or_del(new /obj/item/clothing/head/beret(H), slot_head)
H.equip_to_slot_or_del(new /obj/item/clothing/suit/suspenders(H), slot_wear_suit)
if(H.backbag == 1)
H.equip_to_slot_or_del(new /obj/item/weapon/pen/crayon/mime(H), slot_l_store)
H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(H), slot_l_hand)
else
H.equip_to_slot_or_del(new /obj/item/weapon/pen/crayon/mime(H), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(H), slot_in_backpack)
H.verbs += /client/proc/mimespeak
H.verbs += /client/proc/mimewall
H.mind.special_verbs += /client/proc/mimespeak
H.mind.special_verbs += /client/proc/mimewall
H.miming = 1
return 1
*/
/datum/job/janitor
title = "Janitor"
flag = JANITOR
+3 -37
View File
@@ -185,36 +185,6 @@ var/global/datum/controller/occupations/job_master
return
proc/FillAIPosition()
var/ai_selected = 0
var/datum/job/job = GetJob("AI")
if(!job) return 0
if((job.title == "AI") && (config) && (!config.allow_ai)) return 0
for(var/i = job.total_positions, i > 0, i--)
for(var/level = 1 to 3)
var/list/candidates = list()
if(ticker.mode.name == "AI malfunction")//Make sure they want to malf if its malf
candidates = FindOccupationCandidates(job, level, BE_MALF)
else
candidates = FindOccupationCandidates(job, level)
if(candidates.len)
var/mob/new_player/candidate = pick(candidates)
if(AssignRole(candidate, "AI"))
ai_selected++
break
//Malf NEEDS an AI so force one if we didn't get a player who wanted it
if((ticker.mode.name == "AI malfunction")&&(!ai_selected))
unassigned = shuffle(unassigned)
for(var/mob/new_player/player in unassigned)
if(jobban_isbanned(player, "AI")) continue
if(AssignRole(player, "AI"))
ai_selected++
break
if(ai_selected) return 1
return 0
/** Proc DivideOccupations
* fills var "assigned_role" for all ready players.
* This proc must not have any side effect besides of modifying "assigned_role".
@@ -260,11 +230,6 @@ var/global/datum/controller/occupations/job_master
FillHeadPosition()
Debug("DO, Head Check end")
//Check for an AI
Debug("DO, Running AI Check")
FillAIPosition()
Debug("DO, AI Check end")
//Other jobs are now checked
Debug("DO, Running Standard Check")
@@ -275,6 +240,7 @@ var/global/datum/controller/occupations/job_master
// Loop through all levels from high to low
var/list/shuffledoccupations = shuffle(occupations)
// var/list/disabled_jobs = ticker.mode.disabled_jobs // So we can use .Find down below without a colon.
for(var/level = 1 to 3)
//Check the head jobs first each level
CheckHeadPositions(level)
@@ -284,7 +250,7 @@ var/global/datum/controller/occupations/job_master
// Loop through all jobs
for(var/datum/job/job in shuffledoccupations) // SHUFFLE ME BABY
if(!job)
if(!job || ticker.mode.disabled_jobs.Find(job.title) )
continue
if(jobban_isbanned(player, job.title))
@@ -490,7 +456,7 @@ var/global/datum/controller/occupations/job_master
if(istype(H)) //give humans wheelchairs, if they need them.
var/obj/item/organ/external/l_foot = H.get_organ("l_foot")
var/obj/item/organ/external/r_foot = H.get_organ("r_foot")
if((!l_foot || l_foot.status & ORGAN_DESTROYED) && (!r_foot || r_foot.status & ORGAN_DESTROYED))
if(!l_foot || !r_foot)
var/obj/structure/bed/chair/wheelchair/W = new /obj/structure/bed/chair/wheelchair(H.loc)
H.buckled = W
H.update_canmove()
-66
View File
@@ -1,66 +0,0 @@
//TODO: put these somewhere else
/client/proc/mimewall()
set category = "Mime"
set name = "Invisible wall"
set desc = "Create an invisible wall on your location."
if(usr.stat)
usr << "Not when you're incapicated."
return
if(!ishuman(usr))
return
var/mob/living/carbon/human/H = usr
if(!H.miming)
usr << "You still haven't atoned for your speaking transgression. Wait."
return
H.verbs -= /client/proc/mimewall
spawn(300)
H.verbs += /client/proc/mimewall
for (var/mob/V in viewers(H))
if(V!=usr)
V.show_message("[H] looks as if a wall is in front of them.", 3, "", 2)
usr << "You form a wall in front of yourself."
new /obj/effect/forcefield/mime(locate(usr.x,usr.y,usr.z))
return
///////////Mimewalls///////////
/obj/effect/forcefield/mime
icon_state = "empty"
name = "invisible wall"
desc = "You have a bad feeling about this."
var/timeleft = 300
var/last_process = 0
/obj/effect/forcefield/mime/New()
..()
last_process = world.time
processing_objects.Add(src)
/obj/effect/forcefield/mime/process()
timeleft -= (world.time - last_process)
if(timeleft <= 0)
processing_objects.Remove(src)
qdel(src)
///////////////////////////////
/client/proc/mimespeak()
set category = "Mime"
set name = "Speech"
set desc = "Toggle your speech."
if(!ishuman(usr))
return
var/mob/living/carbon/human/H = usr
if(H.miming)
H.miming = 0
else
H << "You'll have to wait if you want to atone for your sins."
spawn(3000)
H.miming = 1
return
+1 -1
View File
@@ -400,7 +400,7 @@
if(!AN && !open && !infected & !imp)
AN = "None:"
if(!(e.status & ORGAN_DESTROYED))
if(!e.is_stump())
dat += "<td>[e.name]</td><td>[e.burn_dam]</td><td>[e.brute_dam]</td><td>[robot][bled][AN][splint][open][infected][imp][internal_bleeding][lung_ruptured]</td>"
else
dat += "<td>[e.name]</td><td>-</td><td>-</td><td>Not Found</td>"
@@ -17,6 +17,7 @@
var/temperature_resistance = 1000 + T0C
volume = 1000
use_power = 0
interact_offline = 1 // Allows this to be used when not in powered area.
var/release_log = ""
var/update_flag = 0
+12 -2
View File
@@ -140,9 +140,19 @@
if(weld(W, user))
if(assembly)
assembly.loc = src.loc
assembly.state = 1
assembly.anchored = 1
assembly.camera_name = c_tag
assembly.camera_network = english_list(network, "Exodus", ",", ",")
assembly.update_icon()
assembly.dir = src.dir
if(stat & BROKEN)
assembly.state = 2
user << "<span class='notice'>You repaired \the [src] frame.</span>"
else
assembly.state = 1
user << "<span class='notice'>You cut \the [src] free from the wall.</span>"
new /obj/item/stack/cable_coil(src.loc, length=2)
assembly = null //so qdel doesn't eat it.
new /obj/item/stack/cable_coil(src.loc, length=2)
qdel(src)
// OTHER
@@ -11,6 +11,8 @@
// Motion, EMP-Proof, X-Ray
var/list/obj/item/possible_upgrades = list(/obj/item/device/assembly/prox_sensor, /obj/item/stack/material/osmium, /obj/item/weapon/stock_parts/scanning_module)
var/list/upgrades = list()
var/camera_name
var/camera_network
var/state = 0
var/busy = 0
/*
@@ -47,7 +49,7 @@
else if(iswrench(W))
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "You unattach the assembly from it's place."
user << "You unattach the assembly from its place."
anchored = 0
update_icon()
state = 0
@@ -67,7 +69,7 @@
else if(iswelder(W))
if(weld(W, user))
user << "You unweld the assembly from it's place."
user << "You unweld the assembly from its place."
state = 1
anchored = 1
return
@@ -78,7 +80,7 @@
if(isscrewdriver(W))
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
var/input = sanitize(input(usr, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: Exodus,Security,Secret ", "Set Network", "Exodus"))
var/input = sanitize(input(usr, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: Exodus,Security,Secret ", "Set Network", camera_network ? camera_network : "Exodus"))
if(!input)
usr << "No input found please hang up and try your call again."
return
@@ -90,7 +92,7 @@
var/area/camera_area = get_area(src)
var/temptag = "[sanitize(camera_area.name)] ([rand(1, 999)])"
input = sanitizeSafe(input(usr, "How would you like to name the camera?", "Set Camera Name", temptag), MAX_NAME_LEN)
input = sanitizeSafe(input(usr, "How would you like to name the camera?", "Set Camera Name", camera_name ? camera_name : temptag), MAX_NAME_LEN)
state = 4
var/obj/machinery/camera/C = new(src.loc)
+3 -11
View File
@@ -70,7 +70,6 @@
for(var/x in verbs)
verbs -= x
set_broken()
density = 0
/obj/machinery/computer/update_icon()
..()
@@ -124,22 +123,15 @@
for (var/obj/C in src)
C.loc = src.loc
if (src.stat & BROKEN)
user << "\blue The broken glass falls out."
user << "<span class='notice'>The broken glass falls out.</span>"
new /obj/item/weapon/material/shard( src.loc )
A.state = 3
A.icon_state = "3"
else
user << "\blue You disconnect the monitor."
user << "<span class='notice'>You disconnect the monitor.</span>"
A.state = 4
A.icon_state = "4"
M.deconstruct(src)
qdel(src)
else
src.attack_hand(user)
return
..()
+1 -1
View File
@@ -457,7 +457,7 @@
var/counter = 1
while(src.active2.fields[text("com_[]", counter)])
counter++
src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]<BR>[t1]")
src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [worldtime2text()], [game_year]<BR>[t1]")
if (href_list["del_c"])
if ((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])]))
+1 -1
View File
@@ -391,7 +391,7 @@ What a mess.*/
var/counter = 1
while(active2.fields[text("com_[]", counter)])
counter++
active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]<BR>[t1]")
active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [worldtime2text()], [game_year]<BR>[t1]")
if ("Delete Record (ALL)")
if (active1)
@@ -470,7 +470,7 @@
var/counter = 1
while(src.active2.fields[text("com_[]", counter)])
counter++
src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]<BR>[t1]")
src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [worldtime2text()], [game_year]<BR>[t1]")
if (href_list["del_c"])
if ((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])]))
@@ -410,7 +410,7 @@ What a mess.*/
var/counter = 1
while(active2.fields[text("com_[]", counter)])
counter++
active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]<BR>[t1]")
active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [worldtime2text()], [game_year]<BR>[t1]")
if ("Delete Record (ALL)")
if (active1)
+40 -46
View File
@@ -38,16 +38,14 @@
/obj/machinery/lapvend/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(vendmode == 1)
if(istype(W, /obj/item/weapon/card))
var/obj/item/weapon/card/I = W
scan_card(I)
var/obj/item/weapon/card/id/I = W.GetID()
if(vendmode == 1 && I)
scan_id(I, W)
vendmode = 0
if(vendmode == 3 && I)
if(reimburse_id(I, W))
vendmode = 0
if(vendmode == 3)
if(istype(W,/obj/item/weapon/card))
var/obj/item/weapon/card/I = W
if(reimburse(I))
vendmode = 0
if(vendmode == 0)
if(istype(W, /obj/item/device/laptop))
var/obj/item/device/laptop/L = W
@@ -210,26 +208,24 @@
newlap.spawn_parts()
/obj/machinery/lapvend/proc/scan_card(var/obj/item/weapon/card/I)
if (istype(I, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/C = I
visible_message("<span class='info'>[usr] swipes a card through [src].</span>")
var/datum/money_account/CH = get_account(C.associated_account_number)
if(!CH)
usr << "\icon[src]<span class='warning'>No valid account number is associated with this card.</span>"
return
if(CH.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2)
if(vendor_account)
var/attempt_pin = input("Enter pin code", "Vendor transaction") as num
var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2)
if(D)
transfer_and_vend(D, C)
else
usr << "\icon[src]<span class='warning'>Unable to access account. Check security settings and try again.</span>"
/obj/machinery/lapvend/proc/scan_id(var/obj/item/weapon/card/id/C, var/obj/item/I)
visible_message("<span class='info'>\The [usr] swipes \the [I] through \the [src].</span>")
var/datum/money_account/CH = get_account(C.associated_account_number)
if(!CH)
usr << "\icon[src]<span class='warning'>No valid account number is associated with this card.</span>"
return
if(CH.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2)
if(vendor_account)
var/attempt_pin = input("Enter pin code", "Vendor transaction") as num
var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2)
if(D)
transfer_and_vend(D, C)
else
usr << "\icon[src]<span class='warning'>Unable to access vendor account. Please record the machine ID and call CentComm Support.</span>"
else
transfer_and_vend(CH, C)
usr << "\icon[src]<span class='warning'>Unable to access vendor account. Please record the machine ID and call CentComm Support.</span>"
else
transfer_and_vend(CH, C)
// Transfers money and vends the laptop.
@@ -361,30 +357,28 @@
/obj/machinery/lapvend/proc/reimburse(var/obj/item/weapon/card/I)
if (istype(I, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/C = I
visible_message("<span class='info'>[usr] swipes a card through [src].</span>")
var/datum/money_account/CH = get_account(C.associated_account_number)
if(!CH)
usr << "\icon[src]<span class='warning'>No valid account number is associated with this card.</span>"
return 0
if(CH.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2)
if(vendor_account)
var/attempt_pin = input("Enter pin code", "Vendor transaction") as num
var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2)
if(D)
transfer_and_reimburse(D)
return 1
else
usr << "\icon[src]<span class='warning'>Unable to access account. Check security settings and try again.</span>"
return 0
/obj/machinery/lapvend/proc/reimburse_id(var/obj/item/weapon/card/id/C, var/obj/item/I)
visible_message("<span class='info'>\The [usr] swipes \the [I] through \the [src].</span>")
var/datum/money_account/CH = get_account(C.associated_account_number)
if(!CH)
usr << "\icon[src]<span class='warning'>No valid account number is associated with this card.</span>"
return 0
if(CH.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2)
if(vendor_account)
var/attempt_pin = input("Enter pin code", "Vendor transaction") as num
var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2)
if(D)
transfer_and_reimburse(D)
return 1
else
usr << "\icon[src]<span class='warning'>Unable to access vendor account. Please record the machine ID and call CentComm Support.</span>"
return 0
else
transfer_and_reimburse(CH)
return 1
usr << "\icon[src]<span class='warning'>Unable to access vendor account. Please record the machine ID and call CentComm Support.</span>"
return 0
else
transfer_and_reimburse(CH)
return 1
/obj/machinery/lapvend/proc/transfer_and_reimburse(var/datum/money_account/D)
var/transaction_amount = total()
+2 -2
View File
@@ -1067,8 +1067,8 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/emp_act(var/severity)
if(prob(40/severity))
var/duration = world.time + SecondsToTicks(30 / severity)
if(duration > electrified_until)
var/duration = SecondsToTicks(30 / severity)
if(electrified_until > -1 && (duration + world.time) > electrified_until)
electrify(duration)
..()
+2 -2
View File
@@ -409,12 +409,12 @@
set_opacity(0)
sleep(3)
src.density = 0
update_nearby_tiles()
sleep(7)
src.layer = open_layer
explosion_resistance = 0
update_icon()
set_opacity(0)
update_nearby_tiles()
operating = 0
if(autoclose)
@@ -436,12 +436,12 @@
src.density = 1
explosion_resistance = initial(explosion_resistance)
src.layer = closed_layer
update_nearby_tiles()
sleep(7)
update_icon()
if(visible && !glass)
set_opacity(1) //caaaaarn!
operating = 0
update_nearby_tiles()
//I shall not add a check every x ticks if a door has closed over some fire.
var/obj/fire/fire = locate() in loc
+4 -1
View File
@@ -195,7 +195,10 @@ Class Procs:
return (stat & (NOPOWER|BROKEN|additional_flags))
/obj/machinery/CanUseTopic(var/mob/user)
if(!interact_offline && (stat & (NOPOWER|BROKEN)))
if(stat & BROKEN)
return STATUS_CLOSE
if(!interact_offline && (stat & NOPOWER))
return STATUS_CLOSE
return ..()
+1 -1
View File
@@ -88,7 +88,7 @@ obj/machinery/scanner/attack_hand(mob/living/carbon/human/user)
G.fields["rank"] = "Unassigned"
G.fields["real_rank"] = G.fields["rank"]
G.fields["name"] = mname
G.fields["id"] = text("[]", add_zero(num2hex(rand(1, 1.6777215E7)), 6))
G.fields["id"] = generate_record_id()
M.fields["name"] = G.fields["name"]
M.fields["id"] = G.fields["id"]
S.fields["name"] = G.fields["name"]
+1 -4
View File
@@ -819,15 +819,12 @@
dat += "<A href='?src=\ref[src];apply_paintjob=1'><br>\[apply customisation routine\]</a><br><hr>"
if(panel_open)
dat += wires()
wires.Interact(user)
user << browse(dat, "window=suit_cycler")
onclose(user, "suit_cycler")
return
/obj/machinery/suit_cycler/proc/wires()
return wires.GetInteractWindow()
/obj/machinery/suit_cycler/Topic(href, href_list)
if(href_list["eject_suit"])
if(!suit) return
+3 -3
View File
@@ -35,14 +35,14 @@
var/turf/loc = get_turf(usr)
var/area/A = loc.loc
if (!istype(loc, /turf/simulated/floor))
usr << "<span class='danger>\The [src] Alarm cannot be placed on this spot.</span>"
usr << "<span class='danger'>\The [src] Alarm cannot be placed on this spot.</span>"
return
if (A.requires_power == 0 || A.name == "Space")
usr << "<span class='danger>\The [src] Alarm cannot be placed in this area.</span>"
usr << "<span class='danger'>\The [src] Alarm cannot be placed in this area.</span>"
return
if(gotwallitem(loc, ndir))
usr << "<span class='danger>There's already an item on this wall!</span>"
usr << "<span class='danger'>There's already an item on this wall!</span>"
return
var/obj/machinery/M = new build_machine_type(loc, ndir, 1)
+5
View File
@@ -996,6 +996,11 @@
if (usr.stat || !ishuman(usr))
return
if (usr.buckled)
usr << "<span class='warning'>You can't climb into the exosuit while buckled!</span>"
return
src.log_message("[usr] tries to move in.")
if(iscarbon(usr))
var/mob/living/carbon/C = usr
+4 -2
View File
@@ -1,6 +1,7 @@
/obj
var/can_buckle = 0
var/buckle_movable = 0
var/buckle_dir = 0
var/buckle_lying = -1 //bed-like behavior, forces mob.lying = buckle_lying if != -1
var/buckle_require_restraints = 0 //require people to be handcuffed before being able to buckle. eg: pipes
var/mob/living/buckled_mob = null
@@ -31,7 +32,7 @@
M.buckled = src
M.facing_dir = null
M.set_dir(dir)
M.set_dir(buckle_dir ? buckle_dir : dir)
M.update_canmove()
buckled_mob = M
post_buckle_mob(M)
@@ -55,7 +56,8 @@
user << "<span class='warning'>You can't buckle anyone in before the game starts.</span>"
if(!user.Adjacent(M) || user.restrained() || user.lying || user.stat || istype(user, /mob/living/silicon/pai))
return
if(M == buckled_mob)
return
if(istype(M, /mob/living/carbon/slime))
user << "<span class='warning'>The [M] is too squishy to buckle in.</span>"
return
+82 -29
View File
@@ -4,14 +4,76 @@
/obj/effect/effect/smoke/chem
icon = 'icons/effects/chemsmoke.dmi'
opacity = 0
layer = 6
time_to_live = 300
pass_flags = PASSTABLE | PASSGRILLE | PASSGLASS //PASSGLASS is fine here, it's just so the visual effect can "flow" around glass
var/splash_amount = 10 //atoms moving through a smoke cloud get splashed with up to 10 units of reagent
var/turf/destination
/obj/effect/effect/smoke/chem/New()
/obj/effect/effect/smoke/chem/New(var/newloc, smoke_duration, turf/dest_turf = null, icon/cached_icon = null)
time_to_live = smoke_duration
..()
create_reagents(500)
return
if(cached_icon)
icon = cached_icon
set_dir(pick(cardinal))
pixel_x = -32 + rand(-8, 8)
pixel_y = -32 + rand(-8, 8)
//switching opacity on after the smoke has spawned, and then turning it off before it is deleted results in cleaner
//lighting and view range updates (Is this still true with the new lighting system?)
opacity = 1
//float over to our destination, if we have one
destination = dest_turf
if(destination)
walk_to(src, destination)
/obj/effect/effect/smoke/chem/Destroy()
opacity = 0
fadeOut()
..()
/obj/effect/effect/smoke/chem/Move()
var/list/oldlocs = view(1, src)
. = ..()
if(.)
for(var/turf/T in view(1, src) - oldlocs)
for(var/atom/movable/AM in T)
if(!istype(AM, /obj/effect/effect/smoke/chem))
reagents.splash(AM, splash_amount, copy = 1)
if(loc == destination)
bound_width = 96
bound_height = 96
/obj/effect/effect/smoke/chem/Crossed(atom/movable/AM)
..()
if(!istype(AM, /obj/effect/effect/smoke/chem))
reagents.splash(AM, splash_amount, copy = 1)
/obj/effect/effect/smoke/chem/proc/initial_splash()
for(var/turf/T in view(1, src))
for(var/atom/movable/AM in T)
if(!istype(AM, /obj/effect/effect/smoke/chem))
reagents.splash(AM, splash_amount, copy = 1)
// Fades out the smoke smoothly using it's alpha variable.
/obj/effect/effect/smoke/chem/proc/fadeOut(var/frames = 16)
if(!alpha) return //already transparent
frames = max(frames, 1) //We will just assume that by 0 frames, the coder meant "during one frame".
var/alpha_step = round(alpha / frames)
while(alpha > 0)
alpha = max(0, alpha - alpha_step)
sleep(world.tick_lag)
/////////////////////////////////////////////
// Chem Smoke Effect System
/////////////////////////////////////////////
/datum/effect/effect/system/smoke_spread/chem
smoke_type = /obj/effect/effect/smoke/chem
var/obj/chemholder
@@ -115,13 +177,21 @@
else
I = icon('icons/effects/96x96.dmi', "smoke")
//Calculate smoke duration
var/smoke_duration = 150
var/pressure = 0
var/datum/gas_mixture/environment = location.return_air()
if(environment) pressure = environment.return_pressure()
smoke_duration = between(5, smoke_duration*pressure/(ONE_ATMOSPHERE/3), smoke_duration)
var/const/arcLength = 2.3559 //distance between each smoke cloud
for(var/i = 0, i < range, i++) //calculate positions for smoke coverage - then spawn smoke
var/radius = i * 1.5
if(!radius)
spawn(0)
spawnSmoke(location, I, 1)
spawnSmoke(location, I, 1, 1)
continue
var/offset = 0
@@ -146,43 +216,26 @@
// Randomizes and spawns the smoke effect.
// Also handles deleting the smoke once the effect is finished.
//------------------------------------------
/datum/effect/effect/system/smoke_spread/chem/proc/spawnSmoke(var/turf/T, var/icon/I, var/dist = 1, var/obj/effect/effect/smoke/chem/passed_smoke)
/datum/effect/effect/system/smoke_spread/chem/proc/spawnSmoke(var/turf/T, var/icon/I, var/smoke_duration, var/dist = 1, var/splash_initial=0, var/obj/effect/effect/smoke/chem/passed_smoke)
var/obj/effect/effect/smoke/chem/smoke
if(passed_smoke)
smoke = passed_smoke
else
smoke = PoolOrNew(/obj/effect/effect/smoke/chem, location)
smoke = PoolOrNew(/obj/effect/effect/smoke/chem, list(location, smoke_duration + rand(0, 20), T, I))
if(chemholder.reagents.reagent_list.len)
chemholder.reagents.trans_to_obj(smoke, chemholder.reagents.total_volume / dist, copy = 1) //copy reagents to the smoke so mob/breathe() can handle inhaling the reagents
smoke.icon = I
smoke.layer = 6
smoke.set_dir(pick(cardinal))
smoke.pixel_x = -32 + rand(-8, 8)
smoke.pixel_y = -32 + rand(-8, 8)
walk_to(smoke, T)
smoke.opacity = 1 //switching opacity on after the smoke has spawned, and then
sleep(150+rand(0,20)) // turning it off before it is deleted results in cleaner
smoke.opacity = 0 // lighting and view range updates
fadeOut(smoke)
qdel(src)
/datum/effect/effect/system/smoke_spread/chem/spores/spawnSmoke(var/turf/T, var/icon/I, var/dist = 1)
//Kinda ugly, but needed unless the system is reworked
if(splash_initial)
smoke.initial_splash()
/datum/effect/effect/system/smoke_spread/chem/spores/spawnSmoke(var/turf/T, var/smoke_duration, var/icon/I, var/dist = 1)
var/obj/effect/effect/smoke/chem/spores = PoolOrNew(/obj/effect/effect/smoke/chem, location)
spores.name = "cloud of [seed.seed_name] [seed.seed_noun]"
..(T, I, dist, spores)
/datum/effect/effect/system/smoke_spread/chem/proc/fadeOut(var/atom/A, var/frames = 16) // Fades out the smoke smoothly using it's alpha variable.
if(A.alpha == 0) //Handle already transparent case
return
if(frames == 0)
frames = 1 //We will just assume that by 0 frames, the coder meant "during one frame".
var/step = A.alpha / frames
for(var/i = 0, i < frames, i++)
A.alpha -= step
sleep(world.tick_lag)
return
..(T, I, smoke_duration, dist, spores)
/datum/effect/effect/system/smoke_spread/chem/proc/smokeFlow() // Smoke pathfinder. Uses a flood fill method based on zones to quickly check what turfs the smoke (airflow) can actually reach.
@@ -60,7 +60,7 @@ var/global/list/image/splatter_cache=list()
var/obj/item/organ/external/l_foot = perp.get_organ("l_foot")
var/obj/item/organ/external/r_foot = perp.get_organ("r_foot")
var/hasfeet = 1
if((!l_foot || l_foot.status & ORGAN_DESTROYED) && (!r_foot || r_foot.status & ORGAN_DESTROYED))
if((!l_foot || l_foot.is_stump()) && (!r_foot || r_foot.is_stump()))
hasfeet = 0
if(perp.shoes && !perp.buckled)//Adding blood to shoes
var/obj/item/clothing/shoes/S = perp.shoes
@@ -105,27 +105,61 @@
qdel(src)
*/
/client/proc/spawn_tanktransferbomb()
set category = "Debug"
set desc = "Spawn a tank transfer valve bomb"
set name = "Instant TTV"
if(!check_rights(R_SPAWN)) return
var/obj/effect/spawner/newbomb/proto = /obj/effect/spawner/newbomb/radio/custom
var/p = input("Enter phoron amount (mol):","Phoron", initial(proto.phoron_amt)) as num|null
if(p == null) return
var/o = input("Enter oxygen amount (mol):","Oxygen", initial(proto.oxygen_amt)) as num|null
if(o == null) return
var/c = input("Enter carbon dioxide amount (mol):","Carbon Dioxide", initial(proto.carbon_amt)) as num|null
if(c == null) return
new /obj/effect/spawner/newbomb/radio/custom(get_turf(mob), p, o, c)
/obj/effect/spawner/newbomb
name = "bomb"
name = "TTV bomb"
icon = 'icons/mob/screen1.dmi'
icon_state = "x"
var/btype = 0 // 0=radio, 1=prox, 2=time
var/assembly_type = /obj/item/device/assembly/signaler
//Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa and 519K is 16.44 mol.
var/phoron_amt = 10.96
var/oxygen_amt = 16.44
var/carbon_amt = 0.0
timer
btype = 2
/obj/effect/spawner/newbomb/timer
name = "TTV bomb - timer"
assembly_type = /obj/item/device/assembly/timer
syndicate
/obj/effect/spawner/newbomb/timer/syndicate
name = "TTV bomb - merc"
//High yield bombs. Yes, it is possible to make these with toxins
phoron_amt = 15.66
oxygen_amt = 24.66
proximity
btype = 1
/obj/effect/spawner/newbomb/proximity
name = "TTV bomb - proximity"
assembly_type = /obj/item/device/assembly/prox_sensor
radio
btype = 0
/obj/effect/spawner/newbomb/New()
/obj/effect/spawner/newbomb/radio/custom/New(var/newloc, ph, ox, co)
if(ph != null) phoron_amt = ph
if(ox != null) oxygen_amt = ox
if(co != null) carbon_amt = co
..()
/obj/effect/spawner/newbomb/New(newloc)
..(newloc)
var/obj/item/device/transfer_valve/V = new(src.loc)
var/obj/item/weapon/tank/phoron/PT = new(V)
var/obj/item/weapon/tank/oxygen/OT = new(V)
@@ -137,28 +171,15 @@
OT.master = V
PT.air_contents.temperature = PHORON_FLASHPOINT
PT.air_contents.adjust_multi("phoron", 12, "carbon_dioxide", 8)
PT.air_contents.gas["phoron"] = phoron_amt
PT.air_contents.gas["carbon_dioxide"] = carbon_amt
PT.air_contents.update_values()
OT.air_contents.temperature = PHORON_FLASHPOINT
OT.air_contents.adjust_gas("oxygen", 20)
OT.air_contents.gas["oxygen"] = oxygen_amt
OT.air_contents.update_values()
var/obj/item/device/assembly/S
switch (src.btype)
// radio
if (0)
S = new/obj/item/device/assembly/signaler(V)
// proximity
if (1)
S = new/obj/item/device/assembly/prox_sensor(V)
// timer
if (2)
S = new/obj/item/device/assembly/timer(V)
var/obj/item/device/assembly/S = new assembly_type(V)
V.attached_device = S
+6
View File
@@ -151,6 +151,9 @@
if(temp && !temp.is_usable())
user << "<span class='notice'>You try to move your [temp.name], but cannot!"
return
if(!temp)
user << "<span class='notice'>You try to use your hand, but realize it is no longer attached!"
return
src.pickup(user)
if (istype(src.loc, /obj/item/weapon/storage))
var/obj/item/weapon/storage/S = src.loc
@@ -242,6 +245,9 @@
// for items that can be placed in multiple slots
// note this isn't called during the initial dressing of a player
/obj/item/proc/equipped(var/mob/user, var/slot)
layer = 20
if(user.client) user.client.screen |= src
if(user.pulling == src) user.stop_pulling()
return
//Defines which slots correspond to which slot flags
+4 -3
View File
@@ -721,7 +721,8 @@ var/global/list/obj/item/device/pda/PDAs = list()
if("Message")
var/obj/item/device/pda/P = locate(href_list["target"])
src.create_message(U, P, !href_list["notap"])
var/tap = istype(U, /mob/living/carbon)
src.create_message(U, P, tap)
if(mode == 2)
if(href_list["target"] in conversations) // Need to make sure the message went through, if not welp.
active_conversation = href_list["target"]
@@ -1040,7 +1041,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
new_message(sending_device, sending_device.owner, sending_device.ownjob, message)
/obj/item/device/pda/proc/new_message(var/sending_unit, var/sender, var/sender_job, var/message)
var/reception_message = "\icon[src] <b>Message from [sender] ([sender_job]), </b>\"[message]\" (<a href='byond://?src=\ref[src];choice=Message;notap=[istype(loc, /mob/living/silicon)];skiprefresh=1;target=\ref[sending_unit]'>Reply</a>)"
var/reception_message = "\icon[src] <b>Message from [sender] ([sender_job]), </b>\"[message]\" (<a href='byond://?src=\ref[src];choice=Message;skiprefresh=1;target=\ref[sending_unit]'>Reply</a>)"
new_info(message_silent, ttone, reception_message)
log_pda("[usr] (PDA: [sending_unit]) sent \"[message]\" to [name]")
@@ -1052,7 +1053,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
if(ismob(sending_unit.loc) && isAI(loc))
track = "(<a href='byond://?src=\ref[loc];track=\ref[sending_unit.loc];trackname=[html_encode(sender)]'>Follow</a>)"
var/reception_message = "\icon[src] <b>Message from [sender] ([sender_job]), </b>\"[message]\" (<a href='byond://?src=\ref[src];choice=Message;notap=1;skiprefresh=1;target=\ref[sending_unit]'>Reply</a>) [track]"
var/reception_message = "\icon[src] <b>Message from [sender] ([sender_job]), </b>\"[message]\" (<a href='byond://?src=\ref[src];choice=Message;skiprefresh=1;target=\ref[sending_unit]'>Reply</a>) [track]"
new_info(message_silent, newstone, reception_message)
log_pda("[usr] (PDA: [sending_unit]) sent \"[message]\" to [name]")
@@ -18,9 +18,11 @@
/obj/item/device/chameleon/dropped()
disrupt()
..()
/obj/item/device/chameleon/equipped()
disrupt()
..()
/obj/item/device/chameleon/attack_self()
toggle()
+1 -1
View File
@@ -320,7 +320,7 @@
qdel(src)
/obj/item/device/paicard/see_emote(mob/living/M, text)
if(pai && pai.client)
if(pai && pai.client && !pai.canmove)
var/rendered = "<span class='message'>[text]</span>"
pai.show_message(rendered, 2)
..()
@@ -99,17 +99,9 @@
if (src.loc != usr)
return 0
if(tank_one && href_list["tankone"])
split_gases()
valve_open = 0
tank_one.loc = get_turf(src)
tank_one = null
update_icon()
remove_tank(tank_one)
else if(tank_two && href_list["tanktwo"])
split_gases()
valve_open = 0
tank_two.loc = get_turf(src)
tank_two = null
update_icon()
remove_tank(tank_two)
else if(href_list["open"])
toggle_valve()
else if(attached_device)
@@ -148,20 +140,43 @@
if(attached_device)
overlays += "device"
/obj/item/device/transfer_valve/proc/remove_tank(obj/item/weapon/tank/T)
if(tank_one == T)
split_gases()
tank_one = null
else if(tank_two == T)
split_gases()
tank_two = null
else
return
T.loc = get_turf(src)
update_icon()
/obj/item/device/transfer_valve/proc/merge_gases()
if(valve_open)
return
tank_two.air_contents.volume += tank_one.air_contents.volume
var/datum/gas_mixture/temp
temp = tank_one.air_contents.remove_ratio(1)
tank_two.air_contents.merge(temp)
valve_open = 1
/obj/item/device/transfer_valve/proc/split_gases()
if (!valve_open || !tank_one || !tank_two)
if(!valve_open)
return
valve_open = 0
if(deleted(tank_one) || deleted(tank_two))
return
var/ratio1 = tank_one.air_contents.volume/tank_two.air_contents.volume
var/datum/gas_mixture/temp
temp = tank_two.air_contents.remove_ratio(ratio1)
tank_one.air_contents.merge(temp)
tank_two.air_contents.volume -= tank_one.air_contents.volume
/*
Exadv1: I know this isn't how it's going to work, but this was just to check
@@ -169,8 +184,7 @@
*/
/obj/item/device/transfer_valve/proc/toggle_valve()
if(valve_open==0 && (tank_one && tank_two))
valve_open = 1
if(!valve_open && (tank_one && tank_two))
var/turf/bombturf = get_turf(src)
var/area/A = get_area(bombturf)
@@ -196,16 +210,11 @@
message_admins(log_str, 0, 1)
log_game(log_str)
merge_gases()
spawn(20) // In case one tank bursts
for (var/i=0,i<5,i++)
src.update_icon()
sleep(10)
src.update_icon()
else if(valve_open==1 && (tank_one && tank_two))
split_gases()
valve_open = 0
src.update_icon()
src.update_icon()
// this doesn't do anything but the timer etc. expects it to be here
// eventually maybe have it update icon to show state (timer, prox etc.) like old bombs
@@ -71,6 +71,10 @@
icon_state = "meson"
icon = 'icons/obj/clothing/glasses.dmi'
/obj/item/borg/sight/material
name = "\proper material scanner vision"
sight_mode = BORGMATERIAL
/obj/item/borg/sight/hud
name = "hud"
var/obj/item/clothing/glasses/hud/hud = null
+7 -6
View File
@@ -137,6 +137,7 @@
if (istype(O, /obj/item/stack))
var/obj/item/stack/S = O
S.amount = produced
S.add_to_stacks(user)
if (istype(O, /obj/item/weapon/storage)) //BubbleWrap - so newly formed boxes are empty
for (var/obj/item/I in O)
@@ -191,7 +192,7 @@
else
if(get_amount() < used)
return 0
for(var/i = 1 to uses_charge)
for(var/i = 1 to charge_costs.len)
var/datum/matter_synth/S = synths[i]
S.use_charge(charge_costs[i] * used) // Doesn't need to be deleted
return 1
@@ -264,8 +265,8 @@
return 0
var/datum/matter_synth/S = synths[1]
. = round(S.get_charge() / charge_costs[1])
if(uses_charge > 1)
for(var/i = 2 to uses_charge)
if(charge_costs.len > 1)
for(var/i = 2 to charge_costs.len)
S = synths[i]
. = min(., round(S.get_charge() / charge_costs[i]))
return
@@ -284,13 +285,13 @@
return
return max_amount
/obj/item/stack/proc/add_to_stacks(mob/usr as mob)
for (var/obj/item/stack/item in usr.loc)
/obj/item/stack/proc/add_to_stacks(mob/user as mob)
for (var/obj/item/stack/item in user.loc)
if (item==src)
continue
var/transfer = src.transfer_to(item)
if (transfer)
usr << "You add a new [item.singular_name] to the stack. It now contains [item.amount] [item.singular_name]\s."
user << "<span class='notice'>You add a new [item.singular_name] to the stack. It now contains [item.amount] [item.singular_name]\s.</span>"
if(!amount)
break
@@ -1,27 +1,135 @@
#ifndef T_BOARD
#error T_BOARD macro is not defined but we need it!
#error T_BOARD macro is not defined but we need it!
#endif
/obj/item/weapon/circuitboard/air_management
name = T_BOARD("atmosphere monitoring console")
build_path = /obj/machinery/computer/general_air_control
var/console_name
var/frequency = 1439
var/list/sensors = list()
var/list/sensor_information = list()
/obj/item/weapon/circuitboard/air_management/tank_control
name = T_BOARD("tank control")
build_path = /obj/machinery/computer/general_air_control/large_tank_control
frequency = 1441
var/input_tag
var/output_tag
var/list/input_info = list()
var/list/output_info = list()
var/input_flow_setting = 200
var/pressure_setting = ONE_ATMOSPHERE * 45
/obj/item/weapon/circuitboard/air_management/supermatter_core
name = T_BOARD("core control")
build_path = /obj/machinery/computer/general_air_control/supermatter_core
frequency = 1438
var/input_tag
var/output_tag
var/list/input_info = list()
var/list/output_info = list()
var/input_flow_setting = 700
var/pressure_setting = 100
/obj/item/weapon/circuitboard/air_management/injector_control
name = T_BOARD("injector control")
build_path = /obj/machinery/computer/general_air_control/fuel_injection
var/device_tag
var/list/device_info
var/automation = 0
var/cutoff_temperature = 2000
var/on_temperature = 1200
/************
* Construct *
************/
/obj/item/weapon/circuitboard/air_management/construct(var/obj/machinery/computer/general_air_control/C)
if (..(C))
C.frequency = frequency
if(console_name)
C.name = console_name
C.set_frequency(frequency)
C.sensors = sensors.Copy()
C.sensor_information = sensor_information.Copy()
return 1
/obj/item/weapon/circuitboard/air_management/tank_control/construct(var/obj/machinery/computer/general_air_control/large_tank_control/LTC)
if(..(LTC))
LTC.input_tag = input_tag
LTC.output_tag = output_tag
LTC.input_info = input_info.Copy()
LTC.output_info = output_info.Copy()
LTC.input_flow_setting = input_flow_setting
LTC.pressure_setting = pressure_setting
return 1
/obj/item/weapon/circuitboard/air_management/supermatter_core/construct(var/obj/machinery/computer/general_air_control/supermatter_core/SC)
if(..(SC))
SC.input_tag = input_tag
SC.output_tag = output_tag
SC.input_info = input_info.Copy()
SC.output_info = output_info.Copy()
SC.input_flow_setting = input_flow_setting
SC.pressure_setting = input_flow_setting
return 1
/obj/item/weapon/circuitboard/air_management/injector_control/construct(var/obj/machinery/computer/general_air_control/fuel_injection/FI)
if(..(FI))
FI.device_tag = device_tag
FI.device_info = device_info.Copy()
FI.automation = automation
FI.cutoff_temperature = cutoff_temperature
FI.on_temperature = on_temperature
return 1
/**************
* Deconstruct *
**************/
/obj/item/weapon/circuitboard/air_management/deconstruct(var/obj/machinery/computer/general_air_control/C)
if (..(C))
console_name = C.name
frequency = C.frequency
sensors = C.sensors.Copy()
sensor_information = C.sensor_information.Copy()
return 1
/obj/item/weapon/circuitboard/air_management/tank_control/deconstruct(var/obj/machinery/computer/general_air_control/large_tank_control/LTC)
if(..(LTC))
input_tag = LTC.input_tag
output_tag = LTC.output_tag
input_info = LTC.input_info.Copy()
output_info = LTC.output_info.Copy()
input_flow_setting = LTC.input_flow_setting
pressure_setting = LTC.pressure_setting
return 1
/obj/item/weapon/circuitboard/air_management/supermatter_core/deconstruct(var/obj/machinery/computer/general_air_control/supermatter_core/SC)
if(..(SC))
input_tag = SC.input_tag
output_tag = SC.output_tag
input_info = SC.input_info.Copy()
output_info = SC.output_info.Copy()
input_flow_setting = SC.input_flow_setting
pressure_setting = SC.input_flow_setting
return 1
/obj/item/weapon/circuitboard/air_management/injector_control/deconstruct(var/obj/machinery/computer/general_air_control/fuel_injection/FI)
if(..(FI))
device_tag = FI.device_tag
device_info = FI.device_info.Copy()
automation = FI.automation
cutoff_temperature = FI.cutoff_temperature
on_temperature = FI.on_temperature
return 1
@@ -0,0 +1,31 @@
#ifndef T_BOARD
#error T_BOARD macro is not defined but we need it!
#endif
/obj/item/weapon/circuitboard/holodeckcontrol
name = T_BOARD("holodeck control console")
build_path = /obj/machinery/computer/HolodeckControl
origin_tech = "programming=2;bluespace=2"
var/last_to_emag
var/linkedholodeck_area
var/list/supported_programs
var/list/restricted_programs
/obj/item/weapon/circuitboard/holodeckcontrol/construct(var/obj/machinery/computer/HolodeckControl/HC)
if (..(HC))
HC.supported_programs = supported_programs.Copy()
HC.restricted_programs = restricted_programs.Copy()
if(linkedholodeck_area)
HC.linkedholodeck = locate(linkedholodeck_area)
if(last_to_emag)
HC.last_to_emag = last_to_emag
HC.emagged = 1
HC.safety_disabled = 1
/obj/item/weapon/circuitboard/holodeckcontrol/deconstruct(var/obj/machinery/computer/HolodeckControl/HC)
if (..(HC))
linkedholodeck_area = HC.linkedholodeck_area
supported_programs = HC.supported_programs.Copy()
restricted_programs = HC.restricted_programs.Copy()
last_to_emag = HC.last_to_emag
HC.emergencyShutdown()
+13 -2
View File
@@ -15,7 +15,15 @@
/*
* Soap
*/
/obj/item/weapon/soap/Crossed(AM as mob|obj) //EXACTLY the same as bananapeel for now, so it makes sense to put it in the same dm -- Urist
/obj/item/weapon/soap/New()
..()
create_reagents(5)
wet()
/obj/item/weapon/soap/proc/wet()
reagents.add_reagent("cleaner", 5)
/obj/item/weapon/soap/Crossed(AM as mob|obj)
if (istype(AM, /mob/living))
var/mob/living/M = AM
M.slip("the [src.name]",3)
@@ -32,7 +40,10 @@
else if(istype(target,/turf))
user << "<span class='notice'>You scrub \the [target.name] clean.</span>"
var/turf/T = target
T.clean(src)
T.clean(src, user)
else if(istype(target,/obj/structure/sink))
user << "<span class='notice'>You wet \the [src] in the sink.</span>"
wet()
else
user << "<span class='notice'>You clean \the [target.name].</span>"
target.clean_blood()
@@ -6,6 +6,7 @@
w_class = 2.0
force = 2.0
det_time = null
unacidable = 1
var/stage = 0
var/state = 0
var/path = 0
@@ -163,7 +164,7 @@
playsound(src.loc, 'sound/effects/bamf.ogg', 50, 1)
for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
G.reagents.trans_to(src, G.reagents.total_volume)
G.reagents.trans_to_obj(src, G.reagents.total_volume)
if(src.reagents.total_volume) //The possible reactions didnt use up all reagents.
var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread()
@@ -6,6 +6,7 @@
name = "implant"
icon = 'icons/obj/device.dmi'
icon_state = "implant"
w_class = 1
var/implanted = null
var/mob/imp_in = null
var/obj/item/organ/external/part = null
@@ -44,7 +44,8 @@
overlays.Cut()
return
else
..()
user << "<span class='warning'>You don't have anything on \the [src].</span>" //if we have help intent and no food scooped up DON'T STAB OURSELVES WITH THE FORK GODDAMNIT
return
/obj/item/weapon/material/kitchen/utensil/fork
name = "fork"
@@ -77,14 +78,14 @@
/obj/item/weapon/material/kitchen/utensil/knife/attack(target as mob, mob/living/user as mob)
if ((CLUMSY in user.mutations) && prob(50))
user << "\red You accidentally cut yourself with the [src]."
user << "<span class='warning'>You accidentally cut yourself with \the [src].</span>"
user.take_organ_damage(20)
return
return ..()
/obj/item/weapon/material/kitchen/utensil/knife/attack(target as mob, mob/living/user as mob)
if ((CLUMSY in user.mutations) && prob(50))
user << "\red You somehow managed to cut yourself with the [src]."
user << "<span class='warning'>You somehow managed to cut yourself with \the [src].</span>"
user.take_organ_damage(20)
return
return ..()
@@ -107,7 +108,7 @@
/obj/item/weapon/material/kitchen/rollingpin/attack(mob/living/M as mob, mob/living/user as mob)
if ((CLUMSY in user.mutations) && prob(50))
user << "\red The [src] slips out of your hand and hits your head."
user << "<span class='warning'>\The [src] slips out of your hand and hits your head.</span>"
user.take_organ_damage(10)
user.Paralyse(2)
return
+2 -14
View File
@@ -14,19 +14,7 @@
/obj/item/weapon/mop/New()
create_reagents(5)
//expects an atom containing the reagents used to clean the turf
/turf/proc/clean(atom/source)
if(source.reagents.has_reagent("water", 1))
clean_blood()
if(istype(src, /turf/simulated))
var/turf/simulated/T = src
T.dirt = 0
for(var/obj/effect/O in src)
if(istype(O,/obj/effect/rune) || istype(O,/obj/effect/decal/cleanable) || istype(O,/obj/effect/overlay))
qdel(O)
source.reagents.trans_to_turf(src, 1, 10) //10 is the multiplier for the reaction effect. probably needed to wet the floor properly.
create_reagents(30)
/obj/item/weapon/mop/afterattack(atom/A, mob/user, proximity)
if(!proximity) return
@@ -40,7 +28,7 @@
if(do_after(user, 40))
var/turf/T = get_turf(A)
if(T)
T.clean(src)
T.clean(src, user)
user << "<span class='notice'>You have finished mopping!</span>"
@@ -598,32 +598,33 @@
icon_state = "light"
desc = "This box is shaped on the inside so that only light tubes and bulbs fit."
item_state = "syringe_kit"
storage_slots=21
can_hold = list(/obj/item/weapon/light/tube, /obj/item/weapon/light/bulb)
max_storage_space = 42 //holds 21 items of w_class 2
use_to_pickup = 1 // for picking up broken bulbs, not that most people will try
/obj/item/weapon/storage/box/lights/New()
..()
make_exact_fit()
/obj/item/weapon/storage/box/lights/bulbs/New()
..()
for(var/i = 0; i < 21; i++)
new /obj/item/weapon/light/bulb(src)
..()
/obj/item/weapon/storage/box/lights/tubes
name = "box of replacement tubes"
icon_state = "lighttube"
/obj/item/weapon/storage/box/lights/tubes/New()
..()
for(var/i = 0; i < 21; i++)
new /obj/item/weapon/light/tube(src)
..()
/obj/item/weapon/storage/box/lights/mixed
name = "box of replacement lights"
icon_state = "lightmixed"
/obj/item/weapon/storage/box/lights/mixed/New()
..()
for(var/i = 0; i < 14; i++)
new /obj/item/weapon/light/tube(src)
for(var/i = 0; i < 7; i++)
new /obj/item/weapon/light/bulb(src)
..()
@@ -130,8 +130,7 @@
/obj/item/weapon/storage/firstaid/surgery
name = "surgery kit"
desc = "Contains tools for surgery."
storage_slots = 10
desc = "Contains tools for surgery. Has precise foam fitting for safe transport."
/obj/item/weapon/storage/firstaid/surgery/New()
..()
@@ -146,7 +145,8 @@
new /obj/item/weapon/bonegel(src)
new /obj/item/weapon/FixOVein(src)
new /obj/item/stack/medical/advanced/bruise_pack(src)
return
make_exact_fit()
/*
* Pill Bottles
@@ -51,10 +51,10 @@
//there's got to be a better way of doing this.
if (!(src.loc == usr) || (src.loc && src.loc.loc == usr))
return
if (( usr.restrained() ) || ( usr.stat ))
return
if ((src.loc == usr) && !usr.unEquip(src))
return
@@ -232,12 +232,16 @@
usr << "<span class='notice'>[src] is full, make some space.</span>"
return 0 //Storage item is full
if(can_hold.len && !is_type_in_list(W, can_hold))
if(!stop_messages)
if (istype(W, /obj/item/weapon/hand_labeler))
return 0
usr << "<span class='notice'>[src] cannot hold [W].</span>"
return 0
if(can_hold.len)
if(!is_type_in_list(W, can_hold))
if(!stop_messages && ! istype(W, /obj/item/weapon/hand_labeler))
usr << "<span class='notice'>[src] cannot hold \the [W].</span>"
return 0
var/max_instances = can_hold[W.type]
if(max_instances && instances_of_type_in_list(W, contents) >= max_instances)
if(!stop_messages && !istype(W, /obj/item/weapon/hand_labeler))
usr << "<span class='notice'>[src] has no more space specifically for \the [W].</span>"
return 0
if(cant_hold.len && is_type_in_list(W, cant_hold))
if(!stop_messages)
@@ -449,6 +453,17 @@
var/obj/O = A
O.hear_talk(M, text, verb, speaking)
/obj/item/weapon/storage/proc/make_exact_fit()
storage_slots = contents.len
can_hold.Cut()
max_w_class = 0
max_storage_space = 0
for(var/obj/item/I in src)
can_hold[I.type]++
max_w_class = max(I.w_class, max_w_class)
max_storage_space += I.get_storage_cost()
//Returns the storage depth of an atom. This is the number of storage items the atom is contained in before reaching toplevel (the area).
//Returns -1 if the atom was not found on container.
/atom/proc/storage_depth(atom/container)
@@ -1,71 +0,0 @@
/obj/item/robot_parts/attack(mob/living/carbon/human/M as mob, mob/living/carbon/user as mob)
var/limbloc = null
if(!istype(M))
return ..()
if(!((locate(/obj/machinery/optable, M.loc) && M.resting) || (locate(/obj/structure/bed/roller, M.loc) && (M.buckled || M.lying || M.weakened || M.stunned || M.paralysis || M.sleeping || M.stat)) && prob(75) || (locate(/obj/structure/table/, M.loc) && (M.lying || M.weakened || M.stunned || M.paralysis || M.sleeping || M.stat) && prob(66))))
return ..()
if(!istype(M, /mob/living/carbon/human))
return ..()
if((user.zone_sel.selecting == "l_arm") && (istype(src, /obj/item/robot_parts/l_arm)))
limbloc = "l_hand"
else if((user.zone_sel.selecting == "r_arm") && (istype(src, /obj/item/robot_parts/r_arm)))
limbloc = "r_hand"
else if((user.zone_sel.selecting == "r_leg") && (istype(src, /obj/item/robot_parts/r_leg)))
limbloc = "r_foot"
else if((user.zone_sel.selecting == "l_leg") && (istype(src, /obj/item/robot_parts/l_leg)))
limbloc = "l_foot"
else
user << "\red That doesn't fit there!"
return ..()
var/mob/living/carbon/human/H = M
var/datum/organ/external/S = H.organs[user.zone_sel.selecting]
if(S.status & ORGAN_DESTROYED)
if(!(S.status & ORGAN_ATTACHABLE))
user << "\red The wound is not ready for a replacement!"
return 0
if(M != user)
M.visible_message( \
"\red [user] is beginning to attach \the [src] where [H]'s [S.display_name] used to be.", \
"\red [user] begins to attach \the [src] where your [S.display_name] used to be.")
else
M.visible_message( \
"\red [user] begins to attach a robotic limb where \his [S.display_name] used to be with [src].", \
"\red You begin to attach \the [src] where your [S.display_name] used to be.")
if(do_mob(user, H, 100))
if(M != user)
M.visible_message( \
"\red [user] finishes attaching [H]'s new [S.display_name].", \
"\red [user] finishes attaching your new [S.display_name].")
else
M.visible_message( \
"\red [user] finishes attaching \his new [S.display_name].", \
"\red You finish attaching your new [S.display_name].")
if(H == user && prob(25))
user << "\red You mess up!"
S.take_damage(15)
S.status &= ~ORGAN_BROKEN
S.status &= ~ORGAN_SPLINTED
S.status &= ~ORGAN_ATTACHABLE
S.status &= ~ORGAN_DESTROYED
S.status |= ORGAN_ROBOT
var/datum/organ/external/T = H.organs["[limbloc]"]
T.status &= ~ORGAN_BROKEN
T.status &= ~ORGAN_SPLINTED
T.status &= ~ORGAN_ATTACHABLE
T.status &= ~ORGAN_DESTROYED
T.status |= ORGAN_ROBOT
H.update_body()
M.updatehealth()
M.UpdateDamageIcon()
qdel(src)
return 1
return 0

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