mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 18:22:39 +00:00
Merge remote-tracking branch 'upstream/master' into dev
Conflicts: code/ZAS/Turf.dm code/modules/mob/living/carbon/carbon.dm code/modules/mob/living/living.dm code/modules/recycling/sortingmachinery.dm
This commit is contained in:
@@ -1115,6 +1115,7 @@
|
||||
#include "code\modules\mob\living\carbon\carbon_defines.dm"
|
||||
#include "code\modules\mob\living\carbon\carbon_powers.dm"
|
||||
#include "code\modules\mob\living\carbon\give.dm"
|
||||
#include "code\modules\mob\living\carbon\resist.dm"
|
||||
#include "code\modules\mob\living\carbon\shock.dm"
|
||||
#include "code\modules\mob\living\carbon\viruses.dm"
|
||||
#include "code\modules\mob\living\carbon\alien\alien.dm"
|
||||
|
||||
@@ -50,7 +50,7 @@ atom/proc/c_airblock(turf/other)
|
||||
#ifdef ZASDBG
|
||||
ASSERT(isturf(other))
|
||||
#endif
|
||||
return !CanPass(null, other, 0, 0) + 2*!CanPass(null, other, 1.5, 1)
|
||||
return (AIR_BLOCKED*!CanPass(null, other, 0, 0))|(ZONE_BLOCKED*!CanPass(null, other, 1.5, 1))
|
||||
|
||||
|
||||
turf/c_airblock(turf/other)
|
||||
|
||||
@@ -154,7 +154,18 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
|
||||
#ifdef ZASDBG
|
||||
var/updated = 0
|
||||
#endif
|
||||
|
||||
//defer updating of self-zone-blocked turfs until after all other turfs have been updated.
|
||||
//this hopefully ensures that non-self-zone-blocked turfs adjacent to self-zone-blocked ones
|
||||
//have valid zones when the self-zone-blocked turfs update.
|
||||
var/list/deferred = list()
|
||||
|
||||
for(var/turf/T in updating)
|
||||
//check if the turf is self-zone-blocked
|
||||
if(T.c_airblock(T) & ZONE_BLOCKED)
|
||||
deferred += T
|
||||
continue
|
||||
|
||||
T.update_air_properties()
|
||||
T.post_update_air_properties()
|
||||
T.needs_air_update = 0
|
||||
@@ -164,6 +175,15 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
|
||||
#endif
|
||||
//sleep(1)
|
||||
|
||||
for(var/turf/T in deferred)
|
||||
T.update_air_properties()
|
||||
T.post_update_air_properties()
|
||||
T.needs_air_update = 0
|
||||
#ifdef ZASDBG
|
||||
T.overlays -= mark
|
||||
updated++
|
||||
#endif
|
||||
|
||||
#ifdef ZASDBG
|
||||
if(updated != updating.len)
|
||||
tick_progress = "[updating.len - updated] tiles left unupdated."
|
||||
@@ -307,7 +327,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
|
||||
|
||||
/datum/controller/air_system/proc/mark_edge_sleeping(connection_edge/E)
|
||||
#ifdef ZASDBG
|
||||
ASSERT(istype(E)
|
||||
ASSERT(istype(E))
|
||||
#endif
|
||||
if(E.sleeping) return
|
||||
active_edges.Remove(E)
|
||||
@@ -315,7 +335,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
|
||||
|
||||
/datum/controller/air_system/proc/mark_edge_active(connection_edge/E)
|
||||
#ifdef ZASDBG
|
||||
ASSERT(istype(E)
|
||||
ASSERT(istype(E))
|
||||
#endif
|
||||
if(!E.sleeping) return
|
||||
active_edges.Add(E)
|
||||
|
||||
514
code/ZAS/Turf.dm
514
code/ZAS/Turf.dm
@@ -1,255 +1,259 @@
|
||||
/turf/simulated/var/zone/zone
|
||||
/turf/simulated/var/open_directions
|
||||
|
||||
/turf/var/needs_air_update = 0
|
||||
/turf/var/datum/gas_mixture/air
|
||||
|
||||
/turf/simulated/proc/update_graphic(list/graphic_add = null, list/graphic_remove = null)
|
||||
if(graphic_add && graphic_add.len)
|
||||
overlays += graphic_add
|
||||
if(graphic_remove && graphic_remove.len)
|
||||
overlays -= graphic_remove
|
||||
|
||||
/turf/proc/update_air_properties()
|
||||
var/block = c_airblock(src)
|
||||
if(block & AIR_BLOCKED)
|
||||
//dbg(blocked)
|
||||
return 1
|
||||
|
||||
#ifdef ZLEVELS
|
||||
for(var/d = 1, d < 64, d *= 2)
|
||||
#else
|
||||
for(var/d = 1, d < 16, d *= 2)
|
||||
#endif
|
||||
|
||||
var/turf/unsim = get_step(src, d)
|
||||
|
||||
if(!unsim)
|
||||
continue
|
||||
|
||||
block = unsim.c_airblock(src)
|
||||
|
||||
if(block & AIR_BLOCKED)
|
||||
//unsim.dbg(air_blocked, turn(180,d))
|
||||
continue
|
||||
|
||||
var/r_block = c_airblock(unsim)
|
||||
|
||||
if(r_block & AIR_BLOCKED)
|
||||
continue
|
||||
|
||||
if(istype(unsim, /turf/simulated))
|
||||
|
||||
var/turf/simulated/sim = unsim
|
||||
if(air_master.has_valid_zone(sim))
|
||||
|
||||
air_master.connect(sim, src)
|
||||
|
||||
/turf/simulated/update_air_properties()
|
||||
if(zone && zone.invalid)
|
||||
c_copy_air()
|
||||
zone = null //Easier than iterating through the list at the zone.
|
||||
|
||||
var/s_block = c_airblock(src)
|
||||
if(s_block & AIR_BLOCKED)
|
||||
#ifdef ZASDBG
|
||||
if(verbose) world << "Self-blocked."
|
||||
//dbg(blocked)
|
||||
#endif
|
||||
if(zone)
|
||||
var/zone/z = zone
|
||||
if(locate(/obj/machinery/door/airlock) in src) //Hacky, but prevents normal airlocks from rebuilding zones all the time
|
||||
z.remove(src)
|
||||
else
|
||||
z.rebuild()
|
||||
|
||||
return 1
|
||||
|
||||
var/previously_open = open_directions
|
||||
open_directions = 0
|
||||
|
||||
var/list/postponed
|
||||
#ifdef ZLEVELS
|
||||
for(var/d = 1, d < 64, d *= 2)
|
||||
#else
|
||||
for(var/d = 1, d < 16, d *= 2)
|
||||
#endif
|
||||
|
||||
var/turf/unsim = get_step(src, d)
|
||||
|
||||
if(!unsim) //edge of map
|
||||
continue
|
||||
|
||||
var/block = unsim.c_airblock(src)
|
||||
if(block & AIR_BLOCKED)
|
||||
|
||||
#ifdef ZASDBG
|
||||
if(verbose) world << "[d] is blocked."
|
||||
//unsim.dbg(air_blocked, turn(180,d))
|
||||
#endif
|
||||
|
||||
continue
|
||||
|
||||
var/r_block = c_airblock(unsim)
|
||||
if(r_block & AIR_BLOCKED)
|
||||
|
||||
#ifdef ZASDBG
|
||||
if(verbose) world << "[d] is blocked."
|
||||
//dbg(air_blocked, d)
|
||||
#endif
|
||||
|
||||
//Check that our zone hasn't been cut off recently.
|
||||
//This happens when windows move or are constructed. We need to rebuild.
|
||||
if((previously_open & d) && istype(unsim, /turf/simulated))
|
||||
var/turf/simulated/sim = unsim
|
||||
if(zone && sim.zone == zone)
|
||||
zone.rebuild()
|
||||
return
|
||||
|
||||
continue
|
||||
|
||||
open_directions |= d
|
||||
|
||||
if(istype(unsim, /turf/simulated))
|
||||
|
||||
var/turf/simulated/sim = unsim
|
||||
sim.open_directions |= reverse_dir[d]
|
||||
|
||||
if(air_master.has_valid_zone(sim))
|
||||
|
||||
//Might have assigned a zone, since this happens for each direction.
|
||||
if(!zone)
|
||||
|
||||
//if((block & ZONE_BLOCKED) || (r_block & ZONE_BLOCKED && !(s_block & ZONE_BLOCKED)))
|
||||
if(((block & ZONE_BLOCKED) && !(r_block & ZONE_BLOCKED)) || (r_block & ZONE_BLOCKED && !(s_block & ZONE_BLOCKED)))
|
||||
#ifdef ZASDBG
|
||||
if(verbose) world << "[d] is zone blocked."
|
||||
//dbg(zone_blocked, d)
|
||||
#endif
|
||||
|
||||
//Postpone this tile rather than exit, since a connection can still be made.
|
||||
if(!postponed) postponed = list()
|
||||
postponed.Add(sim)
|
||||
|
||||
else
|
||||
|
||||
sim.zone.add(src)
|
||||
|
||||
#ifdef ZASDBG
|
||||
dbg(assigned)
|
||||
if(verbose) world << "Added to [zone]"
|
||||
#endif
|
||||
|
||||
else if(sim.zone != zone)
|
||||
|
||||
#ifdef ZASDBG
|
||||
if(verbose) world << "Connecting to [sim.zone]"
|
||||
#endif
|
||||
|
||||
air_master.connect(src, sim)
|
||||
|
||||
|
||||
#ifdef ZASDBG
|
||||
else if(verbose) world << "[d] has same zone."
|
||||
|
||||
else if(verbose) world << "[d] has invalid zone."
|
||||
#endif
|
||||
|
||||
else
|
||||
|
||||
//Postponing connections to tiles until a zone is assured.
|
||||
if(!postponed) postponed = list()
|
||||
postponed.Add(unsim)
|
||||
|
||||
if(!air_master.has_valid_zone(src)) //Still no zone, make a new one.
|
||||
var/zone/newzone = new/zone()
|
||||
newzone.add(src)
|
||||
|
||||
#ifdef ZASDBG
|
||||
dbg(created)
|
||||
|
||||
ASSERT(zone)
|
||||
#endif
|
||||
|
||||
//At this point, a zone should have happened. If it hasn't, don't add more checks, fix the bug.
|
||||
|
||||
for(var/turf/T in postponed)
|
||||
air_master.connect(src, T)
|
||||
|
||||
/turf/proc/post_update_air_properties()
|
||||
if(connections) connections.update_all()
|
||||
|
||||
/turf/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air
|
||||
return 0
|
||||
|
||||
/turf/proc/assume_gas(gasid, moles, temp = 0)
|
||||
return 0
|
||||
|
||||
/turf/return_air()
|
||||
//Create gas mixture to hold data for passing
|
||||
var/datum/gas_mixture/GM = new
|
||||
|
||||
GM.adjust_multi("oxygen", oxygen, "carbon_dioxide", carbon_dioxide, "nitrogen", nitrogen, "phoron", phoron)
|
||||
GM.temperature = temperature
|
||||
|
||||
return GM
|
||||
|
||||
/turf/remove_air(amount as num)
|
||||
var/datum/gas_mixture/GM = new
|
||||
|
||||
var/sum = oxygen + carbon_dioxide + nitrogen + phoron
|
||||
if(sum>0)
|
||||
GM.gas["oxygen"] = (oxygen/sum)*amount
|
||||
GM.gas["carbon_dioxide"] = (carbon_dioxide/sum)*amount
|
||||
GM.gas["nitrogen"] = (nitrogen/sum)*amount
|
||||
GM.gas["phoron"] = (phoron/sum)*amount
|
||||
|
||||
GM.temperature = temperature
|
||||
GM.update_values()
|
||||
|
||||
return GM
|
||||
|
||||
/turf/simulated/assume_air(datum/gas_mixture/giver)
|
||||
var/datum/gas_mixture/my_air = return_air()
|
||||
my_air.merge(giver)
|
||||
|
||||
/turf/simulated/assume_gas(gasid, moles, temp = null)
|
||||
var/datum/gas_mixture/my_air = return_air()
|
||||
|
||||
if(isnull(temp))
|
||||
my_air.adjust_gas(gasid, moles)
|
||||
else
|
||||
my_air.adjust_gas_temp(gasid, moles, temp)
|
||||
|
||||
return 1
|
||||
|
||||
/turf/simulated/remove_air(amount as num)
|
||||
var/datum/gas_mixture/my_air = return_air()
|
||||
return my_air.remove(amount)
|
||||
|
||||
/turf/simulated/return_air()
|
||||
if(zone)
|
||||
if(!zone.invalid)
|
||||
air_master.mark_zone_update(zone)
|
||||
return zone.air
|
||||
else
|
||||
if(!air)
|
||||
make_air()
|
||||
c_copy_air()
|
||||
return air
|
||||
else
|
||||
if(!air)
|
||||
make_air()
|
||||
return air
|
||||
|
||||
/turf/proc/make_air()
|
||||
air = new/datum/gas_mixture
|
||||
air.temperature = temperature
|
||||
air.adjust_multi("oxygen", oxygen, "carbon_dioxide", carbon_dioxide, "nitrogen", nitrogen, "phoron", phoron)
|
||||
air.group_multiplier = 1
|
||||
air.volume = CELL_VOLUME
|
||||
|
||||
/turf/simulated/proc/c_copy_air()
|
||||
if(!air) air = new/datum/gas_mixture
|
||||
air.copy_from(zone.air)
|
||||
air.group_multiplier = 1
|
||||
/turf/simulated/var/zone/zone
|
||||
/turf/simulated/var/open_directions
|
||||
|
||||
/turf/var/needs_air_update = 0
|
||||
/turf/var/datum/gas_mixture/air
|
||||
|
||||
/turf/simulated/proc/update_graphic(list/graphic_add = null, list/graphic_remove = null)
|
||||
if(graphic_add && graphic_add.len)
|
||||
overlays += graphic_add
|
||||
if(graphic_remove && graphic_remove.len)
|
||||
overlays -= graphic_remove
|
||||
|
||||
/turf/proc/update_air_properties()
|
||||
var/block = c_airblock(src)
|
||||
if(block & AIR_BLOCKED)
|
||||
//dbg(blocked)
|
||||
return 1
|
||||
|
||||
#ifdef ZLEVELS
|
||||
for(var/d = 1, d < 64, d *= 2)
|
||||
#else
|
||||
for(var/d = 1, d < 16, d *= 2)
|
||||
#endif
|
||||
|
||||
var/turf/unsim = get_step(src, d)
|
||||
|
||||
if(!unsim)
|
||||
continue
|
||||
|
||||
block = unsim.c_airblock(src)
|
||||
|
||||
if(block & AIR_BLOCKED)
|
||||
//unsim.dbg(air_blocked, turn(180,d))
|
||||
continue
|
||||
|
||||
var/r_block = c_airblock(unsim)
|
||||
|
||||
if(r_block & AIR_BLOCKED)
|
||||
continue
|
||||
|
||||
if(istype(unsim, /turf/simulated))
|
||||
|
||||
var/turf/simulated/sim = unsim
|
||||
if(air_master.has_valid_zone(sim))
|
||||
|
||||
air_master.connect(sim, src)
|
||||
|
||||
/turf/simulated/update_air_properties()
|
||||
|
||||
if(zone && zone.invalid)
|
||||
c_copy_air()
|
||||
zone = null //Easier than iterating through the list at the zone.
|
||||
|
||||
var/s_block = c_airblock(src)
|
||||
if(s_block & AIR_BLOCKED)
|
||||
#ifdef ZASDBG
|
||||
if(verbose) world << "Self-blocked."
|
||||
//dbg(blocked)
|
||||
#endif
|
||||
if(zone)
|
||||
var/zone/z = zone
|
||||
|
||||
if(s_block & ZONE_BLOCKED) //Hacky, but prevents normal airlocks from rebuilding zones all the time
|
||||
z.remove(src)
|
||||
else
|
||||
z.rebuild()
|
||||
|
||||
return 1
|
||||
|
||||
var/previously_open = open_directions
|
||||
open_directions = 0
|
||||
|
||||
var/list/postponed
|
||||
#ifdef ZLEVELS
|
||||
for(var/d = 1, d < 64, d *= 2)
|
||||
#else
|
||||
for(var/d = 1, d < 16, d *= 2)
|
||||
#endif
|
||||
|
||||
var/turf/unsim = get_step(src, d)
|
||||
|
||||
if(!unsim) //edge of map
|
||||
continue
|
||||
|
||||
var/block = unsim.c_airblock(src)
|
||||
if(block & AIR_BLOCKED)
|
||||
|
||||
#ifdef ZASDBG
|
||||
if(verbose) world << "[d] is blocked."
|
||||
//unsim.dbg(air_blocked, turn(180,d))
|
||||
#endif
|
||||
|
||||
continue
|
||||
|
||||
var/r_block = c_airblock(unsim)
|
||||
if(r_block & AIR_BLOCKED)
|
||||
|
||||
#ifdef ZASDBG
|
||||
if(verbose) world << "[d] is blocked."
|
||||
//dbg(air_blocked, d)
|
||||
#endif
|
||||
|
||||
//Check that our zone hasn't been cut off recently.
|
||||
//This happens when windows move or are constructed. We need to rebuild.
|
||||
if((previously_open & d) && istype(unsim, /turf/simulated))
|
||||
var/turf/simulated/sim = unsim
|
||||
if(zone && sim.zone == zone)
|
||||
zone.rebuild()
|
||||
return
|
||||
|
||||
continue
|
||||
|
||||
open_directions |= d
|
||||
|
||||
if(istype(unsim, /turf/simulated))
|
||||
|
||||
var/turf/simulated/sim = unsim
|
||||
sim.open_directions |= reverse_dir[d]
|
||||
|
||||
if(air_master.has_valid_zone(sim))
|
||||
|
||||
//Might have assigned a zone, since this happens for each direction.
|
||||
if(!zone)
|
||||
|
||||
//We do not merge if
|
||||
// they are blocking us and we are not blocking them, or if
|
||||
// we are blocking them and not blocking ourselves - this prevents tiny zones from forming on doorways.
|
||||
if(((block & ZONE_BLOCKED) && !(r_block & ZONE_BLOCKED)) || ((r_block & ZONE_BLOCKED) && !(s_block & ZONE_BLOCKED)))
|
||||
#ifdef ZASDBG
|
||||
if(verbose) world << "[d] is zone blocked."
|
||||
//dbg(zone_blocked, d)
|
||||
#endif
|
||||
|
||||
//Postpone this tile rather than exit, since a connection can still be made.
|
||||
if(!postponed) postponed = list()
|
||||
postponed.Add(sim)
|
||||
|
||||
else
|
||||
|
||||
sim.zone.add(src)
|
||||
|
||||
#ifdef ZASDBG
|
||||
dbg(assigned)
|
||||
if(verbose) world << "Added to [zone]"
|
||||
#endif
|
||||
|
||||
else if(sim.zone != zone)
|
||||
|
||||
#ifdef ZASDBG
|
||||
if(verbose) world << "Connecting to [sim.zone]"
|
||||
#endif
|
||||
|
||||
air_master.connect(src, sim)
|
||||
|
||||
|
||||
#ifdef ZASDBG
|
||||
else if(verbose) world << "[d] has same zone."
|
||||
|
||||
else if(verbose) world << "[d] has invalid zone."
|
||||
#endif
|
||||
|
||||
else
|
||||
|
||||
//Postponing connections to tiles until a zone is assured.
|
||||
if(!postponed) postponed = list()
|
||||
postponed.Add(unsim)
|
||||
|
||||
if(!air_master.has_valid_zone(src)) //Still no zone, make a new one.
|
||||
var/zone/newzone = new/zone()
|
||||
newzone.add(src)
|
||||
|
||||
#ifdef ZASDBG
|
||||
dbg(created)
|
||||
|
||||
ASSERT(zone)
|
||||
#endif
|
||||
|
||||
//At this point, a zone should have happened. If it hasn't, don't add more checks, fix the bug.
|
||||
|
||||
for(var/turf/T in postponed)
|
||||
air_master.connect(src, T)
|
||||
|
||||
/turf/proc/post_update_air_properties()
|
||||
if(connections) connections.update_all()
|
||||
|
||||
/turf/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air
|
||||
return 0
|
||||
|
||||
/turf/proc/assume_gas(gasid, moles, temp = 0)
|
||||
return 0
|
||||
|
||||
/turf/return_air()
|
||||
//Create gas mixture to hold data for passing
|
||||
var/datum/gas_mixture/GM = new
|
||||
|
||||
GM.adjust_multi("oxygen", oxygen, "carbon_dioxide", carbon_dioxide, "nitrogen", nitrogen, "phoron", phoron)
|
||||
GM.temperature = temperature
|
||||
|
||||
return GM
|
||||
|
||||
/turf/remove_air(amount as num)
|
||||
var/datum/gas_mixture/GM = new
|
||||
|
||||
var/sum = oxygen + carbon_dioxide + nitrogen + phoron
|
||||
if(sum>0)
|
||||
GM.gas["oxygen"] = (oxygen/sum)*amount
|
||||
GM.gas["carbon_dioxide"] = (carbon_dioxide/sum)*amount
|
||||
GM.gas["nitrogen"] = (nitrogen/sum)*amount
|
||||
GM.gas["phoron"] = (phoron/sum)*amount
|
||||
|
||||
GM.temperature = temperature
|
||||
GM.update_values()
|
||||
|
||||
return GM
|
||||
|
||||
/turf/simulated/assume_air(datum/gas_mixture/giver)
|
||||
var/datum/gas_mixture/my_air = return_air()
|
||||
my_air.merge(giver)
|
||||
|
||||
/turf/simulated/assume_gas(gasid, moles, temp = null)
|
||||
var/datum/gas_mixture/my_air = return_air()
|
||||
|
||||
if(isnull(temp))
|
||||
my_air.adjust_gas(gasid, moles)
|
||||
else
|
||||
my_air.adjust_gas_temp(gasid, moles, temp)
|
||||
|
||||
return 1
|
||||
|
||||
/turf/simulated/remove_air(amount as num)
|
||||
var/datum/gas_mixture/my_air = return_air()
|
||||
return my_air.remove(amount)
|
||||
|
||||
/turf/simulated/return_air()
|
||||
if(zone)
|
||||
if(!zone.invalid)
|
||||
air_master.mark_zone_update(zone)
|
||||
return zone.air
|
||||
else
|
||||
if(!air)
|
||||
make_air()
|
||||
c_copy_air()
|
||||
return air
|
||||
else
|
||||
if(!air)
|
||||
make_air()
|
||||
return air
|
||||
|
||||
/turf/proc/make_air()
|
||||
air = new/datum/gas_mixture
|
||||
air.temperature = temperature
|
||||
air.adjust_multi("oxygen", oxygen, "carbon_dioxide", carbon_dioxide, "nitrogen", nitrogen, "phoron", phoron)
|
||||
air.group_multiplier = 1
|
||||
air.volume = CELL_VOLUME
|
||||
|
||||
/turf/simulated/proc/c_copy_air()
|
||||
if(!air) air = new/datum/gas_mixture
|
||||
air.copy_from(zone.air)
|
||||
air.group_multiplier = 1
|
||||
|
||||
@@ -111,6 +111,13 @@ Class Procs:
|
||||
#ifdef ZASDBG
|
||||
T.dbg(merged)
|
||||
#endif
|
||||
|
||||
//rebuild the old zone's edges so that the will be possesed by the new zone
|
||||
for(var/connection_edge/E in edges)
|
||||
if(E.contains_zone(into))
|
||||
continue //don't need to rebuild this edge
|
||||
for(var/turf/T in E.connecting_turfs)
|
||||
air_master.mark_for_update(T)
|
||||
|
||||
/zone/proc/c_invalidate()
|
||||
invalid = 1
|
||||
|
||||
@@ -927,30 +927,6 @@ proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,fl
|
||||
refined_trg -= B
|
||||
continue moving
|
||||
|
||||
var/list/doors = new/list()
|
||||
|
||||
if(toupdate.len)
|
||||
for(var/turf/simulated/T1 in toupdate)
|
||||
for(var/obj/machinery/door/D2 in T1)
|
||||
doors += D2
|
||||
/*if(T1.parent)
|
||||
air_master.groups_to_rebuild += T1.parent
|
||||
else
|
||||
air_master.tiles_to_update += T1*/
|
||||
|
||||
if(fromupdate.len)
|
||||
for(var/turf/simulated/T2 in fromupdate)
|
||||
for(var/obj/machinery/door/D2 in T2)
|
||||
doors += D2
|
||||
/*if(T2.parent)
|
||||
air_master.groups_to_rebuild += T2.parent
|
||||
else
|
||||
air_master.tiles_to_update += T2*/
|
||||
|
||||
for(var/obj/O in doors)
|
||||
O:update_nearby_tiles(1)
|
||||
|
||||
|
||||
|
||||
proc/DuplicateObject(obj/original, var/perfectcopy = 0 , var/sameloc = 0)
|
||||
if(!original)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
var/welded = 0
|
||||
var/wall_mounted = 0 //never solid (You can always pass over it)
|
||||
var/health = 100
|
||||
var/lastbang
|
||||
var/breakout = 0 //if someone is currently breaking out. mutex
|
||||
var/storage_capacity = 30 //This is so that someone can't pack hundreds of items in a locker/crate
|
||||
//then open it in a populated area to crash clients.
|
||||
var/open_sound = 'sound/machines/click.ogg'
|
||||
@@ -262,12 +262,6 @@
|
||||
|
||||
if(!src.open())
|
||||
user << "<span class='notice'>It won't budge!</span>"
|
||||
if(!lastbang)
|
||||
lastbang = 1
|
||||
for (var/mob/M in hearers(src, null))
|
||||
M << text("<FONT size=[]>BANG, bang!</FONT>", max(0, 5 - get_dist(src, M)))
|
||||
spawn(30)
|
||||
lastbang = 0
|
||||
|
||||
/obj/structure/closet/attack_hand(mob/user as mob)
|
||||
src.add_fingerprint(user)
|
||||
@@ -315,3 +309,64 @@
|
||||
dump_contents()
|
||||
spawn(1) qdel(src)
|
||||
return 1
|
||||
|
||||
/obj/structure/closet/proc/req_breakout()
|
||||
if(breakout)
|
||||
return 0 //Already breaking out.
|
||||
if(opened)
|
||||
return 0 //Door's open... wait, why are you in it's contents then?
|
||||
if(!welded)
|
||||
return 0 //closed but not welded...
|
||||
return 1
|
||||
|
||||
/obj/structure/closet/proc/mob_breakout(var/mob/living/escapee)
|
||||
var/breakout_time = 2 //2 minutes by default
|
||||
|
||||
if(!req_breakout())
|
||||
return
|
||||
|
||||
//okay, so the closet is either welded or locked... resist!!!
|
||||
escapee.next_move = world.time + 100
|
||||
escapee.last_special = world.time + 100
|
||||
escapee << "<span class='warning'>You lean on the back of \the [src] and start pushing the door open. (this will take about [breakout_time] minutes)</span>"
|
||||
|
||||
visible_message("<span class='danger'>The [src] begins to shake violently!</span>")
|
||||
|
||||
breakout = 1 //can't think of a better way to do this right now.
|
||||
for(var/i in 1 to (6*breakout_time * 2)) //minutes * 6 * 5seconds * 2
|
||||
playsound(src.loc, 'sound/effects/grillehit.ogg', 100, 1)
|
||||
animate_shake()
|
||||
|
||||
if(!do_after(escapee, 50)) //5 seconds
|
||||
breakout = 0
|
||||
return
|
||||
if(!escapee || escapee.stat || escapee.loc != src)
|
||||
breakout = 0
|
||||
return //closet/user destroyed OR user dead/unconcious OR user no longer in closet OR closet opened
|
||||
//Perform the same set of checks as above for weld and lock status to determine if there is even still a point in 'resisting'...
|
||||
if(!req_breakout())
|
||||
breakout = 0
|
||||
return
|
||||
|
||||
//Well then break it!
|
||||
breakout = 0
|
||||
escapee << "<span class='warning'>You successfully break out!</span>"
|
||||
visible_message("<span class='danger'>\the [escapee] successfully broke out of \the [src]!</span>")
|
||||
playsound(src.loc, 'sound/effects/grillehit.ogg', 100, 1)
|
||||
break_open()
|
||||
animate_shake()
|
||||
|
||||
/obj/structure/closet/proc/break_open()
|
||||
welded = 0
|
||||
update_icon()
|
||||
//Do this to prevent contents from being opened into nullspace (read: bluespace)
|
||||
if(istype(loc, /obj/structure/bigDelivery))
|
||||
var/obj/structure/bigDelivery/BD = loc
|
||||
BD.unwrap()
|
||||
open()
|
||||
|
||||
/obj/structure/closet/proc/animate_shake()
|
||||
var/init_px = pixel_x
|
||||
var/shake_dir = pick(-1, 1)
|
||||
animate(src, transform=turn(matrix(), 8*shake_dir), pixel_x=init_px + 2*shake_dir, time=1)
|
||||
animate(transform=null, pixel_x=init_px, time=6, easing=ELASTIC_EASING)
|
||||
|
||||
@@ -132,3 +132,25 @@
|
||||
overlays += "welded"
|
||||
else
|
||||
icon_state = icon_opened
|
||||
|
||||
|
||||
/obj/structure/closet/secure_closet/req_breakout()
|
||||
if(!opened && locked) return 1
|
||||
return ..() //It's a secure closet, but isn't locked.
|
||||
|
||||
/obj/structure/closet/secure_closet/break_open()
|
||||
desc += " It appears to be broken."
|
||||
icon_state = icon_off
|
||||
spawn()
|
||||
flick(icon_broken, src)
|
||||
sleep(10)
|
||||
flick(icon_broken, src)
|
||||
sleep(10)
|
||||
broken = 1
|
||||
locked = 0
|
||||
update_icon()
|
||||
//Do this to prevent contents from being opened into nullspace (read: bluespace)
|
||||
if(istype(loc, /obj/structure/bigDelivery))
|
||||
var/obj/structure/bigDelivery/BD = loc
|
||||
BD.unwrap()
|
||||
open()
|
||||
@@ -233,12 +233,6 @@
|
||||
if(S.zone) S.zone.rebuild()
|
||||
|
||||
if(ispath(N, /turf/simulated/floor))
|
||||
//if the old turf had a zone, connect the new turf to it as well - Cael
|
||||
//Adjusted by SkyMarshal 5/10/13 - The air master will handle the addition of the new turf.
|
||||
//if(zone)
|
||||
// zone.RemoveTurf(src)
|
||||
// if(!zone.CheckStatus())
|
||||
// zone.SetStatus(ZONE_ACTIVE)
|
||||
|
||||
var/turf/simulated/W = new N( locate(src.x, src.y, src.z) )
|
||||
//W.Assimilate_Air()
|
||||
@@ -258,7 +252,7 @@
|
||||
universe.OnTurfChange(W)
|
||||
|
||||
if(air_master)
|
||||
air_master.mark_for_update(src)
|
||||
air_master.mark_for_update(src) //handle the addition of the new turf.
|
||||
|
||||
for(var/turf/space/S in range(W,1))
|
||||
S.update_starlight()
|
||||
@@ -267,10 +261,6 @@
|
||||
return W
|
||||
|
||||
else
|
||||
//if(zone)
|
||||
// zone.RemoveTurf(src)
|
||||
// if(!zone.CheckStatus())
|
||||
// zone.SetStatus(ZONE_ACTIVE)
|
||||
|
||||
var/turf/W = new N( locate(src.x, src.y, src.z) )
|
||||
W.lighting_lumcount += old_lumcount
|
||||
|
||||
170
code/modules/mob/living/carbon/resist.dm
Normal file
170
code/modules/mob/living/carbon/resist.dm
Normal file
@@ -0,0 +1,170 @@
|
||||
|
||||
/mob/living/carbon/process_resist()
|
||||
|
||||
//drop && roll
|
||||
if(on_fire)
|
||||
fire_stacks -= 2 //reduced
|
||||
Weaken(3)
|
||||
spin(32,2)
|
||||
visible_message(
|
||||
"<span class='danger'>[src] rolls on the floor, trying to put themselves out!</span>",
|
||||
"<span class='notice'>You stop, drop, and roll!</span>"
|
||||
)
|
||||
sleep(30)
|
||||
if(fire_stacks <= 0)
|
||||
visible_message(
|
||||
"<span class='danger'>[src] has successfully extinguished themselves!</span>",
|
||||
"<span class='notice'>You extinguish yourself.</span>"
|
||||
)
|
||||
ExtinguishMob()
|
||||
return
|
||||
|
||||
if(handcuffed)
|
||||
spawn() escape_handcuffs()
|
||||
else if(legcuffed)
|
||||
spawn() escape_legcuffs()
|
||||
|
||||
..()
|
||||
|
||||
/mob/living/carbon/proc/escape_handcuffs()
|
||||
if(!(last_special <= world.time)) return
|
||||
|
||||
next_move = world.time + 100
|
||||
last_special = world.time + 100
|
||||
|
||||
if(can_break_cuffs()) //Don't want to do a lot of logic gating here.
|
||||
break_handcuffs()
|
||||
return
|
||||
|
||||
var/obj/item/weapon/handcuffs/HC = handcuffed
|
||||
|
||||
//A default in case you are somehow handcuffed with something that isn't an obj/item/weapon/handcuffs type
|
||||
var/breakouttime = 1200
|
||||
var/displaytime = 2 //Minutes to display in the "this will take X minutes."
|
||||
//If you are handcuffed with actual handcuffs... Well what do I know, maybe someone will want to handcuff you with toilet paper in the future...
|
||||
if(istype(HC))
|
||||
breakouttime = HC.breakouttime
|
||||
displaytime = breakouttime / 600 //Minutes
|
||||
|
||||
visible_message(
|
||||
"<span class='danger'>[src] attempts to remove \the [HC]!</span>",
|
||||
"<span class='warning'>You attempt to remove \the [HC]. (This will take around [displaytime] minutes and you need to stand still)</span>"
|
||||
)
|
||||
|
||||
if(do_after(src, breakouttime))
|
||||
if(!handcuffed || buckled)
|
||||
return
|
||||
visible_message(
|
||||
"<span class='danger'>[src] manages to remove \the [handcuffed]!</span>",
|
||||
"<span class='notice'>You successfully remove \the [handcuffed].</span>"
|
||||
)
|
||||
drop_from_inventory(handcuffed)
|
||||
|
||||
/mob/living/carbon/proc/escape_legcuffs()
|
||||
if(!(last_special <= world.time)) return
|
||||
|
||||
next_move = world.time + 100
|
||||
last_special = world.time + 100
|
||||
|
||||
if(can_break_cuffs()) //Don't want to do a lot of logic gating here.
|
||||
break_legcuffs()
|
||||
return
|
||||
|
||||
var/obj/item/weapon/legcuffs/HC = legcuffed
|
||||
|
||||
//A default in case you are somehow legcuffed with something that isn't an obj/item/weapon/legcuffs type
|
||||
var/breakouttime = 1200
|
||||
var/displaytime = 2 //Minutes to display in the "this will take X minutes."
|
||||
//If you are legcuffed with actual legcuffs... Well what do I know, maybe someone will want to legcuff you with toilet paper in the future...
|
||||
if(istype(HC))
|
||||
breakouttime = HC.breakouttime
|
||||
displaytime = breakouttime / 600 //Minutes
|
||||
|
||||
visible_message(
|
||||
"<span class='danger'>[usr] attempts to remove \the [HC]!</span>",
|
||||
"<span class='warning'>You attempt to remove \the [HC]. (This will take around [displaytime] minutes and you need to stand still)</span>"
|
||||
)
|
||||
|
||||
if(do_after(src, breakouttime))
|
||||
if(!legcuffed || buckled)
|
||||
return
|
||||
visible_message(
|
||||
"<span class='danger'>[src] manages to remove \the [legcuffed]!</span>",
|
||||
"<span class='notice'>You successfully remove \the [legcuffed].</span>"
|
||||
)
|
||||
|
||||
drop_from_inventory(legcuffed)
|
||||
legcuffed = null
|
||||
update_inv_legcuffed()
|
||||
|
||||
/mob/living/carbon/proc/can_break_cuffs()
|
||||
if(HULK in mutations)
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/proc/break_handcuffs()
|
||||
visible_message(
|
||||
"<span class='danger'>[src] is trying to break \the [handcuffed]!</span>",
|
||||
"<span class='warning'>You attempt to break your [handcuffed.name]. (This will take around 5 seconds and you need to stand still)</span>"
|
||||
)
|
||||
|
||||
if(do_after(src, 50))
|
||||
if(!handcuffed || buckled)
|
||||
return
|
||||
|
||||
visible_message(
|
||||
"<span class='danger'>[src] manages to break \the [handcuffed]!</span>",
|
||||
"<span class='warning'>You successfully break your [handcuffed.name].</span>"
|
||||
)
|
||||
|
||||
say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ))
|
||||
|
||||
del(handcuffed)
|
||||
handcuffed = null
|
||||
if(buckled && buckled.buckle_require_restraints)
|
||||
buckled.unbuckle_mob()
|
||||
update_inv_handcuffed()
|
||||
|
||||
/mob/living/carbon/proc/break_legcuffs()
|
||||
src << "<span class='warning'>You attempt to break your legcuffs. (This will take around 5 seconds and you need to stand still)</span>"
|
||||
visible_message("<span class='danger'>[src] is trying to break the legcuffs!</span>")
|
||||
|
||||
if(do_after(src, 50))
|
||||
if(!legcuffed || buckled)
|
||||
return
|
||||
|
||||
visible_message(
|
||||
"<span class='danger'>[src] manages to break the legcuffs!</span>",
|
||||
"<span class='warning'>You successfully break your legcuffs.</span>"
|
||||
)
|
||||
|
||||
say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ))
|
||||
|
||||
del(legcuffed)
|
||||
legcuffed = null
|
||||
update_inv_legcuffed()
|
||||
|
||||
/mob/living/carbon/human/can_break_cuffs()
|
||||
if(species.can_shred(src,1))
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/escape_buckle()
|
||||
if(!buckled) return
|
||||
if(!(last_special <= world.time)) return
|
||||
|
||||
if(!restrained())
|
||||
..()
|
||||
else
|
||||
next_move = world.time + 100
|
||||
last_special = world.time + 100
|
||||
visible_message(
|
||||
"<span class='danger'>[usr] attempts to unbuckle themself!</span>",
|
||||
"<span class='warning'>You attempt to unbuckle yourself. (This will take around 2 minutes and you need to stand still)</span>"
|
||||
)
|
||||
|
||||
if(do_after(usr, 1200))
|
||||
if(!buckled)
|
||||
return
|
||||
visible_message("<span class='danger'>[usr] manages to unbuckle themself!</span>",
|
||||
"<span class='notice'>You successfully unbuckle yourself.</span>")
|
||||
buckled.user_unbuckle_mob(src)
|
||||
@@ -571,284 +571,84 @@ default behaviour is:
|
||||
set name = "Resist"
|
||||
set category = "IC"
|
||||
|
||||
if(usr.stat || !isliving(usr) || usr.next_move > world.time)
|
||||
return
|
||||
if(can_resist())
|
||||
next_move = world.time + 20
|
||||
process_resist()
|
||||
|
||||
usr.next_move = world.time + 20
|
||||
|
||||
var/mob/living/L = usr
|
||||
/mob/living/proc/can_resist()
|
||||
//need to allow !canmove, or otherwise neck grabs can't be resisted
|
||||
//so just check weakened instead.
|
||||
if(stat || weakened)
|
||||
return 0
|
||||
if(next_move > world.time)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/mob/living/proc/process_resist()
|
||||
//Getting out of someone's inventory.
|
||||
if(istype(src.loc,/obj/item/weapon/holder))
|
||||
var/obj/item/weapon/holder/H = src.loc //Get our item holder.
|
||||
var/mob/M = H.loc //Get our mob holder (if any).
|
||||
|
||||
if(istype(M))
|
||||
M.drop_from_inventory(H)
|
||||
M << "[H] wriggles out of your grip!"
|
||||
src << "You wriggle out of [M]'s grip!"
|
||||
else if(istype(H.loc,/obj/item))
|
||||
src << "You struggle free of [H.loc]."
|
||||
H.loc = get_turf(H)
|
||||
|
||||
if(istype(M))
|
||||
for(var/atom/A in M.contents)
|
||||
if(istype(A,/mob/living/simple_animal/borer) || istype(A,/obj/item/weapon/holder))
|
||||
return
|
||||
|
||||
M.status_flags &= ~PASSEMOTES
|
||||
if(istype(src.loc, /obj/item/weapon/holder))
|
||||
escape_inventory(src.loc)
|
||||
return
|
||||
|
||||
//Resisting control by an alien mind.
|
||||
if(istype(src.loc,/mob/living/simple_animal/borer))
|
||||
var/mob/living/simple_animal/borer/B = src.loc
|
||||
var/mob/living/captive_brain/H = src
|
||||
|
||||
H << "<span class='danger'>You begin doggedly resisting the parasite's control (this will take approximately sixty seconds).</span>"
|
||||
B.host << "<span class='danger'>You feel the captive mind of [src] begin to resist your control.</span>"
|
||||
|
||||
spawn(rand(200,250)+B.host.brainloss)
|
||||
|
||||
if(!B || !B.controlling)
|
||||
return
|
||||
|
||||
B.host.adjustBrainLoss(rand(5,10))
|
||||
H << "<span class='danger'>With an immense exertion of will, you regain control of your body!</span>"
|
||||
B.host << "<span class='danger'>You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.</span>"
|
||||
|
||||
B.detatch()
|
||||
|
||||
verbs -= /mob/living/carbon/proc/release_control
|
||||
verbs -= /mob/living/carbon/proc/punish_host
|
||||
verbs -= /mob/living/carbon/proc/spawn_larvae
|
||||
|
||||
return
|
||||
|
||||
//resisting grabs (as if it helps anyone...)
|
||||
if ((!( L.stat ) && !( L.restrained() )))
|
||||
var/resisting = 0
|
||||
for(var/obj/O in L.requests)
|
||||
L.requests.Remove(O)
|
||||
qdel(O)
|
||||
resisting++
|
||||
for(var/obj/item/weapon/grab/G in usr.grabbed_by)
|
||||
resisting++
|
||||
switch(G.state)
|
||||
if(GRAB_PASSIVE)
|
||||
qdel(G)
|
||||
if(GRAB_AGGRESSIVE)
|
||||
if(prob(60)) //same chance of breaking the grab as disarm
|
||||
L.visible_message("<span class='warning'>[L] has broken free of [G.assailant]'s grip!</span>")
|
||||
qdel(G)
|
||||
if(GRAB_NECK)
|
||||
//If the you move when grabbing someone then it's easier for them to break free. Same if the affected mob is immune to stun.
|
||||
if (((world.time - G.assailant.l_move_time < 30 || !L.stunned) && prob(15)) || prob(3))
|
||||
L.visible_message("<span class='warning'>[L] has broken free of [G.assailant]'s headlock!</span>")
|
||||
qdel(G)
|
||||
if(resisting)
|
||||
L.visible_message("<span class='danger'>[L] resists!</span>")
|
||||
|
||||
if (!restrained())
|
||||
resist_grab()
|
||||
|
||||
//unbuckling yourself
|
||||
if(L.buckled && (L.last_special <= world.time) )
|
||||
if(iscarbon(L))
|
||||
var/mob/living/carbon/C = L
|
||||
if( C.handcuffed )
|
||||
C.next_move = world.time + 100
|
||||
C.last_special = world.time + 100
|
||||
C << "\red You attempt to unbuckle yourself. (This will take around 2 minutes and you need to stand still)"
|
||||
for(var/mob/O in viewers(L))
|
||||
O.show_message("\red <B>[usr] attempts to unbuckle themself!</B>", 1)
|
||||
spawn(0)
|
||||
if(do_after(usr, 1200))
|
||||
if(!C.buckled)
|
||||
return
|
||||
for(var/mob/O in viewers(C))
|
||||
O.show_message("\red <B>[usr] manages to unbuckle themself!</B>", 1)
|
||||
C << "\blue You successfully unbuckle yourself."
|
||||
C.buckled.user_unbuckle_mob(C)
|
||||
else
|
||||
L.buckled.user_unbuckle_mob(L)
|
||||
if(buckled)
|
||||
spawn() escape_buckle()
|
||||
|
||||
//Breaking out of a locker?
|
||||
else if( src.loc && (istype(src.loc, /obj/structure/closet)) )
|
||||
var/breakout_time = 2 //2 minutes by default
|
||||
if( src.loc && (istype(src.loc, /obj/structure/closet)) )
|
||||
var/obj/structure/closet/C = loc
|
||||
spawn() C.mob_breakout(src)
|
||||
|
||||
var/obj/structure/closet/C = L.loc
|
||||
if(C.opened)
|
||||
return //Door's open... wait, why are you in it's contents then?
|
||||
if(istype(L.loc, /obj/structure/closet/secure_closet))
|
||||
var/obj/structure/closet/secure_closet/SC = L.loc
|
||||
if(!SC.locked && !SC.welded)
|
||||
return //It's a secure closet, but isn't locked. Easily escapable from, no need to 'resist'
|
||||
else
|
||||
if(!C.welded)
|
||||
return //closed but not welded...
|
||||
// else Meh, lets just keep it at 2 minutes for now
|
||||
// breakout_time++ //Harder to get out of welded lockers than locked lockers
|
||||
/mob/living/proc/escape_inventory(obj/item/weapon/holder/H)
|
||||
if(H != src.loc) return
|
||||
|
||||
var/mob/M = H.loc //Get our mob holder (if any).
|
||||
|
||||
//okay, so the closet is either welded or locked... resist!!!
|
||||
usr.next_move = world.time + 100
|
||||
L.last_special = world.time + 100
|
||||
L << "\red You lean on the back of \the [C] and start pushing the door open. (this will take about [breakout_time] minutes)"
|
||||
for(var/mob/O in viewers(usr.loc))
|
||||
O.show_message("\red <B>The [L.loc] begins to shake violently!</B>", 1)
|
||||
if(istype(M))
|
||||
M.drop_from_inventory(H)
|
||||
M << "<span class='warning'>[H] wriggles out of your grip!</span>"
|
||||
src << "<span class='warning'>You wriggle out of [M]'s grip!</span>"
|
||||
else if(istype(H.loc,/obj/item))
|
||||
src << "<span class='warning'>You struggle free of [H.loc].</span>"
|
||||
H.loc = get_turf(H)
|
||||
|
||||
if(istype(M))
|
||||
for(var/atom/A in M.contents)
|
||||
if(istype(A,/mob/living/simple_animal/borer) || istype(A,/obj/item/weapon/holder))
|
||||
return
|
||||
|
||||
spawn(0)
|
||||
if(do_after(usr,(breakout_time*60*10))) //minutes * 60seconds * 10deciseconds
|
||||
if(!C || !L || L.stat != CONSCIOUS || L.loc != C || C.opened) //closet/user destroyed OR user dead/unconcious OR user no longer in closet OR closet opened
|
||||
return
|
||||
M.status_flags &= ~PASSEMOTES
|
||||
|
||||
//Perform the same set of checks as above for weld and lock status to determine if there is even still a point in 'resisting'...
|
||||
if(istype(L.loc, /obj/structure/closet/secure_closet))
|
||||
var/obj/structure/closet/secure_closet/SC = L.loc
|
||||
if(!SC.locked && !SC.welded)
|
||||
return
|
||||
else
|
||||
if(!C.welded)
|
||||
return
|
||||
/mob/living/proc/escape_buckle()
|
||||
if(buckled)
|
||||
buckled.user_unbuckle_mob(src)
|
||||
|
||||
//Well then break it!
|
||||
if(istype(usr.loc, /obj/structure/closet/secure_closet))
|
||||
var/obj/structure/closet/secure_closet/SC = L.loc
|
||||
SC.desc = "It appears to be broken."
|
||||
SC.icon_state = SC.icon_off
|
||||
flick(SC.icon_broken, SC)
|
||||
sleep(10)
|
||||
flick(SC.icon_broken, SC)
|
||||
sleep(10)
|
||||
SC.broken = 1
|
||||
SC.locked = 0
|
||||
SC.update_icon()
|
||||
usr << "\red You successfully break out!"
|
||||
for(var/mob/O in viewers(L.loc))
|
||||
O.show_message("\red <B>\the [usr] successfully broke out of \the [SC]!</B>", 1)
|
||||
if(istype(SC.loc, /obj/structure/bigDelivery)) //Do this to prevent contents from being opened into nullspace (read: bluespace)
|
||||
var/obj/structure/bigDelivery/BD = SC.loc
|
||||
BD.attack_hand(usr)
|
||||
SC.open()
|
||||
else
|
||||
C.welded = 0
|
||||
C.update_icon()
|
||||
usr << "\red You successfully break out!"
|
||||
for(var/mob/O in viewers(L.loc))
|
||||
O.show_message("\red <B>\the [usr] successfully broke out of \the [C]!</B>", 1)
|
||||
if(istype(C.loc, /obj/structure/bigDelivery)) //nullspace ect.. read the comment above
|
||||
var/obj/structure/bigDelivery/BD = C.loc
|
||||
BD.attack_hand(usr)
|
||||
C.open()
|
||||
|
||||
//drop && roll or breaking out of handcuffs
|
||||
else if(iscarbon(L))
|
||||
var/mob/living/carbon/CM = L
|
||||
if(CM.on_fire && CM.canmove)
|
||||
CM.fire_stacks -= 5
|
||||
CM.Weaken(3)
|
||||
CM.spin(32,2)
|
||||
CM.visible_message("<span class='danger'>[CM] rolls on the floor, trying to put themselves out!</span>", \
|
||||
"<span class='notice'>You stop, drop, and roll!</span>")
|
||||
sleep(30)
|
||||
if(fire_stacks <= 0)
|
||||
CM.visible_message("<span class='danger'>[CM] has successfully extinguished themselves!</span>", \
|
||||
"<span class='notice'>You extinguish yourself.</span>")
|
||||
ExtinguishMob()
|
||||
return
|
||||
if(CM.handcuffed && CM.canmove && (CM.last_special <= world.time))
|
||||
CM.next_move = world.time + 100
|
||||
CM.last_special = world.time + 100
|
||||
|
||||
var/can_break_cuffs
|
||||
if(HULK in usr.mutations)
|
||||
can_break_cuffs = 1
|
||||
else if(istype(CM,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = CM
|
||||
if(H.species.can_shred(H,1))
|
||||
can_break_cuffs = 1
|
||||
|
||||
if(can_break_cuffs) //Don't want to do a lot of logic gating here.
|
||||
usr << "\red You attempt to break your handcuffs. (This will take around 5 seconds and you need to stand still)"
|
||||
for(var/mob/O in viewers(CM))
|
||||
O.show_message(text("\red <B>[] is trying to break the handcuffs!</B>", CM), 1)
|
||||
spawn(0)
|
||||
if(do_after(CM, 50))
|
||||
if(!CM.handcuffed || CM.buckled)
|
||||
return
|
||||
for(var/mob/O in viewers(CM))
|
||||
O.show_message(text("\red <B>[] manages to break the handcuffs!</B>", CM), 1)
|
||||
CM << "\red You successfully break your handcuffs."
|
||||
CM.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ))
|
||||
qdel(CM.handcuffed)
|
||||
CM.handcuffed = null
|
||||
if(buckled && buckled.buckle_require_restraints)
|
||||
buckled.unbuckle_mob()
|
||||
CM.update_inv_handcuffed()
|
||||
else
|
||||
var/obj/item/weapon/handcuffs/HC = CM.handcuffed
|
||||
var/breakouttime = 1200 //A default in case you are somehow handcuffed with something that isn't an obj/item/weapon/handcuffs type
|
||||
var/displaytime = 2 //Minutes to display in the "this will take X minutes."
|
||||
if(istype(HC)) //If you are handcuffed with actual handcuffs... Well what do I know, maybe someone will want to handcuff you with toilet paper in the future...
|
||||
breakouttime = HC.breakouttime
|
||||
displaytime = breakouttime / 600 //Minutes
|
||||
CM << "\red You attempt to remove \the [HC]. (This will take around [displaytime] minutes and you need to stand still)"
|
||||
for(var/mob/O in viewers(CM))
|
||||
O.show_message( "\red <B>[usr] attempts to remove \the [HC]!</B>", 1)
|
||||
spawn(0)
|
||||
if(do_after(CM, breakouttime))
|
||||
if(!CM.handcuffed || CM.buckled)
|
||||
return // time leniency for lag which also might make this whole thing pointless but the server
|
||||
for(var/mob/O in viewers(CM))// lags so hard that 40s isn't lenient enough - Quarxink
|
||||
O.show_message("\red <B>[CM] manages to remove the handcuffs!</B>", 1)
|
||||
CM << "\blue You successfully remove \the [CM.handcuffed]."
|
||||
CM.drop_from_inventory(CM.handcuffed)
|
||||
|
||||
else if(CM.legcuffed && CM.canmove && (CM.last_special <= world.time))
|
||||
CM.next_move = world.time + 100
|
||||
CM.last_special = world.time + 100
|
||||
|
||||
var/can_break_cuffs
|
||||
if(HULK in usr.mutations)
|
||||
can_break_cuffs = 1
|
||||
else if(istype(CM,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = CM
|
||||
if(H.species.can_shred(H,1))
|
||||
can_break_cuffs = 1
|
||||
|
||||
if(can_break_cuffs) //Don't want to do a lot of logic gating here.
|
||||
usr << "\red You attempt to break your legcuffs. (This will take around 5 seconds and you need to stand still)"
|
||||
for(var/mob/O in viewers(CM))
|
||||
O.show_message(text("\red <B>[] is trying to break the legcuffs!</B>", CM), 1)
|
||||
spawn(0)
|
||||
if(do_after(CM, 50))
|
||||
if(!CM.legcuffed || CM.buckled)
|
||||
return
|
||||
for(var/mob/O in viewers(CM))
|
||||
O.show_message(text("\red <B>[] manages to break the legcuffs!</B>", CM), 1)
|
||||
CM << "\red You successfully break your legcuffs."
|
||||
CM.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ))
|
||||
qdel(CM.legcuffed)
|
||||
CM.legcuffed = null
|
||||
CM.update_inv_legcuffed()
|
||||
else
|
||||
var/obj/item/weapon/legcuffs/HC = CM.legcuffed
|
||||
var/breakouttime = 1200 //A default in case you are somehow legcuffed with something that isn't an obj/item/weapon/legcuffs type
|
||||
var/displaytime = 2 //Minutes to display in the "this will take X minutes."
|
||||
if(istype(HC)) //If you are legcuffed with actual legcuffs... Well what do I know, maybe someone will want to legcuff you with toilet paper in the future...
|
||||
breakouttime = HC.breakouttime
|
||||
displaytime = breakouttime / 600 //Minutes
|
||||
CM << "\red You attempt to remove \the [HC]. (This will take around [displaytime] minutes and you need to stand still)"
|
||||
for(var/mob/O in viewers(CM))
|
||||
O.show_message( "\red <B>[usr] attempts to remove \the [HC]!</B>", 1)
|
||||
spawn(0)
|
||||
if(do_after(CM, breakouttime))
|
||||
if(!CM.legcuffed || CM.buckled)
|
||||
return // time leniency for lag which also might make this whole thing pointless but the server
|
||||
for(var/mob/O in viewers(CM))// lags so hard that 40s isn't lenient enough - Quarxink
|
||||
O.show_message("\red <B>[CM] manages to remove the legcuffs!</B>", 1)
|
||||
CM << "\blue You successfully remove \the [CM.legcuffed]."
|
||||
CM.drop_from_inventory(CM.legcuffed)
|
||||
CM.legcuffed = null
|
||||
CM.update_inv_legcuffed()
|
||||
/mob/living/proc/resist_grab()
|
||||
var/resisting = 0
|
||||
for(var/obj/O in requests)
|
||||
requests.Remove(O)
|
||||
qdel(O)
|
||||
resisting++
|
||||
for(var/obj/item/weapon/grab/G in grabbed_by)
|
||||
resisting++
|
||||
switch(G.state)
|
||||
if(GRAB_PASSIVE)
|
||||
qdel(G)
|
||||
if(GRAB_AGGRESSIVE)
|
||||
if(prob(60)) //same chance of breaking the grab as disarm
|
||||
visible_message("<span class='warning'>[src] has broken free of [G.assailant]'s grip!</span>")
|
||||
qdel(G)
|
||||
if(GRAB_NECK)
|
||||
//If the you move when grabbing someone then it's easier for them to break free. Same if the affected mob is immune to stun.
|
||||
if (((world.time - G.assailant.l_move_time < 30 || !stunned) && prob(15)) || prob(3))
|
||||
visible_message("<span class='warning'>[src] has broken free of [G.assailant]'s headlock!</span>")
|
||||
qdel(G)
|
||||
if(resisting)
|
||||
visible_message("<span class='danger'>[src] resists!</span>")
|
||||
|
||||
/mob/living/verb/lay_down()
|
||||
set name = "Rest"
|
||||
|
||||
@@ -32,4 +32,31 @@
|
||||
M << "The captive mind of [src] whispers, \"[message]\""
|
||||
|
||||
/mob/living/captive_brain/emote(var/message)
|
||||
return
|
||||
return
|
||||
|
||||
/mob/living/captive_brain/can_resist()
|
||||
return !(stat || next_move > world.time)
|
||||
|
||||
/mob/living/captive_brain/process_resist()
|
||||
//Resisting control by an alien mind.
|
||||
if(istype(src.loc,/mob/living/simple_animal/borer))
|
||||
var/mob/living/simple_animal/borer/B = src.loc
|
||||
var/mob/living/captive_brain/H = src
|
||||
|
||||
H << "<span class='danger'>You begin doggedly resisting the parasite's control (this will take approximately sixty seconds).</span>"
|
||||
B.host << "<span class='danger'>You feel the captive mind of [src] begin to resist your control.</span>"
|
||||
|
||||
spawn(rand(200,250)+B.host.brainloss)
|
||||
if(!B || !B.controlling) return
|
||||
|
||||
B.host.adjustBrainLoss(rand(5,10))
|
||||
H << "<span class='danger'>With an immense exertion of will, you regain control of your body!</span>"
|
||||
B.host << "<span class='danger'>You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.</span>"
|
||||
B.detatch()
|
||||
verbs -= /mob/living/carbon/proc/release_control
|
||||
verbs -= /mob/living/carbon/proc/punish_host
|
||||
verbs -= /mob/living/carbon/proc/spawn_larvae
|
||||
|
||||
return
|
||||
|
||||
..()
|
||||
|
||||
@@ -56,7 +56,10 @@
|
||||
verbs += /mob/living/proc/ventcrawl
|
||||
verbs += /mob/living/proc/hide
|
||||
|
||||
name = "[name] ([rand(1, 1000)])"
|
||||
if(name == initial(name))
|
||||
name = "[name] ([rand(1, 1000)])"
|
||||
real_name = name
|
||||
|
||||
if(!body_color)
|
||||
body_color = pick( list("brown","gray","white") )
|
||||
icon_state = "mouse_[body_color]"
|
||||
@@ -112,5 +115,10 @@
|
||||
name = "Tom"
|
||||
desc = "Jerry the cat is not amused."
|
||||
|
||||
/mob/living/simple_animal/mouse/brown/Tom/New()
|
||||
..()
|
||||
// Change my name back, don't want to be named Tom (666)
|
||||
name = initial(name)
|
||||
|
||||
/mob/living/simple_animal/mouse/can_use_vents()
|
||||
return
|
||||
return
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
affecting.loc = assailant.loc
|
||||
|
||||
if(state >= GRAB_NECK)
|
||||
affecting.Stun(1)
|
||||
affecting.Stun(3)
|
||||
if(isliving(affecting))
|
||||
var/mob/living/L = affecting
|
||||
L.adjustOxyLoss(1)
|
||||
|
||||
@@ -15,13 +15,15 @@
|
||||
var/tag_x
|
||||
|
||||
attack_hand(mob/user as mob)
|
||||
unwrap()
|
||||
|
||||
proc/unwrap()
|
||||
if(wrapped) //sometimes items can disappear. For example, bombs. --rastaf0
|
||||
wrapped.loc = (get_turf(src.loc))
|
||||
if(istype(wrapped, /obj/structure/closet))
|
||||
var/obj/structure/closet/O = wrapped
|
||||
O.welded = 0
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/device/destTagger))
|
||||
|
||||
5
html/changelogs/HarpyEagle-NeckgrabFix.yml
Normal file
5
html/changelogs/HarpyEagle-NeckgrabFix.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
author: HarpyEagle
|
||||
delete-after: True
|
||||
|
||||
changes:
|
||||
- bugfix: "Neck-grabbing someone now stuns them properly."
|
||||
5
html/changelogs/PsiOmegaDelta-OfMiceAndMen.yml
Normal file
5
html/changelogs/PsiOmegaDelta-OfMiceAndMen.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
author: PsiOmegaDelta
|
||||
delete-after: True
|
||||
|
||||
changes:
|
||||
- tweak: "Mice are now numbered to aid admins."
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 161 KiB After Width: | Height: | Size: 145 KiB |
Reference in New Issue
Block a user