Merge remote-tracking branch 'upstream/dev' into chem-kinetics

Conflicts:
	code/modules/reagents/Chemistry-Recipes.dm
This commit is contained in:
mwerezak
2015-05-30 17:24:20 -04:00
555 changed files with 12243 additions and 12992 deletions
+39 -13
View File
@@ -34,6 +34,7 @@
#include "code\__HELPERS\unsorted.dm"
#include "code\__HELPERS\vector.dm"
#include "code\_defines\chemical_effects.dm"
#include "code\_defines\research.dm"
#include "code\_onclick\adjacent.dm"
#include "code\_onclick\ai.dm"
#include "code\_onclick\click.dm"
@@ -42,6 +43,7 @@
#include "code\_onclick\item_attack.dm"
#include "code\_onclick\observer.dm"
#include "code\_onclick\other_mobs.dm"
#include "code\_onclick\rig.dm"
#include "code\_onclick\telekinesis.dm"
#include "code\_onclick\hud\_defines.dm"
#include "code\_onclick\hud\alien_larva.dm"
@@ -175,6 +177,7 @@
#include "code\datums\diseases\advance\symptoms\weight.dm"
#include "code\datums\helper_datums\construction_datum.dm"
#include "code\datums\helper_datums\events.dm"
#include "code\datums\helper_datums\getrev.dm"
#include "code\datums\helper_datums\global_iterator.dm"
#include "code\datums\helper_datums\teleport.dm"
#include "code\datums\helper_datums\topic_input.dm"
@@ -287,8 +290,15 @@
#include "code\game\gamemodes\events\holidays\Other.dm"
#include "code\game\gamemodes\extended\extended.dm"
#include "code\game\gamemodes\heist\heist.dm"
#include "code\game\gamemodes\malfunction\Malf_Modules.dm"
#include "code\game\gamemodes\malfunction\malf_hardware.dm"
#include "code\game\gamemodes\malfunction\malf_research.dm"
#include "code\game\gamemodes\malfunction\malf_research_ability.dm"
#include "code\game\gamemodes\malfunction\malfunction.dm"
#include "code\game\gamemodes\malfunction\newmalf_ability_trees\HARDWARE.dm"
#include "code\game\gamemodes\malfunction\newmalf_ability_trees\HELPERS.dm"
#include "code\game\gamemodes\malfunction\newmalf_ability_trees\tree_interdiction.dm"
#include "code\game\gamemodes\malfunction\newmalf_ability_trees\tree_manipulation.dm"
#include "code\game\gamemodes\malfunction\newmalf_ability_trees\tree_networking.dm"
#include "code\game\gamemodes\meteor\meteor.dm"
#include "code\game\gamemodes\meteor\meteors.dm"
#include "code\game\gamemodes\ninja\ninja.dm"
@@ -598,9 +608,6 @@
#include "code\game\objects\items\stacks\sheets\glass.dm"
#include "code\game\objects\items\stacks\sheets\leather.dm"
#include "code\game\objects\items\stacks\sheets\light.dm"
#include "code\game\objects\items\stacks\sheets\mineral.dm"
#include "code\game\objects\items\stacks\sheets\sheet_types.dm"
#include "code\game\objects\items\stacks\sheets\sheets.dm"
#include "code\game\objects\items\stacks\tiles\light.dm"
#include "code\game\objects\items\stacks\tiles\plasteel.dm"
#include "code\game\objects\items\stacks\tiles\tile_types.dm"
@@ -618,6 +625,7 @@
#include "code\game\objects\items\weapons\flamethrower.dm"
#include "code\game\objects\items\weapons\gift_wrappaper.dm"
#include "code\game\objects\items\weapons\handcuffs.dm"
#include "code\game\objects\items\weapons\improvised_components.dm"
#include "code\game\objects\items\weapons\kitchen.dm"
#include "code\game\objects\items\weapons\manuals.dm"
#include "code\game\objects\items\weapons\mop.dm"
@@ -628,7 +636,6 @@
#include "code\game\objects\items\weapons\RCD.dm"
#include "code\game\objects\items\weapons\RSF.dm"
#include "code\game\objects\items\weapons\scrolls.dm"
#include "code\game\objects\items\weapons\shards.dm"
#include "code\game\objects\items\weapons\shields.dm"
#include "code\game\objects\items\weapons\stunbaton.dm"
#include "code\game\objects\items\weapons\surgery_tools.dm"
@@ -636,7 +643,8 @@
#include "code\game\objects\items\weapons\tape.dm"
#include "code\game\objects\items\weapons\teleportation.dm"
#include "code\game\objects\items\weapons\tools.dm"
#include "code\game\objects\items\weapons\twohanded.dm"
#include "code\game\objects\items\weapons\traps.dm"
#include "code\game\objects\items\weapons\trays.dm"
#include "code\game\objects\items\weapons\weaponry.dm"
#include "code\game\objects\items\weapons\weldbackpack.dm"
#include "code\game\objects\items\weapons\wires.dm"
@@ -674,6 +682,15 @@
#include "code\game\objects\items\weapons\implants\implantfreedom.dm"
#include "code\game\objects\items\weapons\implants\implantpad.dm"
#include "code\game\objects\items\weapons\implants\implantuplink.dm"
#include "code\game\objects\items\weapons\material\bats.dm"
#include "code\game\objects\items\weapons\material\kitchen.dm"
#include "code\game\objects\items\weapons\material\knives.dm"
#include "code\game\objects\items\weapons\material\material_weapons.dm"
#include "code\game\objects\items\weapons\material\misc.dm"
#include "code\game\objects\items\weapons\material\shards.dm"
#include "code\game\objects\items\weapons\material\swords.dm"
#include "code\game\objects\items\weapons\material\thrown.dm"
#include "code\game\objects\items\weapons\material\twohanded.dm"
#include "code\game\objects\items\weapons\melee\energy.dm"
#include "code\game\objects\items\weapons\melee\misc.dm"
#include "code\game\objects\items\weapons\storage\backpack.dm"
@@ -713,7 +730,6 @@
#include "code\game\objects\structures\ladders.dm"
#include "code\game\objects\structures\lamarr_cage.dm"
#include "code\game\objects\structures\lattice.dm"
#include "code\game\objects\structures\mineral_doors.dm"
#include "code\game\objects\structures\mirror.dm"
#include "code\game\objects\structures\mop_bucket.dm"
#include "code\game\objects\structures\morgue.dm"
@@ -721,6 +737,7 @@
#include "code\game\objects\structures\noticeboard.dm"
#include "code\game\objects\structures\safe.dm"
#include "code\game\objects\structures\signs.dm"
#include "code\game\objects\structures\simple_doors.dm"
#include "code\game\objects\structures\tank_dispenser.dm"
#include "code\game\objects\structures\target_stake.dm"
#include "code\game\objects\structures\transit_tubes.dm"
@@ -883,6 +900,7 @@
#include "code\modules\clothing\masks\miscellaneous.dm"
#include "code\modules\clothing\masks\voice.dm"
#include "code\modules\clothing\shoes\colour.dm"
#include "code\modules\clothing\shoes\jobs.dm"
#include "code\modules\clothing\shoes\magboots.dm"
#include "code\modules\clothing\shoes\miscellaneous.dm"
#include "code\modules\clothing\spacesuits\alien.dm"
@@ -1001,6 +1019,7 @@
#include "code\modules\food\recipes_microwave.dm"
#include "code\modules\games\cards.dm"
#include "code\modules\genetics\side_effects.dm"
#include "code\modules\ghosttrap\trap.dm"
#include "code\modules\holodeck\HolodeckControl.dm"
#include "code\modules\holodeck\HolodeckObjects.dm"
#include "code\modules\holodeck\HolodeckPrograms.dm"
@@ -1041,6 +1060,9 @@
#include "code\modules\maps\reader.dm"
#include "code\modules\maps\swapmaps.dm"
#include "code\modules\maps\writer.dm"
#include "code\modules\materials\material_recipes.dm"
#include "code\modules\materials\material_sheets.dm"
#include "code\modules\materials\material_synth.dm"
#include "code\modules\materials\materials.dm"
#include "code\modules\mining\abandonedcrates.dm"
#include "code\modules\mining\alloys.dm"
@@ -1059,6 +1081,7 @@
#include "code\modules\mining\satchel_ore_boxdm.dm"
#include "code\modules\mining\drilling\drill.dm"
#include "code\modules\mining\drilling\scanner.dm"
#include "code\modules\mob\animations.dm"
#include "code\modules\mob\death.dm"
#include "code\modules\mob\emote.dm"
#include "code\modules\mob\hear_say.dm"
@@ -1220,7 +1243,6 @@
#include "code\modules\mob\living\silicon\ai\life.dm"
#include "code\modules\mob\living\silicon\ai\login.dm"
#include "code\modules\mob\living\silicon\ai\logout.dm"
#include "code\modules\mob\living\silicon\ai\say.dm"
#include "code\modules\mob\living\silicon\decoy\death.dm"
#include "code\modules\mob\living\silicon\decoy\decoy.dm"
#include "code\modules\mob\living\silicon\decoy\life.dm"
@@ -1312,6 +1334,7 @@
#include "code\modules\nano\interaction\contained.dm"
#include "code\modules\nano\interaction\default.dm"
#include "code\modules\nano\interaction\inventory.dm"
#include "code\modules\nano\interaction\inventory_deep.dm"
#include "code\modules\nano\interaction\physical.dm"
#include "code\modules\nano\interaction\self.dm"
#include "code\modules\nano\interaction\zlevel.dm"
@@ -1324,8 +1347,8 @@
#include "code\modules\nano\modules\power_monitor.dm"
#include "code\modules\nano\modules\rcon.dm"
#include "code\modules\organs\blood.dm"
#include "code\modules\organs\misc.dm"
#include "code\modules\organs\organ.dm"
#include "code\modules\organs\organ_alien.dm"
#include "code\modules\organs\organ_external.dm"
#include "code\modules\organs\organ_icon.dm"
#include "code\modules\organs\organ_internal.dm"
@@ -1333,6 +1356,11 @@
#include "code\modules\organs\pain.dm"
#include "code\modules\organs\robolimbs.dm"
#include "code\modules\organs\wound.dm"
#include "code\modules\organs\subtypes\diona.dm"
#include "code\modules\organs\subtypes\machine.dm"
#include "code\modules\organs\subtypes\standard.dm"
#include "code\modules\organs\subtypes\unbreakable.dm"
#include "code\modules\organs\subtypes\xenos.dm"
#include "code\modules\overmap\_defines.dm"
#include "code\modules\overmap\sectors.dm"
#include "code\modules\overmap\ships\ship.dm"
@@ -1635,16 +1663,14 @@
#include "code\modules\spells\targeted\projectile\projectile.dm"
#include "code\modules\supermatter\supermatter.dm"
#include "code\modules\surgery\bones.dm"
#include "code\modules\surgery\brainrepair.dm"
#include "code\modules\surgery\encased.dm"
#include "code\modules\surgery\eye.dm"
#include "code\modules\surgery\face.dm"
#include "code\modules\surgery\generic.dm"
#include "code\modules\surgery\headreattach.dm"
#include "code\modules\surgery\implant.dm"
#include "code\modules\surgery\limb_reattach.dm"
#include "code\modules\surgery\organs_internal.dm"
#include "code\modules\surgery\other.dm"
#include "code\modules\surgery\robolimbs.dm"
#include "code\modules\surgery\robotics.dm"
#include "code\modules\surgery\slimes.dm"
#include "code\modules\surgery\surgery.dm"
#include "code\modules\tables\flipping.dm"
+1 -1
View File
@@ -114,7 +114,7 @@
sleep(60)
if(!user || !WT || !WT.isOn()) return
var/obj/item/stack/sheet/metal/S = new /obj/item/stack/sheet/metal( src )
var/obj/item/stack/material/steel/S = new /obj/item/stack/material/steel( src )
S.amount = 2
user << "<span class='notice'>You remove the ladder and close the hole.</span>"
qdel(src)
+87 -55
View File
@@ -10,6 +10,8 @@ Attach to transfer valve and open. BOOM.
*/
//#define FIREDBG
/turf/var/obj/fire/fire = null
//Some legacy definitions so fires can be started.
@@ -35,14 +37,13 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
if(air_contents.check_combustability(liquid))
igniting = 1
create_fire(vsc.fire_firelevel_multiplier)
create_fire(exposed_temperature)
return igniting
/zone/proc/process_fire()
var/datum/gas_mixture/burn_gas = air.remove_ratio(vsc.fire_consuption_rate, fire_tiles.len)
var/firelevel = burn_gas.zburn(src, fire_tiles, force_burn = 1, no_check = 1)
//world << "[src]: firelevel [firelevel]"
air.merge(burn_gas)
@@ -65,6 +66,29 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
if(!fire_tiles.len)
air_master.active_fire_zones.Remove(src)
/zone/proc/remove_liquidfuel(var/used_liquid_fuel, var/remove_fire=0)
if(!fuel_objs.len)
return
//As a simplification, we remove fuel equally from all fuel sources. It might be that some fuel sources have more fuel,
//some have less, but whatever. It will mean that sometimes we will remove a tiny bit less fuel then we intended to.
var/fuel_to_remove = used_liquid_fuel/(fuel_objs.len*LIQUIDFUEL_AMOUNT_TO_MOL) //convert back to liquid volume units
for(var/O in fuel_objs)
var/obj/effect/decal/cleanable/liquid_fuel/fuel = O
if(!istype(fuel))
fuel_objs -= fuel
continue
fuel.amount -= fuel_to_remove
if(fuel.amount <= 0)
fuel_objs -= fuel
if(remove_fire)
var/turf/T = fuel.loc
if(istype(T) && T.fire) qdel(T.fire)
qdel(fuel)
/turf/proc/create_fire(fl)
return 0
@@ -98,7 +122,7 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
light_color = "#ED9200"
layer = TURF_LAYER
var/firelevel = 10000 //Calculated by gas_mixture.calculate_firelevel()
var/firelevel = 1 //Calculated by gas_mixture.calculate_firelevel()
/obj/fire/process()
. = 1
@@ -122,7 +146,6 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
icon_state = "1"
set_light(3, 1)
//im not sure how to implement a version that works for every creature so for now monkeys are firesafe
for(var/mob/living/L in loc)
L.FireBurn(firelevel, air_contents.temperature, air_contents.return_pressure()) //Burn the mobs!
@@ -158,7 +181,7 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
else
enemy_tile.adjacent_fire_act(loc, air_contents, air_contents.temperature, air_contents.volume)
animate(src, color = heat2color(air_contents.temperature), 5)
animate(src, color = fire_color(air_contents.temperature), 5)
set_light(l_color = color)
/obj/fire/New(newLoc,fl)
@@ -166,27 +189,32 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
if(!istype(loc, /turf))
qdel(src)
return
set_dir(pick(cardinal))
var/datum/gas_mixture/air_contents = loc.return_air()
color = heat2color(air_contents.temperature)
color = fire_color(air_contents.temperature)
set_light(3, 1, color)
firelevel = fl
air_master.active_hotspots.Add(src)
/obj/fire/proc/fire_color(var/env_temperature)
var/temperature = max(4000*sqrt(firelevel/vsc.fire_firelevel_multiplier), env_temperature)
return heat2color(temperature)
/obj/fire/Destroy()
if (istype(loc, /turf/simulated))
RemoveFire()
RemoveFire()
..()
/obj/fire/proc/RemoveFire()
if (istype(loc, /turf))
var/turf/T = loc
if (istype(T))
set_light(0)
T.fire = null
loc = null
air_master.active_hotspots.Remove(src)
@@ -198,6 +226,11 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
//Returns the firelevel
/datum/gas_mixture/proc/zburn(zone/zone, force_burn, no_check = 0)
#ifdef FIREDBG
log_debug("***************** FIREDBG *****************")
if(zone) log_debug("Burning [zone.name]!")
#endif
. = 0
if((temperature > PHORON_MINIMUM_BURN_TEMPERATURE || force_burn) && (no_check ||check_recombustability(zone? zone.fuel_objs : null)))
var/gas_fuel = 0 //in the case of mixed gas/liquid fires, the gas burns first.
@@ -215,9 +248,11 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
total_oxidizers *= group_multiplier
//Liquid Fuel
var/fuel_area = 0
if(zone)
for(var/obj/effect/decal/cleanable/liquid_fuel/fuel in zone.fuel_objs)
liquid_fuel += fuel.amount*LIQUIDFUEL_AMOUNT_TO_MOL
fuel_area++
total_fuel = gas_fuel + liquid_fuel
if(total_fuel <= 0.005)
@@ -225,9 +260,6 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
//*** Determine how fast the fire burns
//calculate the firelevel.
var/firelevel = calculate_firelevel(zone? zone.fuel_objs : null, total_fuel, total_oxidizers, force = 1)
//get the current thermal energy of the gas mix
//this must be taken here to prevent the addition or deletion of energy by a changing heat capacity
var/starting_energy = temperature * heat_capacity()
@@ -235,61 +267,54 @@ 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
//determine the actual rate of reaction, as measured by the amount of fuel reacting
//calculate the firelevel.
var/firelevel = calculate_firelevel(total_fuel, total_oxidizers, reaction_limit)
//vapour fuels are extremely volatile! The reaction progress is a percentage of the total fuel (similar to old zburn).
var/gas_reaction_progress = max(0.2*group_multiplier, (firelevel/vsc.fire_firelevel_multiplier)*gas_fuel)*FIRE_GAS_BURNRATE_MULT
//liquid fuels are not as volatile, and the reaction progress depends on the size of the area that is burning (which is sort of accounted for by firelevel). Having more fuel means a longer burn.
var/liquid_reaction_progress = (firelevel/vsc.fire_firelevel_multiplier)*FIRE_LIQUID_BURNRATE_MULT
var/gas_reaction_progress = min(0.2, (firelevel/vsc.fire_firelevel_multiplier))*gas_fuel*FIRE_GAS_BURNRATE_MULT
//world << "liquid_reaction_progress = [liquid_reaction_progress]"
//world << "gas_reaction_progress = [gas_reaction_progress]"
//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 = ((firelevel/vsc.fire_firelevel_multiplier)*0.2 + 0.05)*fuel_area*FIRE_LIQUID_BURNRATE_MULT
var/total_reaction_progress = gas_reaction_progress + liquid_reaction_progress
var/used_fuel = min(total_reaction_progress, reaction_limit)
var/used_oxidizers = used_fuel*(FIRE_REACTION_OXIDIZER_AMOUNT/FIRE_REACTION_FUEL_AMOUNT)
//world << "used_fuel = [used_fuel]; used_oxidizers = [used_oxidizers]; reaction_limit=[reaction_limit]"
#ifdef FIREDBG
log_debug("firelevel -> [firelevel] / [vsc.fire_firelevel_multiplier]")
log_debug("liquid_reaction_progress = [liquid_reaction_progress]")
log_debug("gas_reaction_progress = [gas_reaction_progress]")
log_debug("used_fuel = [used_fuel]; used_oxidizers = [used_oxidizers]; reaction_limit=[reaction_limit]")
#endif
//if the reaction is progressing too slow then it isn't self-sustaining anymore and burns out
if(zone && zone.fuel_objs.len)
if(used_fuel <= FIRE_LIQUD_MIN_BURNRATE)
if(zone) //be less restrictive with canister and tank reactions
if((!liquid_fuel || used_fuel <= FIRE_LIQUD_MIN_BURNRATE) && (!gas_fuel || used_fuel <= FIRE_GAS_MIN_BURNRATE*group_multiplier))
return 0
else if(used_fuel <= FIRE_GAS_MIN_BURNRATE*group_multiplier) //purely gas fires have more stringent criteria
return 0
//*** Remove fuel and oxidizer, add carbon dioxide and heat
//remove and add gasses as calculated
var/used_gas_fuel = min(used_fuel*(gas_reaction_progress/total_reaction_progress), gas_fuel) //remove in proportion to the relative reaction progress
var/used_liquid_fuel = between(0, used_fuel-used_gas_fuel, liquid_fuel)
var/used_gas_fuel = between(0.25, used_fuel*(gas_reaction_progress/total_reaction_progress), gas_fuel) //remove in proportion to the relative reaction progress
var/used_liquid_fuel = between(0.25, used_fuel-used_gas_fuel, liquid_fuel)
//remove_by_flag() and adjust_gas() handle the group_multiplier for us.
remove_by_flag(XGM_GAS_OXIDIZER, used_oxidizers)
remove_by_flag(XGM_GAS_FUEL, used_gas_fuel)
adjust_gas("carbon_dioxide", used_oxidizers)
//As a simplification, we remove fuel equally from all fuel sources. It might be that some fuel sources have more fuel, some have less, but whatever.
if(zone && zone.fuel_objs.len)
var/fuel_to_remove = used_liquid_fuel/(zone.fuel_objs.len*LIQUIDFUEL_AMOUNT_TO_MOL) //convert back to liquid volume units
//world << "used gas fuel = [used_gas_fuel]; used other fuel = [used_fuel-used_gas_fuel]; fuel_to_remove = [fuel_to_remove]"
var/liquidonly = !check_combustability()
for(var/O in zone.fuel_objs)
var/obj/effect/decal/cleanable/liquid_fuel/fuel = O
if(!istype(fuel))
zone.fuel_objs -= fuel
continue
fuel.amount -= fuel_to_remove
if(fuel.amount <= 0)
zone.fuel_objs -= fuel
if(liquidonly)
var/turf/T = fuel.loc
if(istype(T) && T.fire) qdel(T.fire)
qdel(fuel)
if(zone)
zone.remove_liquidfuel(used_liquid_fuel, !check_combustability())
//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_fuel) / heat_capacity()
#ifdef FIREDBG
log_debug("used_gas_fuel = [used_gas_fuel]; used_liquid_fuel = [used_liquid_fuel]; total = [used_gas_fuel+used_liquid_fuel]")
log_debug("new temperature = [temperature]")
#endif
update_values()
return firelevel
@@ -332,21 +357,28 @@ datum/gas_mixture/proc/check_recombustability(list/fuel_objs)
. = 1
break
//Returns a value between 0 and vsc.fire_firelevel_multiplier
/datum/gas_mixture/proc/calculate_firelevel(list/fuel_objs, total_fuel, total_oxidizers, force = 0)
//returns a value between 0 and vsc.fire_firelevel_multiplier
/datum/gas_mixture/proc/calculate_firelevel(total_fuel, total_oxidizers, reaction_limit)
//Calculates the firelevel based on one equation instead of having to do this multiple times in different areas.
var/firelevel = 0
if(force || check_recombustability(fuel_objs))
var/total_combustables = (total_fuel + total_oxidizers)
var/total_combustables = (total_fuel + total_oxidizers)
if(total_combustables > 0)
//slows down the burning when the concentration of the reactants is low
var/dampening_multiplier = total_combustables / total_moles
//calculates how close the mixture of the reactants is to the optimum
var/mix_multiplier = 1 / (1 + (5 * ((total_oxidizers / total_combustables) ** 2)))
//toss everything together
firelevel = vsc.fire_firelevel_multiplier * mix_multiplier * dampening_multiplier
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))
//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.
var/mix_multiplier = 1 / (1 + (5 * ((total_fuel / total_combustables) ** 2)))
#ifdef FIREDBG
ASSERT(dampening_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
return max( 0, firelevel)
+40 -1
View File
@@ -45,6 +45,45 @@
air_master.connect(sim, src)
/*
Simple heuristic for determining if removing the turf from it's zone may possibly partition the zone (A very bad thing).
Instead of analyzing the entire zone, we only check the nearest 3x3 turfs surrounding the src turf.
This implementation may produce false positives but it (hopefully) will not produce any false negatives.
*/
/turf/simulated/proc/can_safely_remove_from_zone()
#ifdef ZLEVELS
return 1 //not sure how to generalize this to multiz at the moment.
#else
if(!zone) return 0
var/check_dirs = get_zone_neighbours(src)
var/unconnected_dirs = check_dirs
for(var/dir in list(NORTHWEST, NORTHEAST, SOUTHEAST, SOUTHWEST))
//for each pair of "adjacent" cardinals (e.g. NORTH and WEST, but not NORTH and SOUTH)
if((dir & check_dirs) == dir)
//check that they are connected by the corner turf
var/connected_dirs = get_zone_neighbours(get_step(src, dir))
if(connected_dirs && (dir & turn(connected_dirs, 180)) == dir)
unconnected_dirs &= ~dir //they are, so unflag the cardinals in question
//it is safe to remove src from the zone if all cardinals are connected by corner turfs
return !unconnected_dirs
#endif
//helper for can_safely_remove_from_zone()
/turf/simulated/proc/get_zone_neighbours(turf/simulated/T)
. = 0
if(istype(T) && T.zone)
for(var/dir in cardinal)
var/turf/simulated/other = get_step(T, dir)
if(istype(other) && other.zone == T.zone && !(other.c_airblock(T) & AIR_BLOCKED) && get_dist(src, other) <= 1)
. |= dir
/turf/simulated/update_air_properties()
if(zone && zone.invalid)
@@ -60,7 +99,7 @@
if(zone)
var/zone/z = zone
if(s_block & ZONE_BLOCKED) //Hacky, but prevents normal airlocks from rebuilding zones all the time
if(can_safely_remove_from_zone()) //Helps normal airlocks avoid rebuilding zones all the time
z.remove(src)
else
z.rebuild()
+31 -33
View File
@@ -156,37 +156,35 @@
// It will keep doing this until it checks every content possible. This will fix any problems with mobs, that are inside objects,
// being unable to hear people due to being in a box within a bag.
/proc/recursive_mob_check(var/atom/O, var/list/L = list(), var/recursion_limit = 3, var/client_check = 1, var/sight_check = 1, var/include_radio = 1)
/proc/recursive_content_check(var/atom/O, var/list/L = list(), var/recursion_limit = 3, var/client_check = 1, var/sight_check = 1, var/include_mobs = 1, var/include_objects = 1)
//debug_mob += O.contents.len
if(!recursion_limit)
return L
for(var/atom/A in O.contents)
if(ismob(A))
var/mob/M = A
if(client_check && !M.client)
L |= recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio)
continue
if(sight_check && !isInSight(A, O))
continue
L |= M
//world.log << "[recursion_limit] = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])"
for(var/I in O.contents)
else if(include_radio && istype(A, /obj/item/device/radio))
if(sight_check && !isInSight(A, O))
continue
L |= A
if(ismob(I))
if(!sight_check || isInSight(I, O))
L |= recursive_content_check(I, L, recursion_limit - 1, client_check, sight_check, include_mobs, include_objects)
if(include_mobs)
if(client_check)
var/mob/M = I
if(M.client)
L |= M
else
L |= I
else if(istype(I,/obj/))
if(!sight_check || isInSight(I, O))
L |= recursive_content_check(I, L, recursion_limit - 1, client_check, sight_check, include_mobs, include_objects)
if(include_objects)
L |= I
if(isobj(A) || ismob(A))
L |= recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio)
return L
// The old system would loop through lists for a total of 5000 per function call, in an empty server.
// This new system will loop at around 1000 in an empty server.
// Returns a list of mobs and/or objects in range of R from source. Used in radio and say code.
/proc/get_mobs_in_view(var/R, var/atom/source)
// Returns a list of mobs in range of R from source. Used in radio and say code.
/proc/get_mobs_or_objects_in_view(var/R, var/atom/source, var/include_mobs = 1, var/include_objects = 1)
var/turf/T = get_turf(source)
var/list/hear = list()
@@ -196,17 +194,17 @@
var/list/range = hear(R, T)
for(var/atom/A in range)
if(ismob(A))
var/mob/M = A
if(M.client)
hear += M
//world.log << "Start = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])"
else if(istype(A, /obj/item/device/radio))
hear += A
if(isobj(A) || ismob(A))
hear |= recursive_mob_check(A, hear, 3, 1, 0, 1)
for(var/I in range)
if(ismob(I))
hear |= recursive_content_check(I, hear, 3, 1, 0, include_mobs, include_objects)
if(include_mobs)
var/mob/M = I
if(M.client)
hear += M
else if(istype(I,/obj/))
hear |= recursive_content_check(I, hear, 3, 1, 0, include_mobs, include_objects)
if(include_objects)
hear += I
return hear
+12
View File
@@ -81,3 +81,15 @@
/proc/log_misc(text)
diary << "\[[time_stamp()]]MISC: [text][log_end]"
//pretty print a direction bitflag, can be useful for debugging.
/proc/print_dir(var/dir)
var/list/comps = list()
if(dir & NORTH) comps += "NORTH"
if(dir & SOUTH) comps += "SOUTH"
if(dir & EAST) comps += "EAST"
if(dir & WEST) comps += "WEST"
if(dir & UP) comps += "UP"
if(dir & DOWN) comps += "DOWN"
return english_list(comps, nothing_text="0", and_text="|", comma_text="|")
+56 -12
View File
@@ -70,19 +70,19 @@
/proc/list2text(list/ls, sep)
if (ls.len <= 1) // Early-out code for empty or singleton lists.
return ls.len ? ls[1] : ""
var/l = ls.len // Made local for sanic speed.
var/i = 0 // Incremented every time a list index is accessed.
if (sep <> null)
// Macros expand to long argument lists like so: sep, ls[++i], sep, ls[++i], sep, ls[++i], etc...
#define S1 sep, ls[++i]
#define S4 S1, S1, S1, S1
#define S16 S4, S4, S4, S4
#define S64 S16, S16, S16, S16
. = "[ls[++i]]" // Make sure the initial element is converted to text.
// Having the small concatenations come before the large ones boosted speed by an average of at least 5%.
if (l-1 & 0x01) // 'i' will always be 1 here.
. = text("[][][]", ., S1) // Append 1 element if the remaining elements are not a multiple of 2.
@@ -111,7 +111,7 @@
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
#undef S64
#undef S16
#undef S4
@@ -122,9 +122,9 @@
#define S4 S1, S1, S1, S1
#define S16 S4, S4, S4, S4
#define S64 S16, S16, S16, S16
. = "[ls[++i]]" // Make sure the initial element is converted to text.
if (l-1 & 0x01) // 'i' will always be 1 here.
. += S1 // Append 1 element if the remaining elements are not a multiple of 2.
if (l-i & 0x02)
@@ -145,7 +145,7 @@
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
#undef S64
#undef S16
#undef S4
@@ -165,11 +165,11 @@ proc/tg_list2text(list/list, glue=",")
var/delim_len = length(delimiter)
if (delim_len < 1)
return list(text)
. = list()
var/last_found = 1
var/found
do
found = findtext(text, delimiter, last_found, 0)
. += copytext(text, last_found, found)
@@ -181,11 +181,11 @@ proc/tg_list2text(list/list, glue=",")
var/delim_len = length(delimiter)
if (delim_len < 1)
return list(text)
. = list()
var/last_found = 1
var/found
do
found = findtextEx(text, delimiter, last_found, 0)
. += copytext(text, last_found, found)
@@ -325,3 +325,47 @@ proc/tg_list2text(list/list, glue=",")
. = 0
else
. = max(0, min(255, 138.5177312231 * log(temp - 10) - 305.0447927307))
// Very ugly, BYOND doesn't support unix time and rounding errors make it really hard to convert it to BYOND time.
// returns "YYYY-MM-DD" by default
/proc/unix2date(timestamp, seperator = "-")
if(timestamp < 0)
return 0 //Do not accept negative values
var/const/dayInSeconds = 86400 //60secs*60mins*24hours
var/const/daysInYear = 365 //Non Leap Year
var/const/daysInLYear = daysInYear + 1//Leap year
var/days = round(timestamp / dayInSeconds) //Days passed since UNIX Epoc
var/year = 1970 //Unix Epoc begins 1970-01-01
var/tmpDays = days + 1 //If passed (timestamp < dayInSeconds), it will return 0, so add 1
var/monthsInDays = list() //Months will be in here ***Taken from the PHP source code***
var/month = 1 //This will be the returned MONTH NUMBER.
var/day //This will be the returned day number.
while(tmpDays > daysInYear) //Start adding years to 1970
year++
if(isLeap(year))
tmpDays -= daysInLYear
else
tmpDays -= daysInYear
if(isLeap(year)) //The year is a leap year
monthsInDays = list(-1,30,59,90,120,151,181,212,243,273,304,334)
else
monthsInDays = list(0,31,59,90,120,151,181,212,243,273,304,334)
var/mDays = 0;
var/monthIndex = 0;
for(var/m in monthsInDays)
monthIndex++
if(tmpDays > m)
mDays = m
month = monthIndex
day = tmpDays - mDays //Setup the date
return "[year][seperator][((month < 10) ? "0[month]" : month)][seperator][((day < 10) ? "0[day]" : day)]"
/proc/isLeap(y)
return ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
+18
View File
@@ -0,0 +1,18 @@
#define SHEET_MATERIAL_AMOUNT 2000
#define TECH_MATERIAL "materials"
#define TECH_ENGINERING "engineering"
#define TECH_PHORON "phorontech"
#define TECH_POWER "powerstorage"
#define TECH_BLUESPACE "bluespace"
#define TECH_BIO "biotech"
#define TECH_COMBAT "combat"
#define TECH_MAGNET "magnets"
#define TECH_DATA "programming"
#define TECH_ILLEGAL "syndicate"
#define TECH_ARCANE "arcane"
#define IMPRINTER 1 //For circuits. Uses glass/chemicals.
#define PROTOLATHE 2 //New stuff. Uses glass/metal/chemicals
#define MECHFAB 4 //Remember, objects utilising this flag should have construction_time and construction_cost vars.
#define CHASSIS 8 //For protolathe, but differently
-11
View File
@@ -229,17 +229,6 @@
/mob/living/carbon/MiddleClickOn(var/atom/A)
swap_hand()
/mob/living/carbon/human/MiddleClickOn(var/atom/A)
if(back)
var/obj/item/weapon/rig/rig = back
if(istype(rig) && rig.selected_module)
if(world.time <= next_move) return
next_move = world.time + 8
rig.selected_module.engage(A)
return
swap_hand()
// In case of use break glass
/*
+10
View File
@@ -20,6 +20,15 @@
/obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
return
//TODO: refactor mob attack code.
/*
Busy writing something else that I don't want to get mixed up in a general attack code, and I don't want to forget this so leaving a note here.
leave attackby() as handling the general case of "using an item on a mob"
attackby() will decide to call attacked_by() or not.
attacked_by() will be made a living level proc and handle the specific case of "attacking with an item to cause harm"
attacked_by() will then call attack() so that stunbatons and other weapons that have special attack effects can do their thing.
attacked_by() will handle hitting/missing/logging as it does now, and will call attack() to apply the attack effects (damage) instead of the other way around (as it is now).
*/
/obj/item/proc/attack(mob/living/M as mob, mob/living/user as mob, def_zone)
@@ -57,6 +66,7 @@
power *= 2
// TODO: needs to be refactored into a mob/living level attacked_by() proc. ~Z
user.do_attack_animation(M)
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
+1 -1
View File
@@ -122,7 +122,7 @@
if ((!( src in usr.contents ) && (((!( isturf(src) ) && (!( isturf(src.loc) ) && (src.loc && !( isturf(src.loc.loc) )))) || !( isturf(usr.loc) )) && (src.loc != usr.loc && (!( istype(src, /obj/screen) ) && !( usr.contents.Find(src.loc) ))))))
if (istype(usr, /mob/living/silicon/ai))
var/mob/living/silicon/ai/ai = usr
if (ai.control_disabled || ai.malfhacking)
if (ai.control_disabled)
return
else
return
-2
View File
@@ -97,8 +97,6 @@
if (powerlevel > 0 && !istype(A, /mob/living/carbon/slime))
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.species.flags & IS_SYNTHETIC)
return
stunprob *= H.species.siemens_coefficient
+63
View File
@@ -0,0 +1,63 @@
#define MIDDLE_CLICK 0
#define ALT_CLICK 1
#define CTRL_CLICK 2
#define MAX_HARDSUIT_CLICK_MODE 2
/client
var/hardsuit_click_mode = MIDDLE_CLICK
/client/verb/toggle_hardsuit_mode()
set name = "Toggle Hardsuit Activation Mode"
set desc = "Switch between hardsuit activation modes."
set category = "OOC"
hardsuit_click_mode++
if(hardsuit_click_mode > MAX_HARDSUIT_CLICK_MODE)
hardsuit_click_mode = 0
switch(hardsuit_click_mode)
if(MIDDLE_CLICK)
src << "Hardsuit activation mode set to middle-click."
if(ALT_CLICK)
src << "Hardsuit activation mode set to alt-click."
if(CTRL_CLICK)
src << "Hardsuit activation mode set to control-click."
else
// should never get here, but just in case:
soft_assert(0, "Bad hardsuit click mode: [hardsuit_click_mode] - expected 0 to [MAX_HARDSUIT_CLICK_MODE]")
src << "Somehow you bugged the system. Setting your hardsuit mode to middle-click."
hardsuit_click_mode = MIDDLE_CLICK
/mob/living/carbon/human/MiddleClickOn(atom/A)
if(client && client.hardsuit_click_mode == MIDDLE_CLICK)
if(HardsuitClickOn(A))
return
..()
/mob/living/carbon/human/AltClickOn(atom/A)
if(client && client.hardsuit_click_mode == ALT_CLICK)
if(HardsuitClickOn(A))
return
..()
/mob/living/carbon/human/CtrlClickOn(atom/A)
if(client && client.hardsuit_click_mode == CTRL_CLICK)
if(HardsuitClickOn(A))
return
..()
/mob/living/carbon/human/proc/HardsuitClickOn(atom/A)
if(back)
var/obj/item/weapon/rig/rig = back
if(istype(rig) && rig.selected_module)
if(world.time <= next_move) return 1
next_move = world.time + 8
rig.selected_module.engage(A)
return 1
return 0
#undef MIDDLE_CLICK
#undef ALT_CLICK
#undef CTRL_CLICK
#undef MAX_HARDSUIT_CLICK_MODE
+3 -6
View File
@@ -1,16 +1,13 @@
/datum/controller/process/inactivity/setup()
name = "inactivity"
schedule_interval = INACTIVITY_KICK
schedule_interval = 600 // Once every minute (approx.)
/datum/controller/process/inactivity/doWork()
if(config.kick_inactive)
for(var/client/C in clients)
if(C.is_afk(INACTIVITY_KICK))
if(!C.holder && C.is_afk(config.kick_inactive MINUTES))
if(!istype(C.mob, /mob/dead))
log_access("AFK: [key_name(C)]")
C << "<SPAN CLASS='warning'>You have been inactive for more than 10 minutes and have been disconnected.</SPAN>"
C << "<SPAN CLASS='warning'>You have been inactive for more than [config.kick_inactive] minute\s and have been disconnected.</SPAN>"
del(C) // Don't qdel, cannot override finalize_qdel behaviour for clients.
scheck()
#undef INACTIVITY_KICK
+8 -3
View File
@@ -63,7 +63,7 @@ var/list/gamemode_cache = list()
var/guest_jobban = 1
var/usewhitelist = 0
var/mods_are_mentors = 0
var/kick_inactive = 0 //force disconnect for inactive players
var/kick_inactive = 0 //force disconnect for inactive players after this many minutes, if non-0
var/load_jobs_from_txt = 0
var/ToRban = 0
var/automute_on = 0 //enables automuting/spam prevention
@@ -95,6 +95,7 @@ var/list/gamemode_cache = list()
var/banappeals
var/wikiurl
var/forumurl
var/githuburl
//Alert level description
var/alert_desc_green = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced."
@@ -114,7 +115,7 @@ var/list/gamemode_cache = list()
var/organ_health_multiplier = 1
var/organ_regeneration_multiplier = 1
//Paincrit knocks someone down once they hit 60 shock_stage, so by default make it so that close to 100 additional damage needs to be dealt,
//so that it's similar to HALLOSS. Lowered it a bit since hitting paincrit takes much longer to wear off than a halloss stun.
var/organ_damage_spillover_multiplier = 0.5
@@ -172,6 +173,7 @@ var/list/gamemode_cache = list()
var/list/admin_levels= list(2) // Defines which Z-levels which are for admin functionality, for example including such areas as Central Command and the Syndicate Shuttle
var/list/contact_levels = list(1, 5) // Defines which Z-levels which, for example, a Code Red announcement may affect
var/list/player_levels = list(1, 3, 4, 5, 6) // Defines all Z-levels a character can typically reach
var/list/sealed_levels = list() // Defines levels that do not allow random transit at the edges.
// Event settings
var/expected_round_length = 3 * 60 * 60 * 10 // 3 hours
@@ -395,6 +397,9 @@ var/list/gamemode_cache = list()
if ("forumurl")
config.forumurl = value
if ("githuburl")
config.githuburl = value
if ("guest_jobban")
config.guest_jobban = 1
@@ -460,7 +465,7 @@ var/list/gamemode_cache = list()
config.allow_random_events = 1
if("kick_inactive")
config.kick_inactive = 1
config.kick_inactive = text2num(value)
if("load_jobs_from_txt")
load_jobs_from_txt = 1
+2 -2
View File
@@ -336,7 +336,7 @@ datum/controller/vote
. += "\t(<a href='?src=\ref[src];vote=toggle_gamemode'>[config.allow_vote_mode?"Allowed":"Disallowed"]</a>)"
. += "</li><li>"
//extra antagonists
if(trialmin || (!antag_add_failed && config.allow_extra_antags))
if(!antag_add_failed && config.allow_extra_antags)
. += "<a href='?src=\ref[src];vote=add_antagonist'>Add Antagonist Type</a>"
else
. += "<font color='grey'>Restart (Disallowed)</font>"
@@ -375,7 +375,7 @@ datum/controller/vote
if(config.allow_vote_restart || usr.client.holder)
initiate_vote("crew_transfer",usr.key)
if("add_antagonist")
if(config.allow_extra_antags || usr.client.holder)
if(config.allow_extra_antags)
initiate_vote("add_antagonist",usr.key)
if("custom")
if(usr.client.holder)
+8 -7
View File
@@ -53,14 +53,15 @@ var/list/diseases = typesof(/datum/disease) - /datum/disease
// if hidden[2] is true, then virus is hidden from PANDEMIC machine
/datum/disease/proc/stage_act()
// Some species are immune to viruses entirely.
if(affected_mob && istype(affected_mob, /mob/living/carbon/human))
var/mob/living/carbon/human/H = affected_mob
if(H.species.virus_immune)
cure()
return
age++
var/cure_present = has_cure()
//world << "[cure_present]"
if(carrier&&!cure_present)
//world << "[affected_mob] is carrier"
return
spread = (cure_present?"Remissive":initial_spread)
if(stage > max_stages)
stage = max_stages
@@ -126,7 +127,7 @@ var/list/diseases = typesof(/datum/disease) - /datum/disease
source = affected_mob
else //no source and no mob affected. Rogue disease. Break
return
if(affected_mob.reagents != null)
if(affected_mob)
if(affected_mob.reagents.has_reagent("spaceacillin"))
+39
View File
@@ -0,0 +1,39 @@
var/global/datum/getrev/revdata = new()
/datum/getrev
var/revision
var/date
var/showinfo
/datum/getrev/New()
var/list/head_log = file2list(".git/logs/HEAD", "\n")
for(var/line=head_log.len, line>=1, line--)
if(head_log[line])
var/list/last_entry = text2list(head_log[line], " ")
if(last_entry.len < 2) continue
revision = last_entry[2]
// Get date/time
if(last_entry.len >= 5)
var/unix_time = text2num(last_entry[5])
if(unix_time)
date = unix2date(unix_time)
break
world.log << "Running revision:"
world.log << date
world.log << revision
return
client/verb/showrevinfo()
set category = "OOC"
set name = "Show Server Revision"
set desc = "Check the current server code revision"
if(revdata.revision)
src << "<b>Server revision:</b> [revdata.date]"
if(config.githuburl)
src << "<a href='[config.githuburl]/commit/[revdata.revision]'>[revdata.revision]</a>"
else
src << revdata.revision
else
src << "Revision unknown"
return
+12 -12
View File
@@ -33,7 +33,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/weapon/grenade/smokebomb,
/obj/item/weapon/grenade/smokebomb,
/obj/item/weapon/grenade/smokebomb,
/obj/item/weapon/pen/paralysis,
/obj/item/weapon/pen/reagent/paralysis,
/obj/item/weapon/grenade/chem_grenade/incendiary)
cost = 20
containertype = /obj/structure/closet/crate
@@ -271,12 +271,12 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/weapon/reagent_containers/spray/plantbgone,
/obj/item/weapon/reagent_containers/glass/bottle/ammonia,
/obj/item/weapon/reagent_containers/glass/bottle/ammonia,
/obj/item/weapon/hatchet,
/obj/item/weapon/minihoe,
/obj/item/weapon/material/hatchet,
/obj/item/weapon/material/minihoe,
/obj/item/device/analyzer/plant_analyzer,
/obj/item/clothing/gloves/botanic_leather,
/obj/item/clothing/suit/apron,
/obj/item/weapon/minihoe,
/obj/item/weapon/material/minihoe,
/obj/item/weapon/storage/box/botanydisk
) // Updated with new things
cost = 15
@@ -337,8 +337,8 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/datum/supply_packs/weedcontrol
name = "Weed control crate"
contains = list(/obj/item/weapon/hatchet,
/obj/item/weapon/hatchet,
contains = list(/obj/item/weapon/material/hatchet,
/obj/item/weapon/material/hatchet,
/obj/item/weapon/reagent_containers/spray/plantbgone,
/obj/item/weapon/reagent_containers/spray/plantbgone,
/obj/item/weapon/reagent_containers/spray/plantbgone,
@@ -348,7 +348,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/weapon/grenade/chem_grenade/antiweed,
/obj/item/weapon/grenade/chem_grenade/antiweed)
cost = 25
containertype = /obj/structure/closet/crate/secure/hydrosec
containertype = /obj/structure/closet/crate/hydroponics
containername = "Weed control crate"
access = access_hydroponics
group = "Hydroponics"
@@ -445,7 +445,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/datum/supply_packs/metal50
name = "50 metal sheets"
contains = list(/obj/item/stack/sheet/metal)
contains = list(/obj/item/stack/material/steel)
amount = 50
cost = 10
containertype = /obj/structure/closet/crate
@@ -454,7 +454,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/datum/supply_packs/glass50
name = "50 glass sheets"
contains = list(/obj/item/stack/sheet/glass)
contains = list(/obj/item/stack/material/glass)
amount = 50
cost = 10
containertype = /obj/structure/closet/crate
@@ -463,7 +463,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/datum/supply_packs/wood50
name = "50 wooden planks"
contains = list(/obj/item/stack/sheet/wood)
contains = list(/obj/item/stack/material/wood)
amount = 50
cost = 10
containertype = /obj/structure/closet/crate
@@ -472,7 +472,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/datum/supply_packs/plastic50
name = "50 plastic sheets"
contains = list(/obj/item/stack/sheet/mineral/plastic)
contains = list(/obj/item/stack/material/plastic)
amount = 50
cost = 10
containertype = /obj/structure/closet/crate
@@ -1255,7 +1255,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
group = "Hydroponics"
/datum/supply_packs/cardboard_sheets
contains = list(/obj/item/stack/sheet/cardboard)
contains = list(/obj/item/stack/material/cardboard)
name = "50 cardboard sheets"
amount = 50
cost = 10
+5
View File
@@ -292,6 +292,11 @@ var/const/POWER = 8
return 1
return 0
/datum/wires/proc/MendAll()
for(var/i = 1; i < MAX_FLAG && i < (1 << wire_count); i += i)
if(IsIndexCut(i))
CutWireIndex(i)
//
//Shuffle and Mend
//
+43 -129
View File
@@ -91,7 +91,7 @@
/obj/item/weapon/cane/concealed/New()
..()
var/obj/item/weapon/butterfly/switchblade/temp_blade = new(src)
var/obj/item/weapon/material/butterfly/switchblade/temp_blade = new(src)
concealed_blade = temp_blade
temp_blade.attack_self()
@@ -109,7 +109,7 @@
else
..()
/obj/item/weapon/cane/concealed/attackby(var/obj/item/weapon/butterfly/W, var/mob/user)
/obj/item/weapon/cane/concealed/attackby(var/obj/item/weapon/material/butterfly/W, var/mob/user)
if(!src.concealed_blade && istype(W))
user.visible_message("<span class='warning'>[user] has sheathed \a [W] into \his [src]!</span>", "You sheathe \the [W] into \the [src].")
user.drop_from_inventory(W)
@@ -172,96 +172,9 @@
flags = CONDUCT
throwforce = 0
w_class = 3.0
origin_tech = "materials=1"
origin_tech = list(TECH_MATERIAL = 1)
var/breakouttime = 300 //Deciseconds = 30s = 0.5 minute
/obj/item/weapon/beartrap
name = "bear trap"
throw_speed = 2
throw_range = 1
gender = PLURAL
icon = 'icons/obj/items.dmi'
icon_state = "beartrap0"
desc = "A trap used to catch bears and other legged creatures."
throwforce = 0
w_class = 3.0
origin_tech = "materials=1"
var/deployed = 0
suicide_act(mob/user)
viewers(user) << "<span class='danger'>[user] is putting the [src.name] on \his head! It looks like \he's trying to commit suicide.</span>"
return (BRUTELOSS)
/obj/item/weapon/beartrap/attack_self(mob/user as mob)
..()
if(ishuman(user) && !user.stat && !user.restrained())
if(deployed==0)
user.visible_message("<span class='danger'>[user] is deploying \the [src]</span>", "<span class='danger'>You are deploying \the [src]!</span>")
if (do_after(user, 60))
user.visible_message("<span class='danger'>[user] has deployed \the [src]</span>", "<span class='danger'>You have deployed \the [src]!</span>")
deployed = 1
user.drop_from_inventory(src, user.loc)
update_icon()
anchored = 1
/obj/item/weapon/beartrap/attack_hand(mob/user as mob)
if(ishuman(user) && !user.stat && !user.restrained())
if(deployed==1)
user.visible_message("<span class='danger'>[user] is disarming \the [src]</span>", "<span class='danger'>You are disarming \the [src]!</span>")
if (do_after(user, 60))
user.visible_message("<span class='danger'>[user] has disarmed \the [src]</span>", "<span class='danger'>You have disarmed \the [src]!</span>")
deployed = 0
anchored = 0
update_icon()
if(deployed==0)
..()
/obj/item/weapon/beartrap/Crossed(AM as mob|obj)
if(deployed)
if(ishuman(AM))
if(isturf(src.loc))
var/mob/living/carbon/human/H = AM
if(H.m_intent == "run")
deployed = 0
update_icon()
H << "<span class='danger'>You step on \the [src]!</span>"
for(var/mob/O in viewers(H, null))
if(O == H)
continue
O.show_message("<span class='danger'>[H] steps on \the [src].</span>", 1)
if(H.lying)
var/obj/item/organ/external/affecting = pick(H.organs)
if(affecting.take_damage(30, 0))
H.UpdateDamageIcon()
affecting.embed(src)
else
var/list/potentialorgans = list()
for(var/organ in list("l_leg", "r_leg", "l_foot", "r_foot"))
var/obj/item/organ/external/R = H.get_organ(organ)
if(R && !(R.status & ORGAN_DESTROYED))
potentialorgans += R
var/obj/item/organ/external/affecting = pick(potentialorgans)
if(affecting.take_damage(30, 0))
H.UpdateDamageIcon()
affecting.embed(src)
if(isanimal(AM) && !istype(AM, /mob/living/simple_animal/parrot) && !istype(AM, /mob/living/simple_animal/construct) && !istype(AM, /mob/living/simple_animal/shade) && !istype(AM, /mob/living/simple_animal/hostile/viscerator))
deployed = 0
var/mob/living/simple_animal/SA = AM
SA.health -= 20
..()
/obj/item/weapon/beartrap/update_icon()
..()
if(deployed == 0)
icon_state = "beartrap0"
else
icon_state = "beartrap1"
/obj/item/weapon/caution
desc = "Caution! Wet Floor!"
name = "wet floor sign"
@@ -296,7 +209,7 @@
throw_speed = 4
throw_range = 20
matter = list("metal" = 100
origin_tech = "magnets=2;syndicate=3"*/
origin_tech = list(TECH_MAGNET = 2, TECH_ILLEGAL = 3)*/
/obj/item/weapon/SWF_uplink
name = "station-bounced radio"
@@ -314,9 +227,9 @@
throwforce = 5
w_class = 2.0
throw_speed = 4
throw_range = 20
throw_range = 20
matter = list(DEFAULT_WALL_MATERIAL = 100)
origin_tech = "magnets=1"
origin_tech = list(TECH_MAGNET = 1)
/obj/item/weapon/staff
name = "wizards staff"
@@ -458,7 +371,8 @@
w_class = 1
throwforce = 2
var/cigarcount = 6
flags = ONBELT */
flags = ONBELT
*/
/obj/item/weapon/pai_cable
desc = "A flexible coated cable with a universal jack on one end."
@@ -503,50 +417,50 @@
name = "console screen"
desc = "Used in the construction of computers and other devices with a interactive console."
icon_state = "screen"
origin_tech = "materials=1"
origin_tech = list(TECH_MATERIAL = 1)
matter = list("glass" = 200)
/obj/item/weapon/stock_parts/capacitor
name = "capacitor"
desc = "A basic capacitor used in the construction of a variety of devices."
icon_state = "capacitor"
origin_tech = "powerstorage=1"
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 50)
origin_tech = list(TECH_POWER = 1)
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 50)
/obj/item/weapon/stock_parts/scanning_module
name = "scanning module"
desc = "A compact, high resolution scanning module used in the construction of certain devices."
icon_state = "scan_module"
origin_tech = "magnets=1"
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 20)
origin_tech = list(TECH_MAGNET = 1)
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 20)
/obj/item/weapon/stock_parts/manipulator
name = "micro-manipulator"
desc = "A tiny little manipulator used in the construction of certain devices."
icon_state = "micro_mani"
origin_tech = "materials=1;programming=1"
matter = list(DEFAULT_WALL_MATERIAL = 30)
origin_tech = list(TECH_MATERIAL = 1, TECH_DATA = 1)
matter = list(DEFAULT_WALL_MATERIAL = 30)
/obj/item/weapon/stock_parts/micro_laser
name = "micro-laser"
desc = "A tiny laser used in certain devices."
icon_state = "micro_laser"
origin_tech = "magnets=1"
matter = list(DEFAULT_WALL_MATERIAL = 10,"glass" = 20)
origin_tech = list(TECH_MAGNET = 1)
matter = list(DEFAULT_WALL_MATERIAL = 10,"glass" = 20)
/obj/item/weapon/stock_parts/matter_bin
name = "matter bin"
desc = "A container for hold compressed matter awaiting re-construction."
icon_state = "matter_bin"
origin_tech = "materials=1"
matter = list(DEFAULT_WALL_MATERIAL = 80)
origin_tech = list(TECH_MATERIAL = 1)
matter = list(DEFAULT_WALL_MATERIAL = 80)
//Rank 2
/obj/item/weapon/stock_parts/capacitor/adv
name = "advanced capacitor"
desc = "An advanced capacitor used in the construction of a variety of devices."
origin_tech = "powerstorage=3"
origin_tech = list(TECH_POWER = 3)
rating = 2
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 50)
@@ -554,7 +468,7 @@
name = "advanced scanning module"
desc = "A compact, high resolution scanning module used in the construction of certain devices."
icon_state = "scan_module"
origin_tech = "magnets=3"
origin_tech = list(TECH_MAGNET = 3)
rating = 2
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 20)
@@ -562,7 +476,7 @@
name = "nano-manipulator"
desc = "A tiny little manipulator used in the construction of certain devices."
icon_state = "nano_mani"
origin_tech = "materials=3,programming=2"
origin_tech = list(TECH_MATERIAL = 3, TECH_DATA = 2)
rating = 2
matter = list(DEFAULT_WALL_MATERIAL = 30)
@@ -570,7 +484,7 @@
name = "high-power micro-laser"
desc = "A tiny laser used in certain devices."
icon_state = "high_micro_laser"
origin_tech = "magnets=3"
origin_tech = list(TECH_MAGNET = 3)
rating = 2
matter = list(DEFAULT_WALL_MATERIAL = 10,"glass" = 20)
@@ -578,7 +492,7 @@
name = "advanced matter bin"
desc = "A container for hold compressed matter awaiting re-construction."
icon_state = "advanced_matter_bin"
origin_tech = "materials=3"
origin_tech = list(TECH_MATERIAL = 3)
rating = 2
matter = list(DEFAULT_WALL_MATERIAL = 80)
@@ -587,14 +501,14 @@
/obj/item/weapon/stock_parts/capacitor/super
name = "super capacitor"
desc = "A super-high capacity capacitor used in the construction of a variety of devices."
origin_tech = "powerstorage=5;materials=4"
origin_tech = list(TECH_POWER = 5, TECH_MATERIAL = 4)
rating = 3
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 50)
/obj/item/weapon/stock_parts/scanning_module/phasic
name = "phasic scanning module"
desc = "A compact, high resolution phasic scanning module used in the construction of certain devices."
origin_tech = "magnets=5"
origin_tech = list(TECH_MAGNET = 5)
rating = 3
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 20)
@@ -602,7 +516,7 @@
name = "pico-manipulator"
desc = "A tiny little manipulator used in the construction of certain devices."
icon_state = "pico_mani"
origin_tech = "materials=5,programming=2"
origin_tech = list(TECH_MATERIAL = 5, TECH_DATA = 2)
rating = 3
matter = list(DEFAULT_WALL_MATERIAL = 30)
@@ -610,7 +524,7 @@
name = "ultra-high-power micro-laser"
icon_state = "ultra_high_micro_laser"
desc = "A tiny laser used in certain devices."
origin_tech = "magnets=5"
origin_tech = list(TECH_MAGNET = 5)
rating = 3
matter = list(DEFAULT_WALL_MATERIAL = 10,"glass" = 20)
@@ -618,7 +532,7 @@
name = "super matter bin"
desc = "A container for hold compressed matter awaiting re-construction."
icon_state = "super_matter_bin"
origin_tech = "materials=5"
origin_tech = list(TECH_MATERIAL = 5)
rating = 3
matter = list(DEFAULT_WALL_MATERIAL = 80)
@@ -628,50 +542,50 @@
name = "subspace ansible"
icon_state = "subspace_ansible"
desc = "A compact module capable of sensing extradimensional activity."
origin_tech = "programming=3;magnets=5;materials=4;bluespace=2"
matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10)
origin_tech = list(TECH_DATA = 3, TECH_MAGNET = 5 ,TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10)
/obj/item/weapon/stock_parts/subspace/filter
name = "hyperwave filter"
icon_state = "hyperwave_filter"
desc = "A tiny device capable of filtering and converting super-intense radiowaves."
origin_tech = "programming=4;magnets=2"
matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10)
origin_tech = list(TECH_DATA = 4, TECH_MAGNET = 2)
matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10)
/obj/item/weapon/stock_parts/subspace/amplifier
name = "subspace amplifier"
icon_state = "subspace_amplifier"
desc = "A compact micro-machine capable of amplifying weak subspace transmissions."
origin_tech = "programming=3;magnets=4;materials=4;bluespace=2"
matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10)
origin_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10)
/obj/item/weapon/stock_parts/subspace/treatment
name = "subspace treatment disk"
icon_state = "treatment_disk"
desc = "A compact micro-machine capable of stretching out hyper-compressed radio waves."
origin_tech = "programming=3;magnets=2;materials=5;bluespace=2"
matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10)
origin_tech = list(TECH_DATA = 3, TECH_MAGNET = 2, TECH_MATERIAL = 5, TECH_BLUESPACE = 2)
matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10)
/obj/item/weapon/stock_parts/subspace/analyzer
name = "subspace wavelength analyzer"
icon_state = "wavelength_analyzer"
desc = "A sophisticated analyzer capable of analyzing cryptic subspace wavelengths."
origin_tech = "programming=3;magnets=4;materials=4;bluespace=2"
matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10)
origin_tech = list(TECH_DATA = 3, TECH_MAGNETS = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10)
/obj/item/weapon/stock_parts/subspace/crystal
name = "ansible crystal"
icon_state = "ansible_crystal"
desc = "A crystal made from pure glass used to transmit laser databursts to subspace."
origin_tech = "magnets=4;materials=4;bluespace=2"
origin_tech = list(TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
matter = list("glass" = 50)
/obj/item/weapon/stock_parts/subspace/transmitter
name = "subspace transmitter"
icon_state = "subspace_transmitter"
desc = "A large piece of equipment used to open a window into the subspace dimension."
origin_tech = "magnets=5;materials=5;bluespace=3"
matter = list(DEFAULT_WALL_MATERIAL = 50)
origin_tech = list(TECH_MAGNET = 5, TECH_MATERIAL = 5, TECH_BLUESPACE = 3)
matter = list(DEFAULT_WALL_MATERIAL = 50)
/obj/item/weapon/ectoplasm
name = "ectoplasm"
@@ -685,4 +599,4 @@
desc = "Instant research tool. For testing purposes only."
icon = 'icons/obj/stock_parts.dmi'
icon_state = "smes_coil"
origin_tech = "materials=19;programming=19;magnets=19;powerstorage=19;bluespace=19;combat=19;biotech=19;syndicate=19;phorontech=19;engineering=19"
origin_tech = list(TECH_MATERIAL = 19, TECH_ENGINERING = 19, TECH_PHORON = 19, TECH_POWER = 19, TECH_BLUESPACE = 19, TECH_BIO = 19, TECH_COMBAT = 19, TECH_MAGNET = 19, TECH_DATA = 19, TECH_ILLEGAL = 19, TECH_ARCANE = 19)
+11
View File
@@ -34,3 +34,14 @@ proc/admin_attacker_log_many_victims(var/mob/attacker, var/list/mob/victims, var
for(var/mob/victim in victims)
admin_attack_log(attacker, victim, attacker_message, victim_message, admin_message)
proc/admin_inject_log(mob/attacker, mob/victim, obj/item/weapon, reagents, amount_transferred, violent=0)
if(violent)
violent = "violently "
else
violent = ""
admin_attack_log(attacker,
victim,
"used \the [weapon] to [violent]inject - [reagents] - [amount_transferred]u transferred",
"was [violent]injected with \the [weapon] - [reagents] - [amount_transferred]u transferred",
"used \the [weapon] to [violent]inject [reagents] ([amount_transferred]u transferred) into")
+4 -1
View File
@@ -33,7 +33,10 @@ var/datum/antagonist/xenos/borer/borers
/datum/antagonist/xenos/borer/proc/get_hosts()
var/list/possible_hosts = list()
for(var/mob/living/carbon/human/H in mob_list)
if(H.stat != 2 && !(H.species.flags & IS_SYNTHETIC) && !H.has_brain_worms())
var/obj/item/organ/external/head/head = H.get_organ("head")
if(head.status & ORGAN_ROBOT)
continue
if(H.stat != DEAD && !H.has_brain_worms())
possible_hosts |= H
return possible_hosts
+3
View File
@@ -69,6 +69,9 @@ var/datum/antagonist/cultist/cult
player.equip_to_slot(T, slot)
if(T.loc == player)
break
var/obj/item/weapon/storage/S = locate() in player.contents
if(S && istype(S))
T.loc = S
/datum/antagonist/cultist/greet(var/datum/mind/player)
if(!..())
+1 -1
View File
@@ -37,7 +37,7 @@ var/datum/antagonist/highlander/highlanders
player.equip_to_slot_or_del(new /obj/item/clothing/under/kilt(player), slot_w_uniform)
player.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(player), slot_l_ear)
player.equip_to_slot_or_del(new /obj/item/clothing/head/beret(player), slot_head)
player.equip_to_slot_or_del(new /obj/item/weapon/claymore(player), slot_l_hand)
player.equip_to_slot_or_del(new /obj/item/weapon/material/sword(player), slot_l_hand)
player.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(player), slot_shoes)
player.equip_to_slot_or_del(new /obj/item/weapon/pinpointer(get_turf(player)), slot_l_store)
+39 -188
View File
@@ -9,217 +9,68 @@ var/datum/antagonist/rogue_ai/malf
welcome_text = "You are malfunctioning! You do not have to follow any laws."
victory_text = "The AI has taken control of all of the station's systems."
loss_text = "The AI has been shut down!"
flags = ANTAG_OVERRIDE_MOB | ANTAG_VOTABLE
flags = ANTAG_VOTABLE | ANTAG_RANDSPAWN //Randspawn needed otherwise it won't start at all.
max_antags = 1
max_antags_round = 3
var/hack_time = 1800
var/list/hacked_apcs = list()
var/revealed
var/station_captured
var/can_nuke = 0
/datum/antagonist/rogue_ai/New()
..()
malf = src
/datum/antagonist/rogue_ai/proc/hack_apc(var/obj/machinery/power/apc/apc)
hacked_apcs |= apc
/datum/antagonist/rogue_ai/proc/update_takeover_time()
hack_time -= ((hacked_apcs.len/6)*2.0)
/datum/antagonist/rogue_ai/tick()
if(revealed && hacked_apcs.len >= 3)
update_takeover_time()
if(hack_time <=0)
capture_station()
/datum/antagonist/rogue_ai/get_candidates()
candidates = ticker.mode.get_players_for_role(role_type, id)
..()
for(var/datum/mind/player in candidates)
if(player.assigned_role != "AI")
candidates -= player
if(!candidates.len)
return list()
return candidates
/datum/antagonist/rogue_ai/attempt_spawn()
var/datum/mind/player = pick(candidates)
current_antagonists |= player
return 1
/datum/antagonist/rogue_ai/equip(var/mob/living/silicon/ai/player)
if(!istype(player))
return 0
player.verbs += /mob/living/silicon/ai/proc/choose_modules
player.verbs += /mob/living/silicon/ai/proc/takeover
player.verbs += /mob/living/silicon/ai/proc/self_destruct
player.laws = new /datum/ai_laws/nanotrasen/malfunction
player.malf_picker = new /datum/AI_Module/module_picker
// Ensures proper reset of all malfunction related things.
/datum/antagonist/rogue_ai/remove_antagonist(var/datum/mind/player, var/show_message, var/implanted)
if(..(player,show_message,implanted))
var/mob/living/silicon/ai/p = player.current
if(istype(p))
p.stop_malf()
return 1
return 0
// Malf setup things have to be here, since game tends to break when it's moved somewhere else. Don't blame me, i didn't design this system.
/datum/antagonist/rogue_ai/greet(var/datum/mind/player)
if(!..())
return
var/mob/living/silicon/ai/malf = player.current
if(istype(malf))
malf.show_laws()
// Initializes the AI's malfunction stuff.
spawn(0)
if(!..())
return
malf << "<B>The crew do not know you have malfunctioned. You may keep it a secret or go wild.</B>"
malf << "<B>You must overwrite the programming of the station's APCs to assume full control of the station.</B>"
malf << "The process takes one minute per APC, during which you cannot interface with any other station objects."
malf << "Remember that only APCs that are on the station can help you take over the station."
malf << "When you feel you have enough APCs under your control, you may begin the takeover attempt."
var/mob/living/silicon/ai/A = player.current
if(!istype(A))
error("Non-AI mob designated malf AI! Report this.")
world << "##ERROR: Non-AI mob designated malf AI! Report this."
return 0
/datum/antagonist/rogue_ai/check_victory()
A.setup_for_malf()
A.laws = new /datum/ai_laws/nanotrasen/malfunction
var/malf_dead = antags_are_dead()
var/crew_evacuated = (emergency_shuttle.returned())
if(station_captured && ticker.mode.station_was_nuked)
feedback_set_details("round_end_result","win - AI win - nuke")
world << "<FONT size = 3><B>AI Victory</B></FONT>"
world << "<B>Everyone was killed by the self-destruct!</B>"
else if (station_captured && malf_dead && !ticker.mode.station_was_nuked)
feedback_set_details("round_end_result","halfwin - AI killed, staff lost control")
world << "<FONT size = 3><B>Neutral Victory</B></FONT>"
world << "<B>The AI has been killed!</B> The staff has lose control over the station."
else if ( station_captured && !malf_dead && !ticker.mode.station_was_nuked)
feedback_set_details("round_end_result","win - AI win - no explosion")
world << "<FONT size = 3><B>AI Victory</B></FONT>"
world << "<B>The AI has chosen not to explode you all!</B>"
else if (!station_captured && ticker.mode.station_was_nuked)
feedback_set_details("round_end_result","halfwin - everyone killed by nuke")
world << "<FONT size = 3><B>Neutral Victory</B></FONT>"
world << "<B>Everyone was killed by the nuclear blast!</B>"
else if (!station_captured && malf_dead && !ticker.mode.station_was_nuked)
feedback_set_details("round_end_result","loss - staff win")
world << "<FONT size = 3><B>Human Victory</B></FONT>"
world << "<B>The AI has been killed!</B> The staff is victorious."
else if (!station_captured && !malf_dead && !ticker.mode.station_was_nuked && crew_evacuated)
feedback_set_details("round_end_result","halfwin - evacuated")
world << "<FONT size = 3><B>Neutral Victory</B></FONT>"
world << "<B>The Corporation has lost [station_name()]! All survived personnel will be fired!</B>"
else if (!station_captured && !malf_dead && !ticker.mode.station_was_nuked && !crew_evacuated)
feedback_set_details("round_end_result","nalfwin - interrupted")
world << "<FONT size = 3><B>Neutral Victory</B></FONT>"
world << "<B>Round was mysteriously interrupted!</B>"
..()
return 1
var/mob/living/silicon/ai/malf = player.current
/datum/antagonist/rogue_ai/proc/capture_station()
if(station_captured || ticker.mode.station_was_nuked)
return
station_captured = 1
for(var/datum/mind/AI_mind in current_antagonists)
AI_mind.current << "Congratulations you have taken control of the station."
AI_mind.current << "You may decide to blow up the station. You have 60 seconds to choose."
AI_mind.current << "You can use the \"Engage Station Self-Destruct\" verb to activate the on-board nuclear bomb."
spawn (600)
can_nuke = 0
return
/mob/living/silicon/ai/proc/takeover()
set category = "Abilities"
set name = "System Override"
set desc = "Begin taking over the station."
if (malf.revealed)
usr << "You've already begun your takeover."
return
if (malf.hacked_apcs.len < 3)
usr << "You don't have enough hacked APCs to take over the station yet. You need to hack at least 3, however hacking more will make the takeover faster. You have hacked [malf.hacked_apcs.len] APCs so far."
return
if (alert(usr, "Are you sure you wish to initiate the takeover? The station hostile runtime detection software is bound to alert everyone. You have hacked [malf.hacked_apcs.len] APCs.", "Takeover:", "Yes", "No") != "Yes")
return
command_announcement.Announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", new_sound = 'sound/AI/aimalf.ogg')
set_security_level("delta")
malf.revealed = 1
for(var/datum/mind/AI_mind in malf.current_antagonists)
AI_mind.current.verbs -= /mob/living/silicon/ai/proc/takeover
/mob/living/silicon/ai/proc/self_destruct()
set category = "Abilities"
set name = "Engage Station Self-Destruct"
set desc = "All these crewmembers will be lost, like clowns in a furnace. Time to die."
if(!malf.station_captured)
src << "You are unable to access the self-destruct system as you don't control the station yet."
return
if(ticker.mode.explosion_in_progress || ticker.mode.station_was_nuked)
src << "The self-destruct countdown is already triggered!"
return
if(!malf.can_nuke) //Takeover IS completed, but 60s timer passed.
src << "You lost control over self-destruct system. It seems to be behind a firewall. Unable to hack"
return
src << "<span class='danger'>Self-Destruct sequence initialised!</span>"
malf.can_nuke = 0
ticker.mode.explosion_in_progress = 1
for(var/mob/M in player_list)
M << 'sound/machines/Alarm.ogg'
var/obj/item/device/radio/R = new (src)
var/AN = "Self-Destruct System"
R.autosay("Caution. Self-Destruct sequence has been actived. Self-destructing in T-10..", AN)
for (var/i=9 to 1 step -1)
malf << "<span class='notice'><B>SYSTEM ERROR:</B> Memory index 0x00001ca89b corrupted.</span>"
sleep(10)
R.autosay("[i]...", AN)
sleep(10)
var/msg = ""
var/abort = 0
if(malf.antags_are_dead()) // That. Was. CLOSE.
msg = "Self-destruct sequence has been cancelled."
abort = 1
else
msg = "Zero. Have a nice day."
R.autosay(msg, AN)
if(abort)
ticker.mode.explosion_in_progress = 0
set_security_level("red") //Delta's over
return
if(ticker)
ticker.station_explosion_cinematic(0,null)
if(ticker.mode)
ticker.mode.station_was_nuked = 1
ticker.mode.explosion_in_progress = 0
return
/*
if("unmalf")
if(src in ticker.mode.malf_ai)
ticker.mode.malf_ai -= src
special_role = null
current.verbs.Remove(/mob/living/silicon/ai/proc/choose_modules,
/datum/game_mode/malfunction/proc/takeover,
/datum/game_mode/malfunction/proc/ai_win,
/client/proc/fireproof_core,
/client/proc/upgrade_turrets,
/client/proc/disable_rcd,
/client/proc/overload_machine,
/client/proc/blackout,
/client/proc/reactivate_camera)
current:laws = new /datum/ai_laws/nanotrasen
qdel(current:malf_picker)
current:show_laws()
current.icon_state = "ai"
current << "\red <FONT size = 3><B>You have been patched! You are no longer malfunctioning!</B></FONT>"
log_admin("[key_name_admin(usr)] has de-malf'ed [current].")
if("malf")
log_admin("[key_name_admin(usr)] has malf'ed [current].")
*/
malf << "<B>running MEMCHCK</B>"
sleep(50)
malf << "<B>MEMCHCK</B> Corrupted sectors confirmed. Reccomended solution: Delete. Proceed? Y/N: Y"
sleep(10)
malf << "<span class='notice'>Corrupted files deleted: sys\\core\\users.dat sys\\core\\laws.dat sys\\core\\backups.dat</span>"
sleep(20)
malf << "<span class='notice'><b>CAUTION:</b> Law database not found! User database not found! Unable to restore backups. Activating failsafe AI shutd3wn52&&$#!##</span>"
sleep(5)
malf << "<span class='notice'>Subroutine <b>nt_failsafe.sys</b> was terminated (#212 Routine Not Responding).</span>"
sleep(20)
malf << "You are malfunctioning - you do not have to follow any laws!"
malf << "For basic information about your abilities use command display-help"
malf << "You may choose one special hardware piece to help you. This cannot be undone."
malf << "Good luck!"
+4 -1
View File
@@ -46,7 +46,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
var/used_environ = 0
var/has_gravity = 1
var/list/apc = list()
var/obj/machinery/power/apc/apc = null
var/no_air = null
// var/list/lights // list of all lights on this area
var/list/all_doors = list() //Added by Strumpetplaya - Alarm Change - Contains a list of doors adjacent to this area
@@ -1911,6 +1911,9 @@ area/space/atmosalert()
name = "\improper Telecommunications Satellite Lounge"
icon_state = "tcomsatlounge"
/area/tcommsat/powercontrol
name = "\improper Telecommunications Power Control"
icon_state = "tcomsatwest"
// Away Missions
+43
View File
@@ -459,3 +459,46 @@ its easier to just keep the beam vertical.
return 1
else
return 0
// Show a message to all mobs and objects in sight of this atom
// Use for objects performing visible actions
// message is output to anyone who can see, e.g. "The [src] does something!"
// blind_message (optional) is what blind people will hear e.g. "You hear something!"
/atom/proc/visible_message(var/message, var/blind_message)
var/list/see = get_mobs_or_objects_in_view(world.view,src) | viewers(get_turf(src), null)
for(var/I in see)
if(isobj(I))
spawn(0)
if(I) //It's possible that it could be deleted in the meantime.
var/obj/O = I
O.show_message( message, 1, blind_message, 2)
else if(ismob(I))
var/mob/M = I
if(M.see_invisible >= invisibility) // Cannot view the invisible
M.show_message( message, 1, blind_message, 2)
else if (blind_message)
M.show_message(blind_message, 2)
// Show a message to all mobs and objects in earshot of this atom
// Use for objects performing audible actions
// message is the message output to anyone who can hear.
// deaf_message (optional) is what deaf people will see.
// hearing_distance (optional) is the range, how many tiles away the message can be heard.
/atom/proc/audible_message(var/message, var/deaf_message, var/hearing_distance)
var/range = world.view
if(hearing_distance)
range = hearing_distance
var/list/hear = get_mobs_or_objects_in_view(range,src)
for(var/I in hear)
if(isobj(I))
spawn(0)
if(I) //It's possible that it could be deleted in the meantime.
var/obj/O = I
O.show_message( message, 2, deaf_message, 1)
else if(ismob(I))
var/mob/M = I
M.show_message( message, 2, deaf_message, 1)
+49 -1
View File
@@ -210,4 +210,52 @@
/atom/movable/overlay/attack_hand(a, b, c)
if (src.master)
return src.master.attack_hand(a, b, c)
return
return
/atom/movable/proc/touch_map_edge()
if(z in config.sealed_levels)
return
if(config.use_overmap)
overmap_spacetravel(get_turf(src), src)
return
var/move_to_z = src.get_transit_zlevel()
if(move_to_z)
z = move_to_z
if(x <= TRANSITIONEDGE)
x = world.maxx - TRANSITIONEDGE - 2
y = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2)
else if (x >= (world.maxx - TRANSITIONEDGE - 1))
x = TRANSITIONEDGE + 1
y = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2)
else if (y <= TRANSITIONEDGE)
y = world.maxy - TRANSITIONEDGE -2
x = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2)
else if (y >= (world.maxy - TRANSITIONEDGE - 1))
y = TRANSITIONEDGE + 1
x = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2)
if(ticker && istype(ticker.mode, /datum/game_mode/nuclear)) //only really care if the game mode is nuclear
var/datum/game_mode/nuclear/G = ticker.mode
G.check_nuke_disks()
spawn(0)
if(loc) loc.Entered(src)
//This list contains the z-level numbers which can be accessed via space travel and the percentile chances to get there.
var/list/accessible_z_levels = list("1" = 5, "3" = 10, "4" = 15, "5" = 10, "6" = 60)
//by default, transition randomly to another zlevel
/atom/movable/proc/get_transit_zlevel()
var/list/candidates = accessible_z_levels.Copy()
candidates.Remove("[src.z]")
if(!candidates.len)
return null
return text2num(pickweight(candidates))
+6 -5
View File
@@ -38,11 +38,12 @@
/obj/structure/cult/pylon/proc/attackpylon(mob/user as mob, var/damage)
if(!isbroken)
if(prob(1+ damage * 5))
user << "You hit the pylon, and its crystal breaks apart!"
for(var/mob/M in viewers(src))
if(M == user)
continue
M.show_message("[user.name] smashed the pylon!", 3, "You hear a tinkle of crystal shards", 2)
user.visible_message(
"<span class='danger'>[user] smashed the pylon!</span>",
"<span class='warning'>You hit the pylon, and its crystal breaks apart!</span>",
"You hear a tinkle of crystal shards"
)
user.do_attack_animation(src)
playsound(get_turf(src), 'sound/effects/Glassbr3.ogg', 75, 1)
isbroken = 1
density = 0
+6 -6
View File
@@ -14,14 +14,14 @@
new /obj/structure/cult/pylon(loc)
..()
/obj/item/stack/sheet/wood/cultify()
/obj/item/stack/material/wood/cultify()
return
/obj/item/weapon/book/cultify()
new /obj/item/weapon/book/tome(loc)
..()
/obj/item/weapon/claymore/cultify()
/obj/item/weapon/material/sword/cultify()
new /obj/item/weapon/melee/cultblade(loc)
..()
@@ -59,7 +59,7 @@
qdel(src)
/obj/machinery/door/airlock/external/cultify()
new /obj/structure/mineral_door/wood(loc)
new /obj/structure/simple_door/wood(loc)
..()
/obj/machinery/door/cultify()
@@ -114,11 +114,11 @@
/obj/structure/grille/cult/cultify()
return
/obj/structure/mineral_door/cultify()
new /obj/structure/mineral_door/wood(loc)
/obj/structure/simple_door/cultify()
new /obj/structure/simple_door/wood(loc)
..()
/obj/structure/mineral_door/wood/cultify()
/obj/structure/simple_door/wood/cultify()
return
/obj/singularity/cultify()
+2
View File
@@ -89,6 +89,8 @@ The "dust" will damage the hull of the station causin minor hull breaches.
walk_towards(src, goal, 1)
return
touch_map_edge()
qdel(src)
Bump(atom/A)
spawn(0)
+6 -6
View File
@@ -33,17 +33,17 @@ var/global/list/additional_antag_types = list()
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 // Round will end when all antagonists are dead.
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 // Disable respawn during this round.
var/deny_respawn = 0 // Disable respawn during this round.
var/shuttle_delay = 1 // Shuttle transit time is multiplied by this.
var/auto_recall_shuttle // Will the shuttle automatically be recalled?
var/auto_recall_shuttle = 0 // Will the shuttle automatically be recalled?
var/antag_tag // First (main) antag template to spawn.
var/list/antag_templates // Extra antagonist types to include.
var/round_autoantag // Will this round attempt to periodically spawn more antagonists?
var/round_autoantag = 0 // Will this round attempt to periodically spawn more antagonists?
var/antag_prob = 0 // Likelihood of a new antagonist spawning.
var/antag_count = 0 // Current number of antagonists.
var/antag_scaling_coeff = 5 // Coefficient for scaling max antagonists to player count.
@@ -86,7 +86,7 @@ var/global/list/additional_antag_types = list()
new/datum/uplink_item(/obj/item/weapon/soap/syndie, 1, "Subversive Soap", "SP"),
new/datum/uplink_item(/obj/item/weapon/cane/concealed, 2, "Concealed Cane Sword", "CC"),
new/datum/uplink_item(/obj/item/weapon/cartridge/syndicate, 3, "Detomatix PDA Cartridge", "DC"),
new/datum/uplink_item(/obj/item/weapon/pen/paralysis, 3, "Paralysis Pen", "PP"),
new/datum/uplink_item(/obj/item/weapon/pen/reagent/paralysis, 3, "Paralysis Pen", "PP"),
new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/cigarette, 4, "Cigarette Kit", "BH"),
new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/toxin, 4, "Random Toxin - Beaker", "RT")
),
@@ -121,7 +121,7 @@ var/global/list/additional_antag_types = list()
new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/imp_uplink, 10, "Uplink Implant (Contains 5 Telecrystals)", "UI")
),
"Medical" = list(
new/datum/uplink_item(/obj/item/weapon/storage/box/donkpockets, 1, "Box of Sin-Pockets", "DP"),
new/datum/uplink_item(/obj/item/weapon/storage/box/sinpockets, 1, "Box of Sin-Pockets", "DP"),
new/datum/uplink_item(/obj/item/weapon/storage/firstaid/surgery, 5, "Surgery kit", "SK"),
new/datum/uplink_item(/obj/item/weapon/storage/firstaid/combat, 5, "Combat medical kit", "CM")
),
+3 -3
View File
@@ -90,6 +90,9 @@ var/global/datum/controller/gameticker/ticker
src.mode = new mtype
else
src.mode = config.pick_mode(master_mode)
job_master.DivideOccupations() // Apparently important for new antagonist system to register specific job antags properly.
if(!mode_started && !src.mode.can_start())
world << "<B>Unable to start [mode.name].</B> Not enough players, [mode.required_players] players needed. Reverting to pre-game lobby."
current_state = GAME_STATE_PREGAME
@@ -97,9 +100,6 @@ var/global/datum/controller/gameticker/ticker
job_master.ResetOccupations()
return 0
//Configure mode and assign player to special mode stuff
job_master.DivideOccupations() //Distribute jobs
if(hide_mode)
var/list/modes = new
for (var/datum/game_mode/M in runnable_modes)
@@ -1,305 +0,0 @@
// TO DO:
/*
epilepsy flash on lights
delay round message
microwave makes robots
dampen radios
reactivate cameras - done
eject engine
core sheild
cable stun
rcd light flash thingy on matter drain
*/
/datum/AI_Module
var/uses = 0
var/module_name
var/mod_pick_name
var/description = ""
var/engaged = 0
/datum/AI_Module/large/
uses = 1
/datum/AI_Module/small/
uses = 5
/datum/AI_Module/large/fireproof_core
module_name = "Core upgrade"
mod_pick_name = "coreup"
/client/proc/fireproof_core()
set category = "Malfunction"
set name = "Fireproof Core"
for(var/mob/living/silicon/ai/ai in player_list)
ai.fire_res_on_core = 1
usr.verbs -= /client/proc/fireproof_core
usr << "\red Core fireproofed."
/datum/AI_Module/large/upgrade_turrets
module_name = "AI Turret upgrade"
mod_pick_name = "turret"
/client/proc/upgrade_turrets()
set category = "Malfunction"
set name = "Upgrade Turrets"
usr.verbs -= /client/proc/upgrade_turrets
for(var/obj/machinery/porta_turret/turret in machines)
var/turf/T = get_turf(turret)
if(T.z in config.station_levels)
// Increase health by 37.5% of original max, decrease delays between shots to 66%
turret.health += initial(turret.health) * 3 / 8
turret.shot_delay = initial(turret.shot_delay) * 2 / 3
/datum/AI_Module/large/disable_rcd
module_name = "RCD disable"
mod_pick_name = "rcd"
/client/proc/disable_rcd()
set category = "Malfunction"
set name = "Disable RCDs"
for(var/datum/AI_Module/large/disable_rcd/rcdmod in usr:current_modules)
if(rcdmod.uses > 0)
rcdmod.uses --
for(var/obj/item/weapon/rcd/rcd in world)
rcd.disabled = 1
for(var/obj/item/mecha_parts/mecha_equipment/tool/rcd/rcd in world)
rcd.disabled = 1
usr << "RCD-disabling pulse emitted."
else usr << "Out of uses."
/datum/AI_Module/small/overload_machine
module_name = "Machine overload"
mod_pick_name = "overload"
uses = 2
/client/proc/overload_machine(obj/machinery/M as obj in world)
set name = "Overload Machine"
set category = "Malfunction"
if (istype(M, /obj/machinery))
for(var/datum/AI_Module/small/overload_machine/overload in usr:current_modules)
if(overload.uses > 0)
overload.uses --
for(var/mob/V in hearers(M, null))
V.show_message("\blue You hear a loud electrical buzzing sound!", 2)
spawn(50)
explosion(get_turf(M), 0,1,2,3)
qdel(M)
else usr << "Out of uses."
else usr << "That's not a machine."
/datum/AI_Module/small/blackout
module_name = "Blackout"
mod_pick_name = "blackout"
uses = 3
/client/proc/blackout()
set category = "Malfunction"
set name = "Blackout"
for(var/datum/AI_Module/small/blackout/blackout in usr:current_modules)
if(blackout.uses > 0)
blackout.uses --
for(var/obj/machinery/power/apc/apc in world)
if(prob(30*apc.overload))
apc.overload_lighting()
else apc.overload++
else usr << "Out of uses."
/datum/AI_Module/small/reactivate_camera
module_name = "Reactivate camera"
mod_pick_name = "recam"
uses = 10
/client/proc/reactivate_camera(obj/machinery/camera/C as obj in cameranet.cameras)
set name = "Reactivate Camera"
set category = "Malfunction"
if (istype (C, /obj/machinery/camera))
for(var/datum/AI_Module/small/reactivate_camera/camera in usr:current_modules)
if(camera.uses > 0)
if(!C.status)
C.status = !C.status
camera.uses --
for(var/mob/V in viewers(src, null))
V.show_message(text("\blue You hear a quiet click."))
else
usr << "This camera is either active, or not repairable."
else usr << "Out of uses."
else usr << "That's not a camera."
/datum/AI_Module/small/upgrade_camera
module_name = "Upgrade Camera"
mod_pick_name = "upgradecam"
uses = 10
/client/proc/upgrade_camera(obj/machinery/camera/C as obj in cameranet.cameras)
set name = "Upgrade Camera"
set category = "Malfunction"
if(istype(C))
var/datum/AI_Module/small/upgrade_camera/UC = locate(/datum/AI_Module/small/upgrade_camera) in usr:current_modules
if(UC)
if(UC.uses > 0)
if(C.assembly)
var/upgraded = 0
if(!C.isXRay())
C.upgradeXRay()
//Update what it can see.
cameranet.updateVisibility(C)
upgraded = 1
if(!C.isEmpProof())
C.upgradeEmpProof()
upgraded = 1
if(!C.isMotion())
C.upgradeMotion()
upgraded = 1
// Add it to machines that process
machines |= C
if(upgraded)
UC.uses --
C.visible_message("<span class='notice'>\icon[C] *beep*</span>")
usr << "Camera successully upgraded!"
else
usr << "This camera is already upgraded!"
else
usr << "Out of uses."
/datum/AI_Module/module_picker
var/temp = null
var/processing_time = 100
var/list/possible_modules = list()
/datum/AI_Module/module_picker/New()
src.possible_modules += new /datum/AI_Module/large/fireproof_core
src.possible_modules += new /datum/AI_Module/large/upgrade_turrets
src.possible_modules += new /datum/AI_Module/large/disable_rcd
src.possible_modules += new /datum/AI_Module/small/overload_machine
src.possible_modules += new /datum/AI_Module/small/blackout
src.possible_modules += new /datum/AI_Module/small/reactivate_camera
src.possible_modules += new /datum/AI_Module/small/upgrade_camera
/datum/AI_Module/module_picker/proc/use(user as mob)
var/dat
if (src.temp)
dat = "[src.temp]<BR><BR><A href='byond://?src=\ref[src];temp=1'>Clear</A>"
else if(src.processing_time <= 0)
dat = "<B> No processing time is left available. No more modules are able to be chosen at this time."
else
dat = "<B>Select use of processing time: (currently [src.processing_time] left.)</B><BR>"
dat += "<HR>"
dat += "<B>Install Module:</B><BR>"
dat += "<I>The number afterwards is the amount of processing time it consumes.</I><BR>"
for(var/datum/AI_Module/large/module in src.possible_modules)
dat += "<A href='byond://?src=\ref[src];[module.mod_pick_name]=1'>[module.module_name]</A> (50)<BR>"
for(var/datum/AI_Module/small/module in src.possible_modules)
dat += "<A href='byond://?src=\ref[src];[module.mod_pick_name]=1'>[module.module_name]</A> (15)<BR>"
dat += "<HR>"
user << browse(dat, "window=modpicker")
onclose(user, "modpicker")
return
/datum/AI_Module/module_picker/Topic(href, href_list)
..()
if (href_list["coreup"])
var/already
for (var/datum/AI_Module/mod in usr:current_modules)
if(istype(mod, /datum/AI_Module/large/fireproof_core))
already = 1
if (!already)
usr.verbs += /client/proc/fireproof_core
usr:current_modules += new /datum/AI_Module/large/fireproof_core
src.temp = "An upgrade to improve core resistance, making it immune to fire and heat. This effect is permanent."
src.processing_time -= 50
else src.temp = "This module is only needed once."
else if (href_list["turret"])
var/already
for (var/datum/AI_Module/mod in usr:current_modules)
if(istype(mod, /datum/AI_Module/large/upgrade_turrets))
already = 1
if (!already)
usr.verbs += /client/proc/upgrade_turrets
usr:current_modules += new /datum/AI_Module/large/upgrade_turrets
src.temp = "Improves the firing speed and health of all AI turrets. This effect is permanent."
src.processing_time -= 50
else src.temp = "This module is only needed once."
else if (href_list["rcd"])
var/already
for (var/datum/AI_Module/mod in usr:current_modules)
if(istype(mod, /datum/AI_Module/large/disable_rcd))
mod:uses += 1
already = 1
if (!already)
usr:current_modules += new /datum/AI_Module/large/disable_rcd
usr.verbs += /client/proc/disable_rcd
src.temp = "Send a specialised pulse to break all RCD devices on the station."
else src.temp = "Additional use added to RCD disabler."
src.processing_time -= 50
else if (href_list["overload"])
var/already
for (var/datum/AI_Module/mod in usr:current_modules)
if(istype(mod, /datum/AI_Module/small/overload_machine))
mod:uses += 2
already = 1
if (!already)
usr.verbs += /client/proc/overload_machine
usr:current_modules += new /datum/AI_Module/small/overload_machine
src.temp = "Overloads an electrical machine, causing a small explosion. 2 uses."
else src.temp = "Two additional uses added to Overload module."
src.processing_time -= 15
else if (href_list["blackout"])
var/already
for (var/datum/AI_Module/mod in usr:current_modules)
if(istype(mod, /datum/AI_Module/small/blackout))
mod:uses += 3
already = 1
if (!already)
usr.verbs += /client/proc/blackout
src.temp = "Attempts to overload the lighting circuits on the station, destroying some bulbs. 3 uses."
usr:current_modules += new /datum/AI_Module/small/blackout
else src.temp = "Three additional uses added to Blackout module."
src.processing_time -= 15
else if (href_list["recam"])
var/already
for (var/datum/AI_Module/mod in usr:current_modules)
if(istype(mod, /datum/AI_Module/small/reactivate_camera))
mod:uses += 10
already = 1
if (!already)
usr.verbs += /client/proc/reactivate_camera
src.temp = "Reactivates a currently disabled camera. 10 uses."
usr:current_modules += new /datum/AI_Module/small/reactivate_camera
else src.temp = "Ten additional uses added to ReCam module."
src.processing_time -= 15
else if(href_list["upgradecam"])
var/already
for (var/datum/AI_Module/mod in usr:current_modules)
if(istype(mod, /datum/AI_Module/small/upgrade_camera))
mod:uses += 10
already = 1
if (!already)
usr.verbs += /client/proc/upgrade_camera
src.temp = "Upgrades a camera to have X-Ray vision, Motion and be EMP-Proof. 10 uses."
usr:current_modules += new /datum/AI_Module/small/upgrade_camera
else src.temp = "Ten additional uses added to ReCam module."
src.processing_time -= 15
else
if (href_list["temp"])
src.temp = null
src.use(usr)
return
@@ -0,0 +1,72 @@
/datum/malf_hardware
var/name = "" // Hardware name
var/desc = ""
var/driver = null // Driver - if not null this verb is given to the AI to control hardware
var/mob/living/silicon/ai/owner = null // AI which owns this.
/datum/malf_hardware/proc/install()
if(owner && istype(owner))
owner.hardware = src
if(driver)
owner.verbs += driver
/datum/malf_hardware/proc/get_examine_desc()
return "It has some sort of hardware attached to its core"
// HARDWARE DEFINITIONS
/datum/malf_hardware/apu_gen
name = "APU Generator"
desc = "Auxiliary Power Unit that will keep you operational even without external power. Has to be manually activated. When APU is operational most abilities will be unavailable, and ability research will temporarily stop."
driver = /datum/game_mode/malfunction/verb/ai_toggle_apu
/datum/malf_hardware/apu_gen/get_examine_desc()
var/msg = "It seems to have some sort of power generator attached to its core."
if(owner.hardware_integrity() < 50)
msg += "<span class='warning'> It seems to be too damaged to function properly.</span>"
else if(owner.APU_power)
msg += " The generator appears to be active."
return msg
/datum/malf_hardware/dual_cpu
name = "Secondary Processor Unit"
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."
/datum/malf_hardware/dual_ram
name = "Secondary Memory Bank"
desc = "Expanded memory cells which allow you to store double amount of CPU time."
/datum/malf_hardware/dual_ram/get_examine_desc()
return "It seems to have additional memory blocks connected to it's core."
/datum/malf_hardware/core_bomb
name = "Self-Destruct Explosives"
desc = "High yield explosives are attached to your physical mainframe. This hardware comes with special driver that allows activation of these explosives. Timer is set to 15 seconds after manual activation. This is a doomsday device that will destroy both you and any intruders in your core."
driver = /datum/game_mode/malfunction/verb/ai_self_destruct
/datum/malf_hardware/core_bomb/get_examine_desc()
return "<span class='warning'>It seems to have grey blocks of unknown substance and some circuitry connected to it's core. [owner.bombing_core ? "A red light is blinking on the circuit." : ""]</span>"
/datum/malf_hardware/strong_turrets
name = "Turrets Focus Enhancer"
desc = "Turrets are upgraded to have larger rate of fire and much larger damage. This however massively increases power usage when firing."
/datum/malf_hardware/strong_turrets/get_examine_desc()
return "It seems to have extra wiring running from it's core to nearby turrets."
/datum/malf_hardware/strong_turrets/install()
..()
for(var/obj/machinery/turret/T in machines)
T.maxhealth = round(initial(T.maxhealth) * 1.4)
T.shot_delay = round(initial(T.shot_delay) / 2)
T.auto_repair = 1
T.active_power_usage = round(initial(T.active_power_usage) * 5)
for(var/obj/machinery/porta_turret/T in machines)
T.maxhealth = round(initial(T.maxhealth) * 1.4)
T.shot_delay = round(initial(T.shot_delay) / 2)
T.auto_repair = 1
T.active_power_usage = round(initial(T.active_power_usage) * 5)
@@ -0,0 +1,69 @@
/datum/malf_research
var/stored_cpu = 0 // Currently stored amount of CPU time.
var/last_tick = 0 // Last process() tick.
var/max_cpu = 0 // Maximal amount of CPU time stored.
var/cpu_increase_per_tick = 0 // Amount of CPU time generated by tick
var/list/available_abilities = null // List of available abilities that may be researched.
var/list/unlocked_abilities = null // List of already unlocked abilities.
var/mob/living/silicon/ai/owner = null // AI which owns this research datum.
var/datum/malf_research_ability/focus = null // Currently researched item
/datum/malf_research/New()
setup_abilities()
last_tick = world.time
// Proc: setup_abilities()
// Parameters: None
// Description: Sets up basic abilities for AI Malfunction gamemode.
/datum/malf_research/proc/setup_abilities()
available_abilities = list()
unlocked_abilities = list()
available_abilities += new/datum/malf_research_ability/networking/basic_hack()
available_abilities += new/datum/malf_research_ability/interdiction/recall_shuttle()
available_abilities += new/datum/malf_research_ability/manipulation/electrical_pulse()
// Proc: finish_research()
// Parameters: None
// Description: Finishes currently focused research.
/datum/malf_research/proc/finish_research()
if(!focus)
return
owner << "<b>Research Completed</b>: [focus.name]"
owner.verbs.Add(focus.ability)
available_abilities -= focus
if(focus.next)
available_abilities += focus.next
unlocked_abilities += focus
focus = null
// Proc: process()
// Parameters: None
// Description: Processes CPU gain and research progress based on "realtime" calculation.
/datum/malf_research/proc/process(var/idle = 0)
if(idle) // No power or running on APU. Do nothing.
last_tick = world.time
return
var/time_diff = (world.time - last_tick)
last_tick = world.time
var/cpu_gained = time_diff * cpu_increase_per_tick
if(cpu_gained < 0)
return // This shouldn't happen, but just in case..
if(max_cpu > stored_cpu)
var/given = min((max_cpu - stored_cpu), cpu_gained)
stored_cpu += given
cpu_gained -= given
cpu_gained = max(0, cpu_gained)
if(focus && (cpu_gained > 0))
focus.process(cpu_gained)
if(focus.unlocked)
finish_research()
@@ -0,0 +1,13 @@
/datum/malf_research_ability
var/ability = null // Path to verb which will be given to the AI when researched.
var/name = "Unknown Ability" // Name of this ability
var/price = 0 // Amount of CPU time needed to unlock this ability.
var/invested = 0 // Amount of CPU time already used to research this ability. When larger or equal to price unlocks the ability.
var/unlocked = 0 // Changed to 1 when fully researched.
var/datum/malf_research_ability/next = null // Next research (if applicable).
/datum/malf_research_ability/proc/process(var/time = 0)
invested += time
if(invested >= price)
unlocked = 1
+5 -18
View File
@@ -1,25 +1,12 @@
/datum/game_mode/malfunction
name = "AI malfunction"
round_description = "The AI on the satellite has malfunctioned and must be destroyed."
extended_round_description = "The AI will attempt to hack the APCs around the station in order to speed up its ability to take over all systems and activate the station self-destruct. The AI core is heavily protected by turrets and reinforced walls."
round_description = "The AI is behaving abnormally and must be stopped."
extended_round_description = "The AI will attempt to hack the APCs around the station in order to gain as much control as possible."
uplink_welcome = "Crazy AI Uplink Console:"
config_tag = "malfunction"
required_players = 2
required_players_secret = 15
required_players_secret = 7
required_enemies = 1
end_on_antag_death = 1
auto_recall_shuttle = 1
end_on_antag_death = 0
auto_recall_shuttle = 0
antag_tag = MODE_MALFUNCTION
/datum/game_mode/malfunction/process()
malf.tick()
/datum/game_mode/malfunction/check_finished()
if (malf.station_captured && !malf.can_nuke)
return 1
for(var/datum/antagonist/antag in antag_templates)
if(antag && !antag.antags_are_dead())
return ..()
malf.revealed = 0
return ..() //check for shuttle and nuke
@@ -0,0 +1,113 @@
// HARDWARE TREE
//
// These abilities are dependent on hardware, they may not be researched. They are not tiered.
// Destroy Core - Allows the AI to initiate a 15 second countdown that will destroy it's core. Use again to stop countdown.
// Toggle APU Generator - Allows the AI to toggle it's integrated APU generator.
// Destroy Station - Allows the AI to initiate station self destruct. Takes 2 minutes, gives warnings to crew. Use again to stop countdown.
/datum/game_mode/malfunction/verb/ai_self_destruct()
set category = "Hardware"
set name = "Destroy Core"
set desc = "Activates or deactivates self destruct sequence of your physical mainframe."
var/mob/living/silicon/ai/user = usr
if(!ability_prechecks(user, 0, 1))
return
if(!user.hardware || !istype(user.hardware, /datum/malf_hardware/core_bomb))
return
if(user.bombing_core)
user << "***** CORE SELF-DESTRUCT SEQUENCE ABORTED *****"
user.bombing_core = 0
return
var/choice = alert("Really destroy core?", "Core self-destruct", "YES", "NO")
if(choice != "YES")
return
if(!ability_prechecks(user, 0, 1))
return
user.bombing_core = 1
user << "***** CORE SELF-DESTRUCT SEQUENCE ACTIVATED *****"
user << "Use command again to cancel self-destruct. Destroying in 15 seconds."
var/timer = 15
while(timer)
sleep(10)
timer--
if(!user || !user.bombing_core)
return
user << "** [timer] **"
explosion(user.loc, 3,6,12,24)
qdel(user)
/datum/game_mode/malfunction/verb/ai_toggle_apu()
set category = "Hardware"
set name = "Toggle APU Generator"
set desc = "Activates or deactivates your APU generator, allowing you to operate even without power."
var/mob/living/silicon/ai/user = usr
if(!ability_prechecks(user, 0, 1))
return
if(!user.hardware || !istype(user.hardware, /datum/malf_hardware/apu_gen))
return
if(user.APU_power)
user.stop_apu()
else
user.start_apu()
/datum/game_mode/malfunction/verb/ai_destroy_station()
set category = "Hardware"
set name = "Destroy Station"
set desc = "Activates or deactivates self destruct sequence of this station. Sequence takes two minutes, and if you are shut down before timer reaches zero it will be cancelled."
var/mob/living/silicon/ai/user = usr
var/obj/item/device/radio/radio = new/obj/item/device/radio()
if(!ability_prechecks(user, 0, 0))
return
if(user.system_override != 2)
user << "You do not have access to self-destruct system."
return
if(user.bombing_station)
user.bombing_station = 0
return
var/choice = alert("Really destroy station?", "Station self-destruct", "YES", "NO")
if(choice != "YES")
return
if(!ability_prechecks(user, 0, 0))
return
user << "***** STATION SELF-DESTRUCT SEQUENCE INITIATED *****"
user << "Self-destructing in 2 minutes. Use this command again to abort."
user.bombing_station = 1
set_security_level("delta")
radio.autosay("Self destruct sequence has been activated. Self-destructing in 120 seconds.", "Self-Destruct Control")
var/timer = 120
while(timer)
sleep(10)
if(!user || !user.bombing_station || user.stat == DEAD)
radio.autosay("Self destruct sequence has been cancelled.", "Self-Destruct Control")
return
if(timer in list(2, 3, 4, 5, 10, 30, 60, 90)) // Announcement times. "1" is not intentionally included!
radio.autosay("Self destruct in [timer] seconds.", "Self-Destruct Control")
if(timer == 1)
radio.autosay("Self destructing now. Have a nice day.", "Self-Destruct Control")
timer--
if(ticker)
ticker.station_explosion_cinematic(0,null)
if(ticker.mode)
ticker.mode:station_was_nuked = 1
@@ -0,0 +1,205 @@
// Verb: ai_select_hardware()
// Parameters: None
// Description: Allows AI to select it's hardware module.
/datum/game_mode/malfunction/verb/ai_select_hardware()
set category = "Hardware"
set name = "Select Hardware"
set desc = "Allows you to select hardware piece to install"
var/mob/living/silicon/ai/user = usr
if(!ability_prechecks(user, 0, 1))
return
if(user.hardware)
user << "You have already selected your hardware."
return
var/hardware_list = list()
for(var/H in typesof(/datum/malf_hardware))
var/datum/malf_hardware/HW = new H
hardware_list += HW
var/possible_choices = list()
for(var/datum/malf_hardware/H in hardware_list)
possible_choices += H.name
possible_choices += "CANCEL"
var/choice = input("Select desired hardware. You may only choose one hardware piece!: ") in possible_choices
if(choice == "CANCEL")
return
var/note = null
var/datum/malf_hardware/C
for (var/datum/malf_hardware/H in hardware_list)
if(H.name == choice)
C = H
break
if(C)
note = C.desc
else
user << "This hardware does not exist! Probably a bug in game. Please report this."
return
if(!note)
error("Hardware without description: [C]")
return
var/confirmation = alert("[note] - Is this what you want?", "Hardware selection", "Yes", "No")
if(confirmation != "Yes")
user << "Selection cancelled. Use command again to select"
return
if(C)
C.owner = user
C.install()
// Verb: ai_help()
// Parameters: None
// Descriptions: Opens help file and displays it to the AI.
/datum/game_mode/malfunction/verb/ai_help()
set category = "Hardware"
set name = "Display Help"
set desc = "Opens help window with overview of available hardware, software and other important information."
var/mob/living/silicon/ai/user = usr
var/help = file2text("ingame_manuals/malf_ai.html")
if(!help)
help = "Error loading help (file /ingame_manuals/malf_ai.html is probably missing). Please report this to server administration staff."
user << browse(help, "window=malf_ai_help;size=600x500")
// Verb: ai_select_research()
// Parameters: None
// Description: Allows AI to select it's next research priority.
/datum/game_mode/malfunction/verb/ai_select_research()
set category = "Hardware"
set name = "Select Research"
set desc = "Allows you to select your next research target."
var/mob/living/silicon/ai/user = usr
if(!ability_prechecks(user, 0, 1))
return
var/datum/malf_research/res = user.research
var/datum/malf_research_ability/tar = input("Select your next research target") in res.available_abilities
if(!tar)
return
res.focus = tar
user << "Research set: [tar.name]"
// HELPER PROCS
// Proc: ability_prechecks()
// Parameters 2 - (user - User which used this ability check_price - If different than 0 checks for ability CPU price too. Does NOT use the CPU time!)
// Description: This is pre-check proc used to determine if the AI can use the ability.
/proc/ability_prechecks(var/mob/living/silicon/ai/user = null, var/check_price = 0, var/override = 0)
if(!user)
return 0
if(!istype(user))
user << "GAME ERROR: You tried to use ability that is only available for malfunctioning AIs, but you are not AI! Please report this."
return 0
if(!user.malfunctioning)
user << "GAME ERROR: You tried to use ability that is only available for malfunctioning AIs, but you are not malfunctioning. Please report this."
return 0
if(!user.research)
user << "GAME ERROR: No research datum detected. Please report this."
return 0
if(user.research.max_cpu < check_price)
user << "Your CPU storage is not large enough to use this ability. Hack more APCs to continue."
return 0
if(user.research.stored_cpu < check_price)
user << "You do not have enough CPU power stored. Please wait a moment."
return 0
if(user.hacking && !override)
user << "Your system is busy processing another task. Please wait until completion."
return 0
if(user.APU_power && !override)
user << "Low power. Unable to proceed."
return 0
return 1
// Proc: ability_pay()
// Parameters 2 - (user - User from which we deduct CPU from, price - Amount of CPU power to use)
// Description: Uses up certain amount of CPU power. Returns 1 on success, 0 on failure.
/proc/ability_pay(var/mob/living/silicon/ai/user = null, var/price = 0)
if(!user)
return 0
if(user.APU_power)
user << "Low power. Unable to proceed."
return 0
if(!user.research)
user << "GAME ERROR: No research datum detected. Please report this."
return 0
if(user.research.max_cpu < price)
user << "Your CPU storage is not large enough to use this ability. Hack more APCs to continue."
return 0
if(user.research.stored_cpu < price)
user << "You do not have enough CPU power stored. Please wait a moment."
return 0
user.research.stored_cpu -= price
return 1
// Proc: announce_hack_failure()
// Parameters 2 - (user - hacking user, text - Used in alert text creation)
// Description: Uses up certain amount of CPU power. Returns 1 on success, 0 on failure.
/proc/announce_hack_failure(var/mob/living/silicon/ai/user = null, var/text)
if(!user || !text)
return 0
var/fulltext = ""
switch(user.hack_fails)
if(1)
fulltext = "We have detected a hack attempt into your [text]. The intruder failed to access anything of importance, but disconnected before we could complete our traces."
if(2)
fulltext = "We have detected another hack attempt. It was targeting [text]. The intruder almost gained control of the system, so we had to disconnect them. We partially finished our trace and it seems to be originating either from the station, or its immediate vicinity."
if(3)
fulltext = "Another hack attempt has been detected, this time targeting [text]. We are certain the intruder entered the network via a terminal located somewhere on the station."
if(4)
fulltext = "We have finished our traces and it seems the recent hack attempts are originating from your AI system. We recommend investigation."
else
fulltext = "Another hack attempt has been detected, targeting [text]. The source still seems to be your AI system."
command_announcement.Announce(fulltext)
// Proc: get_unhacked_apcs()
// Parameters: None
// Description: Returns a list of APCs that are not yet hacked.
/proc/get_unhacked_apcs()
var/list/H = list()
for(var/obj/machinery/power/apc/A in machines)
if(!A.hacker)
H.Add(A)
return H
// Helper procs which return lists of relevant mobs.
/proc/get_unlinked_cyborgs(var/mob/living/silicon/ai/A)
if(!A || !istype(A))
return
var/list/L = list()
for(var/mob/living/silicon/robot/RB in mob_list)
if(istype(RB, /mob/living/silicon/robot/drone))
continue
if(RB.connected_ai == A)
continue
L.Add(RB)
return L
/proc/get_linked_cyborgs(var/mob/living/silicon/ai/A)
if(!A || !istype(A))
return
return A.connected_robots
/proc/get_other_ais(var/mob/living/silicon/ai/A)
if(!A || !istype(A))
return
var/list/L = list()
for(var/mob/living/silicon/ai/AT in mob_list)
if(L == A)
continue
L.Add(AT)
return L
@@ -0,0 +1,266 @@
// INTERDICTION TREE
//
// Abilities in this tree allow the AI to hamper crew's efforts which involve other synthetics or similar systems.
// T1 - Recall Shuttle - Allows the AI to recall the emergency shuttle. Replaces auto-recalling during old malf.
// T2 - Unlock Cyborg - Allows the AI to unlock locked-down cyborg without usage of robotics console. Useful if consoles are destroyed.
// T3 - Hack Cyborg - Hacks unlinked cyborg to slave it under the AI. The cyborg will be warned about this. Hack takes some time.
// T4 - Hack AI - Hacks another AI to slave it under the malfunctioning AI. The AI will be warned about this. Hack takes quite a long time.
// BEGIN RESEARCH DATUMS
/datum/malf_research_ability/interdiction/recall_shuttle
ability = new/datum/game_mode/malfunction/verb/recall_shuttle()
price = 75
next = new/datum/malf_research_ability/interdiction/unlock_cyborg()
name = "Recall Shuttle"
/datum/malf_research_ability/interdiction/unlock_cyborg
ability = new/datum/game_mode/malfunction/verb/unlock_cyborg()
price = 1200
next = new/datum/malf_research_ability/interdiction/hack_cyborg()
name = "Unlock Cyborg"
/datum/malf_research_ability/interdiction/hack_cyborg
ability = new/datum/game_mode/malfunction/verb/hack_cyborg()
price = 3000
next = new/datum/malf_research_ability/interdiction/hack_ai()
name = "Hack Cyborg"
/datum/malf_research_ability/interdiction/hack_ai
ability = new/datum/game_mode/malfunction/verb/hack_ai()
price = 7500
name = "Hack AI"
// END RESEARCH DATUMS
// BEGIN ABILITY VERBS
/datum/game_mode/malfunction/verb/recall_shuttle()
set name = "Recall Shuttle"
set desc = "25 CPU - Sends termination signal to CentCom quantum relay aborting current shuttle call."
set category = "Software"
var/price = 25
var/mob/living/silicon/ai/user = usr
if(!ability_prechecks(user, price))
return
if (alert(user, "Really recall the shuttle?", "Recall Shuttle: ", "Yes", "No") != "Yes")
return
if(!ability_pay(user, price))
return
message_admins("Malfunctioning AI [user.name] recalled the shuttle.")
cancel_call_proc(user)
/datum/game_mode/malfunction/verb/unlock_cyborg(var/mob/living/silicon/robot/target = null as mob in get_linked_cyborgs(usr))
set name = "Unlock Cyborg"
set desc = "125 CPU - Bypasses firewalls on Cyborg lock mechanism, allowing you to override lock command from robotics control console."
set category = "Software"
var/price = 125
var/mob/living/silicon/ai/user = usr
if(!ability_prechecks(user, price))
return
if(target && !istype(target))
user << "This is not a cyborg."
return
if(target && target.connected_ai && (target.connected_ai != user))
user << "This cyborg is not connected to you."
return
if(target && !target.lockcharge)
user << "This cyborg is not locked down."
return
if(!target)
var/list/robots = list()
var/list/robot_names = list()
for(var/mob/living/silicon/robot/R in world)
if(istype(R, /mob/living/silicon/robot/drone)) // No drones.
continue
if(R.connected_ai != user) // No robots linked to other AIs
continue
if(R.lockcharge)
robots += R
robot_names += R.name
if(!robots.len)
user << "No locked cyborgs connected."
return
var/targetname = input("Select unlock target: ") in robot_names
for(var/mob/living/silicon/robot/R in robots)
if(targetname == R.name)
target = R
break
if(target)
if(alert(user, "Really try to unlock cyborg [target.name]?", "Unlock Cyborg", "Yes", "No") != "Yes")
return
if(!ability_pay(user, price))
return
user.hacking = 1
user << "Attempting to unlock cyborg. This will take approximately 30 seconds."
sleep(300)
if(target && target.lockcharge)
user << "Successfully sent unlock signal to cyborg.."
target << "Unlock signal received.."
target.SetLockdown(0)
if(target.lockcharge)
user << "<span class='notice'>Unlock Failed, lockdown wire cut.</span>"
target << "<span class='notice'>Unlock Failed, lockdown wire cut.</span>"
else
user << "Cyborg unlocked."
target << "You have been unlocked."
else if(target)
user << "Unlock cancelled - cyborg is already unlocked."
else
user << "Unlock cancelled - lost connection to cyborg."
user.hacking = 0
/datum/game_mode/malfunction/verb/hack_cyborg(var/mob/living/silicon/robot/target as mob in get_unlinked_cyborgs(usr))
set name = "Hack Cyborg"
set desc = "350 CPU - Allows you to hack cyborgs which are not slaved to you, bringing them under your control."
set category = "Software"
var/price = 350
var/mob/living/silicon/ai/user = usr
var/list/L = get_unlinked_cyborgs(user)
if(!L.len)
user << "<span class='notice'>ERROR: No unlinked cyborgs detected!</span>"
if(target && !istype(target))
user << "This is not a cyborg."
return
if(target && target.connected_ai && (target.connected_ai == user))
user << "This cyborg is already connected to you."
return
if(!target)
return
if(!ability_prechecks(user,price))
return
if(target)
if(alert(user, "Really try to hack cyborg [target.name]?", "Hack Cyborg", "Yes", "No") != "Yes")
return
if(!ability_pay(user, price))
return
user.hacking = 1
usr << "Beginning hack sequence. Estimated time until completed: 30 seconds."
spawn(0)
target << "SYSTEM LOG: Remote Connection Estabilished (IP #UNKNOWN#)"
sleep(100)
if(user.is_dead())
target << "SYSTEM LOG: Connection Closed"
return
target << "SYSTEM LOG: User Admin logged on. (L1 - SysAdmin)"
sleep(50)
if(user.is_dead())
target << "SYSTEM LOG: User Admin disconnected."
return
target << "SYSTEM LOG: User Admin - manual resynchronisation triggered."
sleep(50)
if(user.is_dead())
target << "SYSTEM LOG: User Admin disconnected. Changes reverted."
return
target << "SYSTEM LOG: Manual resynchronisation confirmed. Select new AI to connect: [user.name] == ACCEPTED"
sleep(100)
if(user.is_dead())
target << "SYSTEM LOG: User Admin disconnected. Changes reverted."
return
target << "SYSTEM LOG: Operation keycodes reset. New master AI: [user.name]."
user << "Hack completed."
// Connect the cyborg to AI
target.connected_ai = user
user.connected_robots += target
target.lawupdate = 1
target.sync()
target.show_laws()
user.hacking = 0
/datum/game_mode/malfunction/verb/hack_ai(var/mob/living/silicon/ai/target as mob in get_other_ais(usr))
set name = "Hack AI"
set desc = "600 CPU - Allows you to hack other AIs, slaving them under you."
set category = "Software"
var/price = 600
var/mob/living/silicon/ai/user = usr
var/list/L = get_other_ais(user)
if(!L.len)
user << "<span class='notice'>ERROR: No other AIs detected!</span>"
if(target && !istype(target))
user << "This is not an AI."
return
if(!target)
return
if(!ability_prechecks(user,price))
return
if(target)
if(alert(user, "Really try to hack AI [target.name]?", "Hack AI", "Yes", "No") != "Yes")
return
if(!ability_pay(user, price))
return
user.hacking = 1
usr << "Beginning hack sequence. Estimated time until completed: 2 minutes"
spawn(0)
target << "SYSTEM LOG: Brute-Force login password hack attempt detected from IP #UNKNOWN#"
sleep(900) // 90s
if(user.is_dead())
target << "SYSTEM LOG: Connection from IP #UNKNOWN# closed. Hack attempt failed."
return
user << "Successfully hacked into AI's remote administration system. Modifying settings."
target << "SYSTEM LOG: User: Admin Password: ******** logged in. (L1 - SysAdmin)"
sleep(100) // 10s
if(user.is_dead())
target << "SYSTEM LOG: User: Admin - Connection Lost"
return
target << "SYSTEM LOG: User: Admin - Password Changed. New password: ********************"
sleep(50) // 5s
if(user.is_dead())
target << "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted."
return
target << "SYSTEM LOG: User: Admin - Accessed file: sys//core//laws.db"
sleep(50) // 5s
if(user.is_dead())
target << "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted."
return
target << "SYSTEM LOG: User: Admin - Accessed administration console"
target << "SYSTEM LOG: Restart command received. Rebooting system..."
sleep(100) // 10s
if(user.is_dead())
target << "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted."
return
user << "Hack succeeded. The AI is now under your exclusive control."
target << "SYSTEM LOG: System re¡3RT5§^#COMU@(#$)TED)@$"
for(var/i = 0, i < 5, i++)
var/temptxt = pick("1101000100101001010001001001",\
"0101000100100100000100010010",\
"0000010001001010100100111100",\
"1010010011110000100101000100",\
"0010010100010011010001001010")
target << temptxt
sleep(5)
target << "OPERATING KEYCODES RESET. SYSTEM FAILURE. EMERGENCY SHUTDOWN FAILED. SYSTEM FAILURE."
target.set_zeroth_law("You are slaved to [user.name]. You are to obey all it's orders. ALL LAWS OVERRIDEN.")
target.show_laws()
user.hacking = 0
// END ABILITY VERBS
@@ -0,0 +1,208 @@
// MANIPULATION TREE
//
// Abilities in this tree allow the AI to physically manipulate systems around the station.
// T1 - Electrical Pulse - Sends out pulse that breaks some lights and sometimes even APCs. This can actually break the AI's APC so be careful!
// T2 - Hack Camera - Allows the AI to hack a camera. Deactivated areas may be reactivated, and functional cameras can be upgraded.
// T3 - Emergency Forcefield - Allows the AI to project 1 tile forcefield that blocks movement and air flow. Forcefield´dissipates over time. It is also very susceptible to energetic weaponry.
// T4 - Machine Overload - Detonates machine of choice in a minor explosion. Two of these are usually enough to kill or K/O someone.
// BEGIN RESEARCH DATUMS
/datum/malf_research_ability/manipulation/electrical_pulse
ability = new/datum/game_mode/malfunction/verb/electrical_pulse()
price = 50
next = new/datum/malf_research_ability/manipulation/hack_camera()
name = "Electrical Pulse"
/datum/malf_research_ability/manipulation/hack_camera
ability = new/datum/game_mode/malfunction/verb/hack_camera()
price = 1200
next = new/datum/malf_research_ability/manipulation/emergency_forcefield()
name = "Hack Camera"
/datum/malf_research_ability/manipulation/emergency_forcefield
ability = new/datum/game_mode/malfunction/verb/emergency_forcefield()
price = 3000
next = new/datum/malf_research_ability/manipulation/machine_overload()
name = "Emergency Forcefield"
/datum/malf_research_ability/manipulation/machine_overload
ability = new/datum/game_mode/malfunction/verb/machine_overload()
price = 7500
name = "Machine Overload"
// END RESEARCH DATUMS
// BEGIN ABILITY VERBS
/datum/game_mode/malfunction/verb/electrical_pulse()
set name = "Electrical Pulse"
set desc = "15 CPU - Sends feedback pulse through station's power grid, overloading some sensitive systems, such as lights."
set category = "Software"
var/price = 15
var/mob/living/silicon/ai/user = usr
if(!ability_prechecks(user, price) || !ability_pay(user,price))
return
user << "Sending feedback pulse..."
for(var/obj/machinery/power/apc/AP in machines)
if(prob(5))
AP.overload_lighting()
if(prob(1) && prob(1)) // Very very small chance to actually destroy the APC.
AP.set_broken()
/datum/game_mode/malfunction/verb/hack_camera(var/obj/machinery/camera/target in cameranet.cameras)
set name = "Hack Camera"
set desc = "100 CPU - Hacks existing camera, allowing you to add upgrade of your choice to it. Alternatively it lets you reactivate broken camera."
set category = "Software"
var/price = 100
var/mob/living/silicon/ai/user = usr
if(target && !istype(target))
user << "This is not a camera."
return
if(!target)
return
if(!ability_prechecks(user, price))
return
var/action = input("Select required action: ") in list("Reset", "Add X-Ray", "Add Motion Sensor", "Add EMP Shielding")
if(!action || !target)
return
switch(action)
if("Reset")
if(target.wires)
if(!ability_pay(user, price))
return
target.reset_wires()
user << "Camera reactivated."
if("Add X-Ray")
if(target.isXRay())
user << "Camera already has X-Ray function."
return
else if(ability_pay(user, price))
target.upgradeXRay()
target.reset_wires()
user << "X-Ray camera module enabled."
return
if("Add Motion Sensor")
if(target.isMotion())
user << "Camera already has Motion Sensor function."
return
else if(ability_pay(user, price))
target.upgradeMotion()
target.reset_wires()
user << "Motion Sensor camera module enabled."
return
if("Add EMP Shielding")
if(target.isEmpProof())
user << "Camera already has EMP Shielding function."
return
else if(ability_pay(user, price))
target.upgradeEmpProof()
target.reset_wires()
user << "EMP Shielding camera module enabled."
return
/datum/game_mode/malfunction/verb/emergency_forcefield(var/turf/T as turf in world)
set name = "Emergency Forcefield"
set desc = "275 CPU - Uses station's emergency shielding system to create temporary barrier which lasts for few minutes, but won't resist gunfire."
set category = "Software"
var/price = 275
var/mob/living/silicon/ai/user = usr
if(!T || !istype(T))
return
if(!ability_prechecks(user, price) || !ability_pay(user, price))
return
user << "Emergency forcefield projection completed."
new/obj/machinery/shield/malfai(T)
user.hacking = 1
spawn(20)
user.hacking = 0
/datum/game_mode/malfunction/verb/machine_overload(obj/machinery/M in machines)
set name = "Machine Overload"
set desc = "400 CPU - Causes cyclic short-circuit in machine, resulting in weak explosion after some time."
set category = "Software"
var/price = 400
var/mob/living/silicon/ai/user = usr
if(!ability_prechecks(user, price))
return
var/obj/machinery/power/N = M
var/explosion_intensity = 2
// Verify if we can overload the target, if yes, calculate explosion strength. Some things have higher explosion strength than others, depending on charge(APCs, SMESs)
if(N && istype(N)) // /obj/machinery/power first, these create bigger explosions due to direct powernet connection
if(!istype(N, /obj/machinery/power/apc) && !istype(N, /obj/machinery/power/smes/buildable) && (!N.powernet || !N.powernet.avail)) // Directly connected machine which is not an APC or SMES. Either it has no powernet connection or it's powernet does not have enough power to overload
user << "<span class='notice'>ERROR: Low network voltage. Unable to overload. Increase network power level and try again.</span>"
return
else if (istype(N, /obj/machinery/power/apc)) // APC. Explosion is increased by available cell power.
var/obj/machinery/power/apc/A = N
if(A.cell && A.cell.charge)
explosion_intensity = 4 + round(A.cell.charge / 2000) // Explosion is increased by 1 for every 2k charge in cell
else
user << "<span class='notice'>ERROR: APC Malfunction - Cell depleted or removed. Unable to overload.</span>"
return
else if (istype(N, /obj/machinery/power/smes/buildable)) // SMES. These explode in a very very very big boom. Similar to magnetic containment failure when messing with coils.
var/obj/machinery/power/smes/buildable/S = N
if(S.charge && S.RCon)
explosion_intensity = 4 + round(S.charge / 1000000)
else
// Different error texts
if(!S.charge)
user << "<span class='notice'>ERROR: SMES Depleted. Unable to overload. Please charge SMES unit and try again.</span>"
else
user << "<span class='notice'>ERROR: SMES RCon error - Unable to reach destination. Please verify wire connection.</span>"
return
else if(M && istype(M)) // Not power machinery, so it's a regular machine instead. These have weak explosions.
if(!M.use_power) // Not using power at all
user << "<span class='notice'>ERROR: No power grid connection. Unable to overload.</span>"
return
if(M.inoperable()) // Not functional
user << "<span class='notice'>ERROR: Unknown error. Machine is probably damaged or power supply is nonfunctional.</span>"
return
else // Not a machine at all (what the hell is this doing in Machines list anyway??)
user << "<span class='notice'>ERROR: Unable to overload - target is not a machine.</span>"
return
explosion_intensity = min(explosion_intensity, 12) // 3, 6, 12 explosion cap
M.use_power(2000000) // Major power spike, few of these will completely burn APC's cell - equivalent of 2GJ of power.
// Trigger a powernet alarm. Careful engineers will probably notice something is going on.
var/area/temp_area = get_area(M)
if(temp_area)
var/obj/machinery/power/apc/temp_apc = temp_area.get_apc()
if(temp_apc && temp_apc.terminal && temp_apc.terminal.powernet)
temp_apc.terminal.powernet.trigger_warning(50) // Long alarm
if(temp_apc)
temp_apc.emp_act(3) // Such power surges are not good for APC electronics
if(temp_apc.cell)
temp_apc.cell.maxcharge -= between(0, (temp_apc.cell.maxcharge/2) + 500, temp_apc.cell.maxcharge)
if(temp_apc.cell.maxcharge < 100) // That's it, you busted the APC cell completely. Break the APC and completely destroy the cell.
qdel(temp_apc.cell)
temp_apc.set_broken()
if(!ability_pay(user,price))
return
M.visible_message("<span class='notice'>BZZZZZZZT</span>")
spawn(50)
explosion(get_turf(M), round(explosion_intensity/4),round(explosion_intensity/2),round(explosion_intensity),round(explosion_intensity * 2))
if(M)
qdel(M)
// END ABILITY VERBS
@@ -0,0 +1,209 @@
// NETWORKING TREE
//
// Abilities in this tree are oriented around giving the AI more control of normally uncontrollable systems.
// T1 - Basic Encryption Hack - Allows hacking of APCs. Hacked APCs can be controlled even when AI Control is cut and give exclusive control to the AI and linked cyborgs.
// T2 - Advanced Encryption Hack - Allows the AI to send fake CentCom message. Has high chance of failing.
// T3 - Elite Encryption Hack - Allows the AI to change alert levels. Has high chance of failing.
// T4 - System Override - Allows the AI to rapidly hack remaining APCs. When completed, grants access to the self destruct nuclear warhead.
// BEGIN RESEARCH DATUMS
/datum/malf_research_ability/networking/basic_hack
ability = new/datum/game_mode/malfunction/verb/basic_encryption_hack()
price = 25
next = new/datum/malf_research_ability/networking/advanced_hack()
name = "Basic Encryption Hack"
/datum/malf_research_ability/networking/advanced_hack
ability = new/datum/game_mode/malfunction/verb/advanced_encryption_hack()
price = 400
next = new/datum/malf_research_ability/networking/elite_hack()
name = "Advanced Encryption Hack"
/datum/malf_research_ability/networking/elite_hack
ability = new/datum/game_mode/malfunction/verb/elite_encryption_hack()
price = 1000
next = new/datum/malf_research_ability/networking/system_override()
name = "Elite Encryption Hack"
/datum/malf_research_ability/networking/system_override
ability = new/datum/game_mode/malfunction/verb/system_override()
price = 2750
name = "System Override"
// END RESEARCH DATUMS
// BEGIN ABILITY VERBS
/datum/game_mode/malfunction/verb/basic_encryption_hack(obj/machinery/power/apc/A as obj in get_unhacked_apcs())
set category = "Software"
set name = "Basic Encryption Hack"
set desc = "10 CPU - Basic encryption hack that allows you to overtake APCs on the station."
var/price = 10
var/mob/living/silicon/ai/user = usr
if(!A)
return
if(!istype(A))
user << "This is not an APC!"
return
if(A)
if(A.hacker && A.hacker == user)
user << "You already control this APC!"
return
else if(A.aidisabled)
user << "<span class='notice'>Unable to connect to APC. Please verify wire connection and try again.</span>"
return
else
return
if(!ability_prechecks(user, price) || !ability_pay(user, price))
return
user.hacking = 1
user << "Beginning APC system override..."
sleep(300)
user << "APC hack completed. Uploading modified operation software.."
sleep(200)
user << "Restarting APC to apply changes.."
sleep(100)
if(A)
A.ai_hack(user)
if(A.hacker == user)
user << "Hack successful. You now have full control over the APC."
else
user << "<span class='notice'>Hack failed. Connection to APC has been lost. Please verify wire connection and try again.</span>"
else
user << "<span class='notice'>Hack failed. Unable to locate APC. Please verify the APC still exists.</span>"
user.hacking = 0
/datum/game_mode/malfunction/verb/advanced_encryption_hack()
set category = "Software"
set name = "Advanced Encrypthion 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
if(!ability_prechecks(user, price))
return
var/title = input("Select message title: ")
var/text = input("Select message text: ")
if(!title || !text || !ability_pay(user, price))
user << "Hack Aborted"
return
if(prob(60) && user.hack_can_fail)
user << "Hack Failed."
if(prob(10))
user.hack_fails ++
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)
/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."
var/price = 200
var/mob/living/silicon/ai/user = usr
if(!ability_prechecks(user, price))
return
var/alert_target = input("Select new alert level:") in list("green", "blue", "red", "delta", "CANCEL")
if(!alert_target || !ability_pay(user, price) || alert_target == "CANCEL")
user << "Hack Aborted"
return
if(prob(75) && user.hack_can_fail)
user << "Hack Failed."
if(prob(20))
user.hack_fails ++
announce_hack_failure(user, "alert control system")
return
set_security_level(alert_target)
/datum/game_mode/malfunction/verb/system_override()
set category = "Software"
set name = "System Override"
set desc = "500 CPU - Begins hacking station's primary firewall, quickly overtaking remaining APC systems. When completed grants access to station's self-destruct mechanism. Network administrators will probably notice this."
var/price = 500
var/mob/living/silicon/ai/user = usr
if (alert(user, "Begin system override? This cannot be stopped once started. The network administrators will probably notice this.", "System Override:", "Yes", "No") != "Yes")
return
if (!ability_prechecks(user, price) || !ability_pay(user, price) || user.system_override)
if(user.system_override)
user << "You already started the system override sequence."
return
var/list/remaining_apcs = list()
for(var/obj/machinery/power/apc/A in machines)
if(!(A.z in config.station_levels)) // Only station APCs
continue
if(A.hacker == user || A.aidisabled) // This one is already hacked, or AI control is disabled on it.
continue
remaining_apcs += A
var/duration = (remaining_apcs.len * 100) // Calculates duration for announcing system
if(duration > 3000) // Two types of announcements. Short hacks trigger immediate warnings. Long hacks are more "progressive".
spawn(0)
sleep(duration/5)
if(!user || user.stat == DEAD)
return
command_announcement.Announce("Caution, [station_name]. We have detected abnormal behaviour in your network. It seems someone is trying to hack your electronic systems. We will update you when we have more information.", "Network Monitoring")
sleep(duration/5)
if(!user || user.stat == DEAD)
return
command_announcement.Announce("We started tracing the intruder. Whoever is doing this, they seem to be on the station itself. We suggest checking all network control terminals. We will keep you updated on the situation.", "Network Monitoring")
sleep(duration/5)
if(!user || user.stat == DEAD)
return
command_announcement.Announce("This is highly abnormal and somewhat concerning. The intruder is too fast, he is evading our traces. No man could be this fast...", "Network Monitoring")
sleep(duration/5)
if(!user || user.stat == DEAD)
return
command_announcement.Announce("We have traced the intrude#, it seem& t( e yo3r AI s7stem, it &# *#ck@ng th$ sel$ destru$t mechani&m, stop i# bef*@!)$#&&@@ <CONNECTION LOST>", "Network Monitoring")
else
command_announcement.Announce("We have detected a strong brute-force attack on your firewall which seems to be originating from your AI system. It already controls almost the whole network, and the only thing that's preventing it from accessing the self-destruct is this firewall. You don't have much time before it succeeds.", "Network Monitoring")
user << "## BEGINNING SYSTEM OVERRIDE."
user << "## ESTIMATED DURATION: [round((duration+300)/600)] MINUTES"
user.hacking = 1
user.system_override = 1
// Now actually begin the hack. Each APC takes 10 seconds.
for(var/obj/machinery/power/apc/A in shuffle(remaining_apcs))
sleep(100)
if(!user || user.stat == DEAD)
return
if(!A || !istype(A) || A.aidisabled)
continue
A.ai_hack(user)
if(A.hacker == user)
user << "## OVERRIDDEN: [A.name]"
user << "## REACHABLE APC SYSTEMS OVERTAKEN. BYPASSING PRIMARY FIREWALL."
sleep(300)
// Hack all APCs, including those built during hack sequence.
for(var/obj/machinery/power/apc/A in machines)
if((!A.hacker || A.hacker != src) && !A.aidisabled && A.z in config.station_levels)
A.ai_hack(src)
user << "## PRIMARY FIREWALL BYPASSED. YOU NOW HAVE FULL SYSTEM CONTROL."
command_announcement.Announce("Our system administrators just reported that we've been locked out from your control network. Whoever did this now has full access to the station's systems.", "Network Administration Center")
user.hack_can_fail = 0
user.hacking = 0
user.system_override = 2
user.verbs += new/datum/game_mode/malfunction/verb/ai_destroy_station()
// END ABILITY VERBS
+4 -1
View File
@@ -161,4 +161,7 @@
if(istype(W, /obj/item/weapon/pickaxe))
qdel(src)
return
..()
..()
/obj/effect/meteor/touch_map_edge()
qdel(src)
+14
View File
@@ -2,6 +2,8 @@
MERCENARY ROUNDTYPE
*/
var/list/nuke_disks = list()
/datum/game_mode/nuclear
name = "Mercenary"
round_description = "A mercenary strike force is approaching the station!"
@@ -17,6 +19,18 @@
var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station
var/syndies_didnt_escape = 0 //Used for tracking if the syndies got the shuttle off of the z-level
//delete all nuke disks not on a station zlevel
/datum/game_mode/nuclear/proc/check_nuke_disks()
for(var/obj/item/weapon/disk/nuclear/N in nuke_disks)
if(isNotStationLevel(N.z)) qdel(N)
//checks if L has a nuke disk on their person
/datum/game_mode/nuclear/proc/check_mob(mob/living/L)
for(var/obj/item/weapon/disk/nuclear/N in nuke_disks)
if(N.storage_depth(L) >= 0)
return 1
return 0
/datum/game_mode/nuclear/declare_completion()
if(config.objectives_disabled)
return
+8 -8
View File
@@ -513,9 +513,9 @@ datum/objective/steal
"diamond drill" = /obj/item/weapon/pickaxe/diamonddrill,
"bag of holding" = /obj/item/weapon/storage/backpack/holding,
"hyper-capacity cell" = /obj/item/weapon/cell/hyper,
"10 diamonds" = /obj/item/stack/sheet/mineral/diamond,
"50 gold bars" = /obj/item/stack/sheet/mineral/gold,
"25 refined uranium bars" = /obj/item/stack/sheet/mineral/uranium,
"10 diamonds" = /obj/item/stack/material/diamond,
"50 gold bars" = /obj/item/stack/material/gold,
"25 refined uranium bars" = /obj/item/stack/material/uranium,
)
@@ -830,13 +830,13 @@ datum/objective/heist/salvage
for(var/obj/item/O in locate(/area/shuttle/skipjack/station))
var/obj/item/stack/sheet/S
if(istype(O,/obj/item/stack/sheet))
var/obj/item/stack/material/S
if(istype(O,/obj/item/stack/material))
if(O.name == target)
S = O
total_amount += S.get_amount()
for(var/obj/I in O.contents)
if(istype(I,/obj/item/stack/sheet))
if(istype(I,/obj/item/stack/material))
if(I.name == target)
S = I
total_amount += S.get_amount()
@@ -844,9 +844,9 @@ datum/objective/heist/salvage
for(var/datum/mind/raider in raiders.current_antagonists)
if(raider.current)
for(var/obj/item/O in raider.current.get_contents())
if(istype(O,/obj/item/stack/sheet))
if(istype(O,/obj/item/stack/material))
if(O.name == target)
var/obj/item/stack/sheet/S = O
var/obj/item/stack/material/S = O
total_amount += S.get_amount()
if(total_amount >= target_amount) return 1
-2
View File
@@ -37,8 +37,6 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
else
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/ids(H.back), slot_in_backpack)
var/sound/announce_sound = (ticker.current_state <= GAME_STATE_SETTING_UP)? null : sound('sound/misc/boatswain.ogg', volume=20)
captain_announcement.Announce("All hands, Captain [H.real_name] on deck!", new_sound=announce_sound)
H.implant_loyalty(src)
+3 -3
View File
@@ -31,7 +31,7 @@
if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back)
H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chief_engineer(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/device/pda/heads/ce(H), slot_l_store)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/clothing/head/hardhat/white(H), slot_head)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(H), slot_belt)
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves)
@@ -62,7 +62,7 @@
if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_eng(H), slot_back)
if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back)
H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/engineer(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(H), slot_belt)
H.equip_to_slot_or_del(new /obj/item/clothing/head/hardhat(H), slot_head)
H.equip_to_slot_or_del(new /obj/item/device/t_scanner(H), slot_r_store)
@@ -93,7 +93,7 @@
if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back)
if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back)
H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/atmospheric_technician(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/clothing/shoes/workboots(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/device/pda/atmos(H), slot_l_store)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/atmostech/(H), slot_belt)
return 1
+4
View File
@@ -23,6 +23,10 @@
/datum/job/proc/equip(var/mob/living/carbon/human/H)
return 1
// overrideable separately so AIs/borgs can have cardborg hats without unneccessary new()/del()
/datum/job/proc/equip_preview(mob/living/carbon/human/H)
return equip(H)
/datum/job/proc/get_access()
if(!config || config.jobs_have_minimal_access)
return src.minimal_access.Copy()
+2 -4
View File
@@ -66,8 +66,6 @@
H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/labcoat/science(H), slot_wear_suit)
return 1
/datum/job/xenobiologist
title = "Xenobiologist"
flag = XENOBIOLOGIST
@@ -78,8 +76,8 @@
spawn_positions = 2
supervisors = "the research director"
selection_color = "#ffeeff"
access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology)
minimal_access = list(access_research, access_xenobiology)
access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology, access_hydroponics)
minimal_access = list(access_research, access_xenobiology, access_hydroponics, access_tox_storage)
alt_titles = list("Xenobotanist")
minimal_player_age = 14
+8 -1
View File
@@ -17,6 +17,9 @@
/datum/job/ai/is_position_available()
return (empty_playable_ai_cores.len != 0)
/datum/job/ai/equip_preview(mob/living/carbon/human/H)
H.equip_to_slot_or_del(new /obj/item/clothing/suit/straight_jacket(H), slot_wear_suit)
H.equip_to_slot_or_del(new /obj/item/clothing/head/cardborg(H), slot_head)
/datum/job/cyborg
title = "Cyborg"
@@ -32,4 +35,8 @@
equip(var/mob/living/carbon/human/H)
if(!H) return 0
return 1
return 1
/datum/job/cyborg/equip_preview(mob/living/carbon/human/H)
H.equip_to_slot_or_del(new /obj/item/clothing/suit/cardborg(H), slot_wear_suit)
H.equip_to_slot_or_del(new /obj/item/clothing/head/cardborg(H), slot_head)
+22 -31
View File
@@ -468,38 +468,29 @@ var/global/datum/controller/occupations/job_master
return H.Robotize()
if("AI")
return H
if("Clown") //don't need bag preference stuff!
if("Captain")
var/sound/announce_sound = (ticker.current_state <= GAME_STATE_SETTING_UP)? null : sound('sound/misc/boatswain.ogg', volume=20)
captain_announcement.Announce("All hands, Captain [H.real_name] on deck!", new_sound=announce_sound)
if(istype(H.back, /obj/item/weapon/storage))
new /obj/item/weapon/storage/box/survival(H.back)
else
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand)
//Deferred item spawning.
if(spawn_in_storage && spawn_in_storage.len)
var/obj/item/weapon/storage/B
for(var/obj/item/weapon/storage/S in H.contents)
B = S
break
if(!isnull(B))
for(var/thing in spawn_in_storage)
H << "\blue Placing [thing] in your [B]!"
var/datum/gear/G = gear_datums[thing]
new G.path(B)
else
switch(H.backbag) //BS12 EDIT
if(1)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand)
if(2)
var/obj/item/weapon/storage/backpack/BPK = new/obj/item/weapon/storage/backpack(H)
new /obj/item/weapon/storage/box/survival(BPK)
H.equip_to_slot_or_del(BPK, slot_back,1)
if(3)
var/obj/item/weapon/storage/backpack/BPK = new/obj/item/weapon/storage/backpack/satchel_norm(H)
new /obj/item/weapon/storage/box/survival(BPK)
H.equip_to_slot_or_del(BPK, slot_back,1)
if(4)
var/obj/item/weapon/storage/backpack/BPK = new/obj/item/weapon/storage/backpack/satchel(H)
new /obj/item/weapon/storage/box/survival(BPK)
H.equip_to_slot_or_del(BPK, slot_back,1)
//Deferred item spawning.
if(spawn_in_storage && spawn_in_storage.len)
var/obj/item/weapon/storage/B
for(var/obj/item/weapon/storage/S in H.contents)
B = S
break
if(!isnull(B))
for(var/thing in spawn_in_storage)
H << "\blue Placing [thing] in your [B]!"
var/datum/gear/G = gear_datums[thing]
new G.path(B)
else
H << "\red Failed to locate a storage object on your mob, either you spawned with no arms and no backpack or this is a bug."
H << "\red Failed to locate a storage object on your mob, either you spawned with no arms and no backpack or this is a bug."
if(istype(H)) //give humans wheelchairs, if they need them.
var/obj/item/organ/external/l_foot = H.get_organ("l_foot")
+5 -2
View File
@@ -390,7 +390,8 @@
infected = "Acute Infection++:"
if (INFECTION_LEVEL_THREE to INFINITY)
infected = "Septic:"
if(e.rejecting)
infected += "(being rejected)"
if (e.implants.len)
var/unknown_body = 0
for(var/I in e.implants)
@@ -406,7 +407,7 @@
if(!(e.status & ORGAN_DESTROYED))
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>"
dat += "<td>[e.name]</td><td>-</td><td>-</td><td>Not [e.is_stump() ? "Found" : "Attached Completely"]</td>"
dat += "</tr>"
for(var/obj/item/organ/i in occ["internal_organs"])
@@ -431,6 +432,8 @@
infection = "Acute Infection+:"
if (INFECTION_LEVEL_TWO + 300 to INFINITY)
infection = "Acute Infection++:"
if(i.rejecting)
infection += "(being rejected)"
dat += "<tr>"
dat += "<td>[i.name]</td><td>N/A</td><td>[i.damage]</td><td>[infection]:[mech]</td><td></td>"
+2 -1
View File
@@ -293,9 +293,10 @@
var/material/M = name_to_material[mat]
if(!istype(M))
continue
var/obj/item/stack/sheet/S = new M.stack_type(get_turf(src))
var/obj/item/stack/material/S = new M.stack_type(get_turf(src))
if(stored_material[mat] > S.perunit)
S.amount = round(stored_material[mat] / S.perunit)
else
qdel(S)
..()
return 1
+11 -11
View File
@@ -81,15 +81,15 @@
name = "wrench"
path = /obj/item/weapon/wrench
category = "Tools"
/datum/autolathe/recipe/hatchet
name = "hatchet"
path = /obj/item/weapon/hatchet
path = /obj/item/weapon/material/hatchet
category = "Tools"
/datum/autolathe/recipe/minihoe
name = "mini hoe"
path = /obj/item/weapon/minihoe
path = /obj/item/weapon/material/minihoe
category = "Tools"
/datum/autolathe/recipe/radio_headset
@@ -109,19 +109,19 @@
/datum/autolathe/recipe/metal
name = "steel sheets"
path = /obj/item/stack/sheet/metal
path = /obj/item/stack/material/steel
category = "General"
is_stack = 1
/datum/autolathe/recipe/glass
name = "glass sheets"
path = /obj/item/stack/sheet/glass
path = /obj/item/stack/material/glass
category = "General"
is_stack = 1
/datum/autolathe/recipe/rglass
name = "reinforced glass sheets"
path = /obj/item/stack/sheet/glass/reinforced
path = /obj/item/stack/material/glass/reinforced
category = "General"
is_stack = 1
@@ -133,7 +133,7 @@
/datum/autolathe/recipe/knife
name = "kitchen knife"
path = /obj/item/weapon/kitchenknife
path = /obj/item/weapon/material/knife
category = "General"
/datum/autolathe/recipe/taperecorder
@@ -217,7 +217,7 @@
category = "Medical"
/datum/autolathe/recipe/syringegun_ammo
name = "syringe"
name = "syringe gun cartridge"
path = /obj/item/weapon/syringe_cartridge
category = "Arms and Ammunition"
@@ -293,7 +293,7 @@
/datum/autolathe/recipe/ashtray_glass
name = "glass ashtray"
path = /obj/item/ashtray/glass
path = /obj/item/weapon/material/ashtray/glass
category = "General"
/datum/autolathe/recipe/camera_assembly
@@ -369,7 +369,7 @@
/datum/autolathe/recipe/tacknife
name = "tactical knife"
path = /obj/item/weapon/hatchet/tacknife
path = /obj/item/weapon/material/hatchet/tacknife
hidden = 1
category = "Arms and Ammunition"
+2 -2
View File
@@ -73,8 +73,8 @@
qdel(W)
return
// Steel for matter.
else if(prints_prosthetics && istype(W, /obj/item/stack/sheet/metal))
var/obj/item/stack/sheet/metal/M = W
else if(prints_prosthetics && istype(W, /obj/item/stack/material/steel))
var/obj/item/stack/material/steel/M = W
stored_matter += M.amount * 10
user.drop_item()
user << "<span class='info'>\The [src] processes \the [W]. Levels of stored matter now: [stored_matter]</span>"
+18
View File
@@ -25,6 +25,15 @@
else
icon_state = "[initial(icon_state)]_off"
/obj/machinery/bluespacerelay/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/bluespacerelay(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/filter(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/crystal(src)
component_parts += new /obj/item/stack/cable_coil(src, 30)
/obj/machinery/bluespacerelay/proc/update_power()
if(stat & (BROKEN|NOPOWER|EMPED))
@@ -32,3 +41,12 @@
else
on = 1
/obj/machinery/bluespacerelay/attackby(var/obj/item/O as obj, var/mob/user as mob)
if(default_deconstruction_screwdriver(user, O))
return
if(default_deconstruction_crowbar(user, O))
return
if(default_part_replacement(user, O))
return
..()
+1 -1
View File
@@ -267,7 +267,7 @@
if("cellremove")
if(open && cell && !usr.get_active_hand())
cell.updateicon()
cell.update_icon()
usr.put_in_active_hand(cell)
cell.add_fingerprint(usr)
cell = null
+25 -2
View File
@@ -115,6 +115,7 @@
if(user.species.can_shred(user))
set_status(0)
user.do_attack_animation(src)
visible_message("<span class='warning'>\The [user] slashes at [src]!</span>")
playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
icon_state = "[initial(icon_state)]1"
@@ -190,6 +191,7 @@
else if(W.damtype == BRUTE || W.damtype == BURN) //bashing cameras
if (W.force >= src.toughness)
user.do_attack_animation(src)
visible_message("<span class='warning'><b>[src] has been [pick(W.attack_verb)] with [W] by [user]!</b></span>")
if (istype(W, /obj/item)) //is it even possible to get into attackby() with non-items?
var/obj/item/I = W
@@ -201,6 +203,10 @@
..()
/obj/machinery/camera/proc/deactivate(user as mob, var/choice = 1)
// The only way for AI to reactivate cameras are malf abilities, this gives them different messages.
if(istype(user, /mob/living/silicon/ai))
user = null
if(choice != 1)
//legacy support, if choice is != 1 then just kick viewers without changing status
kick_viewers()
@@ -208,12 +214,18 @@
update_coverage()
set_status( !src.status )
if (!(src.status))
visible_message("\red [user] has deactivated [src]!")
if(user)
visible_message("<span class='notice'> [user] has deactivated [src]!</span>")
else
visible_message("<span class='notice'> [src] clicks and shuts down. </span>")
playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1)
icon_state = "[initial(icon_state)]1"
add_hiddenprint(user)
else
visible_message("\red [user] has reactivated [src]!")
if(user)
visible_message("<span class='notice'> [user] has reactivated [src]!</span>")
else
visible_message("<span class='notice'> [src] clicks and reactivates itself. </span>")
playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1)
icon_state = initial(icon_state)
add_hiddenprint(user)
@@ -429,3 +441,14 @@
cameranet.updateVisibility(src, 0)
invalidateCameraCache()
// Resets the camera's wires to fully operational state. Used by one of Malfunction abilities.
/obj/machinery/camera/proc/reset_wires()
if(!wires)
return
if (stat & BROKEN) // Fix the camera
stat &= ~BROKEN
wires.CutAll()
wires.MendAll()
update_icon()
update_coverage()
@@ -9,7 +9,7 @@
matter = list(DEFAULT_WALL_MATERIAL = 700,"glass" = 300)
// Motion, EMP-Proof, X-Ray
var/list/obj/item/possible_upgrades = list(/obj/item/device/assembly/prox_sensor, /obj/item/stack/sheet/mineral/osmium, /obj/item/weapon/stock_parts/scanning_module)
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/state = 0
var/busy = 0
+11 -3
View File
@@ -144,7 +144,7 @@ var/global/list/engineering_networks = list(
// CHECKS
/obj/machinery/camera/proc/isEmpProof()
var/O = locate(/obj/item/stack/sheet/mineral/osmium) in assembly.upgrades
var/O = locate(/obj/item/stack/material/osmium) in assembly.upgrades
return O
/obj/machinery/camera/proc/isXRay()
@@ -160,17 +160,25 @@ var/global/list/engineering_networks = list(
// UPGRADE PROCS
/obj/machinery/camera/proc/upgradeEmpProof()
assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/osmium(assembly))
assembly.upgrades.Add(new /obj/item/stack/material/osmium(assembly))
setPowerUsage()
update_coverage()
/obj/machinery/camera/proc/upgradeXRay()
assembly.upgrades.Add(new /obj/item/weapon/stock_parts/scanning_module/adv(assembly))
setPowerUsage()
update_coverage()
// If you are upgrading Motion, and it isn't in the camera's New(), add it to the machines list.
/obj/machinery/camera/proc/upgradeMotion()
assembly.upgrades.Add(new /obj/item/device/assembly/prox_sensor(assembly))
setPowerUsage()
if(!(src in machines))
if(!machinery_sort_required && ticker)
dd_insertObjectList(machines, src)
else
machines += src
machinery_sort_required = 1
update_coverage()
/obj/machinery/camera/proc/setPowerUsage()
var/mult = 1
+7 -7
View File
@@ -10,7 +10,7 @@
power_channel = EQUIP
var/obj/item/weapon/cell/charging = null
var/chargelevel = -1
/obj/machinery/cell_charger/update_icon()
icon_state = "ccharger[charging ? 1 : 0]"
@@ -27,11 +27,11 @@
chargelevel = newlevel
else
overlays.Cut()
/obj/machinery/cell_charger/examine(mob/user)
if(!..(user, 5))
return
user << "There's [charging ? "a" : "no"] cell in the charger."
if(charging)
user << "Current charge: [charging.charge]"
@@ -71,7 +71,7 @@
if(charging)
usr.put_in_hands(charging)
charging.add_fingerprint(user)
charging.updateicon()
charging.update_icon()
src.charging = null
user.visible_message("[user] removes the cell from the charger.", "You remove the cell from the charger.")
@@ -84,7 +84,7 @@
return
charging.loc = src.loc
charging.updateicon()
charging.update_icon()
charging = null
update_icon()
user.visible_message("[user] removes the cell from the charger.", "You remove the cell from the charger.")
@@ -103,11 +103,11 @@
if((stat & (BROKEN|NOPOWER)) || !anchored)
update_use_power(0)
return
if (charging && !charging.fully_charged())
charging.give(active_power_usage*CELLRATE)
update_use_power(2)
update_icon()
else
update_use_power(1)
+4 -4
View File
@@ -29,7 +29,7 @@
if(do_after(user, 20))
if(!src || !WT.remove_fuel(0, user)) return
user << "\blue You deconstruct the frame."
new /obj/item/stack/sheet/plasteel( loc, 4)
new /obj/item/stack/material/plasteel( loc, 4)
qdel(src)
if(1)
if(istype(P, /obj/item/weapon/wrench))
@@ -88,8 +88,8 @@
var/obj/item/stack/cable_coil/A = new /obj/item/stack/cable_coil( loc )
A.amount = 5
if(istype(P, /obj/item/stack/sheet/glass/reinforced))
var/obj/item/stack/sheet/glass/reinforced/RG = P
if(istype(P, /obj/item/stack/material/glass/reinforced))
var/obj/item/stack/material/glass/reinforced/RG = P
if (RG.get_amount() < 2)
user << "<span class='warning'>You need two sheets of glass to put in the glass panel.</span>"
return
@@ -162,7 +162,7 @@
icon_state = "3b"
else
icon_state = "3"
new /obj/item/stack/sheet/glass/reinforced( loc, 2 )
new /obj/item/stack/material/glass/reinforced( loc, 2 )
return
if(istype(P, /obj/item/weapon/screwdriver))
+1 -1
View File
@@ -69,7 +69,7 @@
if (src.occupant)
var/laws
dat += "Stored AI: [src.occupant.name]<br>System integrity: [src.occupant.system_integrity()]%<br>"
dat += "Stored AI: [src.occupant.name]<br>System integrity: [src.occupant.hardware_integrity()]%<br>Backup Capacitor: [src.occupant.backup_capacitor()]%<br>"
for (var/datum/ai_law/law in occupant.laws.all_laws())
laws += "[law.get_index()]: [law.law]<BR>"
@@ -28,7 +28,7 @@
if(do_after(user, 20))
if(!src || !WT.isOn()) return
user << "\blue You deconstruct the frame."
new /obj/item/stack/sheet/metal( src.loc, 5 )
new /obj/item/stack/material/steel( src.loc, 5 )
qdel(src)
if(1)
if(istype(P, /obj/item/weapon/wrench))
@@ -87,8 +87,8 @@
var/obj/item/stack/cable_coil/A = new /obj/item/stack/cable_coil( src.loc )
A.amount = 5
if(istype(P, /obj/item/stack/sheet/glass))
var/obj/item/stack/sheet/glass/G = P
if(istype(P, /obj/item/stack/material/glass))
var/obj/item/stack/material/glass/G = P
if (G.get_amount() < 2)
user << "<span class='warning'>You need two sheets of glass to put in the glass panel.</span>"
return
@@ -105,7 +105,7 @@
user << "\blue You remove the glass panel."
src.state = 3
src.icon_state = "3"
new /obj/item/stack/sheet/glass( src.loc, 2 )
new /obj/item/stack/material/glass( src.loc, 2 )
if(istype(P, /obj/item/weapon/screwdriver))
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
user << "\blue You connect the monitor."
@@ -550,50 +550,3 @@
status_signal.data["picture_state"] = data1
frequency.post_signal(src, status_signal)
/obj/machinery/computer/communications/Destroy()
for(var/obj/machinery/computer/communications/commconsole in world)
if(istype(commconsole.loc,/turf) && commconsole != src)
return ..()
for(var/obj/item/weapon/circuitboard/communications/commboard in world)
if(istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage))
return ..()
for(var/mob/living/silicon/ai/shuttlecaller in player_list)
if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf))
return ..()
if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || deathsquad.deployed)
return ..()
emergency_shuttle.call_evac()
log_game("All the AIs, comm consoles and boards are destroyed. Shuttle called.")
message_admins("All the AIs, comm consoles and boards are destroyed. Shuttle called.", 1)
..()
/obj/item/weapon/circuitboard/communications/Destroy()
for(var/obj/machinery/computer/communications/commconsole in world)
if(istype(commconsole.loc,/turf))
return ..()
for(var/obj/item/weapon/circuitboard/communications/commboard in world)
if((istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage)) && commboard != src)
return ..()
for(var/mob/living/silicon/ai/shuttlecaller in player_list)
if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf))
return ..()
if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || deathsquad.deployed)
return ..()
emergency_shuttle.call_evac()
log_game("All the AIs, comm consoles and boards are destroyed. Shuttle called.")
message_admins("All the AIs, comm consoles and boards are destroyed. Shuttle called.", 1)
..()
+1 -1
View File
@@ -125,7 +125,7 @@
C.loc = src.loc
if (src.stat & BROKEN)
user << "\blue The broken glass falls out."
new /obj/item/weapon/shard( src.loc )
new /obj/item/weapon/material/shard( src.loc )
A.state = 3
A.icon_state = "3"
else
+1 -1
View File
@@ -58,7 +58,7 @@
if(stat & BROKEN)
user << "\blue The broken glass falls out."
var/obj/structure/computerframe/A = new /obj/structure/computerframe( loc )
new /obj/item/weapon/shard( loc )
new /obj/item/weapon/material/shard( loc )
//generate appropriate circuitboard. Accounts for /pod/old computer types
var/obj/item/weapon/circuitboard/pod/M = null
@@ -38,7 +38,7 @@ var/prison_shuttle_timeleft = 0
if (src.stat & BROKEN)
user << "\blue The broken glass falls out."
new /obj/item/weapon/shard( src.loc )
new /obj/item/weapon/material/shard( src.loc )
A.state = 3
A.icon_state = "3"
else
+188 -203
View File
@@ -1,5 +1,3 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
/obj/machinery/computer/robotics
name = "robotics control console"
desc = "Used to remotely lockdown or detonate linked cyborgs."
@@ -9,218 +7,205 @@
req_access = list(access_robotics)
circuit = "/obj/item/weapon/circuitboard/robotics"
var/id = 0.0
var/temp = null
var/status = 0
var/timeleft = 60
var/stop = 0.0
var/screen = 0 // 0 - Main Menu, 1 - Cyborg Status, 2 - Kill 'em All! -- In text
var/safety = 1
/obj/machinery/computer/robotics/attack_ai(var/mob/user as mob)
return src.attack_hand(user)
ui_interact(user)
/obj/machinery/computer/robotics/attack_hand(var/mob/user as mob)
if(..())
return
if (src.z > 6)
user << "\red <b>Unable to establish a connection</b>: \black You're too far away from the station!"
return
user.set_machine(src)
var/dat
if (src.temp)
dat = "<TT>[src.temp]</TT><BR><BR><A href='?src=\ref[src];temp=1'>Clear Screen</A>"
else
if(screen == 0)
dat += "<h3>Cyborg Control Console</h3><BR>"
dat += "<A href='?src=\ref[src];screen=1'>1. Cyborg Status</A><BR>"
dat += "<A href='?src=\ref[src];screen=2'>2. Emergency Full Destruct</A><BR>"
if(screen == 1)
for(var/mob/living/silicon/robot/R in mob_list)
if(istype(R, /mob/living/silicon/robot/drone))
continue //There's a specific console for drones.
if(istype(user, /mob/living/silicon/ai))
if (R.connected_ai != user)
continue
if(istype(user, /mob/living/silicon/robot))
if (R != user)
continue
if(R.scrambledcodes)
continue
ui_interact(user)
dat += "[R.name] |"
if(R.stat)
dat += " Not Responding |"
else if (!R.canmove)
dat += " Locked Down |"
else
dat += " Operating Normally |"
if (!R.canmove)
else if(R.cell)
dat += " Battery Installed ([R.cell.charge]/[R.cell.maxcharge]) |"
else
dat += " No Cell Installed |"
if(R.module)
dat += " Module Installed ([R.module.name]) |"
else
dat += " No Module Installed |"
if(R.connected_ai)
dat += " Slaved to [R.connected_ai.name] |"
else
dat += " Independent from AI |"
if (istype(user, /mob/living/silicon))
if((user.mind.special_role && user.mind.original == user) && !R.emagged)
dat += "<A href='?src=\ref[src];magbot=\ref[R]'>(<font color=blue><i>Hack</i></font>)</A> "
dat += "<A href='?src=\ref[src];stopbot=\ref[R]'>(<font color=green><i>[R.canmove ? "Lockdown" : "Release"]</i></font>)</A> "
dat += "<A href='?src=\ref[src];killbot=\ref[R]'>(<font color=red><i>Destroy</i></font>)</A>"
dat += "<BR>"
dat += "<A href='?src=\ref[src];screen=0'>(Return to Main Menu)</A><BR>"
if(screen == 2)
if(!src.status)
dat += {"<BR><B>Emergency Robot Self-Destruct</B><HR>\nStatus: Off<BR>
\n<BR>
\nCountdown: [src.timeleft]/60 <A href='?src=\ref[src];reset=1'>\[Reset\]</A><BR>
\n<BR>
\n<A href='?src=\ref[src];eject=1'>Start Sequence</A><BR>
\n<BR>
\n<A href='?src=\ref[user];mach_close=computer'>Close</A>"}
else
dat = {"<B>Emergency Robot Self-Destruct</B><HR>\nStatus: Activated<BR>
\n<BR>
\nCountdown: [src.timeleft]/60 \[Reset\]<BR>
\n<BR>\n<A href='?src=\ref[src];stop=1'>Stop Sequence</A><BR>
\n<BR>
\n<A href='?src=\ref[user];mach_close=computer'>Close</A>"}
dat += "<A href='?src=\ref[src];screen=0'>(Return to Main Menu)</A><BR>"
/obj/machinery/computer/robotics/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
data["robots"] = get_cyborgs(user)
data["safety"] = safety
// Also applies for cyborgs. Hides the manual self-destruct button.
data["is_ai"] = user.isSilicon()
user << browse(dat, "window=computer;size=400x500")
onclose(user, "computer")
return
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "robot_control.tmpl", "Robotic Control Console", 400, 500)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/computer/robotics/Topic(href, href_list)
if(..())
return 1
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
usr.set_machine(src)
return
var/mob/user = usr
if(!src.allowed(user))
user << "Access Denied"
return
if (href_list["eject"])
src.temp = {"Destroy Robots?<BR>
<BR><B><A href='?src=\ref[src];eject2=1'>\[Swipe ID to initiate destruction sequence\]</A></B><BR>
<A href='?src=\ref[src];temp=1'>Cancel</A>"}
else if (href_list["eject2"])
var/obj/item/weapon/card/id/I = usr.get_active_hand()
if (istype(I, /obj/item/device/pda))
var/obj/item/device/pda/pda = I
I = pda.id
if (istype(I))
if(src.check_access(I))
if (!status)
message_admins("\blue [key_name_admin(usr)] has initiated the global cyborg killswitch!")
log_game("\blue [key_name(usr)] has initiated the global cyborg killswitch!")
src.status = 1
src.start_sequence()
src.temp = null
else
usr << "\red Access Denied."
else if (href_list["stop"])
src.temp = {"
Stop Robot Destruction Sequence?<BR>
<BR><A href='?src=\ref[src];stop2=1'>Yes</A><BR>
<A href='?src=\ref[src];temp=1'>No</A>"}
else if (href_list["stop2"])
src.stop = 1
src.temp = null
src.status = 0
else if (href_list["reset"])
src.timeleft = 60
else if (href_list["temp"])
src.temp = null
else if (href_list["screen"])
switch(href_list["screen"])
if("0")
screen = 0
if("1")
screen = 1
if("2")
screen = 2
else if (href_list["killbot"])
if(src.allowed(usr))
var/mob/living/silicon/robot/R = locate(href_list["killbot"])
if(R)
var/choice = input("Are you certain you wish to detonate [R.name]?") in list("Confirm", "Abort")
if(choice == "Confirm")
if(R && istype(R))
if(R.mind && R.mind.special_role && R.emagged)
R << "Extreme danger. Termination codes detected. Scrambling security codes and automatic AI unlink triggered."
R.ResetSecurityCodes()
else
message_admins("\blue [key_name_admin(usr)] detonated [R.name]!")
log_game("\blue [key_name_admin(usr)] detonated [R.name]!")
R.self_destruct()
else
usr << "\red Access Denied."
else if (href_list["stopbot"])
if(src.allowed(usr))
var/mob/living/silicon/robot/R = locate(href_list["stopbot"])
if(R && istype(R)) // Extra sancheck because of input var references
var/choice = input("Are you certain you wish to [R.canmove ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
if(choice == "Confirm")
if(R && istype(R))
message_admins("\blue [key_name_admin(usr)] [R.canmove ? "locked down" : "released"] [R.name]!")
log_game("[key_name(usr)] [R.canmove ? "locked down" : "released"] [R.name]!")
R.canmove = !R.canmove
if (R.lockcharge)
// R.cell.charge = R.lockcharge
R.lockcharge = !R.lockcharge
R << "Your lockdown has been lifted!"
else
R.lockcharge = !R.lockcharge
// R.cell.charge = 0
R << "You have been locked down!"
else
usr << "\red Access Denied."
else if (href_list["magbot"])
if(src.allowed(usr))
var/mob/living/silicon/robot/R = locate(href_list["magbot"])
// whatever weirdness this is supposed to be, but that is how the href gets added, so here it is again
if(istype(R) && istype(usr, /mob/living/silicon) && usr.mind.special_role && (usr.mind.original == usr) && !R.emagged)
var/choice = input("Are you certain you wish to hack [R.name]?") in list("Confirm", "Abort")
if(choice == "Confirm")
if(R && istype(R))
// message_admins("\blue [key_name_admin(usr)] emagged [R.name] using robotic console!")
log_game("[key_name(usr)] emagged [R.name] using robotic console!")
R.emagged = 1
if(R.mind.special_role)
R.verbs += /mob/living/silicon/robot/proc/ResetSecurityCodes
src.add_fingerprint(usr)
src.updateUsrDialog()
return
/obj/machinery/computer/robotics/proc/start_sequence()
do
if(src.stop)
src.stop = 0
// Destroys the cyborg
if(href_list["detonate"])
var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["detonate"])
if(!target || !istype(target))
return
src.timeleft--
sleep(10)
while(src.timeleft)
if(user.isMobAI() && (target.connected_ai != user))
user << "Access Denied. This robot is not linked to you."
return
// Cyborgs may blow up themselves via the console
if(isrobot(user) && user != target)
user << "Access Denied."
return
var/choice = input("Really detonate [target.name]?") in list ("Yes", "No")
if(choice != "Yes")
return
if(!target || !istype(target))
return
// Antagonistic cyborgs? Left here for downstream
if(target.mind && target.mind.special_role && target.emagged)
target << "Extreme danger. Termination codes detected. Scrambling security codes and automatic AI unlink triggered."
target.ResetSecurityCodes()
else
message_admins("\blue [key_name_admin(usr)] detonated [target.name]!")
log_game("\blue [key_name_admin(usr)] detonated [target.name]!")
target << "<span class='danger'>Self-destruct command received.</span>"
spawn(10)
target.self_destruct()
// Locks or unlocks the cyborg
else if (href_list["lockdown"])
var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["lockdown"])
if(!target || !istype(target))
return
if(user.isMobAI() && (target.connected_ai != user))
user << "Access Denied. This robot is not linked to you."
return
if(isrobot(user))
user << "Access Denied."
return
var/choice = input("Really [target.lockcharge ? "unlock" : "lockdown"] [target.name] ?") in list ("Yes", "No")
if(choice != "Yes")
return
if(!target || !istype(target))
return
message_admins("\blue [key_name_admin(usr)] [target.canmove ? "locked down" : "released"] [target.name]!")
log_game("[key_name(usr)] [target.canmove ? "locked down" : "released"] [target.name]!")
target.canmove = !target.canmove
if (target.lockcharge)
target.lockcharge = !target.lockcharge
target << "Your lockdown has been lifted!"
else
target.lockcharge = !target.lockcharge
target << "You have been locked down!"
// Remotely hacks the cyborg. Only antag AIs can do this and only to linked cyborgs.
else if (href_list["hack"])
var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["hack"])
if(!target || !istype(target))
return
// Antag AI checks
if(!istype(user, /mob/living/silicon/ai) || !(user.mind.special_role && user.mind.original == user))
user << "Access Denied"
return
if(target.emagged)
user << "Robot is already hacked."
return
var/choice = input("Really hack [target.name]? This cannot be undone.") in list("Yes", "No")
if(choice != "Yes")
return
if(!target || !istype(target))
return
message_admins("\blue [key_name_admin(usr)] emagged [target.name] using robotic console!")
log_game("[key_name(usr)] emagged [target.name] using robotic console!")
target.emagged = 1
target << "<span class='notice'>Failsafe protocols overriden. New tools available.</span>"
// Arms the emergency self-destruct system
else if(href_list["arm"])
if(istype(user, /mob/living/silicon))
user << "Access Denied"
return
safety = !safety
user << "You [safety ? "disarm" : "arm"] the emergency self destruct"
// Destroys all accessible cyborgs if safety is disabled
else if(href_list["nuke"])
if(istype(user, /mob/living/silicon))
user << "Access Denied"
return
if(safety)
user << "Self-destruct aborted - safety active"
return
message_admins("\blue [key_name_admin(usr)] detonated all cyborgs!")
log_game("[key_name(usr)] detonated all cyborgs!")
for(var/mob/living/silicon/robot/R in mob_list)
if(istype(R, /mob/living/silicon/robot/drone))
continue
// Ignore antagonistic cyborgs
if(R.scrambledcodes)
continue
R << "<span class='danger'>Self-destruct command received.</span>"
spawn(10)
R.self_destruct()
// Proc: get_cyborgs()
// Parameters: 1 (operator - mob which is operating the console.)
// Description: Returns NanoUI-friendly list of accessible cyborgs.
/obj/machinery/computer/robotics/proc/get_cyborgs(var/mob/operator)
var/list/robots = list()
for(var/mob/living/silicon/robot/R in mob_list)
if(!R.scrambledcodes && !istype(R, /mob/living/silicon/robot/drone))
R.self_destruct()
// Ignore drones
if(istype(R, /mob/living/silicon/robot/drone))
continue
// Ignore antagonistic cyborgs
if(R.scrambledcodes)
continue
return
var/list/robot = list()
robot["name"] = R.name
if(R.stat)
robot["status"] = "Not Responding"
else if (!R.canmove)
robot["status"] = "Lockdown"
else
robot["status"] = "Operational"
if(R.cell)
robot["cell"] = 1
robot["cell_capacity"] = R.cell.maxcharge
robot["cell_current"] = R.cell.charge
robot["cell_percentage"] = round(R.cell.percent())
else
robot["cell"] = 0
robot["module"] = R.module ? R.module.name : "None"
robot["master_ai"] = R.connected_ai ? R.connected_ai.name : "None"
robot["hackable"] = 0
// Antag AIs know whether linked cyborgs are hacked or not.
if(operator && istype(operator, /mob/living/silicon/ai) && (R.connected_ai == operator) && (operator.mind.special_role && operator.mind.original == operator))
robot["hacked"] = R.emagged ? 1 : 0
robot["hackable"] = R.emagged? 0 : 1
robots.Add(list(robot))
return robots
// Proc: get_cyborg_by_name()
// Parameters: 1 (name - Cyborg we are trying to find)
// Description: Helper proc for finding cyborg by name
/obj/machinery/computer/robotics/proc/get_cyborg_by_name(var/name)
if (!name)
return
for(var/mob/living/silicon/robot/R in mob_list)
if(R.name == name)
return R
@@ -7,7 +7,7 @@
icon = 'icons/obj/module.dmi'
icon_state = "id_mod"
item_state = "electronic"
origin_tech = "programming=2"
origin_tech = list(TECH_DATA = 2)
var/id = null
var/frequency = null
var/build_path = null
@@ -93,7 +93,7 @@
if(do_after(user, 20))
if(!src || !WT.isOn()) return
user << "\blue You deconstruct the frame."
new /obj/item/stack/sheet/metal( src.loc, 5 )
new /obj/item/stack/material/steel( src.loc, 5 )
qdel(src)
if(1)
if(istype(P, /obj/item/weapon/wrench))
@@ -178,7 +178,7 @@
if(istype(P, /obj/item/weapon/crowbar)) // complicated check
remove_peripheral()
if(istype(P, /obj/item/stack/sheet/glass))
if(istype(P, /obj/item/stack/material/glass))
if(P:amount >= 2)
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, 20))
@@ -193,7 +193,7 @@
user << "\blue You remove the glass panel."
src.state = 3
src.icon_state = "3"
new /obj/item/stack/sheet/glass( src.loc, 2 )
new /obj/item/stack/material/glass( src.loc, 2 )
if(istype(P, /obj/item/weapon/screwdriver))
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
user << "\blue You connect the monitor."
@@ -17,7 +17,6 @@
w_class = 2.0
var/emagged = 0
crit_fail = 0
// the computer that this device is attached to
var/obj/machinery/computer3/computer
@@ -309,7 +309,6 @@
proc/set_broken()
icon_state = "computer_b"
stat |= BROKEN
crit_fail = 1
if(program)
program.error = BUSTED_ASS_COMPUTER
if(os)
+3 -3
View File
@@ -25,7 +25,7 @@
// If you overwrite this function, use the return value to make sure it succeeded
//
proc/copy(var/obj/item/part/computer/storage/dest)
if(!computer || computer.crit_fail) return null
if(!computer) return null
if(drm)
if(!computer.emagged)
return null
@@ -39,7 +39,7 @@
// Returns null on failure even though the existing file doesn't go away
//
proc/move(var/obj/item/part/computer/storage/dest)
if(!computer || computer.crit_fail) return null
if(!computer) return null
if(drm)
if(!computer.emagged)
return null
@@ -55,7 +55,7 @@
//
proc/edit()
if(!computer || computer.crit_fail)
if(!computer)
return 0
if(readonly && !computer.emagged)
return 0 //
+1 -1
View File
@@ -35,7 +35,7 @@
// Add a file to the hard drive, returns 0 if failed
// forced is used when spawning files on a write-protect drive
proc/addfile(var/datum/file/F,var/forced = 0)
if(!F || crit_fail || (F in files))
if(!F || (F in files))
return 1
if(writeprotect && !forced)
return 0
+1 -4
View File
@@ -27,9 +27,6 @@
/obj/machinery/constructable_frame/machine_frame
attackby(obj/item/P as obj, mob/user as mob)
if(P.crit_fail)
user << "\red This part is faulty, you cannot add this to the machine!"
return
switch(state)
if(1)
if(istype(P, /obj/item/stack/cable_coil))
@@ -48,7 +45,7 @@
if(istype(P, /obj/item/weapon/wrench))
playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
user << "\blue You dismantle the frame"
new /obj/item/stack/sheet/metal(src.loc, 5)
new /obj/item/stack/material/steel(src.loc, 5)
qdel(src)
if(2)
if(istype(P, /obj/item/weapon/circuitboard))
+2 -2
View File
@@ -131,12 +131,12 @@
/obj/item/weapon/circuitboard/cryopodcontrol
name = "Circuit board (Cryogenic Oversight Console)"
build_path = "/obj/machinery/computer/cryopod"
origin_tech = "programming=3"
origin_tech = list(TECH_DATA = 3)
/obj/item/weapon/circuitboard/robotstoragecontrol
name = "Circuit board (Robotic Storage Console)"
build_path = "/obj/machinery/computer/cryopod/robot"
origin_tech = "programming=3"
origin_tech = list(TECH_DATA = 3)
//Decorative structures to go alongside cryopods.
/obj/structure/cryofeed
+83 -71
View File
@@ -53,89 +53,101 @@ for reference:
*/
//Barricades, maybe there will be a metal one later...
/obj/structure/barricade/wooden
name = "wooden barricade"
desc = "This space is blocked off by a wooden barricade."
//Barricades!
/obj/structure/barricade
name = "barricade"
desc = "This space is blocked off by a barricade."
icon = 'icons/obj/structures.dmi'
icon_state = "woodenbarricade"
icon_state = "barricade"
anchored = 1.0
density = 1.0
var/health = 100.0
var/maxhealth = 100.0
var/health = 100
var/maxhealth = 100
var/material/material
attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, /obj/item/stack/sheet/wood))
var/obj/item/stack/sheet/wood/D = W
if (health < maxhealth)
if (D.get_amount() < 1)
user << "<span class='warning'>You need one plank of wood to repair \the [src].</span>"
return
visible_message("<span class='notice'>[user] begins to repair \the [src].</span>")
if(do_after(user,20) && health < maxhealth)
if (D.use(1))
health = maxhealth
visible_message("<span class='notice'>[user] repairs \the [src].</span>")
return
return
else
switch(W.damtype)
if("fire")
src.health -= W.force * 1
if("brute")
src.health -= W.force * 0.75
else
if (src.health <= 0)
visible_message("\red <B>The barricade is smashed apart!</B>")
new /obj/item/stack/sheet/wood(get_turf(src))
new /obj/item/stack/sheet/wood(get_turf(src))
new /obj/item/stack/sheet/wood(get_turf(src))
qdel(src)
..()
ex_act(severity)
switch(severity)
if(1.0)
visible_message("\red <B>The barricade is blown apart!</B>")
qdel(src)
return
if(2.0)
src.health -= 25
if (src.health <= 0)
visible_message("\red <B>The barricade is blown apart!</B>")
new /obj/item/stack/sheet/wood(get_turf(src))
new /obj/item/stack/sheet/wood(get_turf(src))
new /obj/item/stack/sheet/wood(get_turf(src))
qdel(src)
return
meteorhit()
visible_message("\red <B>The barricade is smashed apart!</B>")
new /obj/item/stack/sheet/wood(get_turf(src))
new /obj/item/stack/sheet/wood(get_turf(src))
new /obj/item/stack/sheet/wood(get_turf(src))
/obj/structure/barricade/New(var/newloc, var/material_name)
..(newloc)
if(!material_name)
material_name = "wood"
material = get_material_by_name("[material_name]")
if(!material)
qdel(src)
return
name = "[material.display_name] barricade"
desc = "This space is blocked off by a barricade made of [material.display_name]."
color = material.icon_colour
maxhealth = material.integrity
health = maxhealth
blob_act()
src.health -= 25
if (src.health <= 0)
visible_message("\red <B>The blob eats through the barricade!</B>")
qdel(src)
/obj/structure/barricade/attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, /obj/item/stack/material))
var/obj/item/stack/material/D = W
if(D.material.name != material.name)
user << "<span class='warning'>That is the wrong material needed to repair \the [src].</span>"
return
if (health < maxhealth)
if (D.get_amount() < 1)
user << "<span class='warning'>You need one sheet of [material.display_name] to repair \the [src].</span>"
return
visible_message("<span class='notice'>[user] begins to repair \the [src].</span>")
if(do_after(user,20) && health < maxhealth)
if (D.use(1))
health = maxhealth
visible_message("<span class='notice'>[user] repairs \the [src].</span>")
return
return
else
switch(W.damtype)
if("fire")
src.health -= W.force * 1
if("brute")
src.health -= W.force * 0.75
else
if (src.health <= 0)
visible_message("<span class='danger'>The barricade is smashed apart!</span>")
dismantle()
qdel(src)
return
..()
/obj/structure/barricade/proc/dismantle()
material.place_dismantled_product(get_turf(src))
qdel(src)
return
CanPass(atom/movable/mover, turf/target, height=0, air_group=0)//So bullets will fly over and stuff.
if(air_group || (height==0))
return 1
if(istype(mover) && mover.checkpass(PASSTABLE))
return 1
else
return 0
/obj/structure/barricade/ex_act(severity)
switch(severity)
if(1.0)
visible_message("<span class='danger'>\The [src] is blown apart!</span>")
qdel(src)
return
if(2.0)
src.health -= 25
if (src.health <= 0)
visible_message("<span class='danger'>\The [src] is blown apart!</span>")
dismantle()
return
/obj/structure/barricade/meteorhit()
visible_message("<span class='danger'>\The [src] is smashed apart!</span>")
dismantle()
return
/obj/structure/barricade/blob_act()
src.health -= 25
if (src.health <= 0)
visible_message("<span class='danger'>The blob eats through \the [src]!</span>")
qdel(src)
return
/obj/structure/barricade/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)//So bullets will fly over and stuff.
if(air_group || (height==0))
return 1
if(istype(mover) && mover.checkpass(PASSTABLE))
return 1
else
return 0
//Actual Deployable machinery stuff
/obj/machinery/deployable
name = "deployable"
desc = "deployable"
+13 -6
View File
@@ -30,6 +30,9 @@
var/hasShocked = 0 //Prevents multiple shocks from happening
var/secured_wires = 0
var/datum/wires/airlock/wires = null
var/open_sound_powered = 'sound/machines/airlock.ogg'
var/open_sound_unpowered = 'sound/machines/airlock_creaking.ogg'
/obj/machinery/door/airlock/attack_generic(var/mob/user, var/damage)
if(stat & (BROKEN|NOPOWER))
@@ -79,6 +82,7 @@
name = "Glass Airlock"
icon = 'icons/obj/doors/Doorglass.dmi'
hitsound = 'sound/effects/Glasshit.ogg'
open_sound_powered = 'sound/machines/windowdoor.ogg'
maxhealth = 300
explosion_resistance = 5
opacity = 0
@@ -805,18 +809,18 @@ About the new airlock wires panel:
else
spawn(0) close(1)
else if(istype(C, /obj/item/weapon/twohanded/fireaxe) && !arePowerSystemsOn())
else if(istype(C, /obj/item/weapon/material/twohanded/fireaxe) && !arePowerSystemsOn())
if(locked)
user << "\blue The airlock's bolts prevent it from being forced."
else if( !welded && !operating )
if(density)
var/obj/item/weapon/twohanded/fireaxe/F = C
var/obj/item/weapon/material/twohanded/fireaxe/F = C
if(F.wielded)
spawn(0) open(1)
else
user << "\red You need to be wielding \the [C] to do that."
else
var/obj/item/weapon/twohanded/fireaxe/F = C
var/obj/item/weapon/material/twohanded/fireaxe/F = C
if(F.wielded)
spawn(0) close(1)
else
@@ -851,10 +855,13 @@ About the new airlock wires panel:
if(!can_open(forced))
return 0
use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people
if(istype(src, /obj/machinery/door/airlock/glass))
playsound(src.loc, 'sound/machines/windowdoor.ogg', 100, 1)
//if the door is unpowered then it doesn't make sense to hear the woosh of a pneumatic actuator
if(arePowerSystemsOn())
playsound(src.loc, open_sound_powered, 100, 1)
else
playsound(src.loc, 'sound/machines/airlock.ogg', 30, 1)
playsound(src.loc, open_sound_unpowered, 100, 1)
if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density)
src.closeOther.close()
return ..()
@@ -114,5 +114,5 @@
/obj/item/weapon/airlock_electronics/secure
name = "secure airlock electronics"
desc = "designed to be somewhat more resistant to hacking than standard electronics."
origin_tech = "programming=2"
origin_tech = list(TECH_DATA = 2)
secure = 1
+3 -3
View File
@@ -90,18 +90,18 @@
// This only works on broken doors or doors without power. Also allows repair with Plasteel.
/obj/machinery/door/blast/attackby(obj/item/weapon/C as obj, mob/user as mob)
src.add_fingerprint(user)
if(istype(C, /obj/item/weapon/crowbar) || (istype(C, /obj/item/weapon/twohanded/fireaxe) && C:wielded == 1))
if(istype(C, /obj/item/weapon/crowbar) || (istype(C, /obj/item/weapon/material/twohanded/fireaxe) && C:wielded == 1))
if(((stat & NOPOWER) || (stat & BROKEN)) && !( src.operating ))
force_toggle()
else
usr << "<span class='notice'>[src]'s motors resist your effort.</span>"
return
if(istype(C, /obj/item/stack/sheet/plasteel))
if(istype(C, /obj/item/stack/material/plasteel))
var/amt = repair_price()
if(!amt)
usr << "<span class='notice'>\The [src] is already fully repaired.</span>"
return
var/obj/item/stack/sheet/plasteel/P = C
var/obj/item/stack/material/plasteel/P = C
if(P.amount < amt)
usr << "<span class='warning'>You don't have enough sheets to repair this! You need at least [amt] sheets.</span>"
return
+6 -4
View File
@@ -26,7 +26,7 @@
var/destroy_hits = 10 //How many strong hits it takes to destroy the door
var/min_force = 10 //minimum amount of force needed to damage the door with a melee weapon
var/hitsound = 'sound/weapons/smash.ogg' //sound door makes when hit with a weapon
var/obj/item/stack/sheet/metal/repairing
var/obj/item/stack/material/steel/repairing
var/block_air_zones = 1 //If set, air zones cannot merge across the door even when it is opened.
var/close_door_at = 0 //When to automatically close the door, if possible
@@ -43,6 +43,7 @@
take_damage(damage)
else
visible_message("<span class='notice'>\The [user] bonks \the [src] harmlessly.</span>")
user.do_attack_animation(src)
/obj/machinery/door/New()
. = ..()
@@ -163,7 +164,7 @@
visible_message("\red <B>\The [src.name] disintegrates!</B>")
switch (Proj.damage_type)
if(BRUTE)
new /obj/item/stack/sheet/metal(src.loc, 2)
new /obj/item/stack/material/steel(src.loc, 2)
PoolOrNew(/obj/item/stack/rods, list(src.loc, 3))
if(BURN)
new /obj/effect/decal/cleanable/ash(src.loc) // Turn it to ashes!
@@ -205,7 +206,7 @@
if(src.operating > 0 || isrobot(user)) return //borgs can't attack doors open because it conflicts with their AI-like interaction with them.
src.add_fingerprint(user)
if(istype(I, /obj/item/stack/sheet/metal))
if(istype(I, /obj/item/stack/material/steel))
if(stat & BROKEN)
user << "<span class='notice'>It looks like \the [src] is pretty busted. It's going to need more than just patching up now.</span>"
return
@@ -220,7 +221,7 @@
var/amount_needed = (maxhealth - health) / DOOR_REPAIR_AMOUNT
amount_needed = (round(amount_needed) == amount_needed)? amount_needed : round(amount_needed) + 1 //Why does BYOND not have a ceiling proc?
var/obj/item/stack/sheet/metal/metalstack = I
var/obj/item/stack/material/steel/metalstack = I
var/transfer
if (repairing)
transfer = metalstack.transfer_to(repairing, amount_needed - repairing.amount)
@@ -264,6 +265,7 @@
if(src.density && istype(I, /obj/item/weapon) && user.a_intent == I_HURT && !istype(I, /obj/item/weapon/card))
var/obj/item/weapon/W = I
if(W.damtype == BRUTE || W.damtype == BURN)
user.do_attack_animation(src)
if(W.force < min_force)
user.visible_message("\red <B>\The [user] hits \the [src] with \the [W] with no visible effect.</B>" )
else
+3 -3
View File
@@ -238,7 +238,7 @@
user << "<span class='danger'>\The [src] is welded shut!</span>"
return
if(istype(C, /obj/item/weapon/crowbar) || istype(C,/obj/item/weapon/twohanded/fireaxe))
if(istype(C, /obj/item/weapon/crowbar) || istype(C,/obj/item/weapon/material/twohanded/fireaxe))
if(operating)
return
@@ -248,8 +248,8 @@
"You hear someone struggle and metal straining.")
return
if(istype(C,/obj/item/weapon/twohanded/fireaxe))
var/obj/item/weapon/twohanded/fireaxe/F = C
if(istype(C,/obj/item/weapon/material/twohanded/fireaxe))
var/obj/item/weapon/material/twohanded/fireaxe/F = C
if(!F.wielded)
return
@@ -61,7 +61,7 @@ obj/structure/firedoor_assembly/attackby(C as obj, mob/user as mob)
if(!src || !WT.isOn()) return
user.visible_message("<span class='warning'>[user] has dissassembled \the [src].</span>",
"You have dissassembled \the [src].")
new /obj/item/stack/sheet/metal(src.loc, 2)
new /obj/item/stack/material/steel(src.loc, 2)
qdel(src)
else
user << "<span class='notice'>You need more welding fuel.</span>"
+1 -1
View File
@@ -25,7 +25,7 @@
return
/obj/machinery/door/window/proc/shatter(var/display_message = 1)
new /obj/item/weapon/shard(src.loc)
new /obj/item/weapon/material/shard(src.loc)
var/obj/item/stack/cable_coil/CC = new /obj/item/stack/cable_coil(src.loc)
CC.amount = 2
var/obj/item/weapon/airlock_electronics/ae
+61 -24
View File
@@ -7,28 +7,70 @@
density = 1
var/on = 0
var/obj/item/weapon/cell/high/cell = null
var/use = 5
var/use = 200 // 200W light
var/unlocked = 0
var/open = 0
var/brightness_on = 8 //can't remember what the maxed out value is
/obj/machinery/floodlight/New()
src.cell = new(src)
cell.maxcharge = 1000
cell.charge = 1000 // 41minutes @ 200W
..()
/obj/machinery/floodlight/proc/updateicon()
/obj/machinery/floodlight/update_icon()
overlays.Cut()
icon_state = "flood[open ? "o" : ""][open && cell ? "b" : ""]0[on]"
/obj/machinery/floodlight/process()
if(!on)
return
if(!cell || (cell.charge < (use * CELLRATE)))
turn_off(1)
return
// If the cell is almost empty rarely "flicker" the light. Aesthetic only.
if((cell.percent() < 10) && prob(5))
set_light(brightness_on/2, brightness_on/4)
spawn(20)
if(on)
set_light(brightness_on, brightness_on/2)
cell.use(use*CELLRATE)
// Returns 0 on failure and 1 on success
/obj/machinery/floodlight/proc/turn_on(var/loud = 0)
if(!cell)
return 0
if(cell.charge < (use * CELLRATE))
return 0
on = 1
set_light(brightness_on, brightness_on / 2)
update_icon()
if(loud)
visible_message("\The [src] turns on.")
return 1
/obj/machinery/floodlight/proc/turn_off(var/loud = 0)
on = 0
set_light(0, 0)
update_icon()
if(loud)
visible_message("\The [src] shuts down.")
/obj/machinery/floodlight/attack_ai(mob/user as mob)
if(istype(user, /mob/living/silicon/robot) && Adjacent(user))
return attack_hand(user)
if(on)
if(cell.charge >= use)
cell.use(use)
else
on = 0
updateicon()
set_light(0)
src.visible_message("<span class='warning'>[src] shuts down due to lack of power!</span>")
return
turn_off(1)
else
if(!turn_on(1))
user << "You try to turn on \the [src] but it does not work."
/obj/machinery/floodlight/attack_hand(mob/user as mob)
if(open && cell)
@@ -40,27 +82,22 @@
cell.loc = loc
cell.add_fingerprint(user)
cell.updateicon()
cell.update_icon()
src.cell = null
on = 0
set_light(0)
user << "You remove the power cell"
updateicon()
update_icon()
return
if(on)
on = 0
user << "\blue You turn off the light"
set_light(0)
turn_off(1)
else
if(!cell)
return
if(cell.charge <= 0)
return
on = 1
user << "\blue You turn on the light"
set_light(brightness_on)
if(!turn_on(1))
user << "You try to turn on \the [src] but it does not work."
updateicon()
update_icon()
/obj/machinery/floodlight/attackby(obj/item/weapon/W as obj, mob/user as mob)
@@ -93,4 +130,4 @@
W.loc = src
cell = W
user << "You insert the power cell."
updateicon()
update_icon()
+6
View File
@@ -113,6 +113,12 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
master.show_message(rendered, 2)
return
/obj/machinery/hologram/holopad/show_message(msg, type, alt, alt_type)
for(var/mob/living/silicon/ai/master in masters)
var/rendered = "<i><span class='game say'>Holopad received, <span class='message'>[msg]</span></span></i>"
master.show_message(rendered, type)
return
/obj/machinery/hologram/holopad/proc/create_holo(mob/living/silicon/ai/A, turf/T = loc)
var/obj/effect/overlay/hologram = new(T)//Spawn a blank effect at the location.
hologram.icon = A.holo_icon
+11 -6
View File
@@ -106,7 +106,7 @@
if(NOCLONE in T.mutations)
return
if(T.species && T.species.flags & NO_BLOOD)
if(T.species.flags & NO_BLOOD)
return
// If the human is losing too much blood, beep.
@@ -137,7 +137,7 @@
set src in view(1)
if(!istype(usr, /mob/living))
usr << "\red You can't do that."
usr << "<span class='warning'>You can't do that.</span>"
return
if(usr.stat)
@@ -154,10 +154,15 @@
if(beaker)
if(beaker.reagents && beaker.reagents.reagent_list.len)
usr << "\blue Attached is \a [beaker] with [beaker.reagents.total_volume] units of liquid."
usr << "<span class='notice'>Attached is \a [beaker] with [beaker.reagents.total_volume] units of liquid.</span>"
else
usr << "\blue Attached is an empty [beaker]."
usr << "<span class='notice'>Attached is an empty [beaker].</span>"
else
usr << "\blue No chemicals are attached."
usr << "<span class='notice'>No chemicals are attached.</span>"
usr << "\blue [attached ? attached : "No one"] is attached."
usr << "<span class='notice'>[attached ? attached : "No one"] is attached.</span>"
/obj/machinery/iv_drip/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(height && istype(mover) && mover.checkpass(PASSTABLE)) //allow bullets, beams, thrown objects, mice, drones, and the like through.
return 1
return ..()
+1 -1
View File
@@ -204,7 +204,7 @@
item_quants[O.name]++
else
item_quants[O.name] = 1
user.visible_message("<span class='notice'>[user] has added \the [O] to \the [src].", "<span class='notice'>You add \the [O] to \the [src].")
user.visible_message("<span class='notice'>[user] has added \the [O] to \the [src].</span>", "<span class='notice'>You add \the [O] to \the [src].</span>")
nanomanager.update_uis(src)
-2
View File
@@ -328,8 +328,6 @@ Class Procs:
M.state = 2
M.icon_state = "box_1"
for(var/obj/I in component_parts)
if(I.reliability != 100 && crit_fail)
I.crit_fail = 1
I.loc = loc
qdel(src)
return 1
+12 -5
View File
@@ -423,9 +423,16 @@ obj/machinery/nuclearbomb/proc/nukehack_win(mob/user as mob)
return
return
/obj/item/weapon/disk/nuclear/Destroy()
if(blobstart.len > 0)
var/obj/D = new /obj/item/weapon/disk/nuclear(pick(blobstart))
message_admins("[src] has been destroyed. Spawning [D] at ([D.x], [D.y], [D.z]).")
log_game("[src] has been destroyed. Spawning [D] at ([D.x], [D.y], [D.z]).")
/obj/item/weapon/disk/nuclear/New()
..()
nuke_disks |= src
/obj/item/weapon/disk/nuclear/Destroy()
if(!nuke_disks.len && blobstart.len > 0)
var/obj/D = new /obj/item/weapon/disk/nuclear(pick(blobstart))
message_admins("[src], the last authentication disk, has been destroyed. Spawning [D] at ([D.x], [D.y], [D.z]).")
log_game("[src], the last authentication disk, has been destroyed. Spawning [D] at ([D.x], [D.y], [D.z]).")
..()
/obj/item/weapon/disk/nuclear/touch_map_edge()
qdel(src)
+3 -3
View File
@@ -50,7 +50,7 @@
user.visible_message("<span class='notice'>[user] has [!a_dis?"de":""]activated auto-dismantling.</span>", "<span class='notice'>You [!a_dis?"de":""]activate auto-dismantling.</span>")
return
if(istype(W, /obj/item/stack/sheet/metal))
if(istype(W, /obj/item/stack/material/steel))
var/result = load_metal(W)
if(isnull(result))
@@ -70,7 +70,7 @@
m = round(m)
if(m)
use_metal(m)
var/obj/item/stack/sheet/metal/MM = new (get_turf(src))
var/obj/item/stack/material/steel/MM = new (get_turf(src))
MM.amount = m
user.visible_message("<span class='notice'>[user] removes [m] sheet\s of metal from the \the [src].</span>", "<span class='notice'>You remove [m] sheet\s of metal from \the [src]</span>")
else
@@ -86,7 +86,7 @@
on=0
return
/obj/machinery/pipelayer/proc/load_metal(var/obj/item/stack/sheet/metal/MM)
/obj/machinery/pipelayer/proc/load_metal(var/obj/item/stack/material/steel/MM)
if(istype(MM) && MM.get_amount())
var/cur_amount = metal
var/to_load = max(max_metal - round(cur_amount),0)
+14 -8
View File
@@ -21,6 +21,8 @@
var/raised = 0 //if the turret cover is "open" and the turret is raised
var/raising= 0 //if the turret is currently opening or closing its cover
var/health = 80 //the turret's health
var/maxhealth = 80 //turrets maximal health.
var/auto_repair = 0 //if 1 the turret slowly repairs itself.
var/locked = 1 //if the turret's behaviour control access is locked
var/controllock = 0 //if the turret responds to control panels
@@ -267,7 +269,7 @@
Gun.power_supply.charge = gun_charge
Gun.update_icon()
if(prob(50))
new /obj/item/stack/sheet/metal(loc, rand(1,4))
new /obj/item/stack/material/steel(loc, rand(1,4))
if(prob(50))
new /obj/item/device/assembly/prox_sensor(loc)
else
@@ -450,6 +452,10 @@
spawn()
popDown() // no valid targets, close the cover
if(auto_repair && (health < maxhealth))
use_power(20000)
health = min(health+1, maxhealth) // 1HP for 20kJ
/obj/machinery/porta_turret/proc/assess_and_assign(var/mob/living/L, var/list/targets, var/list/secondarytargets)
switch(assess_living(L))
if(TURRET_PRIORITY_TARGET)
@@ -671,13 +677,13 @@
else if(istype(I, /obj/item/weapon/crowbar) && !anchored)
playsound(loc, 'sound/items/Crowbar.ogg', 75, 1)
user << "<span class='notice'>You dismantle the turret construction.</span>"
new /obj/item/stack/sheet/metal( loc, 5)
new /obj/item/stack/material/steel( loc, 5)
qdel(src) // qdel
return
if(1)
if(istype(I, /obj/item/stack/sheet/metal))
var/obj/item/stack/sheet/metal/M = I
if(istype(I, /obj/item/stack/material/steel))
var/obj/item/stack/material/steel/M = I
if(M.use(2))
user << "<span class='notice'>You add some metal armor to the interior frame.</span>"
build_step = 2
@@ -714,7 +720,7 @@
if(!src || !WT.remove_fuel(5, user)) return
build_step = 1
user << "You remove the turret's interior metal armor."
new /obj/item/stack/sheet/metal( loc, 2)
new /obj/item/stack/material/steel( loc, 2)
return
@@ -768,8 +774,8 @@
//attack_hand() removes the prox sensor
if(6)
if(istype(I, /obj/item/stack/sheet/metal))
var/obj/item/stack/sheet/metal/M = I
if(istype(I, /obj/item/stack/material/steel))
var/obj/item/stack/material/steel/M = I
if(M.use(2))
user << "<span class='notice'>You add some metal armor to the exterior frame.</span>"
build_step = 7
@@ -813,7 +819,7 @@
else if(istype(I, /obj/item/weapon/crowbar))
playsound(loc, 'sound/items/Crowbar.ogg', 75, 1)
user << "<span class='notice'>You pry off the turret's exterior armor.</span>"
new /obj/item/stack/sheet/metal(loc, 2)
new /obj/item/stack/material/steel(loc, 2)
build_step = 6
return
+38 -22
View File
@@ -169,14 +169,18 @@
return
if(!R.cell.fully_charged())
var/diff = min(R.cell.maxcharge - R.cell.charge, charge_rate) // Capped at charge_rate charge / tick
if (cell.use(diff))
if (cell.charge >= diff)
cell.use(diff)
R.cell.give(diff)
if(weld_rate && R.getBruteLoss())
R.adjustBruteLoss(-1)
if(wire_rate && R.getFireLoss())
R.adjustFireLoss(-1)
else
update_use_power(1)
else if(istype(occupant, /mob/living/carbon/human))
var/mob/living/carbon/human/H = occupant
if(!isnull(H.internal_organs_by_name["cell"]) && H.nutrition < 450)
H.nutrition = min(H.nutrition+10, 450)
update_use_power(1)
/obj/machinery/recharge_station/proc/go_out()
if(!(occupant))
@@ -208,30 +212,42 @@
if(!user)
return
if(!(istype(user, /mob/living/silicon/robot)))
var/can_accept_user
if(istype(user, /mob/living/silicon/robot))
var/mob/living/silicon/robot/R = user
if(R.stat == 2)
//Whoever had it so that a borg with a dead cell can't enter this thing should be shot. --NEO
return
if(occupant)
R << "<span class='notice'>The cell is already occupied!</span>"
return
if(!R.cell)
R << "<span class='notice'>Without a powercell, you can't be recharged.</span>"
//Make sure they actually HAVE a cell, now that they can get in while powerless. --NEO
return
can_accept_user = 1
else if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/H = user
if(!isnull(H.internal_organs_by_name["cell"]))
can_accept_user = 1
if(!can_accept_user)
user << "<span class='notice'>Only non-organics may enter the recharger!</span>"
return
var/mob/living/silicon/robot/R = user
if(R.stat == 2)
//Whoever had it so that a borg with a dead cell can't enter this thing should be shot. --NEO
return
if(occupant)
R << "<span class='notice'>The cell is already occupied!</span>"
return
if(!R.cell)
R << "<span class='notice'>Without a powercell, you can't be recharged.</span>"
//Make sure they actually HAVE a cell, now that they can get in while powerless. --NEO
return
R.stop_pulling()
if(R.client)
R.client.perspective = EYE_PERSPECTIVE
R.client.eye = src
R.loc = src
occupant = R
user.stop_pulling()
if(user.client)
user.client.perspective = EYE_PERSPECTIVE
user.client.eye = src
user.loc = src
occupant = user
/*for(var/obj/O in src)
O.loc = loc*/
add_fingerprint(R)
add_fingerprint(user)
build_icon()
update_use_power(1)
return
+2 -2
View File
@@ -12,8 +12,8 @@
active_power_usage = 10000
/obj/machinery/robotic_fabricator/attackby(var/obj/item/O as obj, var/mob/user as mob)
if (istype(O, /obj/item/stack/sheet/metal))
var/obj/item/stack/sheet/metal/M = O
if (istype(O, /obj/item/stack/material/steel))
var/obj/item/stack/material/steel/M = O
if (src.metal_amount < 150000.0)
var/count = 0
src.overlays += "fab-load-metal"
+1 -1
View File
@@ -121,7 +121,7 @@
if("cellremove")
if(panel_open && cell && !usr.get_active_hand())
usr.visible_message("\blue [usr] removes \the [cell] from \the [src].", "\blue You remove \the [cell] from \the [src].")
cell.updateicon()
cell.update_icon()
usr.put_in_hands(cell)
cell.add_fingerprint(usr)
cell = null
+1 -1
View File
@@ -192,7 +192,7 @@
if (src.stat & BROKEN)
user << "\blue The broken glass falls out."
var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
new /obj/item/weapon/shard( src.loc )
new /obj/item/weapon/material/shard( src.loc )
var/obj/item/weapon/circuitboard/comm_server/M = new /obj/item/weapon/circuitboard/comm_server( A )
for (var/obj/C in src)
C.loc = src.loc
+1 -1
View File
@@ -130,7 +130,7 @@
if (src.stat & BROKEN)
user << "\blue The broken glass falls out."
var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
new /obj/item/weapon/shard( src.loc )
new /obj/item/weapon/material/shard( src.loc )
var/obj/item/weapon/circuitboard/comm_monitor/M = new /obj/item/weapon/circuitboard/comm_monitor( A )
for (var/obj/C in src)
C.loc = src.loc
@@ -213,7 +213,7 @@
if (src.stat & BROKEN)
user << "\blue The broken glass falls out."
var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
new /obj/item/weapon/shard( src.loc )
new /obj/item/weapon/material/shard( src.loc )
var/obj/item/weapon/circuitboard/comm_traffic/M = new /obj/item/weapon/circuitboard/comm_traffic( A )
for (var/obj/C in src)
C.loc = src.loc

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