mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-20 19:44:46 +01:00
Merge remote-tracking branch 'upstream/dev' into chem-kinetics
Conflicts: code/modules/reagents/Chemistry-Recipes.dm
This commit is contained in:
+39
-13
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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))
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
/*
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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(!..())
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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!"
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
),
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -161,4 +161,7 @@
|
||||
if(istype(W, /obj/item/weapon/pickaxe))
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
..()
|
||||
|
||||
/obj/effect/meteor/touch_map_edge()
|
||||
qdel(src)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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>"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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>"
|
||||
|
||||
@@ -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
|
||||
|
||||
..()
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
..()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 //
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user