Newmap - SMC, Openturf, Arrivals Controller, and Mine Turf Improvements (#1958)

* Replace SSingulo with SScalamity; processing cleanup
- SScalamity now handles blobs as well as singularity-types.
- Processing subtypes have been simplified to not require a stop_processing definition.

* this is probably important

* Remove cascade disabling SSgarbage

* Fixed a bug where dust() did not qdel the target mob

* Misc fixes

* Fix decals surviving break-to-plating

* Subsystem flag tweaks

* Apparently subsystems are new'd before config is.

* Fix paper icons

* Speculative fix for insane lag

* Better machinery stat

* Make organs not use SSoverlay

* Misc bugfixes & tweaks

* Nightmode fixes

* Changelog for SMC

* Port /tg/'s improved MC crash handling

* Add some more SS Recover() procs

* supply_controller -> SScargo

* More New() -> Initialize()

* pAI and robot construction overlays

* Fix cargo unit tests

* Merge the DMM Suite's atom/New() into atoms_init

* Lighting pre-baking

* Lighting initialization logging

* Fix some bad SS init orders

* Fix SSlighting logging; rename Processes to MC

* Speculative fix for insane GC lag

* Prebaked openturf/icon_smooth & fix lighting prebake

* SS init status; SSatoms LATEQDEL

* Fix bug with MC init stat panel

* Fix parallax

* Misc

* Ignore SS_NO_DISPLAY during init

* apparently this is important

* REEEEEE

* Image GC fixes; broadcaster radio-new sanity

* RCON Cleanup

* Move pAI recruiter into subsystem

* Move global solars list into sun subsystem

* Make chickens not use a global

* Demote SSdisposals to SS_BACKGROUND; garbage-debug cleanup

* Speed up space init a little

* Fix bad timer flags on floor drying

* Subsystem panic-restart verb for mins

* Explosion speedup

* Minor subsystem & MC logging tweaks

* SSopenturf improvements

* Make pipenet actually initialize (whoops)

* Minor tweaks

* Implement lighting rounding

* comments are hard okay

* Minor lattice tweaks

* Fix some timer issues & better closet init

* Timer sanity

* Request console tweaks + Storage init sanity

* Minor SSmachiner RCON improvements

* Further reduce world-start timer count

* Standardize subsystem logging

* Garbage hard delete profiling from /tg/

* Timer hang detection & recovery

* Log machines that sleep in process() and fuck up SSmachinery

* Fix an issue with external airlocks sleeping in process()

* Failsafe logging

* Minor tweaks

* Revert "Request console tweaks + Storage init sanity"

This reverts commit 98d3579e35.

* Re-implement RC changes

* Fix SQL FT saving

* Fix SSmachinery sleep in disposals

* Minor SS tweaks

* Paper fixes

* Blood drying fixes

* Merge gameticker and SSticker

* Minor global list init cleanup

* Lagcheck biogenerator & bags

* Tweak SScargo init order; RIG Initialize()

* Caching tweaks

* Remove rogue comma

* Initialize fixes

* Lighting destroy cleanup

* Fix emagging airlocks

* Initial SSicon implementation

* Tweaks & Fixes

* Fire + Air alarm queued icon updates

* Overlays + Queued icon cleanup

* Runtime & background fixes

* Kill some meaningless set statements

* Kill some image qdels

* Bump up lighting rounding val

* Fix adv. scanner destroy runtimes

* Remove unneeded icon update limiting

* Move icon smoothing into helpers

* Show a warning if DM 510 compiles without memory leak hack enabled

* Re-organize subsystems & MC defines a little

* Airlock SFX

* Log of Changes

* Make SSicon_update disable itself when not doing anything

* Fix respawn verb runtime when used early in server-init

* Add more information to MC's stat_entry()

* Replace direct refernces to gcDestroyed with QDEL* macros

* plant_controller -> SSplants

* More plant tweaks

* Add more humor to changelog

* Move parallax globals into SSparallax

* Lighting responsiveness tweaks

* Fix parallax init order & better MC init panel stat

* Make mobs GC

* More overlays + Remove intercom spawn()

* SSfast_process; make pinpointers not use spawn-recursion to process
Also made the SM Cascade beach process with SSprocessing instead of a spawn loop.

* Update changelog

* Mob GC tweaks

* Del() cleanup

* Fix insomniac ZAS connection edges

* Minor pAI cleanup

* Convert more things to SSoverlay; fix duplicated overlay in field gens

* SM Bluespace turf tweaks

* Update SSgarbage debug globals list

* Human-type qdel tweaks

* Subsystem suspension; stat_entry improvements

* SQL Statistics cleanup

* Fix runtimes with ambrosia

* More disable() -> suspend(); fix nightmode again

* Human qdel fix; minor tweaks

* Update turbolift to work with StonedMC

* Make lifts use timers instead of a subsystem

* Make SSassets start earlier

* Convert the radio controller into a subsystem

* Fix some missing CHECK_TICKs in asteroid generation

* MC stat tweaks; make shouldnt_see a typecache

* Kill some redundant debug-controller entries

* radio_controller -> SSradio

* Better SSgarbage hard-del logging from /tg/ upstream

* Logging tweaks + GELF

* Misc client caching improvements

* Slime SSoverlay

* Oven icon fixes

* Implant fixes
- Death implants will no longer spam Common on death of user.
- Death implants should handle a deleted user better.

* Holder tweaks + Welding tool Initialize()

* Fix some bad subsystem logging

* Fix suit cooling units spawning without cells

* Starlight tweaks

* Gibber infinite gib fix

* More SSoverlay stuff

* Make crates use CUT_OVERLAY_IN

* Make SSarrivals suspend instead of disable

* Make openturf use split/phased tick checks

* Speculative fix for unwet timer runtimes

* Blood overlay tweaks/fixes

* Update crusher to play nice with SMC + SSoverlay

* Openturf improvements and fixes

* Minor turbolift tweaks

* Lighting performance improvements + ChangeTurf tweaks

* this is probably important

* Fix wall weld noises on changeturf

* More ChangeTurf tweaks

* Explosion tweaks

* Pre-game lobby tweaks

* Openturf tweaks

* Prevent admins from starting the game before init finishes

* Fix Travis

* Kill an unused var

* Fix ChangeTurf runtimes on openturfs

* Fixes

* Browser datum fixes, asset caching

* Update changelog

* Changelog

* Lobby tweaks

* Ticker tweaks; kill ticker var

* Further lobby tweaks

* Cascade tweaks

* air_master -> SSair

* Reduce overhead from radio autosay

* alarm_manager -> SSalarm

* bomb_processor -> SSexplosives

* corp_regs -> SSlaw

* ZAS overlay fixes

* Small wall icon optimization

* Fix effects master

* Assembly tweaks

* Megavend fixes

* Shuttle fixes

* Camera alert performance improvements

* Fix some world.log spam from lighting overlays

* Fix some Initialize() procs

* Openspace responsiveness tweaks

* Make HE pipes animate through openturfs

* Kill a spawn
This commit is contained in:
Lohikar
2017-05-02 14:40:40 -04:00
committed by LordFowl
parent 9dbf27a0f4
commit f6dc33a465
872 changed files with 17767 additions and 13417 deletions
+2 -1
View File
@@ -467,7 +467,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
src << "<span class='warning'>Spawning as a mouse is currently disabled.</span>"
return
if(ticker.current_state < GAME_STATE_PLAYING)
if(!ROUND_IS_STARTED)
src << "<span class='warning'>You can not spawn as a mouse before round start!</span>"
return
@@ -730,6 +730,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
for(var/image/I in client.images)
if(I.icon_state == icon)
iconRemoved = 1
client.images -= I
qdel(I)
if(!iconRemoved)
+6 -8
View File
@@ -18,9 +18,8 @@
flick(anim, animation)
if(do_gibs) gibs(loc, viruses, dna)
spawn(15)
if(animation) qdel(animation)
if(src) qdel(src)
QDEL_IN(animation, 15)
QDEL_IN(src, 15)
//This is the proc for turning a mob into ash. Mostly a copy of gib code (above).
//Originally created for wizard disintegrate. I've removed the virus code since it's irrelevant here.
@@ -45,10 +44,9 @@
new remains(loc)
dead_mob_list -= src
spawn(15)
if(animation) qdel(animation)
if(src) qdel(src)
QDEL_IN(animation, 15)
QDEL_IN(src, 15)
/mob/proc/death(gibbed,deathmessage="seizes up and falls limp...")
@@ -95,8 +93,8 @@
updateicon()
if(ticker && ticker.mode)
ticker.mode.check_win()
if(SSticker.mode)
SSticker.mode.check_win()
return 1
+10
View File
@@ -20,3 +20,13 @@ var/mob/dview/dview_mob = new
dead_mob_list -= src
else
living_mob_list -= src
/mob/dview/Destroy(force = FALSE)
crash_with("Some fuck [force ? "force-" : ""]qdeleted the dview mob.")
if (!force)
return QDEL_HINT_LETMELIVE
world.log << "Dview was force-qdeleted, this should never happen!"
dview_mob = new
return QDEL_HINT_QUEUE
+1 -1
View File
@@ -10,7 +10,7 @@
/datum/visualnet/camera/proc/process_sort()
if(cameras_unsorted)
cameras = dd_sortedObjectList(cameras)
sortTim(cameras, /proc/cmp_camera, FALSE)
cameras_unsorted = 0
// Removes a camera from a chunk.
+2 -2
View File
@@ -42,7 +42,7 @@
/mob/living/silicon/ai/proc/create_eyeobj(var/newloc)
if(eyeobj) destroy_eyeobj()
if(!newloc) newloc = src.loc
eyeobj = getFromPool(/mob/eye/aiEye, newloc)
eyeobj = new /mob/eye/aiEye(newloc)
eyeobj.owner = src
eyeobj.name = "[src.name] (AI Eye)" // Give it a name
if(client) client.eye = eyeobj
@@ -58,7 +58,7 @@
/mob/living/silicon/ai/Destroy()
destroy_eyeobj()
..()
return ..()
/atom/proc/move_camera_by_click()
if(istype(usr, /mob/living/silicon/ai))
+10 -12
View File
@@ -18,19 +18,17 @@
cameranet.updatePortableCamera(src.camera)
updating = 0
/mob/living/silicon/AI/Move()
/mob/living/silicon/ai/Move()
var/oldLoc = src.loc
. = ..()
if(.)
if(provides_camera_vision())
if(!updating)
updating = 1
spawn(BORG_CAMERA_BUFFER)
if(oldLoc != src.loc)
cameranet.updateVisibility(oldLoc, 0)
cameranet.updateVisibility(loc, 0)
updating = 0
addtimer(CALLBACK(src, .proc/camera_post_move, oldLoc), BORG_CAMERA_BUFFER, TIMER_UNIQUE)
/mob/living/silicon/ai/proc/camera_post_move(oldLoc)
if(oldLoc != src.loc)
cameranet.updateVisibility(oldLoc, 0)
cameranet.updateVisibility(loc, 0)
#undef BORG_CAMERA_BUFFER
// CAMERA
@@ -46,10 +44,10 @@
src.set_light(0)
cameranet.removeCamera(src)
/obj/machinery/camera/New()
..()
/obj/machinery/camera/Initialize()
. = ..()
//Camera must be added to global list of all cameras no matter what...
if(cameranet.cameras_unsorted || !ticker)
if(cameranet.cameras_unsorted)
cameranet.cameras += src
cameranet.cameras_unsorted = 1
else
@@ -59,7 +57,7 @@
/obj/machinery/camera/Destroy()
clear_all_networks()
cameranet.cameras -= src
..()
return ..()
// Mobs
/mob/living/silicon/ai/rejuvenate()
+4 -3
View File
@@ -71,8 +71,7 @@
// The actual updating.
/datum/chunk/proc/update()
set background = 1
set waitfor = FALSE
var/list/newVisibleTurfs = new()
acquireVisibleTurfs(newVisibleTurfs)
@@ -128,7 +127,9 @@
src.y = y
src.z = z
for(var/turf/t in range(10, locate(x + 8, y + 8, z)))
var/turf/center = locate(x + 8, y + 8, z)
for(var/turf/t in RANGE_TURFS(10, center))
if(t.x >= x && t.y >= y && t.x < x + 16 && t.y < y + 16)
turfs[t] = t
+2 -2
View File
@@ -32,14 +32,14 @@
updateallghostimages()
..()
mob/eye/Destroy()
/mob/eye/Destroy()
if (ghostimage)
ghost_darkness_images -= ghostimage
ghost_sightless_images -= ghostimage
qdel(ghostimage)
ghostimage = null
updateallghostimages()
..()
return ..()
/mob/eye/Move(n, direct)
if(owner == src)
@@ -25,7 +25,7 @@
/mob/living/Destroy()
cultnet.updateVisibility(src, 0)
..()
return ..()
/mob/living/rejuvenate()
var/was_dead = stat == DEAD
+5 -6
View File
@@ -3,9 +3,8 @@
// TURFS
/proc/updateVisibility(atom/A, var/opacity_check = 1)
if(ticker)
for(var/datum/visualnet/VN in visual_nets)
VN.updateVisibility(A, opacity_check)
for(var/datum/visualnet/VN in visual_nets)
VN.updateVisibility(A, opacity_check)
/turf
var/list/image/obfuscations = new()
@@ -17,8 +16,8 @@
updateVisibility(src)
return ..()
/turf/simulated/New()
..()
/turf/simulated/Initialize()
. = ..()
updateVisibility(src)
@@ -46,4 +45,4 @@
// Glass door glass = 1
// don't check then?
if(!glass)
updateVisibility(src, 0)
updateVisibility(src, 0)
+2 -2
View File
@@ -14,7 +14,7 @@
/datum/visualnet/Destroy()
visual_nets -= src
..()
return ..()
// Checks if a chunk has been Generated in x, y, z.
/datum/visualnet/proc/chunkGenerated(x, y, z)
@@ -64,7 +64,7 @@
/datum/visualnet/proc/updateVisibility(atom/A, var/opacity_check = 1)
if(!ticker || (opacity_check && !A.opacity))
if((opacity_check && !A.opacity))
return
majorChunkChange(A, 2)
+35 -43
View File
@@ -14,25 +14,38 @@ var/list/holder_mob_icon_cache = list()
var/name_dead
var/isalive
var/last_loc_general//This stores a general location of the object. Ie, a container or a mob
var/last_loc_specific//This stores specific extra information about the location, pocket, hand, worn on head, etc. Only relevant to mobs
var/static/list/unsafe_containers
var/last_loc_general //This stores a general location of the object. Ie, a container or a mob
var/last_loc_specific //This stores specific extra information about the location, pocket, hand, worn on head, etc. Only relevant to mobs
/obj/item/weapon/holder/proc/setup_unsafe_list()
unsafe_containers = typecacheof(list(
/obj/item/weapon/storage,
/obj/item/weapon/reagent_containers,
/obj/structure/closet/crate,
/obj/machinery/appliance,
/obj/machinery/microwave
))
/obj/item/weapon/holder/Initialize()
. = ..()
if (!unsafe_containers)
setup_unsafe_list()
/obj/item/weapon/holder/New()
tag = rand(0,9999)
if (!item_state)
item_state = icon_state
flags_inv |= ALWAYSDRAW
..()
processing_objects.Add(src)
START_PROCESSING(SSprocessing, src)
/obj/item/weapon/holder/Destroy()
reagents = null
processing_objects.Remove(src)
STOP_PROCESSING(SSprocessing, src)
if (contained)
release_mob()
..()
return ..()
/obj/item/weapon/holder/examine(mob/user)
if (contained)
@@ -66,7 +79,6 @@ var/list/holder_mob_icon_cache = list()
release_mob()
return
if (isalive && contained.stat == DEAD)
held_death(1)//If we get here, it means the mob died sometime after we picked it up. We pass in 1 so that we can play its deathmessage
@@ -74,22 +86,8 @@ var/list/holder_mob_icon_cache = list()
//This function checks if the current location is safe to release inside
//it returns 1 if the creature will bug out when released
/obj/item/weapon/holder/proc/is_unsafe_container(var/obj/place)
if (istype(place, /turf))
return 0
else if (istype(place, /obj/item/weapon/storage))
return 1
else if (istype(place, /obj/item/weapon/reagent_containers))
return 1
else if (istype(place, /obj/structure/closet/crate))
return 1
else if (istype(place, /obj/machinery/appliance))
return 1
else if (istype(place, /obj/machinery/microwave))
return 1
else
return 0
/obj/item/weapon/holder/proc/is_unsafe_container(atom/place)
return is_type_in_typecache(place, unsafe_containers)
//Releases all mobs inside the holder, then deletes it.
//is_unsafe_container should be checked before calling this
@@ -103,7 +101,6 @@ var/list/holder_mob_icon_cache = list()
M.reset_view()
M.Released()
contained = null
var/mob/L = get_holding_mob()
if (L)
@@ -111,7 +108,6 @@ var/list/holder_mob_icon_cache = list()
qdel(src)
//Similar to above function, but will not deposit things in any container, only directly on a turf.
//Can be called safely anywhere. Notably on holders held or worn on a mob
/obj/item/weapon/holder/proc/release_to_floor()
@@ -139,18 +135,18 @@ var/list/holder_mob_icon_cache = list()
//once with it on the floor, and then once in the container
//This conditional allows us to ignore that first one. Handling of mobs dropped on the floor is done in process
if (istype(loc, /turf))
spawn(3)
//Repeat this check
//If we're still on the turf a few frames later, then we have actually been dropped or thrown
//Release the mob accordingly
if (istype(loc, /turf))
release_mob()
//Repeat this check
//If we're still on the turf a few frames later, then we have actually been dropped or thrown
//Release the mob accordingly
addtimer(CALLBACK(src, .proc/post_drop), 3)
return
if (istype(loc, /obj/item/weapon/storage)) //The second drop reads the container its placed into as the location
update_location()
/obj/item/weapon/holder/proc/post_drop()
if (isturf(loc))
release_mob()
/obj/item/weapon/holder/equipped(var/mob/user, var/slot)
..()
@@ -163,10 +159,6 @@ var/list/holder_mob_icon_cache = list()
report_onmob_location(1, slotnumber, contained)
/obj/item/weapon/holder/attack_self(mob/M as mob)
if (contained && !(contained.stat & DEAD))
@@ -174,11 +166,11 @@ var/list/holder_mob_icon_cache = list()
var/mob/living/carbon/human/H = M
switch(H.a_intent)
if(I_HELP)
H.visible_message("\blue [H] pets [contained]")
H.visible_message("<span class='notice'>[H] pets [contained].</span>")
if(I_HURT)
contained.adjustBruteLoss(3)
H.visible_message("\red [H] crushes [contained]")
H.visible_message("<span class='alert'>[H] crushes [contained].</span>")
else
M << "[contained] is dead."
@@ -209,7 +201,7 @@ var/list/holder_mob_icon_cache = list()
//We have to play it as a visible message on the grabber, because the normal death message played on the dying mob won't show if it's being held
var/mob/M = get_holding_mob()
if (M)
M.visible_message("<b>\The [contained.name]</b> dies")
M.visible_message("<b>[contained.name]</b> dies.")
//update_icon()
@@ -507,7 +499,7 @@ var/list/holder_mob_icon_cache = list()
/obj/item/weapon/holder/lizard
name = "lizard"
desc = "It's a hissy little lizard. Is it related to Unathi?"
desc_dead = "It doesn't hiss anymore"
desc_dead = "It doesn't hiss anymore."
icon_state_dead = "lizard_dead"
icon_state = "lizard"
@@ -553,7 +545,7 @@ var/list/holder_mob_icon_cache = list()
name = "walking mushroom"
name_dead = "mushroom"
desc = "It's a massive mushroom... with legs?"
desc_dead = "Shame, he was a really fun-guy."
desc_dead = "Shame, he was a really fun-guy." // HA
icon_state = "mushroom"
icon_state_dead = "mushroom_dead"
slot_flags = SLOT_HEAD
+5
View File
@@ -30,6 +30,11 @@
access_scanner.req_access = req_access.Copy()
access_scanner.req_one_access = req_one_access.Copy()
/mob/living/bot/Destroy()
QDEL_NULL(botcard)
QDEL_NULL(access_scanner)
return ..()
/mob/living/bot/Life()
..()
if(health <= 0)
+9 -4
View File
@@ -54,8 +54,8 @@ var/list/cleanbot_types // Going to use this to generate a list of types once th
janitorial_supplies |= src
if(radio_controller)
radio_controller.add_object(listener, beacon_freq, filter = RADIO_NAVBEACONS)
if(SSradio)
SSradio.add_object(listener, beacon_freq, filter = RADIO_NAVBEACONS)
/mob/living/bot/cleanbot/Destroy()
. = ..()
@@ -63,7 +63,8 @@ var/list/cleanbot_types // Going to use this to generate a list of types once th
patrol_path = null
target = null
ignorelist = null
janitorial_supplies -= src
QDEL_NULL(listener)
global.janitorial_supplies -= src
/mob/living/bot/cleanbot/proc/handle_target()
if(target.clean_marked && target.clean_marked != src)
@@ -158,7 +159,7 @@ var/list/cleanbot_types // Going to use this to generate a list of types once th
if(!found_spot && !target) // No targets in range
if(!patrol_path || !patrol_path.len)
if(!signal_sent || signal_sent > world.time + 200) // Waited enough or didn't send yet
var/datum/radio_frequency/frequency = radio_controller.return_frequency(beacon_freq)
var/datum/radio_frequency/frequency = SSradio.return_frequency(beacon_freq)
if(!frequency)
return
@@ -354,6 +355,10 @@ var/list/cleanbot_types // Going to use this to generate a list of types once th
cleanbot.closest_dist = dist
cleanbot.next_dest = signal.data["next_patrol"]
/obj/cleanbot_listener/Destroy()
cleanbot = null
return ..()
/* Assembly */
/obj/item/weapon/bucket_sensor
+9 -6
View File
@@ -27,12 +27,15 @@
var/atom/target
var/frustration = 0
/mob/living/bot/farmbot/New()
..()
spawn(5)
tank = locate() in contents
if(!tank)
tank = new /obj/structure/reagent_dispensers/watertank(src)
/mob/living/bot/farmbot/Initialize()
. = ..()
tank = locate() in contents
if(!tank)
tank = new /obj/structure/reagent_dispensers/watertank(src)
/mob/living/bot/farmbot/Destroy()
QDEL_NULL(tank)
return ..()
/mob/living/bot/farmbot/attack_hand(var/mob/user as mob)
. = ..()
+1 -1
View File
@@ -229,7 +229,7 @@
if(building == 1)
I = new /obj/item/stack/tile/floor(src)
else
I = getFromPool(/obj/item/stack/rods, src)
I = new /obj/item/stack/rods(src)
A.attackby(I, src)
target = null
repairing = 0
+12 -8
View File
@@ -29,6 +29,11 @@
var/treatment_emag = "toxin"
var/declare_treatment = 0 //When attempting to treat a patient, should it notify everyone wearing medhuds?
/mob/living/bot/medbot/Destroy()
QDEL_NULL(reagent_glass)
return ..()
/mob/living/bot/medbot/Life()
..()
@@ -111,9 +116,9 @@
update_icons()
/mob/living/bot/medbot/update_icons()
overlays.Cut()
cut_overlays()
if(skin)
overlays += image('icons/obj/aibots.dmi', "medskin_[skin]")
add_overlay("medskin_[skin]")
if(currently_healing)
icon_state = "medibots"
else
@@ -337,11 +342,10 @@
var/skin = null //Same as medbot, set to tox or ointment for the respective kits.
w_class = 3.0
/obj/item/weapon/firstaid_arm_assembly/New()
..()
spawn(5) // Terrible. TODO: fix
if(skin)
overlays += image('icons/obj/aibots.dmi', "kit_skin_[src.skin]")
/obj/item/weapon/firstaid_arm_assembly/Initialize()
. = ..()
if(skin)
add_overlay("kit_skin_[skin]")
/obj/item/weapon/firstaid_arm_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
@@ -361,7 +365,7 @@
build_step++
user << "<span class='notice'>You add the health sensor to [src].</span>"
name = "First aid/robot arm/health analyzer assembly"
overlays += image('icons/obj/aibots.dmi', "na_scanner")
add_overlay("na_scanner")
return 1
if(1)
+19 -11
View File
@@ -48,15 +48,19 @@
desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey."
auto_patrol = 1
/mob/living/bot/secbot/New()
..()
/mob/living/bot/secbot/Initialize()
. = ..()
listener = new /obj/secbot_listener(src)
listener.secbot = src
spawn(5) // Since beepsky is made on the start... this delay is necessary
if(radio_controller)
radio_controller.add_object(listener, control_freq, filter = RADIO_SECBOT)
radio_controller.add_object(listener, beacon_freq, filter = RADIO_NAVBEACONS)
if(SSradio)
SSradio.add_object(listener, control_freq, filter = RADIO_SECBOT)
SSradio.add_object(listener, beacon_freq, filter = RADIO_NAVBEACONS)
/mob/living/bot/secbot/Destroy()
QDEL_NULL(listener)
target = null
return ..()
/mob/living/bot/secbot/turn_off()
..()
@@ -315,7 +319,7 @@
var/obj/item/weapon/secbot_assembly/Sa = new /obj/item/weapon/secbot_assembly(Tsec)
Sa.build_step = 1
Sa.overlays += image('icons/obj/aibots.dmi', "hs_hole")
Sa.add_overlay("hs_hole")
Sa.created_name = name
new /obj/item/device/assembly/prox_sensor(Tsec)
new /obj/item/weapon/melee/baton(Tsec)
@@ -405,11 +409,15 @@
/obj/secbot_listener
var/mob/living/bot/secbot/secbot = null
/obj/secbot_listener/Destroy()
secbot = null
return ..()
/obj/secbot_listener/proc/post_signal(var/freq, var/key, var/value) // send a radio signal with a single data key/value pair
post_signal_multiple(freq, list("[key]" = value))
/obj/secbot_listener/proc/post_signal_multiple(var/freq, var/list/keyval) // send a radio signal with multiple data key/values
var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq)
var/datum/radio_frequency/frequency = SSradio.return_frequency(freq)
if(!frequency)
return
@@ -520,7 +528,7 @@
var/obj/item/weapon/weldingtool/WT = O
if(WT.remove_fuel(0, user))
build_step = 1
overlays += image('icons/obj/aibots.dmi', "hs_hole")
add_overlay("hs_hole")
user << "You weld a hole in \the [src]."
return 1
@@ -528,7 +536,7 @@
user.drop_item()
build_step = 2
user << "You add \the [O] to [src]."
overlays += image('icons/obj/aibots.dmi', "hs_eye")
add_overlay("hs_eye")
name = "helmet/signaler/prox sensor assembly"
qdel(O)
return 1
@@ -538,7 +546,7 @@
build_step = 3
user << "You add \the [O] to [src]."
name = "helmet/signaler/prox sensor/robot arm assembly"
overlays += image('icons/obj/aibots.dmi', "hs_arm")
add_overlay("hs_arm")
qdel(O)
return 1
+1 -3
View File
@@ -1,8 +1,6 @@
// Alien larva are quite simple.
/mob/living/carbon/alien/Life()
set invisibility = 0
set background = 1
set background = BACKGROUND_ENABLED
if (transforming) return
if(!loc) return
+1 -1
View File
@@ -134,7 +134,7 @@
if(brainmob)
qdel(brainmob)
brainmob = null
..()
return ..()
/obj/item/device/mmi/radio_enabled
name = "radio-enabled man-machine interface"
@@ -20,7 +20,7 @@
if(stat!=DEAD) //If not dead.
death(1) //Brains can die again. AND THEY SHOULD AHA HA HA HA HA HA
ghostize() //Ghostize checks for key so nothing else is necessary.
..()
return ..()
say_understands(var/other)//Goddamn is this hackish, but this say code is so odd
if (istype(other, /mob/living/silicon/ai))
@@ -43,7 +43,7 @@
if(brainmob)
qdel(brainmob)
brainmob = null
..()
return ..()
/obj/item/organ/brain/proc/transfer_identity(var/mob/living/carbon/H)
name = "\the [H]'s [initial(src.name)]"
+1 -1
View File
@@ -2,7 +2,7 @@
//Start of a breath chain, calls breathe()
/mob/living/carbon/handle_breathing()
if(air_master.current_cycle%4==2 || failed_last_breath || (health < config.health_threshold_crit)) //First, resolve location and get a breath
if(SSair.times_fired%4==2 || failed_last_breath || (health < config.health_threshold_crit)) //First, resolve location and get a breath
breathe()
/mob/living/carbon/proc/breathe()
+4 -3
View File
@@ -18,7 +18,8 @@
/mob/living/carbon/Destroy()
QDEL_NULL(touching)
// We don't qdel(bloodstr) because it's the same as qdel(reagents)
bloodstr = null
QDEL_NULL(dna)
for(var/guts in internal_organs)
qdel(guts)
return ..()
@@ -66,13 +67,13 @@
if(prob(src.getBruteLoss() - 50))
for(var/atom/movable/A in stomach_contents)
A.loc = loc
stomach_contents.Remove(A)
LAZYREMOVE(stomach_contents, A)
src.gib()
/mob/living/carbon/gib()
for(var/mob/M in src)
if(M in src.stomach_contents)
src.stomach_contents.Remove(M)
LAZYREMOVE(src.stomach_contents, M)
M.loc = src.loc
for(var/mob/N in viewers(src, null))
if(N.client)
+1 -1
View File
@@ -513,7 +513,7 @@ var/list/diona_banned_languages = list(
/datum/dionastats/Destroy()
light_organ = null//Nulling out these references to prevent GC errors
nutrient_organ = null
..()
return ..()
#undef FLASHLIGHT_STRENGTH
@@ -60,9 +60,9 @@
if(!gibbed && species.death_sound)
playsound(loc, species.death_sound, 80, 1, 1)
if(ticker && ticker.mode)
if(SSticker.mode)
sql_report_death(src)
ticker.mode.check_win()
SSticker.mode.check_win()
if(wearing_rig)
wearing_rig.notify_ai("<span class='danger'>Warning: user death event. Mobility control passed to integrated intelligence system.</span>")
@@ -88,6 +88,8 @@
bad_internal_organs = null
bad_external_organs = null
QDEL_NULL(vessel)
QDEL_NULL(DS)
// qdel and null out our equipment.
QDEL_NULL(shoes)
@@ -39,7 +39,7 @@
return
for(var/obj/item/organ/external/E in bad_external_organs)
if(!E)
if(QDELETED(E))
continue
if(!E.need_process())
bad_external_organs -= E
@@ -200,12 +200,12 @@
set desc = "Empties the contents of your stomach"
set category = "Abilities"
if(stomach_contents.len)
if(LAZYLEN(stomach_contents))
for(var/mob/M in src)
if(M in stomach_contents)
stomach_contents.Remove(M)
M.loc = loc
src.visible_message("\red <B>[src] hurls out the contents of their stomach!</B>")
LAZYREMOVE(stomach_contents, M)
M.forceMove(loc)
src.visible_message(span("danger", "\The [src] hurls out the contents of their stomach!"))
return
/mob/living/carbon/human/proc/psychic_whisper(mob/M as mob in oview())
@@ -35,7 +35,6 @@
var/global/list/overlays_cache = null
/mob/living/carbon/human/Life()
set invisibility = 0
set background = BACKGROUND_ENABLED
if (transforming)
@@ -1265,23 +1264,6 @@
if(T.dynamic_lighting && T.get_lumcount() < 0.01) // give a little bit of tolerance for near-dark areas.
playsound_local(src,pick(scarySounds),50, 1, -1)
/mob/living/carbon/human/handle_stomach()
spawn(0)
for(var/mob/living/M in stomach_contents)
if(M.loc != src)
stomach_contents.Remove(M)
continue
if(iscarbon(M)|| isanimal(M))
if(M.stat == 2)
M.death(1)
stomach_contents.Remove(M)
qdel(M)
continue
if(air_master.current_cycle%3==1)
if(!(M.status_flags & GODMODE))
M.adjustBruteLoss(5)
nutrition += 10
/mob/living/carbon/human/proc/handle_changeling()
if(mind && mind.changeling)
mind.changeling.regenerate()
@@ -146,6 +146,9 @@ Please contact me on #coderbus IRC. ~Carn x
//UPDATES OVERLAYS FROM OVERLAYS_LYING/OVERLAYS_STANDING
//Fixed by Nanako
/mob/living/carbon/human/update_icons()
if (QDELING(src))
return // No point.
//so we don't update overlays for lying/standing unless our stance changes again
update_hud() //TODO: remove the need for this
overlays.Cut()
@@ -234,6 +237,9 @@ var/global/list/damage_icon_parts = list()
//Passing in a value of 2 for update_icons will ignore any cached icon, and force a new one to be generated
/mob/living/carbon/human/proc/update_body(var/update_icons=1)
if (QDELING(src))
return
var/husk_color_mod = rgb(96,88,80)
var/hulk_color_mod = rgb(48,224,40)
@@ -355,6 +361,9 @@ var/global/list/damage_icon_parts = list()
//HAIR OVERLAY
/mob/living/carbon/human/proc/update_hair(var/update_icons=1)
if (QDELING(src))
return
//Reset our hair
overlays_standing[HAIR_LAYER] = null
@@ -404,6 +413,9 @@ var/global/list/damage_icon_parts = list()
if(update_icons) update_icons()
/mob/living/carbon/human/update_mutations(var/update_icons=1)
if (QDELING(src))
return
var/fat
if(FAT in mutations)
fat = "fat"
@@ -449,6 +461,9 @@ var/global/list/damage_icon_parts = list()
/* --------------------------------------- */
//For legacy support.
/mob/living/carbon/human/regenerate_icons()
if (QDELING(src))
return
..()
if(transforming) return
@@ -483,6 +498,9 @@ var/global/list/damage_icon_parts = list()
//vvvvvv UPDATE_INV PROCS vvvvvv
/mob/living/carbon/human/update_inv_w_uniform(var/update_icons=1)
if (QDELING(src))
return
overlays_standing[UNIFORM_LAYER] = null
if(check_draw_underclothing())
w_uniform.screen_loc = ui_iclothing
@@ -543,6 +561,9 @@ var/global/list/damage_icon_parts = list()
update_icons()
/mob/living/carbon/human/update_inv_wear_id(var/update_icons=1)
if (QDELING(src))
return
overlays_standing[ID_LAYER] = null
if(wear_id)
@@ -566,6 +587,9 @@ var/global/list/damage_icon_parts = list()
if(update_icons) update_icons()
/mob/living/carbon/human/update_inv_gloves(var/update_icons=1)
if (QDELING(src))
return
overlays_standing[GLOVES_LAYER] = null
if(check_draw_gloves())
@@ -607,6 +631,9 @@ var/global/list/damage_icon_parts = list()
/mob/living/carbon/human/update_inv_glasses(var/update_icons=1)
if (QDELING(src))
return
overlays_standing[GLASSES_LAYER] = null
if(check_draw_glasses())
if(glasses.contained_sprite)
@@ -632,6 +659,9 @@ var/global/list/damage_icon_parts = list()
if(update_icons) update_icons()
/mob/living/carbon/human/update_inv_ears(var/update_icons=1)
if (QDELING(src))
return
overlays_standing[L_EAR_LAYER] = null
overlays_standing[R_EAR_LAYER] = null
@@ -688,6 +718,9 @@ var/global/list/damage_icon_parts = list()
if(update_icons) update_icons()
/mob/living/carbon/human/update_inv_shoes(var/update_icons=1)
if (QDELING(src))
return
overlays_standing[SHOES_LAYER] = null
if(check_draw_shoes())
var/image/standing
@@ -725,6 +758,9 @@ var/global/list/damage_icon_parts = list()
if(update_icons) update_icons()
/mob/living/carbon/human/update_inv_s_store(var/update_icons=1)
if (QDELING(src))
return
if(s_store)
//s_store.auto_adapt_species(src)
var/t_state = s_store.item_state
@@ -737,6 +773,9 @@ var/global/list/damage_icon_parts = list()
/mob/living/carbon/human/update_inv_head(var/update_icons=1)
if (QDELING(src))
return
overlays_standing[HEAD_LAYER] = null
if(head)
head.screen_loc = ui_head //TODO
@@ -789,6 +828,9 @@ var/global/list/damage_icon_parts = list()
if(update_icons) update_icons()
/mob/living/carbon/human/update_inv_belt(var/update_icons=1)
if (QDELING(src))
return
overlays_standing[BELT_LAYER] = null
if(belt)
@@ -852,6 +894,9 @@ var/global/list/damage_icon_parts = list()
/mob/living/carbon/human/update_inv_wear_suit(var/update_icons=1)
if (QDELING(src))
return
if( wear_suit && istype(wear_suit, /obj/item/) )
@@ -904,12 +949,18 @@ var/global/list/damage_icon_parts = list()
if(update_icons) update_icons()
/mob/living/carbon/human/update_inv_pockets(var/update_icons=1)
if (QDELING(src))
return
if(l_store) l_store.screen_loc = ui_storage1 //TODO
if(r_store) r_store.screen_loc = ui_storage2 //TODO
if(update_icons) update_icons()
/mob/living/carbon/human/update_inv_wear_mask(var/update_icons=1)
if (QDELING(src))
return
overlays_standing[FACEMASK_LAYER] = null
if(check_draw_mask())
wear_mask.screen_loc = ui_mask //TODO
@@ -943,6 +994,9 @@ var/global/list/damage_icon_parts = list()
/mob/living/carbon/human/update_inv_back(var/update_icons=1)
if (QDELING(src))
return
overlays_standing[BACK_LAYER] = null
if(back)
@@ -1007,6 +1061,9 @@ var/global/list/damage_icon_parts = list()
/mob/living/carbon/human/update_inv_handcuffed(var/update_icons=1)
if (QDELING(src))
return
if(handcuffed)
drop_r_hand()
drop_l_hand()
@@ -1026,6 +1083,9 @@ var/global/list/damage_icon_parts = list()
if(update_icons) update_icons()
/mob/living/carbon/human/update_inv_legcuffed(var/update_icons=1)
if (QDELING(src))
return
if(legcuffed)
var/image/standing
@@ -1048,6 +1108,9 @@ var/global/list/damage_icon_parts = list()
/mob/living/carbon/human/update_inv_r_hand(var/update_icons=1)
if (QDELING(src))
return
overlays_standing[R_HAND_LAYER] = null
if(r_hand)
r_hand.screen_loc = ui_rhand //TODO
@@ -1090,6 +1153,9 @@ var/global/list/damage_icon_parts = list()
/mob/living/carbon/human/update_inv_l_hand(var/update_icons=1)
if (QDELING(src))
return
overlays_standing[L_HAND_LAYER] = null
if(l_hand)
l_hand.screen_loc = ui_lhand //TODO
@@ -1131,6 +1197,9 @@ var/global/list/damage_icon_parts = list()
if(update_icons) update_icons()
/mob/living/carbon/human/proc/update_tail_showing(var/update_icons=1)
if (QDELING(src))
return
overlays_standing[TAIL_LAYER] = null
if(species.tail && !(wear_suit && wear_suit.flags_inv & HIDETAIL))
@@ -1142,6 +1211,9 @@ var/global/list/damage_icon_parts = list()
update_icons()
/mob/living/carbon/human/proc/get_tail_icon()
if (QDELING(src))
return
var/icon_key = "[species.race_key][r_skin][g_skin][b_skin][r_hair][g_hair][b_hair]"
var/icon/tail_icon = tail_icon_cache[icon_key]
if(!tail_icon)
@@ -1182,12 +1254,12 @@ var/global/list/damage_icon_parts = list()
tail_overlay = set_tail_state(t_state)
if(tail_overlay)
spawn(20)
//check that the animation hasn't changed in the meantime
if(overlays_standing[TAIL_LAYER] == tail_overlay && tail_overlay.icon_state == t_state)
animate_tail_stop()
addtimer(CALLBACK(src, .proc/end_animate_tail_once, tail_overlay), 20)
/mob/living/carbon/human/proc/end_animate_tail_once(image/tail_overlay)
//check that the animation hasn't changed in the meantime
if(overlays_standing[TAIL_LAYER] == tail_overlay && tail_overlay.icon_state == "[species.tail]_once")
animate_tail_stop()
/mob/living/carbon/human/proc/animate_tail_start()
set_tail_state("[species.tail]_slow[rand(0,9)]")
@@ -1214,6 +1286,9 @@ var/global/list/damage_icon_parts = list()
//Adds a collar overlay above the helmet layer if the suit has one
// Suit needs an identically named sprite in icons/mob/collar.dmi
/mob/living/carbon/human/proc/update_collar(var/update_icons=1)
if (QDELING(src))
return
var/icon/C = new('icons/mob/collar.dmi')
var/image/standing = null
@@ -1227,6 +1302,9 @@ var/global/list/damage_icon_parts = list()
/mob/living/carbon/human/update_fire(var/update_icons=1)
if (QDELING(src))
return
overlays_standing[FIRE_LAYER] = null
if(on_fire)
overlays_standing[FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"="Standing", "layer"=FIRE_LAYER)
@@ -142,19 +142,24 @@
watching -= eavesdropping
//now mobs
var/speech_bubble_test = say_test(message)
var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]")
spawn(30) qdel(speech_bubble)
var/list/listening_clients = list() // The clients we're going to show the speech bubble to.
for(var/mob/M in listening)
M << speech_bubble
M.hear_say(message, verb, speaking, alt_name, italics, src)
if (M.client)
listening_clients += M.client
if (eavesdropping.len)
var/new_message = stars(message) //hopefully passing the message twice through stars() won't hurt... I guess if you already don't understand the language, when they speak it too quietly to hear normally you would be able to catch even less.
for(var/mob/M in eavesdropping)
M << speech_bubble
M.hear_say(new_message, verb, speaking, alt_name, italics, src)
if (M.client)
listening_clients += M.client
var/speech_bubble_test = say_test(message)
var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]")
INVOKE_ASYNC(GLOBAL_PROC, /proc/flick_overlay, speech_bubble, listening_clients, 30)
if (watching.len)
var/rendered = "<span class='game say'><span class='name'>[src.name]</span> [not_heard].</span>"
@@ -1,6 +1,5 @@
/mob/living/carbon/slime/Life()
set invisibility = 0
set background = 1
set background = BACKGROUND_ENABLED
if (src.transforming)
return
@@ -3,7 +3,7 @@
icon_state = "[colour] baby slime dead"
else
icon_state = "[colour] [is_adult ? "adult" : "baby"] slime[Victim ? "" : " eat"]"
overlays.len = 0
cut_overlays()
if (mood)
overlays += image('icons/mob/slimes.dmi', icon_state = "aslime-[mood]")
..()
add_overlay("aslime-[mood]")
..()
+18 -45
View File
@@ -18,11 +18,6 @@
#define PPM 9//Protein per meat, used for calculating the quantity of protein in an animal
/mob/living/var/swallowed_mob = 0
//This is set true if there are any mobs in this mob's contents. they will be slowly digested.
//just used as a boolean to minimise extra processing
@@ -85,26 +80,16 @@
else
devour_gradual(victim,mouth_size)
/mob/living/proc/swallow(var/mob/living/victim, var/mouth_size)
//This function will move the victim inside the eater's contents.. There they will be digested over time
var/swallow_time = max(3 + (victim.mob_size * victim.mob_size) - mouth_size, 3)
src.visible_message("[src] starts swallowing [victim]","You start swallowing [victim], this will take approximately [swallow_time] seconds")
src.visible_message("[src] starts swallowing \the [victim]!","You start swallowing \the [victim], this will take approximately [swallow_time] seconds.")
var/turf/ourloc = src.loc
var/turf/victimloc = victim.loc
if (do_mob(src, victim, swallow_time*10))
victim.loc = src
stomach_contents.Add(victim)
victim.forceMove(src)
LAZYADD(stomach_contents, victim)
else if (victimloc != victim.loc)
src << "[victim] moved away, you need to keep it still. Try grabbing, stunning or killing it first."
else if (ourloc != src.loc)
@@ -112,9 +97,6 @@
else
src << "Swallowing failed!"//reason unknown, maybe the eater got stunned?
/mob/living/proc/devour_gradual(var/mob/living/victim, var/mouth_size)
//This function will start consuming the victim by taking bites out of them.
//Victim or attacker moving will interrupt it
@@ -180,48 +162,43 @@
//This can also happen if you start devouring something else
break
//this function gradually digests things inside the mob's contents.
//It is called from life.dm. Any creatures that don't want to digest their contents simply don't call it
/mob/living/proc/handle_stomach()
for(var/mob/living/M in stomach_contents)
if(M.loc != src)//if something somehow escaped the stomach, then we remove it
stomach_contents.Remove(M)
LAZYREMOVE(stomach_contents, M)
continue
if(!M.composition_reagent_quantity)
M.calculate_composition()
var/digestion_power = (((mob_size * mob_size)/10) / (M.mob_size * M.mob_size))
var/digestion_time = digestion_power * 60//Number of seconds it will take to digest in total
var/DPPP = 1 / (digestion_time / 2.1)//Digestion percentage per proc
var/digestion_time = digestion_power * 60 //Number of seconds it will take to digest in total
var/DPPP = 1 / (digestion_time / 2.1) //Digestion percentage per proc
M.adjustCloneLoss(M.maxHealth*DPPP)
//Digestion power is how much of the creature we can digest per minute. Calculated as a tenth of our mob size squared, divided by the victim's mob size squared
//If the resulting value is >1, digestion will take under a minute.
src.ingested.add_reagent(M.composition_reagent, M.composition_reagent_quantity*DPPP)
if ((M.stat != DEAD) && (M.cloneloss > (M.maxHealth*0.5)))//If we've consumed half of the victim, then it dies
if ((M.stat != DEAD) && (M.cloneloss > (M.maxHealth*0.5))) //If we've consumed half of the victim, then it dies
M.death()
M.stat = DEAD //Just in case the death function doesn't set it
src << "Your stomach feels a little more relaxed as [M] finally stops fighting"
src << "Your stomach feels a little more relaxed as \the [M] finally stops fighting."
if (M.cloneloss >= M.maxHealth)//If we've consumed all of it, then digestion is finished.
stomach_contents.Remove(M)
src << "Your stomach feels a little more empty as you finish digesting [M]"
if (M.cloneloss >= M.maxHealth) //If we've consumed all of it, then digestion is finished.
LAZYREMOVE(stomach_contents, M)
src << "Your stomach feels a little more empty as you finish digesting \the [M]."
qdel(M)
//Helpers
/proc/bitemessage(var/mob/living/victim)
return pick("You take a bite out of [victim]",
"You rip a chunk off of [victim]",
"You consume a piece of [victim]",
"You feast upon your prey",
"You chow down on [victim]",
"You gobble [victim]'s flesh")
return pick(
"You take a bite out of \the [victim].",
"You rip a chunk off of \the [victim].",
"You consume a piece of \the [victim].",
"You feast upon your prey.",
"You chow down on \the [victim].",
"You gobble \the [victim]'s flesh.")
/proc/handle_devour_mess(var/mob/user, var/mob/living/victim, var/datum/reagents/vessel, var/finish = 0)
//The maximum number of blood placements is equal to the mob size of the victim
@@ -286,10 +263,6 @@
B.fluorescent = 0
B.invisibility = 0
/proc/turf_hasblood(var/turf/test)
for (var/obj/effect/decal/cleanable/blood/b in test)
return 1
+4 -2
View File
@@ -1,7 +1,9 @@
/mob/living/Life()
set invisibility = 0
set background = BACKGROUND_ENABLED
if (QDELETED(src)) // If they're being deleted, why bother?
return
..()
if (transforming)
@@ -127,7 +129,7 @@
//this handles hud updates. Calls update_vision() and handle_hud_icons()
/mob/living/proc/handle_regular_hud_updates()
if(!client) return 0
if(!client || QDELETED(src)) return 0
handle_hud_icons()
handle_vision()
+2 -2
View File
@@ -712,8 +712,8 @@ default behaviour is:
//check for nuke disks
if(client && stat != DEAD) //if they are clientless and dead don't bother, the parent will treat them as any other container
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
if(istype(SSticker.mode, /datum/game_mode/nuclear)) //only really care if the game mode is nuclear
var/datum/game_mode/nuclear/G = SSticker.mode
if(G.check_mob(src))
if(x <= TRANSITIONEDGE)
inertia_dir = 4
+4 -2
View File
@@ -47,7 +47,7 @@
var/failed_last_breath = 0 //This is used to determine if the mob failed a breath. If they did fail a brath, they will attempt to breathe each tick, otherwise just once per 4 ticks.
var/possession_candidate // Can be possessed by ghosts if unplayed.
var/list/stomach_contents = list()//This is moved here from carbon defines
var/list/stomach_contents //This is moved here from carbon defines
var/composition_reagent
var/composition_reagent_quantity
var/mouth_size = 2//how large of a creature it can swallow at once, and how big of a bite it can take out of larger things
@@ -69,4 +69,6 @@
var/move_delay_mod = 0//Added to move delay, used for calculating movement speeds. Provides a centralised value for modifiers to alter
var/total_radiation // DON'T MODIFY THIS DIRECTLY. USE apply_radiation()!
var/cloaked = 0//Set to 1 by cloaking devices, optimises update_icons
var/cloaked = 0//Set to 1 by cloaking devices, optimises update_icons
var/tesla_ignore = 0 // If true, mob is not affected by tesla bolts.
+1 -1
View File
@@ -103,7 +103,7 @@ var/controlling
if(host) src.loc = host.loc
src.stat = 2
..()
del src
qdel(src)
// When a meme speaks, it speaks through its host
/mob/living/parasite/meme/say(message as text)
+7 -5
View File
@@ -243,13 +243,15 @@ proc/get_radio_key_from_channel(var/channel)
get_mobs_and_objs_in_view_fast(T, message_range, listening, listening_obj)
var/list/hear_clients = list()
for(var/mob/M in listening)
M.hear_say(message, verb, speaking, alt_name, italics, src, speech_sound, sound_vol)
if (M.client)
hear_clients += M.client
var/speech_bubble_test = say_test(message)
var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]")
spawn(30) qdel(speech_bubble)
for(var/mob/M in listening)
M << speech_bubble
M.hear_say(message, verb, speaking, alt_name, italics, src, speech_sound, sound_vol)
INVOKE_ASYNC(GLOBAL_PROC, /proc/flick_overlay, speech_bubble, hear_clients, 30)
for(var/obj/O in listening_obj)
spawn(0)
+8 -5
View File
@@ -48,7 +48,7 @@ var/list/ai_verbs_default = list(
anchored = 1 // -- TLE
density = 1
status_flags = CANSTUN|CANPARALYSE|CANPUSH
shouldnt_see = list(/obj/effect/rune)
//shouldnt_see - set in New()
var/list/network = list("Exodus")
var/obj/machinery/camera/camera = null
var/list/connected_robots = list()
@@ -99,6 +99,7 @@ var/list/ai_verbs_default = list(
src.verbs -= silicon_subsystems
/mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B, var/safety = 0)
shouldnt_see = typecacheof(/obj/effect/rune)
announcement = new()
announcement.title = "A.I. Announcement"
announcement.announcement_type = "A.I. Announcement"
@@ -123,7 +124,7 @@ var/list/ai_verbs_default = list(
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1"))
proc_holder_list = new()
//proc_holder_list = new() // This ain't even used, why are we initializing it?
if(L)
if (istype(L, /datum/ai_laws))
@@ -168,8 +169,7 @@ var/list/ai_verbs_default = list(
on_mob_init()
spawn(5)
new /obj/machinery/ai_powersupply(src)
addtimer(CALLBACK(src, .proc/create_powersupply), 5)
hud_list[HEALTH_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
hud_list[STATUS_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
@@ -184,6 +184,9 @@ var/list/ai_verbs_default = list(
ai_list += src
..()
/mob/living/silicon/ai/proc/init_powersupply()
new /obj/machinery/ai_powersupply(src)
/mob/living/silicon/ai/proc/on_mob_init()
src << "<B>You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras).</B>"
src << "<B>To look at other parts of the station, click on yourself to get a camera menu.</B>"
@@ -541,7 +544,7 @@ var/list/ai_verbs_default = list(
for(var/i in tempnetwork)
cameralist[i] = i
cameralist = sortAssoc(cameralist)
sortTim(cameralist, /proc/cmp_text_asc)
return cameralist
/mob/living/silicon/ai/proc/ai_network_change(var/network in get_camera_network_list())
@@ -1,7 +1,7 @@
var/global/list/empty_playable_ai_cores = list()
/hook/roundstart/proc/spawn_empty_ai()
if("AI" in ticker.mode.disabled_jobs)
if("AI" in SSticker.mode.disabled_jobs)
return 1 // Don't make empty AI's if you can't have them (also applies to Malf)
for(var/obj/effect/landmark/start/S in landmarks_list)
if(S.name != "AI")
@@ -35,7 +35,7 @@ var/global/list/empty_playable_ai_cores = list()
set category = "OOC"
set desc = "Wipe your core. This is functionally equivalent to cryo or robotic storage, freeing up your job slot."
if(ticker && ticker.mode && ticker.mode.name == "AI malfunction")
if(SSticker.mode && SSticker.mode.name == "AI malfunction")
usr << "<span class='danger'>You cannot use this verb in malfunction. If you need to leave, please adminhelp.</span>"
return
@@ -11,5 +11,5 @@
src.anchored = 1
src.canmove = 0
/mob/living/silicon/decoy/initialize()
return
/mob/living/silicon/decoy/Initialize()
return INITIALIZE_HINT_NORMAL
@@ -1,380 +0,0 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
// Recruiting observers to play as pAIs
var/datum/paiController/paiController // Global handler for pAI candidates
/datum/paiCandidate
var/name
var/key
var/description
var/role
var/comments
var/ready = 0
/hook/startup/proc/paiControllerSetup()
paiController = new /datum/paiController()
return 1
/datum/paiController
var/inquirer = null
var/list/pai_candidates = list()
var/list/asked = list()
var/askDelay = 10 * 60 * 1 // One minute [ms * sec * min]
/datum/paiController/Topic(href, href_list[])
if(href_list["download"])
var/datum/paiCandidate/candidate = locate(href_list["candidate"])
var/obj/item/device/paicard/card = locate(href_list["device"])
if (!candidate in pai_candidates)
return
if(card.pai)
return
if(istype(card,/obj/item/device/paicard) && istype(candidate,/datum/paiCandidate))
var/mob/living/silicon/pai/pai = new(card)
if(!candidate.name)
pai.name = pick(ninja_names)
else
pai.name = candidate.name
pai.real_name = pai.name
pai.key = candidate.key
card.setPersonality(pai)
card.looking_for_personality = 0
if(pai.mind) update_antag_icons(pai.mind)
pai_candidates -= candidate
usr << browse(null, "window=findPai")
if(href_list["new"])
var/datum/paiCandidate/candidate = locate(href_list["candidate"])
var/option = href_list["option"]
var/t = ""
switch(option)
if("name")
t = sanitizeSafe(input("Enter a name for your pAI", "pAI Name", candidate.name) as text, MAX_NAME_LEN)
if(t)
candidate.name = t
if("desc")
t = input("Enter a description for your pAI", "pAI Description", candidate.description) as message
if(t)
candidate.description = sanitize(t)
if("role")
t = input("Enter a role for your pAI", "pAI Role", candidate.role) as text
if(t)
candidate.role = sanitize(t)
if("ooc")
t = input("Enter any OOC comments", "pAI OOC Comments", candidate.comments) as message
if(t)
candidate.comments = sanitize(t)
if("save")
if (config.sql_saves)
usr.client.prefs.save_preferences()
else
candidate.savefile_save(usr)
if("load")
if (config.sql_saves)
usr.client.prefs.load_preferences()
else
candidate.savefile_load(usr)
//In case people have saved unsanitized stuff.
if(candidate.name)
candidate.name = sanitizeSafe(candidate.name, MAX_NAME_LEN)
if(candidate.description)
candidate.description = sanitize(candidate.description)
if(candidate.role)
candidate.role = sanitize(candidate.role)
if(candidate.comments)
candidate.comments = sanitize(candidate.comments)
if("submit")
if(candidate)
candidate.ready = 1
for(var/obj/item/device/paicard/p in world)
if(p.looking_for_personality == 1)
p.alertUpdate()
usr << browse(null, "window=paiRecruit")
return
if (config.sql_saves)
usr.client.prefs.save_preferences()
else
candidate.savefile_save(usr)
recruitWindow(usr, href_list["allow_submit"] != "0")
/datum/paiController/proc/recruitWindow(var/mob/M as mob, allowSubmit = 1)
var/datum/paiCandidate/candidate
for(var/datum/paiCandidate/c in pai_candidates)
if(!istype(c) || !istype(M))
break
if(c.key == M.key)
candidate = c
if(!candidate)
candidate = new /datum/paiCandidate()
candidate.key = M.key
pai_candidates.Add(candidate)
// Load the data before displaying.
if (!config.sql_saves)
candidate.savefile_load(M)
else
M.client.prefs.load_preferences()
var/dat = ""
dat += {"
<style type="text/css">
body {
margin-top:5px;
font-family:Verdana;
color:white;
font-size:13px;
background-image:url('uiBackground.png');
background-repeat:repeat-x;
background-color:#272727;
background-position:center top;
}
table {
border-collapse:collapse;
font-size:13px;
}
th, td {
border: 1px solid #333333;
}
p.top {
background-color: none;
color: white;
}
tr.d0 td {
background-color: #c0c0c0;
color: black;
border:0px;
border: 1px solid #333333;
}
tr.d0 th {
background-color: none;
color: #4477E0;
text-align:right;
vertical-align:top;
width:120px;
border:0px;
}
tr.d1 td {
background-color: #555555;
color: white;
}
td.button {
border: 1px solid #161616;
background-color: #40628a;
}
td.desc {
font-weight:bold;
}
a {
color:#4477E0;
}
a.button {
color:white;
text-decoration: none;
}
</style>
"}
dat += {"
<body>
<b><font size="3px">pAI Personality Configuration</font></b>
<p class="top">Please configure your pAI personality's options. Remember, what you enter here could determine whether or not the user requesting a personality chooses you!</p>
<table>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=\ref[src];option=name;new=1;allow_submit=[allowSubmit];candidate=\ref[candidate]'>Name</a>:</th>
<td class="desc">[candidate.name]&nbsp;</td>
</tr>
<tr class="d1">
<td>What you plan to call yourself. Suggestions: Any character name you would choose for a station character OR an AI.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=\ref[src];option=desc;new=1;allow_submit=[allowSubmit];candidate=\ref[candidate]'>Description</a>:</th>
<td class="desc">[candidate.description]&nbsp;</td>
</tr>
<tr class="d1">
<td>What sort of pAI you typically play; your mannerisms, your quirks, etc. This can be as sparse or as detailed as you like.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=\ref[src];option=role;new=1;allow_submit=[allowSubmit];candidate=\ref[candidate]'>Preferred Role</a>:</th>
<td class="desc">[candidate.role]&nbsp;</td>
</tr>
<tr class="d1">
<td>Do you like to partner with sneaky social ninjas? Like to help security hunt down thugs? Enjoy watching an engineer's back while he saves the station yet again? This doesn't have to be limited to just station jobs. Pretty much any general descriptor for what you'd like to be doing works here.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=\ref[src];option=ooc;new=1;allow_submit=[allowSubmit];candidate=\ref[candidate]'>OOC Comments</a>:</th>
<td class="desc">[candidate.comments]&nbsp;</td>
</tr>
<tr class="d1">
<td>Anything you'd like to address specifically to the player reading this in an OOC manner. \"I prefer more serious RP.\", \"I'm still learning the interface!\", etc. Feel free to leave this blank if you want.</td>
</tr>
</table>
<br>
"}
if(allowSubmit)
dat += {"
<table>
<td class="button"><a href='byond://?src=\ref[src];option=submit;new=1;candidate=\ref[candidate]' class="button"><b><font size="4px">Submit Personality</font></b></a></td>
</table><br>
"}
dat += {"
<body>
"}
M << browse(dat, "window=paiRecruit;size=580x580;")
/datum/paiController/proc/findPAI(var/obj/item/device/paicard/p, var/mob/user)
requestRecruits(user)
var/list/available = list()
for(var/datum/paiCandidate/c in paiController.pai_candidates)
if(c.ready)
var/found = 0
for(var/mob/dead/observer/o in player_list)
if(o.key == c.key && o.MayRespawn())
found = 1
if(found)
available.Add(c)
var/dat = ""
dat += {"
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">
<html>
<head>
<style>
body {
margin-top:5px;
font-family:Verdana;
color:white;
font-size:13px;
background-image:url('uiBackground.png');
background-repeat:repeat-x;
background-color:#272727;
background-position:center top;
}
table {
font-size:13px;
}
table.desc {
border-collapse:collapse;
font-size:13px;
border: 1px solid #161616;
width:100%;
}
table.download {
border-collapse:collapse;
font-size:13px;
border: 1px solid #161616;
width:100%;
}
tr.d0 td, tr.d0 th {
background-color: #506070;
color: white;
}
tr.d1 td, tr.d1 th {
background-color: #708090;
color: white;
}
tr.d2 td {
background-color: #00FF00;
color: white;
text-align:center;
}
td.button {
border: 1px solid #161616;
background-color: #40628a;
text-align: center;
}
td.download {
border: 1px solid #161616;
background-color: #40628a;
text-align: center;
}
th {
text-align:left;
width:125px;
vertical-align:top;
}
a.button {
color:white;
text-decoration: none;
}
</style>
</head>
<body>
<b><font size='3px'>pAI Availability List</font></b><br><br>
"}
dat += "<p>Displaying available AI personalities from central database... If there are no entries, or if a suitable entry is not listed, check again later as more personalities may be added.</p>"
for(var/datum/paiCandidate/c in available)
dat += {"
<table class="desc">
<tr class="d0">
<th>Name:</th>
<td>[c.name]</td>
</tr>
<tr class="d1">
<th>Description:</th>
<td>[c.description]</td>
</tr>
<tr class="d0">
<th>Preferred Role:</th>
<td>[c.role]</td>
</tr>
<tr class="d1">
<th>OOC Comments:</th>
<td>[c.comments]</td>
</tr>
</table>
<table class="download">
<td class="download"><a href='byond://?src=\ref[src];download=1;candidate=\ref[c];device=\ref[p]' class="button"><b>Download [c.name]</b></a>
</td>
</table>
<br>
"}
dat += {"
</body>
</html>
"}
user << browse(dat, "window=findPai")
/datum/paiController/proc/requestRecruits(var/mob/user)
inquirer = user
for(var/mob/dead/observer/O in player_list)
if(!O.MayRespawn())
continue
if(jobban_isbanned(O, "pAI"))
continue
if(asked.Find(O.key))
if(world.time < asked[O.key] + askDelay)
continue
else
asked.Remove(O.key)
if(O.client)
if(BE_PAI in O.client.prefs.be_special_role)
question(O.client)
/datum/paiController/proc/question(var/client/C)
spawn(0)
if(!C) return
asked.Add(C.key)
asked[C.key] = world.time
var/response = alert(C, "[inquirer] is requesting a pAI personality. Would you like to play as a personal AI?", "pAI Request", "Yes", "No", "Never for this round")
if(!C) return //handle logouts that happen whilst the alert is waiting for a response.
if(response == "Yes")
recruitWindow(C.mob)
else if (response == "Never for this round")
C.prefs.be_special_role -= BE_PAI
@@ -16,26 +16,9 @@ var/list/pai_emotions = list(
"Question Mark" = 15
)
var/global/list/pai_software_by_key = list()
var/global/list/default_pai_software = list()
/hook/startup/proc/populate_pai_software_list()
var/r = 1 // I would use ., but it'd sacrifice runtime detection
for(var/type in typesof(/datum/pai_software) - /datum/pai_software)
var/datum/pai_software/P = new type()
if(pai_software_by_key[P.id])
var/datum/pai_software/O = pai_software_by_key[P.id]
world << "<span class='warning'>pAI software module [P.name] has the same key as [O.name]!</span>"
r = 0
continue
pai_software_by_key[P.id] = P
if(P.default)
default_pai_software[P.id] = P
return r
/mob/living/silicon/pai/New()
/mob/living/silicon/pai/Initialize()
..()
software = default_pai_software.Copy()
software = SSpai.default_pai_software.Copy()
/mob/living/silicon/pai/verb/paiInterface()
set category = "pAI Commands"
@@ -62,6 +45,8 @@ var/global/list/default_pai_software = list()
var/bought_software[0]
// Software we have not bought
var/not_bought_software[0]
var/list/pai_software_by_key = SSpai.pai_software_by_key
for(var/key in pai_software_by_key)
var/datum/pai_software/S = pai_software_by_key[key]
@@ -118,7 +103,7 @@ var/global/list/default_pai_software = list()
else if(href_list["purchase"])
var/soft = href_list["purchase"]
var/datum/pai_software/S = pai_software_by_key[soft]
var/datum/pai_software/S = SSpai.pai_software_by_key[soft]
if(S && (ram >= S.ram_cost))
ram -= S.ram_cost
software[S.id] = S
@@ -90,7 +90,7 @@ var/list/mob_hat_cache = list()
/mob/living/silicon/robot/drone/Destroy()
if(hat)
hat.loc = get_turf(src)
..()
return ..()
/mob/living/silicon/robot/drone/construction
icon_state = "constructiondrone"
@@ -149,13 +149,11 @@ var/list/mob_hat_cache = list()
/mob/living/silicon/robot/drone/updateicon()
overlays.Cut()
cut_overlays()
if(stat == 0)
overlays += "eyes-[icon_state]"
else
overlays -= "eyes"
add_overlay("eyes-[icon_state]")
if(hat) // Let the drones wear hats.
overlays |= get_hat_icon(hat, hat_x_offset, hat_y_offset)
add_overlay(get_hat_icon(hat, hat_x_offset, hat_y_offset))
/mob/living/silicon/robot/drone/choose_icon()
return
@@ -4,7 +4,7 @@
set desc = "Tag yourself for delivery through the disposals system."
set category = "Robot Commands"
var/new_tag = input("Select the desired destination.", "Set Mail Tag", null) as null|anything in tagger_locations
var/new_tag = input("Select the desired destination.", "Set Mail Tag", null) as null|anything in SSdisposals.tagger_locations
if(!new_tag)
mail_destination = ""
@@ -19,8 +19,6 @@
src << "<span class='notice'>\The [D] acknowledges your signal.</span>"
D.flush_count = D.flush_every_ticks
return
/mob/living/silicon/robot/drone/MouseDrop(atom/over_object)
var/mob/living/carbon/H = over_object
if(!istype(H) || !Adjacent(H)) return ..()
@@ -34,4 +32,4 @@
hat = null
updateicon()
else
return ..()
return ..()
@@ -59,7 +59,7 @@
if (href_list["setarea"])
//Probably should consider using another list, but this one will do.
var/t_area = input("Select the area to ping.", "Set Target Area", null) as null|anything in tagger_locations
var/t_area = input("Select the area to ping.", "Set Target Area", null) as null|anything in SSdisposals.tagger_locations
if(!t_area)
return
@@ -120,4 +120,4 @@
dronefab.produce_drones = !dronefab.produce_drones
usr << "<span class='notice'>You [dronefab.produce_drones ? "enable" : "disable"] drone production in the nearby fabricator.</span>"
src.updateUsrDialog()
src.updateUsrDialog()
@@ -29,9 +29,6 @@
fabricator_tag = "Derelict"
drone_type = /mob/living/silicon/robot/drone/construction
/obj/machinery/drone_fabricator/New()
..()
/obj/machinery/drone_fabricator/power_change()
..()
if (stat & NOPOWER)
@@ -39,7 +36,7 @@
/obj/machinery/drone_fabricator/process()
if(ticker.current_state < GAME_STATE_PLAYING)
if(!ROUND_IS_STARTED)
return
if(stat & NOPOWER || !produce_drones)
@@ -78,8 +75,10 @@
flick("h_lathe_leave",src)
time_last_drone = world.time
if(player.mob && player.mob.mind) player.mob.mind.reset()
var/mob/living/silicon/robot/drone/new_drone = getFromPool(drone_type, get_turf(src))
if(player.mob && player.mob.mind)
player.mob.mind.reset()
var/mob/living/silicon/robot/drone/new_drone = new drone_type(get_turf(src))
new_drone.transfer_personality(player)
new_drone.master_fabricator = src
@@ -93,7 +92,7 @@
/proc/try_drone_spawn(var/mob/user, var/obj/machinery/drone_fabricator/fabricator)
if(ticker.current_state < GAME_STATE_PLAYING)
if(!ROUND_IS_STARTED)
user << "<span class='danger'>The game hasn't started yet!</span>"
return
@@ -1,6 +1,5 @@
/mob/living/silicon/robot/Life()
set invisibility = 0
set background = 1
set background = BACKGROUND_ENABLED
if (src.transforming)
return
@@ -765,30 +765,28 @@
return 0
/mob/living/silicon/robot/updateicon()
overlays.Cut()
cut_overlays()
if(stat == CONSCIOUS)
overlays += "eyes-[module_sprites[icontype]]"
add_overlay("eyes-[module_sprites[icontype]]")
if(opened)
var/panelprefix = custom_sprite ? src.ckey : "ov"
if(wiresexposed)
overlays += "[panelprefix]-openpanel +w"
add_overlay("[panelprefix]-openpanel +w")
else if(cell)
overlays += "[panelprefix]-openpanel +c"
add_overlay("[panelprefix]-openpanel +c")
else
overlays += "[panelprefix]-openpanel -c"
add_overlay("[panelprefix]-openpanel -c")
if(module_active && istype(module_active,/obj/item/borg/combat/shield))
overlays += "[module_sprites[icontype]]-shield"
add_overlay("[module_sprites[icontype]]-shield")
if(modtype == "Combat")
if(module_active && istype(module_active,/obj/item/borg/combat/mobility))
icon_state = "[module_sprites[icontype]]-roll"
else
icon_state = module_sprites[icontype]
return
/mob/living/silicon/robot/proc/installed_modules()
if(weapon_lock)
@@ -28,28 +28,27 @@
verbs += /mob/living/silicon/robot/proc/choose_icon
/mob/living/silicon/robot/syndicate/updateicon() //because this was the only way I found out how to make their eyes and etc works
overlays.Cut()
cut_overlays()
if(stat == 0)
overlays += "eyes-[icon_state]"
add_overlay("eyes-[icon_state]")
if(opened)
var/panelprefix = custom_sprite ? src.ckey : "ov"
if(wiresexposed)
overlays += "[panelprefix]-openpanel +w"
add_overlay("[panelprefix]-openpanel +w")
else if(cell)
overlays += "[panelprefix]-openpanel +c"
add_overlay("[panelprefix]-openpanel +c")
else
overlays += "[panelprefix]-openpanel -c"
add_overlay("[panelprefix]-openpanel -c")
if(module_active && istype(module_active,/obj/item/borg/combat/shield))
overlays += "[icon_state]-shield"
add_overlay("[icon_state]-shield")
if(modtype == "Combat")
if(module_active && istype(module_active,/obj/item/borg/combat/mobility))
icon_state = "[icon_state]-roll"
else
icon_state = module_sprites[icontype]
return
/mob/living/silicon/robot/syndicate/death()
..()
+2 -2
View File
@@ -45,9 +45,9 @@
/mob/living/silicon/Destroy()
silicon_mob_list -= src
for(var/datum/alarm_handler/AH in alarm_manager.all_handlers)
for(var/datum/alarm_handler/AH in SSalarm.all_handlers)
AH.unregister_alarm(src)
..()
return ..()
/mob/living/silicon/proc/init_id()
if(idcard)
+1 -1
View File
@@ -69,7 +69,7 @@
if(!register_alarms)
return
for(var/datum/alarm_handler/AH in alarm_manager.all_handlers)
for(var/datum/alarm_handler/AH in SSalarm.all_handlers)
AH.register_alarm(src, /mob/living/silicon/proc/receive_alarm)
queued_alarms[AH] = list() // Makes sure alarms remain listed in consistent order
@@ -28,7 +28,11 @@
/mob/living/simple_animal/bee/Destroy()
if(parent)
parent.owned_bee_swarms.Remove(src)
..()
my_hydrotray = null
parent = null
target_turf = null
target_mob = null
return ..()
//Special death behaviour. When bees accumulate enough damage to 'die', they don't outright die. Thus no call to parent
@@ -36,7 +40,7 @@
//Repeat until strength hits zero. only THEN do they die, and they qdel and leave no corpse in doing so
//Because we don't have sprites for a carpet made of bee corpses.
/mob/living/simple_animal/bee/death()
if (!gcDestroyed)
if (!QDELING(src))
strength -= 1
if (strength <= 0)
if (prob(35))//probability to reduce spam
@@ -261,4 +265,4 @@
/mob/living/simple_animal/bee/beegun
maxHealth = 30
strength = 5
feral = 30
feral = 30
@@ -27,7 +27,7 @@
var/corpseidaccess = null //This is for access. See access.dm for which jobs give what access. Again, put in quotes. Use "Captain" if you want it to be all access.
var/corpseidicon = null //For setting it to be a gold, silver, centcomm etc ID
/obj/effect/landmark/mobcorpse/New()
/obj/effect/landmark/mobcorpse/Initialize()
createCorpse()
/obj/effect/landmark/mobcorpse/proc/createCorpse() //Creates a mob and checks for gear in each slot before attempting to equip it.
@@ -154,4 +154,4 @@
corpsehelmet = /obj/item/clothing/head/bearpelt
/obj/effect/landmark/mobcorpse/russian/ranged
corpsehelmet = /obj/item/clothing/head/ushanka
corpsehelmet = /obj/item/clothing/head/ushanka
@@ -63,8 +63,7 @@
if (!movement_target)
walk_to(src,0)
spawn(2)
attack_mice()
addtimer(CALLBACK(src, .proc/attack_mice), 2)
if(prob(2)) //spooky
var/mob/dead/observer/spook = locate() in range(src,5)
@@ -110,8 +109,7 @@
/mob/living/simple_animal/cat/Released()
//A thrown cat will immediately attack mice near where it lands
handle_movement_target()
spawn(3)
attack_mice()
addtimer(CALLBACK(src, .proc/attack_mice), 3)
..()
/mob/living/simple_animal/cat/death()
@@ -164,7 +162,7 @@
var/befriend_job = null
/mob/living/simple_animal/cat/fluff/handle_movement_target()
if (friend)
if (!QDELETED(friend))
var/follow_dist = 5
if (friend.stat >= DEAD || friend.health <= config.health_threshold_softcrit) //danger
follow_dist = 1
@@ -197,7 +195,7 @@
/mob/living/simple_animal/cat/fluff/Life()
..()
if (stat || !friend)
if (stat || QDELETED(friend))
return
if (get_dist(src, friend) <= 1)
if (friend.stat >= DEAD || friend.health <= config.health_threshold_softcrit)
@@ -200,9 +200,6 @@
..()
desc = "How could you do this? You monster!"
var/const/MAX_CHICKENS = 50
var/global/chicken_count = 0
/mob/living/simple_animal/chicken
name = "\improper chicken"
desc = "Hopefully the eggs are good this season."
@@ -230,6 +227,8 @@ var/global/chicken_count = 0
mob_size = 2
hunger_enabled = FALSE
var/static/chicken_count = 0
/mob/living/simple_animal/chicken/New()
..()
if(!body_color)
@@ -283,16 +282,19 @@ var/global/chicken_count = 0
E.pixel_x = rand(-6,6)
E.pixel_y = rand(-6,6)
if(chicken_count < MAX_CHICKENS && prob(10))
processing_objects.Add(E)
START_PROCESSING(SSprocessing, E)
/obj/item/weapon/reagent_containers/food/snacks/egg
var/amount_grown = 0
/obj/item/weapon/reagent_containers/food/snacks/egg/var/amount_grown = 0
/obj/item/weapon/reagent_containers/food/snacks/egg/process()
if(isturf(loc))
amount_grown += rand(1,2)
if(amount_grown >= 100)
visible_message("[src] hatches with a quiet cracking sound.")
new /mob/living/simple_animal/chick(get_turf(src))
processing_objects.Remove(src)
STOP_PROCESSING(SSprocessing, src)
qdel(src)
else
STOP_PROCESSING(SSprocessing, src)
processing_objects.Remove(src)
@@ -40,7 +40,7 @@
/mob/living/simple_animal/adultslime/New()
..()
overlays += "aslime-:33"
add_overlay("aslime-:33")
/mob/living/simple_animal/slime/adult/death()
@@ -54,4 +54,4 @@
S2.icon_living = "[src.colour] baby slime"
S2.icon_dead = "[src.colour] baby slime dead"
S2.colour = "[src.colour]"
qdel(src)
qdel(src)
@@ -156,7 +156,7 @@
eject_brain()
death()
/mob/living/simple_animal/spiderbot/proc/update_icon()
/mob/living/simple_animal/spiderbot/update_icon()
if(mmi)
if(positronic)
icon_state = "spiderbot-chassis-posi"
@@ -183,7 +183,7 @@
/mob/living/simple_animal/spiderbot/Destroy()
eject_brain()
..()
return ..()
/mob/living/simple_animal/spiderbot/New()
@@ -47,6 +47,10 @@
/mob/living/simple_animal/hostile/scarybat/Allow_Spacemove(var/check_drift = 0)
return ..() //No drifting in space for space carp! //original comments do not steal
/mob/living/simple_animal/hostile/scarybat/Destroy()
owner = null
return ..()
/mob/living/simple_animal/hostile/scarybat/FindTarget()
. = ..()
if(.)
@@ -151,7 +151,7 @@
if(busy == LAYING_EGGS)
E = locate() in get_turf(src)
if(!E)
getFromPool(/obj/effect/spider/eggcluster, loc, src)
new /obj/effect/spider/eggcluster(loc, src)
fed--
busy = 0
stop_automated_movement = 0
@@ -19,6 +19,11 @@
var/shuttletarget = null
var/enroute = 0
/mob/living/simple_animal/hostile/Destroy()
friends = null
target_mob = null
return ..()
/mob/living/simple_animal/hostile/proc/FindTarget()
var/atom/T = null
@@ -74,7 +79,7 @@
/mob/living/simple_animal/hostile/proc/MoveToTarget()
stop_automated_movement = 1
if(!target_mob || SA_attackable(target_mob))
if(QDELETED(target_mob) || SA_attackable(target_mob))
LoseTarget()
if(target_mob in ListTargets(10))
if(ranged)
@@ -89,7 +94,7 @@
/mob/living/simple_animal/hostile/proc/AttackTarget()
stop_automated_movement = 1
if(!target_mob || SA_attackable(target_mob))
if(QDELETED(target_mob) || SA_attackable(target_mob))
LoseTarget()
return 0
if(!(target_mob in ListTargets(10)))
@@ -129,7 +134,7 @@
/mob/living/simple_animal/hostile/proc/ListTargets(var/dist = 7)
var/list/L = hearers(src, dist)
var/list/L = view(src, dist)
for (var/obj/mecha/M in mechas_list)
if (M.z == src.z && get_dist(src, M) <= dist)
@@ -170,18 +175,11 @@
visible_message("\red <b>[src]</b> fires at [target]!", 1)
if(rapid)
spawn(1)
Shoot(target, src.loc, src)
if(casingtype)
new casingtype(get_turf(src))
spawn(4)
Shoot(target, src.loc, src)
if(casingtype)
new casingtype(get_turf(src))
spawn(6)
Shoot(target, src.loc, src)
if(casingtype)
new casingtype(get_turf(src))
var/datum/callback/shoot_cb = CALLBACK(src, .proc/shoot_wrapper, target, loc, src)
addtimer(shoot_cb, 1)
addtimer(shoot_cb, 4)
addtimer(shoot_cb, 6)
else
Shoot(target, src.loc, src)
if(casingtype)
@@ -191,6 +189,10 @@
target_mob = null
return
/mob/living/simple_animal/hostile/proc/shoot_wrapper(target, location, user)
Shoot(target, location, user)
if (casingtype)
new casingtype(loc)
/mob/living/simple_animal/hostile/proc/Shoot(var/target, var/start, var/user, var/bullet = 0)
if(target == start)
@@ -60,8 +60,8 @@
var/attempt_open = 0
// Pickup loot
/mob/living/simple_animal/hostile/mimic/crate/initialize()
..()
/mob/living/simple_animal/hostile/mimic/crate/Initialize()
. = ..()
for(var/obj/item/I in loc)
I.loc = src
@@ -157,6 +157,7 @@
qdel(src)
/mob/living/simple_animal/hostile/retaliate/malf_drone/Destroy()
QDEL_NULL(ion_trail)
//some random debris left behind
if(has_loot)
spark(src, 3, alldirs)
@@ -176,16 +177,16 @@
step_to(O, get_turf(pick(view(7, src))))
//rods
O = getFromPool(/obj/item/stack/rods, src.loc)
O = new /obj/item/stack/rods(src.loc)
step_to(O, get_turf(pick(view(7, src))))
if(prob(75))
O = getFromPool(/obj/item/stack/rods, src.loc)
O = new /obj/item/stack/rods(src.loc)
step_to(O, get_turf(pick(view(7, src))))
if(prob(50))
O = getFromPool(/obj/item/stack/rods, src.loc)
O = new /obj/item/stack/rods(src.loc)
step_to(O, get_turf(pick(view(7, src))))
if(prob(25))
O = getFromPool(/obj/item/stack/rods, src.loc)
O = new /obj/item/stack/rods(src.loc)
step_to(O, get_turf(pick(view(7, src))))
//plasteel
@@ -263,7 +264,7 @@
C.name = "Corrupted drone morality core"
C.origin_tech = list(TECH_ILLEGAL = rand(3,6))
..()
return ..()
/obj/item/projectile/beam/drone
damage = 15
@@ -1,6 +1,10 @@
/mob/living/simple_animal/hostile/retaliate
var/list/enemies = list()
/mob/living/simple_animal/hostile/retaliate/Destroy()
enemies = null
return ..()
/mob/living/simple_animal/hostile/retaliate/Found(var/atom/A)
if(isliving(A))
var/mob/living/L = A
@@ -100,6 +100,11 @@
/mob/living/simple_animal/parrot/verb/drop_held_item_player, \
/mob/living/simple_animal/parrot/proc/perch_player)
/mob/living/simple_animal/parrot/Destroy()
QDEL_NULL(ears)
parrot_interest = null
parrot_perch = null
return ..()
/mob/living/simple_animal/parrot/death()
if(held_item)
@@ -751,4 +756,4 @@
parrot_interest = user
parrot_state = PARROT_SWOOP | PARROT_ATTACK //Attack other animals regardless
icon_state = "parrot_fly"
return success
return success
@@ -101,7 +101,7 @@
Destroy() //if a chunk a destroyed, make a new worm out of the split halves
if(previous)
previous.Detach()
..()
return ..()
Move()
var/attachementNextPosition = loc
@@ -123,7 +123,7 @@
return
proc/update_icon() //only for the sake of consistency with the other update icon procs
update_icon() //only for the sake of consistency with the other update icon procs
if(stat == CONSCIOUS || stat == UNCONSCIOUS)
if(previous) //midsection
icon_state = "spaceworm[get_dir(src,previous) | get_dir(src,next)]" //see 3 lines below
+1 -1
View File
@@ -3,7 +3,7 @@
player_list -= src
log_access("Logout: [key_name(src)]",ckey=key_name(src))
if(admin_datums[src.ckey])
if (ticker && ticker.current_state == GAME_STATE_PLAYING) //Only report this stuff if we are currently playing.
if (SSticker.current_state == GAME_STATE_PLAYING) //Only report this stuff if we are currently playing.
var/admins_number = 0
var/admins_number_afk = 0
for (var/client/C)
+45 -40
View File
@@ -3,7 +3,7 @@
dead_mob_list -= src
living_mob_list -= src
unset_machine()
qdel(hud_used)
QDEL_NULL(hud_used)
if(client)
for(var/obj/screen/movable/spell_master/spell_master in spell_masters)
qdel(spell_master)
@@ -15,8 +15,7 @@
spellremove(src)
for(var/infection in viruses)
qdel(infection)
viruses.Cut()
//Added this to prevent nonliving mobs from ghostising
//The only non 'living' mobs are:
@@ -28,7 +27,9 @@
//Ghosts are the only ones that even technically 'exist' and aren't just an abstraction using mob code for convenience
if (istype(src, /mob/living))
ghostize()
..()
return ..()
/mob/proc/remove_screen_obj_references()
flash = null
@@ -103,6 +104,10 @@
for(var/A in player_list)
var/mob/M = A
if (QDELETED(M))
warning("Null or QDELETED object [DEBUG_REF(M)] found in player list! Removing.")
player_list -= M
continue
if (!M.client || istype(M, /mob/new_player))
continue
if(get_turf(M) in messageturfs)
@@ -174,7 +179,6 @@
M.show_message(message,2,deaf_message,1)
for(var/o in objs)
var/obj/O = o
O.show_message(message,2,deaf_message,1)
@@ -302,15 +306,13 @@
pointing_effect = new /obj/effect/decal/point(tile)
pointing_effect.invisibility = invisibility
spawn (20)
if(pointing_effect)
qdel(pointing_effect) // qdel
pointing_effect = null
addtimer(CALLBACK(src, .proc/clear_point), 20)
face_atom(A)
return 1
/mob/proc/clear_point()
QDEL_NULL(pointing_effect)
/mob/proc/ret_grab(obj/effect/list_container/mobl/L as obj, flag)
if ((!( istype(l_hand, /obj/item/weapon/grab) ) && !( istype(r_hand, /obj/item/weapon/grab) )))
@@ -448,10 +450,10 @@
if (!( config.abandon_allowed ))
usr << "<span class='notice'>Respawn is disabled.</span>"
return
if ((stat != DEAD || !( ticker )))
if (stat != DEAD)
usr << "<span class='notice'><B>You must be dead to use this!</B></span>"
return
if (ticker.mode.deny_respawn) //BS12 EDIT
if (SSticker.mode && SSticker.mode.deny_respawn) //BS12 EDIT
usr << "<span class='notice'>Respawn is disabled for this roundtype.</span>"
return
else if(!MayRespawn(1, CREW))
@@ -487,26 +489,8 @@
/client/verb/changes()
set name = "Changelog"
set category = "OOC"
getFiles(
'html/88x31.png',
'html/bug-minus.png',
'html/cross-circle.png',
'html/hard-hat-exclamation.png',
'html/image-minus.png',
'html/image-plus.png',
'html/map-pencil.png',
'html/music-minus.png',
'html/music-plus.png',
'html/tick-circle.png',
'html/wrench-screwdriver.png',
'html/spell-check.png',
'html/burn-exclamation.png',
'html/chevron.png',
'html/chevron-expand.png',
'html/changelog.css',
'html/changelog.js',
'html/changelog.html'
)
var/datum/asset/changelog = get_asset_datum(/datum/asset/simple/changelog)
changelog.send(src)
src << browse('html/changelog.html', "window=changes;size=675x650")
if(prefs.lastchangelog != changelog_hash)
prefs.lastchangelog = changelog_hash
@@ -746,7 +730,7 @@
. = (is_client_active(10 MINUTES))
if(.)
if(statpanel("Status") && ticker && ticker.current_state != GAME_STATE_PREGAME)
if(statpanel("Status") && SSticker.current_state != GAME_STATE_PREGAME)
stat("Game ID", game_id)
stat("Station Time", worldtime2text())
stat("Round Duration", round_duration())
@@ -755,24 +739,45 @@
if(client.holder)
if(statpanel("Status"))
stat("Location:", "([x], [y], [z]) [loc]")
stat("CPU:","[world.cpu]")
stat("Instances:","[world.contents.len]")
if(statpanel("Processes"))
if(processScheduler)
processScheduler.statProcesses()
if (LAZYLEN(client.holder.watched_processes))
for (var/datum/controller/ctrl in client.holder.watched_processes)
if (!ctrl)
LAZYREMOVE(client.holder.watched_processes, ctrl)
else
ctrl.stat_entry()
if(statpanel("MC"))
stat("CPU:", world.cpu)
stat("Tick Usage:", world.tick_usage)
stat("Instances:", world.contents.len)
if(Master)
Master.stat_entry()
else
stat("Master Controller:", "ERROR")
if(Failsafe)
Failsafe.stat_entry()
else
stat("Failsafe Controller:", "ERROR")
if (Master)
stat(null, "- Subsystems -")
for(var/datum/controller/subsystem/SS in Master.subsystems)
if (!Master.initializing && SS.flags & SS_NO_DISPLAY)
continue
SS.stat_entry()
if(listed_turf && client)
if(!TurfAdjacent(listed_turf))
listed_turf = null
else
if(statpanel("Turf"))
stat("\icon[listed_turf]", listed_turf.name)
stat("Turf:", listed_turf)
for(var/atom/A in listed_turf)
if(!A.mouse_opacity)
continue
if(A.invisibility > see_invisible)
continue
if(is_type_in_list(A, shouldnt_see))
if(is_type_in_typecache(A, shouldnt_see))
continue
stat(A)
+3 -3
View File
@@ -170,7 +170,7 @@
var/captured = 0 //Functionally, should give the same effect as being buckled into a chair when true.
//Generic list for proc holders. Only way I can see to enable certain verbs/procs. Should be modified if needed.
var/proc_holder_list[] = list()//Right now unused.
//var/proc_holder_list[] = list()//Right now unused.
//Also unlike the spell list, this would only store the object in contents, not an object in itself.
/* Add this line to whatever stat module you need in order to use the proc holder list.
@@ -186,7 +186,7 @@
var/mob/living/carbon/LAssailant = null
//Wizard mode, but can be used in other modes thanks to the brand new "Give Spell" badmin button
var/spell/list/spell_list = list()
var/spell/list/spell_list
//Changlings, but can be used in other modes
// var/obj/effect/proc_holder/changpower/list/power_list = list()
@@ -226,7 +226,7 @@
var/mob/teleop = null
var/turf/listed_turf = null //the current turf being examined in the stat panel
var/list/shouldnt_see = list() //list of objects that this mob shouldn't see in the stat panel. this silliness is needed because of AI alt+click and cult blood runes
var/list/shouldnt_see = list() //typecache of objects that this mob shouldn't see in the stat panel. this silliness is needed because of AI alt+click and cult blood runes
var/list/active_genes=list()
var/mob_size = MOB_MEDIUM
+2 -2
View File
@@ -90,7 +90,7 @@
hud.screen_loc = ui_lhand
/obj/item/weapon/grab/process()
if(gcDestroyed) // GC is trying to delete us, we'll kill our processing so we can cleanly GC
if(QDELING(src)) // GC is trying to delete us, we'll kill our processing so we can cleanly GC
return PROCESS_KILL
confirm()
@@ -361,4 +361,4 @@
qdel(hud)
hud = null
destroying = 1 // stops us calling qdel(src) on dropped()
..()
return ..()
+42 -92
View File
@@ -184,34 +184,26 @@
if(!mob)
return // Moved here to avoid nullrefs below
if(mob.control_object) Move_object(direct)
if(mob.control_object)
Move_object(direct)
if(mob.incorporeal_move && isobserver(mob))
Process_Incorpmove(direct)
return
if(moving) return 0
if(moving || world.time < move_delay)
return 0
if(world.time < move_delay)
return
//This compensates for the inaccuracy of move ticks
//Whenever world.time overshoots the movedelay, due to it only ticking once per decisecond
//The overshoot value is subtracted from our next delay, farther down where move delay is set.
//This doesn't entirely remove the problem, but it keeps travel times accurate to within 0.1 seconds
//Over an infinite distance, and prevents the inaccuracy from compounding. Thus making it basically a non-issue
//This compensates for the inaccuracy of move ticks
//Whenever world.time overshoots the movedelay, due to it only ticking once per decisecond
//The overshoot value is subtracted from our next delay, farther down where move delay is set.
//This doesn't entirely remove the problem, but it keeps travel times accurate to within 0.1 seconds
//Over an infinite distance, and prevents the inaccuracy from compounding. Thus making it basically a non-issue
var/leftover = world.time - move_delay
if (leftover > 1)
leftover = 0
if(locate(/obj/effect/stop/, mob.loc))
for(var/obj/effect/stop/S in mob.loc)
if(S.victim == mob)
return
if(mob.stat==DEAD && isliving(mob))
if(mob.stat == DEAD && isliving(mob))
mob.ghostize()
return
@@ -219,21 +211,24 @@
if(mob.eyeobj)
return mob.EyeMove(n,direct)
if(mob.transforming) return//This is sota the goto stop mobs from moving var
if(mob.transforming)
return //This is sota the goto stop mobs from moving var
if(isliving(mob))
var/mob/living/L = mob
if(L.incorporeal_move)//Move though walls
Process_Incorpmove(direct)
return
if(mob.client)
if(mob.client.view != world.view) // If mob moves while zoomed in with device, unzoom them.
for(var/obj/item/item in mob.contents)
if(item.zoom)
item.zoom(mob)
break
if(Process_Grab()) return
if(mob.client && mob.client.view != world.view) // If mob moves while zoomed in with device, unzoom them.
for(var/obj/item/item in mob)
if(item.zoom)
item.zoom(mob)
break
// Only meaningful for living mobs.
if(Process_Grab())
return
if(!mob.canmove)
return
@@ -244,22 +239,18 @@
if(!mob.lastarea)
mob.lastarea = get_area(mob.loc)
if(!mob.check_solid_ground())
var/allowmove = mob.Allow_Spacemove(0)
if(!allowmove)
return 0
else if(allowmove == -1 && mob.handle_spaceslipping()) //Check to see if we slipped
return 0
else
mob.inertia_dir = 0 //If not then we can reset inertia and move
if(isobj(mob.loc) || ismob(mob.loc))//Inside an object, tell it we moved
var/atom/O = mob.loc
return O.relaymove(mob, direct)
if(isturf(mob.loc))
if(!mob.check_solid_ground())
var/allowmove = mob.Allow_Spacemove(0)
if(!allowmove)
return 0
else if(allowmove == -1 && mob.handle_spaceslipping()) //Check to see if we slipped
return 0
else
mob.inertia_dir = 0 //If not then we can reset inertia and move
if(mob.restrained())//Why being pulled while cuffed prevents you from moving
if(mob.restrained()) //Why being pulled while cuffed prevents you from moving
for(var/mob/M in range(mob, 1))
if(M.pulling == mob)
if(!M.restrained() && M.stat == 0 && M.canmove && mob.Adjacent(M))
@@ -284,9 +275,6 @@
direct = pick(cardinal)
return mob.buckled.relaymove(mob,direct)
if(istype(mob.loc, /turf/space)) // Wheelchair driving!
return // No wheelchair driving in space
//TODO: Fuck wheelchairs.
//Toss away all this snowflake code here, and rewrite wheelchairs as a vehicle.
else if(istype(mob.buckled, /obj/structure/bed/chair/wheelchair))
@@ -306,8 +294,9 @@
var/tally = mob.movement_delay() + config.walk_speed
// Apply huuman specific modifiers.
if (ishuman(mob))
// Apply human specific modifiers.
var/mob_is_human = ishuman(mob) // Only check this once and just reuse the value.
if (mob_is_human)
var/mob/living/carbon/human/H = mob
//If we're sprinting and able to continue sprinting, then apply the sprint bonus ontop of this
if (H.m_intent == "run" && H.species.handle_sprint_cost(H, tally)) //This will return false if we collapse from exhaustion
@@ -319,7 +308,6 @@
move_delay += tally
var/tickcomp = 0 //moved this out here so we can use it for vehicles
if(config.Tickcomp)
// move_delay -= 1.3 //~added to the tickcomp calculation below
@@ -336,12 +324,10 @@
move_delay += 1
return mob.pulledby.relaymove(mob, direct)
//We are now going to move
moving = 1
//Something with pulling things
if(locate(/obj/item/weapon/grab, mob))
if (mob_is_human && (istype(mob:l_hand, /obj/item/weapon/grab) || istype(mob:r_hand, /obj/item/weapon/grab)))
move_delay = max(move_delay, world.time + 7)
var/list/L = mob.ret_grab()
if(istype(L, /list))
@@ -378,28 +364,28 @@
else
. = mob.SelfMove(n, direct)
for (var/obj/item/weapon/grab/G in mob)
for (var/obj/item/weapon/grab/G in list(mob:l_hand, mob:r_hand))
if (G.state == GRAB_NECK)
mob.set_dir(reverse_dir[direct])
G.adjust_position()
for (var/obj/item/weapon/grab/G in mob.grabbed_by)
G.adjust_position()
moving = 0
return .
return
if(isobj(mob.loc) || ismob(mob.loc)) //Inside an object, tell it we moved
var/atom/O = mob.loc
return O.relaymove(mob, direct)
/mob/proc/SelfMove(turf/n, direct)
return Move(n, direct)
///Process_Incorpmove
///Called by client/Move()
///Allows mobs to run though walls
/client/proc/Process_Incorpmove(direct)
var/turf/mobloc = get_turf(mob)
switch(mob.incorporeal_move)
if(1)
var/turf/T = get_step(mob, direct)
@@ -410,44 +396,8 @@
mob.forceMove(get_step(mob, direct))
mob.dir = direct
if(2)
if(prob(50))
var/locx
var/locy
switch(direct)
if(NORTH)
locx = mobloc.x
locy = (mobloc.y+2)
if(locy>world.maxy)
return
if(SOUTH)
locx = mobloc.x
locy = (mobloc.y-2)
if(locy<1)
return
if(EAST)
locy = mobloc.y
locx = (mobloc.x+2)
if(locx>world.maxx)
return
if(WEST)
locy = mobloc.y
locx = (mobloc.x-2)
if(locx<1)
return
else
return
mob.forceMove(locate(locx,locy,mobloc.z))
spawn(0)
var/limit = 2//For only two trailing shadows.
for(var/turf/T in getline(mobloc, mob.loc))
spawn(0)
anim(T,mob,'icons/mob/mob.dmi',,"shadow",,mob.dir)
limit--
if(limit<=0) break
else
spawn(0)
anim(mobloc,mob,'icons/mob/mob.dmi',,"shadow",,mob.dir)
mob.forceMove(get_step(mob, direct))
anim(mobloc,mob,'icons/mob/mob.dmi',,"shadow",,mob.dir)
mob.forceMove(get_step(mob, direct))
mob.dir = direct
// Crossed is always a bit iffy
for(var/obj/S in mob.loc)
+14 -3
View File
@@ -1,4 +1,4 @@
/var/obj/effect/lobby_image = new/obj/effect/lobby_image()
/var/obj/effect/lobby_image
/obj/effect/lobby_image
name = "Aurorastation"
@@ -6,7 +6,8 @@
icon = 'icons/misc/title.dmi'
screen_loc = "WEST,SOUTH"
/obj/effect/lobby_image/initialize()
/obj/effect/lobby_image/New()
..()
var/list/known_icon_states = icon_states(icon)
for(var/lobby_screen in config.lobby_screens)
if(!(lobby_screen in known_icon_states))
@@ -32,7 +33,8 @@
mind.current = src
loc = null
client.screen += lobby_image
show_title()
my_client = client
sight |= SEE_TURFS
player_list |= src
@@ -42,3 +44,12 @@
if(client)
handle_privacy_poll()
client.playtitlemusic()
/mob/new_player/proc/show_title()
set waitfor = FALSE
if (lobby_image)
client.screen += lobby_image
return
sleep(5)
.()
+29 -16
View File
@@ -18,6 +18,10 @@
New()
mob_list += src
Destroy()
mob_list -= src
return ..()
verb/new_player_panel()
set src = usr
new_player_panel_proc()
@@ -28,7 +32,7 @@
output +="<hr>"
output += "<p><a href='byond://?src=\ref[src];show_preferences=1'>Setup Character</A></p>"
if(!ticker || ticker.current_state <= GAME_STATE_PREGAME)
if(!ROUND_IS_STARTED)
if(ready)
output += "<p>\[ <b>Ready</b> | <a href='byond://?src=\ref[src];ready=0'>Not Ready</a> \]</p>"
else
@@ -67,24 +71,28 @@
Stat()
..()
if(statpanel("Lobby") && ticker)
if(statpanel("Lobby"))
stat("Game ID:", game_id)
if(ticker.hide_mode)
if(SSticker.hide_mode)
stat("Game Mode:", "Secret")
else
if(ticker.hide_mode == 0)
if(SSticker.hide_mode == 0)
stat("Game Mode:", "[master_mode]") // Old setting for showing the game mode
if(ticker.current_state == GAME_STATE_PREGAME)
stat("Time To Start:", "[ticker.pregame_timeleft][round_progressing ? "" : " (DELAYED)"]")
if(SSticker.current_state == GAME_STATE_PREGAME)
if (SSticker.lobby_ready)
stat("Time To Start:", "[SSticker.pregame_timeleft][round_progressing ? "" : " (DELAYED)"]")
else
stat("Time To Start:", "Waiting for Server")
stat("Players: [totalPlayers]", "Players Ready: [totalPlayersReady]")
totalPlayers = 0
totalPlayersReady = 0
for(var/mob/new_player/player in player_list)
stat("[player.key]", (player.ready)?("(Playing)"):(null))
totalPlayers++
if(player.ready)totalPlayersReady++
if(player.ready)
totalPlayersReady++
Topic(href, href_list[])
if(!client) return 0
@@ -94,7 +102,7 @@
return 1
if(href_list["ready"])
if(!ticker || ticker.current_state <= GAME_STATE_PREGAME) // Make sure we don't ready up after the round has started
if(SSticker.current_state <= GAME_STATE_PREGAME) // Make sure we don't ready up after the round has started
// Cannot join without a saved character, if we're on SQL saves.
if (config.sql_saves && !client.prefs.current_character)
alert(src, "You have not saved your character yet. Please do so before readying up.")
@@ -109,6 +117,11 @@
new_player_panel_proc()
if(href_list["observe"])
if (SSatoms.initialized < INITIALIZATION_INNEW_REGULAR)
// Don't allow players to observe until initialization is more or less complete.
// Letting them join too early breaks things, they can wait.
src << span("alert", "The server is still initializing, try observing again in a minute or so.")
return
if(alert(src,"Are you sure you wish to observe? You will have to wait 30 minutes before being able to respawn!","Player Setup","Yes","No") == "Yes")
if(!client) return 1
@@ -144,7 +157,7 @@
if(href_list["late_join"])
if(!ticker || ticker.current_state != GAME_STATE_PLAYING)
if(SSticker.current_state != GAME_STATE_PLAYING)
usr << "\red The round is either not ready, or has already finished..."
return
@@ -173,7 +186,7 @@
if(!config.enter_allowed)
usr << "<span class='notice'>There is an administrative lock on entering the game!</span>"
return
else if(ticker && ticker.mode && ticker.mode.explosion_in_progress)
else if(SSticker.mode && SSticker.mode.explosion_in_progress)
usr << "<span class='danger'>The station is currently exploding. Joining would go poorly.</span>"
return
@@ -300,7 +313,7 @@
proc/AttemptLateSpawn(rank,var/spawning_at)
if(src != usr)
return 0
if(!ticker || ticker.current_state != GAME_STATE_PLAYING)
if(SSticker.current_state != GAME_STATE_PLAYING)
usr << "\red The round is either not ready, or has already finished..."
return 0
if(!config.enter_allowed)
@@ -338,7 +351,7 @@
character.loc = C.loc
AnnounceCyborg(character, rank, "has been downloaded to the empty core in \the [character.loc.loc]")
ticker.mode.handle_latejoin(character)
SSticker.mode.handle_latejoin(character)
qdel(C)
qdel(src)
@@ -353,11 +366,11 @@
character.buckled.loc = character.loc
character.buckled.set_dir(character.dir)
ticker.mode.handle_latejoin(character)
SSticker.mode.handle_latejoin(character)
if(character.mind.assigned_role != "Cyborg")
data_core.manifest_inject(character)
ticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn
SSticker.minds += character.mind //Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn
//Grab some data from the character prefs for use in random news procs.
@@ -368,7 +381,7 @@
qdel(src)
proc/AnnounceCyborg(var/mob/living/character, var/rank, var/join_message)
if (ticker.current_state == GAME_STATE_PLAYING)
if (SSticker.current_state == GAME_STATE_PLAYING)
if(character.mind.role_alt_title)
rank = character.mind.role_alt_title
// can't use their name here, since cyborg namepicking is done post-spawn, so we'll just say "A new Cyborg has arrived"/"A new Android has arrived"/etc.
@@ -433,7 +446,7 @@
|| (new_character.species && (chosen_language.name in new_character.species.secondary_langs)))
new_character.add_language(lang)
if(ticker.random_players)
if(SSticker.random_players)
new_character.gender = pick(MALE, FEMALE)
client.prefs.real_name = random_name(new_character.gender)
client.prefs.randomize_appearance_for(new_character)