diff --git a/baystation12.dme b/baystation12.dme
index bdbb2ffbcb1..18ee361f931 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -397,6 +397,7 @@
#include "code\defines\procs\icon_procs_readme.dm"
#include "code\defines\procs\logging.dm"
#include "code\defines\procs\religion_name.dm"
+#include "code\defines\procs\sd_Alert.dm"
#include "code\defines\procs\station_name.dm"
#include "code\defines\procs\statistics.dm"
#include "code\defines\procs\syndicate_name.dm"
diff --git a/code/ZAS/Airflow.dm b/code/ZAS/Airflow.dm
index 661fe74d9b5..e2edcaac7a2 100644
--- a/code/ZAS/Airflow.dm
+++ b/code/ZAS/Airflow.dm
@@ -133,15 +133,16 @@ proc/Airflow(zone/A, zone/B)
else
connected_turfs |= C.B
- //Get lists of things that can be thrown across the room for each zone.
- var/list/pplz = B.movables()
- var/list/otherpplz = A.movables()
+ //Get lists of things that can be thrown across the room for each zone (assumes air is moving from zone B to zone A)
+ var/list/air_sucked = B.movables()
+ var/list/air_repelled = A.movables()
if(n < 0)
- var/list/temporary_pplz = pplz
- pplz = otherpplz
- otherpplz = temporary_pplz
+ //air is moving from zone A to zone B
+ var/list/temporary_pplz = air_sucked
+ air_sucked = air_repelled
+ air_repelled = temporary_pplz
- for(var/atom/movable/M in pplz)
+ for(var/atom/movable/M in air_sucked)
if(M.last_airflow > world.time - vsc.airflow_delay) continue
@@ -166,7 +167,7 @@ proc/Airflow(zone/A, zone/B)
spawn M.GotoAirflowDest(abs(n)/5)
//Do it again for the stuff in the other zone, making it fly away.
- for(var/atom/movable/M in otherpplz)
+ for(var/atom/movable/M in air_repelled)
if(M.last_airflow > world.time - vsc.airflow_delay) continue
@@ -240,12 +241,15 @@ atom/movable
if(airflow_dest == loc)
step_away(src,loc)
if(ismob(src))
- if(src:nodamage) return
+ if(src:nodamage)
+ return
if(istype(src, /mob/living/carbon/human))
- if(istype(src, /mob/living/carbon/human))
- if(src:buckled) return
- if(src:shoes)
- if(src:shoes.type == /obj/item/clothing/shoes/magboots && src:shoes.flags & NOSLIP) return
+ if(src:buckled)
+ return
+ if(src:shoes)
+ if(src:shoes.type == /obj/item/clothing/shoes/magboots)
+ if(src:shoes.flags & NOSLIP)
+ return
src << "\red You are sucked away by airflow!"
var/airflow_falloff = 9 - ul_FalloffAmount(airflow_dest) //It's a fast falloff calc. Very useful.
if(airflow_falloff < 1)
@@ -266,9 +270,15 @@ atom/movable
airflow_speed -= vsc.airflow_speed_decay
if(airflow_speed > 7)
if(airflow_time++ >= airflow_speed - 7)
+ if(od)
+ density = 0
sleep(1 * tick_multiplier)
else
+ if(od)
+ density = 0
sleep(max(1,10-(airflow_speed+3)) * tick_multiplier)
+ if(od)
+ density = 1
if ((!( src.airflow_dest ) || src.loc == src.airflow_dest))
src.airflow_dest = locate(min(max(src.x + xo, 1), world.maxx), min(max(src.y + yo, 1), world.maxy), src.z)
if ((src.x == 1 || src.x == world.maxx || src.y == 1 || src.y == world.maxy))
@@ -276,7 +286,8 @@ atom/movable
if(!istype(loc, /turf))
return
step_towards(src, src.airflow_dest)
- if(ismob(src) && src:client) src:client:move_delay = world.time + vsc.airflow_mob_slowdown
+ if(ismob(src) && src:client)
+ src:client:move_delay = world.time + vsc.airflow_mob_slowdown
airflow_dest = null
airflow_speed = 0
airflow_time = 0
@@ -295,12 +306,15 @@ atom/movable
if(airflow_dest == loc)
step_away(src,loc)
if(ismob(src))
- if(src:nodamage) return
+ if(src:nodamage)
+ return
if(istype(src, /mob/living/carbon/human))
- if(istype(src, /mob/living/carbon/human))
- if(src:buckled) return
- if(src:shoes)
- if(src:shoes.type == /obj/item/clothing/shoes/magboots && src:shoes.flags & NOSLIP) return
+ if(src:buckled)
+ return
+ if(src:shoes)
+ if(src:shoes.type == /obj/item/clothing/shoes/magboots)
+ if(src:shoes.flags & NOSLIP)
+ return
src << "\red You are pushed away by airflow!"
var/airflow_falloff = 9 - ul_FalloffAmount(airflow_dest) //It's a fast falloff calc. Very useful.
if(airflow_falloff < 1)
@@ -331,7 +345,8 @@ atom/movable
if(!istype(loc, /turf))
return
step_towards(src, src.airflow_dest)
- if(ismob(src) && src:client) src:client:move_delay = world.time + vsc.airflow_mob_slowdown
+ if(ismob(src) && src:client)
+ src:client:move_delay = world.time + vsc.airflow_mob_slowdown
airflow_dest = null
airflow_speed = 0
airflow_time = 0
diff --git a/code/ZAS/ZAS_Zones.dm b/code/ZAS/ZAS_Zones.dm
index afda25eba8c..50c0e15cff7 100644
--- a/code/ZAS/ZAS_Zones.dm
+++ b/code/ZAS/ZAS_Zones.dm
@@ -33,7 +33,7 @@ zone
if(!istype(T,/turf/simulated))
AddTurf(T)
- //Generate the gas_mixture for use in this zone by using the average of the gases
+ //Generate the gas_mixture for use in txhis zone by using the average of the gases
//defined at startup.
air = new
var/members = contents.len
@@ -283,6 +283,7 @@ proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles)
if(sharing_lookup_table.len >= connecting_tiles) //6 or more interconnecting tiles will max at 42% of air moved per tick.
ratio = sharing_lookup_table[connecting_tiles]
+ ratio *= 3
A.oxygen = max(0, (A.oxygen - oxy_avg) * (1-ratio) + oxy_avg )
A.nitrogen = max(0, (A.nitrogen - nit_avg) * (1-ratio) + nit_avg )
@@ -345,23 +346,23 @@ proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles)
size = max(1,A.group_multiplier)
share_size = max(1,unsimulated_tiles.len)
- full_oxy = A.oxygen * size
- full_nitro = A.nitrogen * size
- full_co2 = A.carbon_dioxide * size
- full_plasma = A.toxins * size
+ //full_oxy = A.oxygen * size
+ //full_nitro = A.nitrogen * size
+ //full_co2 = A.carbon_dioxide * size
+ //full_plasma = A.toxins * size
- full_heat_capacity = A.heat_capacity() * size
+ //full_heat_capacity = A.heat_capacity() * size
- oxy_avg = (full_oxy + unsim_oxygen) / (size + share_size)
- nit_avg = (full_nitro + unsim_nitrogen) / (size + share_size)
- co2_avg = (full_co2 + unsim_co2) / (size + share_size)
- plasma_avg = (full_plasma + unsim_plasma) / (size + share_size)
+ oxy_avg = unsim_oxygen//(full_oxy + unsim_oxygen) / (size + share_size)
+ nit_avg = unsim_nitrogen//(full_nitro + unsim_nitrogen) / (size + share_size)
+ co2_avg = unsim_co2//(full_co2 + unsim_co2) / (size + share_size)
+ plasma_avg = unsim_plasma//(full_plasma + unsim_plasma) / (size + share_size)
- temp_avg = (A.temperature * full_heat_capacity + unsim_temperature * unsim_heat_capacity) / (full_heat_capacity + unsim_heat_capacity)
+ temp_avg = unsim_temperature//(A.temperature * full_heat_capacity + unsim_temperature * unsim_heat_capacity) / (full_heat_capacity + unsim_heat_capacity)
if(sharing_lookup_table.len >= unsimulated_tiles.len) //6 or more interconnecting tiles will max at 42% of air moved per tick.
ratio = sharing_lookup_table[unsimulated_tiles.len]
- ratio *= 2
+ ratio *= 3
A.oxygen = max(0, (A.oxygen - oxy_avg) * (1-ratio) + oxy_avg )
A.nitrogen = max(0, (A.nitrogen - nit_avg) * (1-ratio) + nit_avg )
diff --git a/code/defines/procs/global_lists.dm b/code/defines/procs/global_lists.dm
index 29e9ad28ad5..dda5d364bde 100644
--- a/code/defines/procs/global_lists.dm
+++ b/code/defines/procs/global_lists.dm
@@ -10,6 +10,7 @@ var/global/list/client_list = list() //List of all clients, based on ckey
var/global/list/cable_list = list() //Index for all cables, so that powernets don't have to look through the entire world all the time
var/global/list/hair_styles_list = list() //stores /datum/sprite_accessory/hair indexed by name
var/global/list/facial_hair_styles_list = list() //stores /datum/sprite_accessory/facial_hair indexed by name
+var/global/list/skin_styles_list = list() //stores /datum/sprite_accessory/skin indexed by name
var/global/list/chemical_reactions_list //list of all /datum/chemical_reaction datums. Used during chemical reactions
var/global/list/chemical_reagents_list //list of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff
var/global/list/landmarks_list = list() //list of all landmarks created
@@ -26,12 +27,21 @@ var/global/list/landmarks_list = list() //list of all landmarks created
for(var/path in paths)
var/datum/sprite_accessory/hair/H = new path()
hair_styles_list[H.name] = H
+
//Facial Hair - Initialise all /datum/sprite_accessory/facial_hair into an list indexed by facialhair-style name
paths = typesof(/datum/sprite_accessory/facial_hair) - /datum/sprite_accessory/facial_hair
for(var/path in paths)
var/datum/sprite_accessory/facial_hair/H = new path()
facial_hair_styles_list[H.name] = H
+ //Skin Styles - Initialise all /datum/sprite_accessory/skin into a list indexed by the name
+ //Check to make sure the icon file exists first
+ paths = typesof(/datum/sprite_accessory/skin) - /datum/sprite_accessory/skin
+ for(var/path in paths)
+ var/datum/sprite_accessory/skin/S = new path()
+ if(fexists("[S.icon].dmi"))
+ skin_styles_list[S.name] = S
+
proc/make_player_list()//Global proc that rebuilds the player list
for(var/mob/p in player_list)//Clears out everyone that logged out
if(!(p.client))
diff --git a/code/defines/procs/sd_Alert.dm b/code/defines/procs/sd_Alert.dm
new file mode 100644
index 00000000000..c63cab8f8b7
--- /dev/null
+++ b/code/defines/procs/sd_Alert.dm
@@ -0,0 +1,168 @@
+/* sd_Alert library
+ by Shadowdarke (shadowdarke@byond.com)
+
+ sd_Alert() is a powerful and flexible alternative to the built in BYOND
+ alert() proc. sd_Alert offers timed popups, unlimited buttons, custom
+ appearance, and even the option to popup without stealing keyboard focus
+ from the map or command line.
+
+ Please see demo.dm for detailed examples.
+
+FORMAT
+ sd_Alert(who, message, title, buttons, default, duration, unfocus, \
+ size, table, style, tag, select, flags)
+
+ARGUMENTS
+ who - the client or mob to display the alert to.
+ message - text message to display
+ title - title of the alert box
+ buttons - list of buttons
+ Default Value: list("Ok")
+ default - default button selestion
+ Default Value: the first button in the list
+ duration - the number of ticks before this alert expires. If not
+ set, the alert lasts until a button is clicked.
+ Default Value: 0 (unlimited)
+ unfocus - if this value is set, the popup will not steal keyboard
+ focus from the map or command line.
+ Default Value: 1 (do not take focus)
+ size - size of the popup window in px
+ Default Value: "300x200"
+ table - optional parameters for the HTML table in the alert
+ Default Value: "width=100% height=100%" (fill the window)
+ style - optional style sheet information
+ tag - lets you specify a certain tag for this sd_Alert so you may manipulate it
+ externally. (i.e. force the alert to close, change options and redisplay,
+ reuse the same window, etc.)
+ select - if set, the buttons will be replaced with a selection box with a number of
+ lines displayed equal to this value.
+ Default value: 0 (use buttons)
+ flags - optional flags effecting the alert display. These flags may be ORed (|)
+ together for multiple effects.
+ SD_ALERT_SCROLL = display a scrollbar
+ SD_ALERT_SELECT_MULTI = forces selection box display (instead of
+ buttons) allows the user to select multiple
+ choices.
+ SD_ALERT_LINKS = display each choice as a plain text link.
+ Any selection box style overrides this flag.
+ SD_ALERT_NOVALIDATE = don't validate responses
+ Default value: SD_ALERT_SCROLL
+ (button display with scroll bar, validate responses)
+RETURNS
+ The text of the selected button, or null if the alert duration expired
+ without a button click.
+
+Version 1 changes (from version 0):
+* Added the tag, select, and flags arguments, thanks to several suggestions from Foomer.
+* Split the sd_Alert/Alert() proc into New(), Display(), and Response() to allow more
+ customization by developers. Primarily developers would want to use Display() to change
+ the display of active tagged windows
+
+*/
+
+
+#define SD_ALERT_SCROLL 1
+#define SD_ALERT_SELECT_MULTI 2
+#define SD_ALERT_LINKS 4
+#define SD_ALERT_NOVALIDATE 8
+
+proc/sd_Alert(client/who, message, title, buttons = list("Ok"),\
+ default, duration = 0, unfocus = 1, size = "300x200", \
+ table = "width=100% height=100%", style, tag, select, flags = SD_ALERT_SCROLL)
+
+ if(ismob(who))
+ var/mob/M = who
+ who = M.client
+ if(!istype(who)) CRASH("sd_Alert: Invalid target:[who] (\ref[who])")
+
+ var/sd_alert/T = locate(tag)
+ if(T)
+ if(istype(T)) del(T)
+ else CRASH("sd_Alert: tag \"[tag]\" is already in use by datum '[T]' (type: [T.type])")
+ T = new(who, tag)
+ if(duration)
+ spawn(duration)
+ if(T) del(T)
+ return
+ T.Display(message,title,buttons,default,unfocus,size,table,style,select,flags)
+ . = T.Response()
+
+sd_alert
+ var
+ client/target
+ response
+ list/validation
+
+ Del()
+ target << browse(null,"window=\ref[src]")
+ ..()
+
+ New(who, tag)
+ ..()
+ target = who
+ src.tag = tag
+
+ Topic(href,params[])
+ if(usr.client != target) return
+ response = params["clk"]
+
+ proc/Display(message,title,list/buttons,default,unfocus,size,table,style,select,flags)
+ if(unfocus) spawn() target << browse(null,null)
+ if(istext(buttons)) buttons = list(buttons)
+ if(!default) default = buttons[1]
+ if(!(flags & SD_ALERT_NOVALIDATE)) validation = buttons.Copy()
+
+ var/html = {"
[title][style]"
+
+ target << browse(html,"window=\ref[src];size=[size];can_close=0")
+
+ proc/Response()
+ var/validated
+ while(!validated)
+ while(target && !response) // wait for a response
+ sleep(2)
+
+ if(response && validation)
+ if(istype(response, /list))
+ var/list/L = response - validation
+ if(L.len) response = null
+ else validated = 1
+ else if(response in validation) validated = 1
+ else response=null
+ else validated = 1
+ spawn(2) del(src)
+ return response
diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm
index facc5f88eb6..de6f670abab 100644
--- a/code/game/gamemodes/events.dm
+++ b/code/game/gamemodes/events.dm
@@ -21,8 +21,11 @@
/proc/event()
event = 1
+ if(!sent_ninja_to_station)
+ choose_space_ninja()
+ return
- var/eventNumbersToPickFrom = list(1,2,4,5,6,7,8,9,10,11,12,13,14, 15) //so ninjas don't cause "empty" events.
+ var/eventNumbersToPickFrom = list(1,2,4,5,6,7,8,9,10,11,12,13,14,15) //so ninjas don't cause "empty" events.
if((world.time/10)>=3600 && toggle_space_ninja && !sent_ninja_to_station)//If an hour has passed, relatively speaking. Also, if ninjas are allowed to spawn and if there is not already a ninja for the round.
eventNumbersToPickFrom += 3
@@ -36,7 +39,6 @@
spawn(700)
meteor_wave()
spawn_meteors()
-
/*if(2)
command_alert("Gravitational anomalies detected on the station. There is no additional data.", "Anomaly Alert")
world << sound('sound/AI/granomalies.ogg')
@@ -44,8 +46,7 @@
var/obj/effect/bhole/bh = new /obj/effect/bhole( T.loc, 30 )
spawn(rand(50, 300))
del(bh)*/
- /*
- if(3) //Leaving the code in so someone can try and delag it, but this event can no longer occur randomly, per SoS's request. --NEO
+ /*if(3) //Leaving the code in so someone can try and delag it, but this event can no longer occur randomly, per SoS's request. --NEO
command_alert("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert")
world << sound('sound/AI/spanomalies.ogg')
var/list/turfs = new
@@ -65,14 +66,12 @@
P.icon_state = "anom"
P.name = "wormhole"
spawn(rand(300,600))
- del(P)
- */
+ del(P)*/
if(3)
- if((world.time/10)>=3600 && toggle_space_ninja && !sent_ninja_to_station)//If an hour has passed, relatively speaking. Also, if ninjas are allowed to spawn and if there is not already a ninja for the round.
- space_ninja_arrival()//Handled in space_ninja.dm. Doesn't announce arrival, all sneaky-like.
+ //Handled in space_ninja.dm. Doesn't announce arrival, all sneaky-like.
+ choose_space_ninja()
if(4)
mini_blob_event()
-
if(5)
high_radiation_event()
if(6)
@@ -524,4 +523,4 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is
world << "Finished processing FIREDOORS. Processed: [firedoornum]"
world << "Ion Storm Main Done"
- */
\ No newline at end of file
+ */
diff --git a/code/game/gamemodes/events/space_ninja.dm b/code/game/gamemodes/events/space_ninja.dm
index 2801807815b..90ac38ca970 100644
--- a/code/game/gamemodes/events/space_ninja.dm
+++ b/code/game/gamemodes/events/space_ninja.dm
@@ -93,7 +93,33 @@ When I already created about 4 new objectives, this doesn't seem terribly import
/var/global/toggle_space_ninja = 1//If ninjas can spawn or not.
/var/global/sent_ninja_to_station = 0//If a ninja is already on the station.
-/proc/space_ninja_arrival()
+/proc/choose_space_ninja()
+ var/list/candidates = list() //list of candidate keys
+ for(var/mob/dead/observer/G in player_list)
+ if(G.client && ((G.client.inactivity/10)/60) <= 5 && G.client.be_spaceninja)
+ if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
+ candidates += G
+ if(!candidates.len) return
+ candidates = shuffle(candidates)//Incorporating Donkie's list shuffle
+
+ //loop over all viable candidates, giving them a popup asking if they want to be space ninja
+ var/mob/dead/observer/accepted_ghost
+ while(candidates.len && !accepted_ghost)
+ //ask a different random candidate
+ var/mob/dead/observer/G = pick(candidates)
+ //give the popup a 30 second timeout in case the player is AFK
+ if(sd_Alert(G, "A space ninja is about to spawn. Would you like to play as the ninja?", "Space Ninja", list("Yes","No"), "Yes", 300, 1, "350x125") == "Yes")
+ accepted_ghost = G
+ else
+ candidates -= G
+
+ if(accepted_ghost)
+ //someone accepted
+ space_ninja_arrival(accepted_ghost)
+
+/proc/space_ninja_arrival(var/mob/dead/observer/G)
+ if(!G)
+ return choose_space_ninja()
var/datum/game_mode/current_mode = ticker.mode
var/datum/mind/current_mind
@@ -137,19 +163,9 @@ Malf AIs/silicons aren't added. Monkeys aren't added. Messes with objective comp
if(L.name == "carpspawn")
spawn_list.Add(L)
-
- var/list/candidates = list() //list of candidate keys
- for(var/mob/dead/observer/G in player_list)
- if(G.client && !G.client.holder && ((G.client.inactivity/10)/60) <= 5)
- if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
- candidates += G.key
- if(!candidates.len) return
- candidates = shuffle(candidates)//Incorporating Donkie's list shuffle
-
-
//The ninja will be created on the right spawn point or at late join.
var/mob/living/carbon/human/new_ninja = create_space_ninja(pick(spawn_list.len ? spawn_list : latejoin ))
- new_ninja.key = pick(candidates)
+ new_ninja.key = G.ckey
new_ninja.wear_suit:randomize_param()//Give them a random set of suit parameters.
new_ninja.internal = new_ninja.s_store //So the poor ninja has something to breath when they spawn in spess.
new_ninja.internals.icon_state = "internal1"
diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm
index ecb8ea81dfd..23fd8ab112a 100644
--- a/code/game/gamemodes/gameticker.dm
+++ b/code/game/gamemodes/gameticker.dm
@@ -148,18 +148,6 @@ var/global/datum/controller/gameticker/ticker
spawn(3000)
statistic_cycle() // Polls population totals regularly and stores them in an SQL DB -- TLE
- //setup vermin spawn areas
- var/list/vermin_spawn_areas = list("/area/maintenance","/area/mine/maintenance","/area/crew_quarters/locker/locker_toilet","/area/crew_quarters/toilet")
- vermin_spawn_turfs = new/list()
- for(var/area_text in vermin_spawn_areas)
- var/area_base_type = text2path(area_text)
- for(var/area in typesof(area_base_type))
- var/list/area_turfs = get_area_turfs(area)
- for(var/turf/T in area_turfs)
- if(T.density)
- area_turfs -= T
- vermin_spawn_turfs.Add(area_turfs)
-
return 1
/datum/controller/gameticker
diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm
index ce43e6e1130..a49d6ade13a 100644
--- a/code/modules/client/client defines.dm
+++ b/code/modules/client/client defines.dm
@@ -26,6 +26,7 @@
var/be_alien = 0 //Check if that guy wants to be an alien
var/be_pai = 1 //Consider client when searching for players to recruit as a pAI
var/be_syndicate = 1 //Consider client for late-game autotraitor
+ var/be_spaceninja = 0
var/activeslot = 1 //Default active slot!
var/STFU_ghosts //80+ people rounds are fun to admin when text flies faster than airport security
var/STFU_radio //80+ people rounds are fun to admin when text flies faster than airport security
diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm
index 6cf7cf3174c..7d540121325 100644
--- a/code/modules/customitems/item_defines.dm
+++ b/code/modules/customitems/item_defines.dm
@@ -608,22 +608,6 @@ hi
desc = "A colorful pair of magboots with the name Susan Harris clearly written on the back."
icon = 'custom_items.dmi'
icon_state = "atmosmagboots0"
- toggle()
- set name = "Toggle Magboots"
- set category = "Object"
- set src in usr
- if(src.magpulse)
- src.flags &= ~NOSLIP
- src.slowdown = SHOES_SLOWDOWN
- src.magpulse = 0
- icon_state = "atmosmagboots0"
- usr << "You disable the mag-pulse traction system."
- else
- src.flags |= NOSLIP
- src.slowdown = 2
- src.magpulse = 1
- icon_state = "atmosmagboots1"
- usr << "You enable the mag-pulse traction system."
//////////// Sets ////////////
@@ -681,4 +665,4 @@ hi
name = "Peacemaker"
desc = "A nickel-plated revolver with pearl grips. It has a certain Old West flair!"
icon = 'custom_items.dmi'
- icon_state = "peacemaker"
\ No newline at end of file
+ icon_state = "peacemaker"
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 42e0f89d68a..614aaec63b0 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -257,6 +257,17 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
client.be_pai = 1
src << "You will now be considered a viable candidate when a pAI device requests a new personality, effective until the end of this round."
+/mob/dead/observer/verb/toggle_spaceninja_candidate()
+ set name = "Toggle Be Space Ninja Candidate"
+ set category = "Ghost"
+ set desc = "Determines whether you will be a candidate for when a new space ninja spawns. (toggle)"
+ if(client.be_spaceninja)
+ client.be_spaceninja = 0
+ src << "You are now excluded from space ninja candidate lists until end of round."
+ else
+ client.be_spaceninja = 1
+ src << "You are now included in space ninja candidate lists until end of round."
+
/mob/dead/observer/memory()
set hidden = 1
src << "\red You are dead! You have no mind to store memory!"
diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm
index 2005af2994d..fd406e7222c 100644
--- a/code/modules/mob/living/carbon/alien/alien.dm
+++ b/code/modules/mob/living/carbon/alien/alien.dm
@@ -21,7 +21,7 @@
var/move_delay_add = 0 // movement delay to add
status_flags = CANPARALYSE
- var/heal_rate = 5
+ var/heal_rate = 1
var/plasma_rate = 5
var/oxygen_alert = 0
diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
index a366503ac5c..0c25c791996 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
@@ -106,7 +106,7 @@ I kind of like the right click only--the window version can get a little confusi
/mob/living/carbon/alien/humanoid/proc/neurotoxin(mob/target as mob in oview())
set name = "Spit Neurotoxin (50)"
- set desc = "Spits neurotoxin at someone, paralyzing them for a short time."
+ set desc = "Spits neurotoxin at someone, paralyzing them for a short time if they are not wearing protective gear."
set category = "Alien"
if(powerc(50))
@@ -129,12 +129,12 @@ I kind of like the right click only--the window version can get a little confusi
if(!istype(T, /turf))
return
if (U == T)
- usr.bullet_act(src, get_organ_target())
+ usr.bullet_act(new /obj/item/projectile/neurotoxin(usr.loc), get_organ_target())
return
if(!istype(U, /turf))
return
- var/obj/item/projectile/energy/dart/A = new /obj/item/projectile/energy/dart(usr.loc)
+ var/obj/item/projectile/neurotoxin/A = new /obj/item/projectile/neurotoxin(usr.loc)
A.current = U
A.yo = U.y - T.y
diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm
index 909bf25219a..c67017d7953 100644
--- a/code/modules/mob/living/carbon/alien/special/facehugger.dm
+++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm
@@ -89,7 +89,8 @@ var/const/MAX_ACTIVE_TIME = 400
return
/obj/item/clothing/mask/facehugger/throw_impact(atom/hit_atom)
- Attach(hit_atom)
+ if(prob(25))
+ Attach(hit_atom)
return
/obj/item/clothing/mask/facehugger/proc/Attach(M as mob)
@@ -129,17 +130,21 @@ var/const/MAX_ACTIVE_TIME = 400
for(var/mob/O in viewers(target, null))
O.show_message("\red \b [src] tears [W] off of [target]'s face!", 1)
- loc = target
- layer = 20
- target.wear_mask = src
- target.update_inv_wear_mask()
+ if(prob(75))
+ loc = target
+ layer = 20
+ target.wear_mask = src
+ target.update_inv_wear_mask()
- GoIdle() //so it doesn't jump the people that tear it off
+ GoIdle() //so it doesn't jump the people that tear it off
- if(!sterile) target.Paralyse(MAX_IMPREGNATION_TIME/6) //something like 25 ticks = 20 seconds with the default settings
+ if(!sterile) target.Paralyse(MAX_IMPREGNATION_TIME/6) //something like 25 ticks = 20 seconds with the default settings
- spawn(rand(MIN_IMPREGNATION_TIME,MAX_IMPREGNATION_TIME))
- Impregnate(target)
+ spawn(rand(MIN_IMPREGNATION_TIME,MAX_IMPREGNATION_TIME))
+ Impregnate(target)
+ else
+ for(var/mob/O in viewers(target, null))
+ O.show_message("\red \b [src] misses [target]'s face!", 1)
return
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 939d78b0d67..6a189778d42 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -192,7 +192,7 @@
swap_hand()
/mob/living/carbon/proc/help_shake_act(mob/living/carbon/M)
- if (src.health > 0)
+ if (src.health > config.health_threshold_crit)
if(src == M && istype(src, /mob/living/carbon/human))
var/mob/living/carbon/human/H = src
src.visible_message( \
diff --git a/code/modules/mob/living/carbon/human/human_attackalien.dm b/code/modules/mob/living/carbon/human/human_attackalien.dm
index 5c35fe9bb72..29081bab34d 100644
--- a/code/modules/mob/living/carbon/human/human_attackalien.dm
+++ b/code/modules/mob/living/carbon/human/human_attackalien.dm
@@ -42,19 +42,20 @@
apply_damage(damage, BRUTE, affecting, armor_block)
if (damage >= 25)
visible_message("\red [M] has wounded [src]!")
- apply_effect(4, WEAKEN, armor_block)
+ apply_effect(rand(0.5,3), WEAKEN, armor_block)
updatehealth()
if("disarm")
- var/randn = rand(1, 100)
- if (randn <= 90)
+ if (prob(80))
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
- Weaken(rand(10,15))
+ Weaken(rand(0.5,3))
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message(text("\red [] has tackled down []!", M, src), 1)
+ if (prob(25))
+ M.Weaken(rand(2,4))
else
- if (randn <= 99)
+ if (prob(80))
playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
drop_item()
for(var/mob/O in viewers(src, null))
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index db7342061cd..fe14579d1e6 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -304,7 +304,7 @@
/obj/effect/equip_e/human/process()
if (item)
item.add_fingerprint(source)
- if (!item)
+ else
switch(place)
if("mask")
if (!( target.wear_mask ))
@@ -541,7 +541,7 @@ It can still be worn/put on as normal.
if (target.legcuffed)
strip_item = target.legcuffed
if("CPR")
- if ((target.health >= -99.0 && target.health <= 0))
+ if ((target.health > config.health_threshold_dead && target.health < config.health_threshold_crit))
var/suff = min(target.getOxyLoss(), 7)
target.adjustOxyLoss(-suff)
target.updatehealth()
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 0dbd1dd272c..402757f62ea 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -274,7 +274,7 @@
if(E.name == "l_hand" || E.name == "l_arm")
if(hand && equipped())
drop_item()
- emote("custom v drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!")
+ emote("me", 1, "drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!")
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
@@ -284,7 +284,7 @@
else if(E.name == "r_hand" || E.name == "r_arm")
if(!hand && equipped())
drop_item()
- emote("custom v drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!")
+ emote("me", 1, "drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!")
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
diff --git a/code/modules/mob/new_player/preferences.dm b/code/modules/mob/new_player/preferences.dm
index 1b236500d61..78eaa36f473 100644
--- a/code/modules/mob/new_player/preferences.dm
+++ b/code/modules/mob/new_player/preferences.dm
@@ -12,6 +12,7 @@ var/global/list/special_roles = list( //keep synced with the defines BE_* in set
"pAI candidate" = 1, // -- TLE // 7
"cultist" = IS_MODE_COMPILED("cult"), // 8
"infested monkey" = IS_MODE_COMPILED("monkey"), // 9
+ "space ninja" = "true", // 9
)
var/global/list/underwear_m = list("White", "Grey", "Green", "Blue", "Black", "Mankini", "Love-Hearts", "Black2", "Grey2", "Stripey", "Kinky", "None") //Curse whoever made male/female underwear diffrent colours
@@ -28,6 +29,7 @@ var/const/BE_ALIEN =(1<<6)
var/const/BE_PAI =(1<<7)
var/const/BE_CULTIST =(1<<8)
var/const/BE_MONKEY =(1<<9)
+var/const/BE_SPACENINJA=(1<<10)
var/const/MAX_SAVE_SLOTS = 10
@@ -236,8 +238,8 @@ datum/preferences
dat += "Rename slot - "
dat += "Reload slot"
- //column 1
- dat += "
"
+ //COLUMN 1
+ dat += "
"
dat += "Name: "
dat += "[real_name] "
@@ -263,41 +265,68 @@ datum/preferences
dat += "[(sound_adminhelp)?"On":"Off"] toggle "
if(user.client.holder.level >= 5)
- dat += " OOC "
- dat += "Change color "
+ dat += " OOC color "
- dat += " Occupation Choices "
- dat += "\tSet Preferences
"
+ dat += "\tOccupation Preferences "
if(jobban_isbanned(user, "Records"))
dat += "You are banned from using character records. "
else
- dat += "Character Records
"
+ dat += "Character Records "
- dat += "Flavor Text "
- dat += "Change "
+ dat += "\tSet Skills ([GetSkillClass(used_skillpoints)][used_skillpoints > 0 ? " [used_skillpoints]" : "0"]) "
+
+ dat += "Set Flavor Text "
if(lentext(flavor_text) <= 40)
- dat += "[flavor_text]"
+ if(!lentext(flavor_text))
+ dat += "\[...\]"
+ else
+ dat += "[flavor_text]"
else
dat += "[copytext(flavor_text, 1, 37)]... "
dat += " "
- dat += "Skill Choices "
- dat += "\t[GetSkillClass(used_skillpoints)] ([used_skillpoints]) "
- dat += "\tSet Skills
"
-
- //column 2
- dat += " | " //height='300px'
-
- dat += "Body "
- dat += "(®)"
+ //antag
dat += " "
+ if(jobban_isbanned(user, "Syndicate"))
+ dat += "You are banned from antagonist roles."
+ src.be_special = 0
+ else
+ var/n = 0
+ for (var/i in special_roles)
+ if(special_roles[i]) //if mode is available on the server
+ if(jobban_isbanned(user, i))
+ dat += "Be [i]: \[BANNED] "
+ else if(i == "pai candidate")
+ if(jobban_isbanned(user, "pAI"))
+ dat += "Be [i]: \[BANNED] "
+ else
+ dat += "Be [i]: [src.be_special&(1< "
+ n++
+ dat += " | "
+
+ //COLUMN 2
+ dat += ""
+ dat += ""
+
+ //display limbs below
+ var/ind = 0
for(var/name in organ_data)
+ //world << "[ind] \ [organ_data.len]"
var/status = organ_data[name]
var/organ_name = null
switch(name)
@@ -319,11 +348,18 @@ datum/preferences
organ_name = "right hand"
if(status == "cyborg")
- dat += "\tRobotical [organ_name] prothesis "
- if(status == "amputated")
- dat += "\tAmputated [organ_name] "
- dat+=" "
-
+ ++ind
+ if(ind > 1)
+ dat += ", "
+ dat += "\tMechanical [organ_name] prothesis"
+ else if(status == "amputated")
+ ++ind
+ if(ind > 1)
+ dat += ", "
+ dat += "\tAmputated [organ_name]"
+ if(ind)
+ dat += "\[...\]"
+ dat += "
"
if(gender == MALE)
dat += "Underwear: [underwear_m[underwear]] "
@@ -332,8 +368,6 @@ datum/preferences
dat += "Backpack Type: [backbaglist[backbag]] "
- dat += " | Preview
  | "
-
dat += " Hair "
dat += "Change Color "
dat += "Style: [h_style] "
@@ -345,22 +379,7 @@ datum/preferences
dat += " Eyes "
dat += "Change Color "
- dat += "
"
- if(jobban_isbanned(user, "Syndicate"))
- dat += "You are banned from antagonist roles."
- src.be_special = 0
- else
- var/n = 0
- for (var/i in special_roles)
- if(special_roles[i]) //if mode is available on the server
- if(jobban_isbanned(user, i))
- dat += "Be [i]: \[BANNED] "
- else if(i == "pai candidate")
- if(jobban_isbanned(user, "pAI"))
- dat += "Be [i]: \[BANNED] "
- else
- dat += "Be [i]: [src.be_special&(1< "
- n++
+ dat += " "
dat += " | "
dat += " "
@@ -1021,6 +1040,10 @@ datum/preferences
if(second_limb)
organ_data[second_limb] = "cyborg"
+ if("skin_style")
+ var/skin_style_name = input(user, "Select a new skin style") as null|anything in list("default1", "default2", "default3")
+ if(!skin_style_name) return
+
else
switch(href_list["preference"])
@@ -1231,6 +1254,7 @@ datum/preferences
C.be_alien = be_special & BE_ALIEN
C.be_pai = be_special & BE_PAI
C.be_syndicate = be_special & BE_TRAITOR
+ C.be_spaceninja = be_special & BE_SPACENINJA
if(isnull(src.ghost_ears)) src.ghost_ears = 1 //There were problems where the default was null before someone saved their profile.
C.ghost_ears = src.ghost_ears
C.ghost_sight = src.ghost_sight
diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm
index 8bf5982eec4..792e1abb143 100644
--- a/code/modules/mob/new_player/sprite_accessories.dm
+++ b/code/modules/mob/new_player/sprite_accessories.dm
@@ -331,3 +331,29 @@
name = "Tajaran Ears"
icon_state = "tajears"
species_allowed = list("Tajaran")
+
+//skin styles - WIP
+
+/datum/sprite_accessory/skin
+ human
+ name = "Default human skin"
+ icon = "human"
+
+ human_tatt01
+ name = "Tatt01 human skin"
+ icon = "human_tattoo1"
+
+ tajaran
+ name = "Default tajaran skin"
+ icon = "tajaran"
+ species_allowed = list("Tajaran")
+
+ soghun
+ name = "Default soghun skin"
+ icon = "soghun"
+ species_allowed = list("Soghun")
+
+ skrell
+ name = "Default skrell skin"
+ icon = "skrell"
+ species_allowed = list("Skrell")
diff --git a/code/modules/mob/screen.dm b/code/modules/mob/screen.dm
index 3cc082d1798..640f199ac10 100644
--- a/code/modules/mob/screen.dm
+++ b/code/modules/mob/screen.dm
@@ -518,6 +518,7 @@
if ((!( L.stat ) && L.canmove && !( L.restrained() )))
var/resisting = 0
for(var/obj/O in L.requests)
+ L.requests.Remove(O)
del(O)
resisting++
for(var/obj/item/weapon/grab/G in usr.grabbed_by)
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index ab930dcfe56..de55322f00e 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -36,7 +36,7 @@
var/damage = 10
var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE are the only things that should be in here
var/nodamage = 0 //Determines if the projectile will skip any damage inflictions
- var/flag = "bullet" //Defines what armor to use when it hits things. Must be set to bullet, laser, energy,or bomb
+ var/flag = "bullet" //Defines what armor to use when it hits things. Must be set to bullet, laser, energy,or bomb //Cael - bio and rad are also valid
var/projectile_type = "/obj/item/projectile"
var/kill_count = 50 //This will de-increment every process(). When 0, it will delete the projectile.
//Effects
diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm
index 99be701f987..b9710358b07 100644
--- a/code/modules/projectiles/projectile/special.dm
+++ b/code/modules/projectiles/projectile/special.dm
@@ -124,4 +124,12 @@
else if (istype(target, /mob/living/carbon/))
M.show_message("\blue The radiation beam dissipates harmlessly through your body.")
else
- return 1
\ No newline at end of file
+ return 1
+
+/obj/item/projectile/neurotoxin
+ name = "neurotoxin"
+ icon_state = "toxin"
+ damage = 5
+ damage_type = TOX
+ weaken = 5
+ flag = "bio"
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index 48f044c6cc6..830fdaa319e 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -6,8 +6,9 @@
name = "hypospray"
desc = "The DeForest Medical Corporation hypospray is a sterile, air-needle autoinjector for rapid administration of drugs to patients."
icon = 'icons/obj/syringe.dmi'
- item_state = "hypo"
+ item_state = "hypo1"
icon_state = "hypo"
+ var/original_icon_state = "hypo"
amount_per_transfer_from_this = 5
volume = 30
possible_transfer_amounts = null
@@ -56,6 +57,7 @@
name = "autoinjector"
desc = "A rapid and safe way to administer small amounts of drugs by untrained or trained personnel."
icon_state = "autoinjector"
+ original_icon_state = "autoinjector"
item_state = "autoinjector"
amount_per_transfer_from_this = 5
volume = 5
@@ -74,9 +76,9 @@
/obj/item/weapon/reagent_containers/hypospray/autoinjector/update_icon()
if(reagents.total_volume > 0)
- icon_state = "[initial(icon_state)]1"
+ icon_state = "[original_icon_state]1"
else
- icon_state = "[initial(icon_state)]0"
+ icon_state = "[original_icon_state]0"
/obj/item/weapon/reagent_containers/hypospray/autoinjector/examine()
..()
diff --git a/html/changelog.html b/html/changelog.html
index 1c8f86afc98..1de473de9fb 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -56,6 +56,14 @@ Stuff which is in development and not yet visible to players or just code relate
should be listed in the changelog upon commit though. Thanks. -->
+
+ December 3rd
+ Cael_Aislinn updated:
+
+ - Aliens have been significantly nerfed: neurotoxin is affected by bio protection suits, tackle stuns for much shorter time and facehuggers have a chance to fail when leaping.
+
+
+
23.11.12
CIB updated:
|