Merge remote-tracking branch 'upstream/dev' into admin_stuff

Conflicts:
	code/modules/admin/admin_verbs.dm
This commit is contained in:
volas
2015-03-09 18:11:10 +03:00
22 changed files with 1185 additions and 495 deletions
+4
View File
@@ -31,6 +31,7 @@
#include "code\__HELPERS\turfs.dm"
#include "code\__HELPERS\type2type.dm"
#include "code\__HELPERS\unsorted.dm"
#include "code\__HELPERS\vector.dm"
#include "code\_onclick\adjacent.dm"
#include "code\_onclick\ai.dm"
#include "code\_onclick\click.dm"
@@ -1096,6 +1097,7 @@
#include "code\modules\mob\living\carbon\brain\posibrain.dm"
#include "code\modules\mob\living\carbon\brain\robot.dm"
#include "code\modules\mob\living\carbon\brain\say.dm"
#include "code\modules\mob\living\carbon\human\appearance.dm"
#include "code\modules\mob\living\carbon\human\death.dm"
#include "code\modules\mob\living\carbon\human\emote.dm"
#include "code\modules\mob\living\carbon\human\examine.dm"
@@ -1257,6 +1259,7 @@
#include "code\modules\nano\nanoui.dm"
#include "code\modules\nano\modules\alarm_monitor.dm"
#include "code\modules\nano\modules\crew_monitor.dm"
#include "code\modules\nano\modules\human_appearance.dm"
#include "code\modules\nano\modules\power_monitor.dm"
#include "code\modules\nano\modules\rcon.dm"
#include "code\modules\organs\blood.dm"
@@ -1346,6 +1349,7 @@
#include "code\modules\power\singularity\particle_accelerator\particle_emitter.dm"
#include "code\modules\power\singularity\particle_accelerator\particle_power.dm"
#include "code\modules\projectiles\ammunition.dm"
#include "code\modules\projectiles\effects.dm"
#include "code\modules\projectiles\gun.dm"
#include "code\modules\projectiles\projectile.dm"
#include "code\modules\projectiles\targeting.dm"
+141
View File
@@ -0,0 +1,141 @@
/*
plot_vector is a helper datum for plotting a path in a straight line towards a target turf.
This datum converts from world space (turf.x and turf.y) to pixel space, which the datum keeps track of itself. This
should work with any size turfs (i.e. 32x32, 64x64) as it references world.icon_size (note: not actually tested with
anything other than 32x32 turfs).
setup()
This should be called after creating a new instance of a plot_vector datum.
This does the initial setup and calculations. Since we are travelling in a straight line we only need to calculate
the vector and x/y steps once. x/y steps are capped to 1 full turf, whichever is further. If we are travelling along
the y axis each step will be +/- 1 y, and the x movement reduced based on the angle (tangent calculation). After
this every subsequent step will be incremented based on these calculations.
Inputs:
source - the turf the object is starting from
target - the target turf the object is travelling towards
xo - starting pixel_x offset, typically won't be needed, but included in case someone has a need for it later
yo - same as xo, but for the y_pixel offset
increment()
Adds the offset to the current location - incrementing it by one step along the vector.
return_angle()
Returns the direction (angle in degrees) the object is travelling in.
(N)
90°
^
|
(W) 180° <--+--> 0° (E)
|
v
-90°
(S)
return_hypotenuse()
Returns the distance of travel for each step of the vector, relative to each full step of movement. 1 is a full turf
length. Currently used as a multiplier for scaling effects that should be contiguous, like laser beams.
return_location()
Returns a vector_loc datum containing the current location data of the object (see /datum/vector_loc). This includes
the turf it currently should be at, as well as the pixel offset from the centre of that turf. Typically increment()
would be called before this if you are going to move an object based on it's vector data.
*/
/datum/plot_vector
var/turf/source
var/turf/target
var/angle = 0 // direction of travel in degrees
var/loc_x = 0 // in pixels from the left edge of the map
var/loc_y = 0 // in pixels from the bottom edge of the map
var/loc_z = 0 // loc z is in world space coordinates (i.e. z level) - we don't care about measuring pixels for this
var/offset_x = 0 // distance to increment each step
var/offset_y = 0
/datum/plot_vector/proc/setup(var/turf/S, var/turf/T, var/xo = 0, var/yo = 0)
source = S
target = T
if(!istype(source))
source = get_turf(source)
if(!istype(target))
target = get_turf(target)
if(!istype(source) || !istype(target))
return
// convert coordinates to pixel space (default is 32px/turf, 8160px across for a size 255 map)
loc_x = source.x * world.icon_size + xo
loc_y = source.y * world.icon_size + yo
loc_z = source.z
// calculate initial x and y difference
var/dx = target.x - source.x
var/dy = target.y - source.y
// if we aren't moving anywhere; quit now
if(dx == 0 && dy == 0)
return
// calculate the angle
angle = Atan2(dx, dy)
// and some rounding to stop the increments jumping whole turfs - because byond favours certain angles
if(angle > -135 && angle < 45)
angle = Ceiling(angle)
else
angle = Floor(angle)
// calculate the offset per increment step
if(abs(angle) in list(0, 45, 90, 135, 180)) // check if the angle is a cardinal
if(abs(angle) in list(0, 45, 135, 180)) // if so we can skip the trigonometry and set these to absolutes as
offset_x = sign(dx) // they will always be a full step in one or more directions
if(abs(angle) in list(45, 90, 135))
offset_y = sign(dy)
else if(abs(dy) > abs(dx))
offset_x = Cot(abs(angle)) // otherwise set the offsets
offset_y = sign(dy)
else
offset_x = sign(dx)
offset_y = Tan(angle)
if(dx < 0)
offset_y = -offset_y
// multiply the offset by the turf pixel size
offset_x *= world.icon_size
offset_y *= world.icon_size
/datum/plot_vector/proc/increment()
loc_x += offset_x
loc_y += offset_y
/datum/plot_vector/proc/return_angle()
return angle
/datum/plot_vector/proc/return_hypotenuse()
return sqrt(((offset_x / 32) ** 2) + ((offset_y / 32) ** 2))
/datum/plot_vector/proc/return_location(var/datum/vector_loc/data)
if(!data)
data = new()
data.loc = locate(round(loc_x / world.icon_size), round(loc_y / world.icon_size), loc_z)
if(!data.loc)
return
data.pixel_x = loc_x - (data.loc.x * world.icon_size)
data.pixel_y = loc_y - (data.loc.y * world.icon_size)
return data
/*
vector_loc is a helper datum for returning precise location data from plot_vector. It includes the turf the object is in
as well as the pixel offsets.
return_turf()
Returns the turf the object should be currently located in.
*/
/datum/vector_loc
var/turf/loc
var/pixel_x
var/pixel_y
/datum/vector_loc/proc/return_turf()
return loc
+6
View File
@@ -184,6 +184,8 @@
var/starlight = 0 // Whether space turfs have ambient light or not
var/list/ert_species = list("Human")
/datum/configuration/New()
var/list/L = typesof(/datum/game_mode) - /datum/game_mode
for (var/T in L)
@@ -609,6 +611,10 @@
value = text2num(value)
config.starlight = value >= 0 ? value : 0
if("ert_species")
config.ert_species = text2list(value, ";")
if(!config.ert_species.len)
config.ert_species += "Human"
else
log_misc("Unknown setting in configuration: '[name]'")
+1
View File
@@ -605,6 +605,7 @@
//Shooting Code:
A.current = T
A.starting = T
A.yo = U.y - T.y
A.xo = U.x - T.x
spawn(1)
+1
View File
@@ -265,6 +265,7 @@
A = new /obj/item/projectile/energy/electrode( loc )
use_power(200)
A.current = T
A.starting = T
A.yo = U.y - T.y
A.xo = U.x - T.x
spawn( 0 )
+7 -47
View File
@@ -7,59 +7,19 @@
density = 0
anchored = 1
var/shattered = 0
var/list/ui_users = list()
/obj/structure/mirror/attack_hand(mob/user as mob)
if(shattered) return
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(H.a_intent == "hurt")
if(prob(30) || H.species.can_shred(H))
attack_generic(user,1)
else
attack_generic(user)
return
var/userloc = H.loc
//see code/modules/mob/new_player/preferences.dm at approx line 545 for comments!
//this is largely copypasted from there.
//handle facial hair (if necessary)
if(H.gender == MALE)
var/list/species_facial_hair = list()
if(H.species)
for(var/i in facial_hair_styles_list)
var/datum/sprite_accessory/facial_hair/tmp_facial = facial_hair_styles_list[i]
if(H.species.name in tmp_facial.species_allowed)
species_facial_hair += i
else
species_facial_hair = facial_hair_styles_list
var/new_style = input(user, "Select a facial hair style", "Grooming") as null|anything in species_facial_hair
if(userloc != H.loc) return //no tele-grooming
if(new_style)
H.f_style = new_style
//handle normal hair
var/list/species_hair = list()
if(H.species)
for(var/i in hair_styles_list)
var/datum/sprite_accessory/hair/tmp_hair = hair_styles_list[i]
if(H.species.name in tmp_hair.species_allowed)
species_hair += i
else
species_hair = hair_styles_list
var/new_style = input(user, "Select a hair style", "Grooming") as null|anything in species_hair
if(userloc != H.loc) return //no tele-grooming
if(new_style)
H.h_style = new_style
H.update_hair()
var/obj/nano_module/appearance_changer/AC = ui_users[user]
if(!AC)
AC = new(src, user)
AC.name = "SalonPro Nano-Mirror(TM)"
ui_users[user] = AC
AC.ui_interact(user)
/obj/structure/mirror/proc/shatter()
if(shattered) return
+245 -331
View File
@@ -1,331 +1,245 @@
//STRIKE TEAMS
//Thanks to Kilakk for the admin-button portion of this code.
var/list/response_team_members = list()
var/global/send_emergency_team = 0 // Used for automagic response teams
// 'admin_emergency_team' for admin-spawned response teams
var/ert_base_chance = 10 // Default base chance. Will be incremented by increment ERT chance.
var/can_call_ert
/client/proc/response_team()
set name = "Dispatch Emergency Response Team"
set category = "Special Verbs"
set desc = "Send an emergency response team to the station"
if(!holder)
usr << "\red Only administrators may use this command."
return
if(!ticker)
usr << "\red The game hasn't started yet!"
return
if(ticker.current_state == 1)
usr << "\red The round hasn't started yet!"
return
if(send_emergency_team)
usr << "\red Central Command has already dispatched an emergency response team!"
return
if(alert("Do you want to dispatch an Emergency Response Team?",,"Yes","No") != "Yes")
return
if(get_security_level() != "red") // Allow admins to reconsider if the alert level isn't Red
switch(alert("The station is not in red alert. Do you still want to dispatch a response team?",,"Yes","No"))
if("No")
return
if(send_emergency_team)
usr << "\red Looks like somebody beat you to it!"
return
message_admins("[key_name_admin(usr)] is dispatching an Emergency Response Team.", 1)
log_admin("[key_name(usr)] used Dispatch Response Team.")
trigger_armed_response_team(1)
client/verb/JoinResponseTeam()
set category = "IC"
if(istype(usr,/mob/dead/observer) || istype(usr,/mob/new_player))
if(!send_emergency_team)
usr << "No emergency response team is currently being sent."
return
/* if(admin_emergency_team)
usr << "An emergency response team has already been sent."
return */
if(jobban_isbanned(usr, "Syndicate") || jobban_isbanned(usr, "Emergency Response Team") || jobban_isbanned(usr, "Security Officer"))
usr << "<font color=red><b>You are jobbanned from the emergency reponse team!"
return
if(response_team_members.len > 5) usr << "The emergency response team is already full!"
for (var/obj/effect/landmark/L in landmarks_list) if (L.name == "Commando")
L.name = null//Reserving the place.
var/new_name = input(usr, "Pick a name","Name") as null|text
if(!new_name)//Somebody changed his mind, place is available again.
L.name = "Commando"
return
var/leader_selected = isemptylist(response_team_members)
var/mob/living/carbon/human/new_commando = create_response_team(L.loc, leader_selected, new_name)
del(L)
new_commando.mind.key = usr.key
new_commando.key = usr.key
new_commando << "\blue You are [!leader_selected?"a member":"the <B>LEADER</B>"] of an Emergency Response Team, a type of military division, under CentComm's service. There is a code red alert on [station_name()], you are tasked to go and fix the problem."
new_commando << "<b>You should first gear up and discuss a plan with your team. More members may be joining, don't move out before you're ready."
if(!leader_selected)
new_commando << "<b>As member of the Emergency Response Team, you answer only to your leader and CentComm officials.</b>"
else
new_commando << "<b>As leader of the Emergency Response Team, you answer only to CentComm, and have authority to override the Captain where it is necessary to achieve your mission goals. It is recommended that you attempt to cooperate with the captain where possible, however."
return
else
usr << "You need to be an observer or new player to use this."
// returns a number of dead players in %
proc/percentage_dead()
var/total = 0
var/deadcount = 0
for(var/mob/living/carbon/human/H in mob_list)
if(H.client) // Monkeys and mice don't have a client, amirite?
if(H.stat == 2) deadcount++
total++
if(total == 0) return 0
else return round(100 * deadcount / total)
// counts the number of antagonists in %
proc/percentage_antagonists()
var/total = 0
var/antagonists = 0
for(var/mob/living/carbon/human/H in mob_list)
if(is_special_character(H) >= 1)
antagonists++
total++
if(total == 0) return 0
else return round(100 * antagonists / total)
// Increments the ERT chance automatically, so that the later it is in the round,
// the more likely an ERT is to be able to be called.
proc/increment_ert_chance()
while(send_emergency_team == 0) // There is no ERT at the time.
if(get_security_level() == "green")
ert_base_chance += 1
if(get_security_level() == "blue")
ert_base_chance += 2
if(get_security_level() == "red")
ert_base_chance += 3
if(get_security_level() == "delta")
ert_base_chance += 10 // Need those big guns
sleep(600 * 3) // Minute * Number of Minutes
proc/trigger_armed_response_team(var/force = 0)
if(!can_call_ert && !force)
return
if(send_emergency_team)
return
var/send_team_chance = ert_base_chance // Is incremented by increment_ert_chance.
send_team_chance += 2*percentage_dead() // the more people are dead, the higher the chance
send_team_chance += percentage_antagonists() // the more antagonists, the higher the chance
send_team_chance = min(send_team_chance, 100)
if(force) send_team_chance = 100
// there's only a certain chance a team will be sent
if(!prob(send_team_chance))
command_announcement.Announce("It would appear that an emergency response team was requested for [station_name()]. Unfortunately, we were unable to send one at this time.", "Central Command")
can_call_ert = 0 // Only one call per round, ladies.
return
command_announcement.Announce("It would appear that an emergency response team was requested for [station_name()]. We will prepare and send one as soon as possible.", "Central Command")
can_call_ert = 0 // Only one call per round, gentleman.
send_emergency_team = 1
sleep(600 * 5)
send_emergency_team = 0 // Can no longer join the ERT.
/* var/area/security/nuke_storage/nukeloc = locate()//To find the nuke in the vault
var/obj/machinery/nuclearbomb/nuke = locate() in nukeloc
if(!nuke)
nuke = locate() in world
var/obj/item/weapon/paper/P = new
P.info = "Your orders, Commander, are to use all means necessary to return the station to a survivable condition.<br>To this end, you have been provided with the best tools we can give in the three areas of Medicine, Engineering, and Security. The nuclear authorization code is: <b>[ nuke ? nuke.r_code : "AHH, THE NUKE IS GONE!"]</b>. Be warned, if you detonate this without good reason, we will hold you to account for damages. Memorise this code, and then burn this message."
P.name = "Emergency Nuclear Code, and ERT Orders"
for (var/obj/effect/landmark/A in world)
if (A.name == "nukecode")
P.loc = A.loc
del(A)
continue
*/
/client/proc/create_response_team(obj/spawn_location, leader_selected = 0, commando_name)
//usr << "\red ERT has been temporarily disabled. Talk to a coder."
//return
var/mob/living/carbon/human/M = new(null)
response_team_members |= M
//todo: god damn this.
//make it a panel, like in character creation
var/new_facial = input("Please select facial hair color.", "Character Generation") as color
if(new_facial)
M.r_facial = hex2num(copytext(new_facial, 2, 4))
M.g_facial = hex2num(copytext(new_facial, 4, 6))
M.b_facial = hex2num(copytext(new_facial, 6, 8))
var/new_hair = input("Please select hair color.", "Character Generation") as color
if(new_facial)
M.r_hair = hex2num(copytext(new_hair, 2, 4))
M.g_hair = hex2num(copytext(new_hair, 4, 6))
M.b_hair = hex2num(copytext(new_hair, 6, 8))
var/new_eyes = input("Please select eye color.", "Character Generation") as color
if(new_eyes)
M.r_eyes = hex2num(copytext(new_eyes, 2, 4))
M.g_eyes = hex2num(copytext(new_eyes, 4, 6))
M.b_eyes = hex2num(copytext(new_eyes, 6, 8))
var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation") as text
if (!new_tone)
new_tone = 35
M.s_tone = max(min(round(text2num(new_tone)), 220), 1)
M.s_tone = -M.s_tone + 35
// hair
var/list/all_hairs = typesof(/datum/sprite_accessory/hair) - /datum/sprite_accessory/hair
var/list/hairs = list()
// loop through potential hairs
for(var/x in all_hairs)
var/datum/sprite_accessory/hair/H = new x // create new hair datum based on type x
hairs.Add(H.name) // add hair name to hairs
del(H) // delete the hair after it's all done
// var/new_style = input("Please select hair style", "Character Generation") as null|anything in hairs
//hair
var/new_hstyle = input(usr, "Select a hair style", "Grooming") as null|anything in hair_styles_list
if(new_hstyle)
M.h_style = new_hstyle
// facial hair
var/new_fstyle = input(usr, "Select a facial hair style", "Grooming") as null|anything in facial_hair_styles_list
if(new_fstyle)
M.f_style = new_fstyle
// if new style selected (not cancel)
/* if (new_style)
M.h_style = new_style
for(var/x in all_hairs) // loop through all_hairs again. Might be slightly CPU expensive, but not significantly.
var/datum/sprite_accessory/hair/H = new x // create new hair datum
if(H.name == new_style)
M.h_style = H // assign the hair_style variable a new hair datum
break
else
del(H) // if hair H not used, delete. BYOND can garbage collect, but better safe than sorry
// facial hair
var/list/all_fhairs = typesof(/datum/sprite_accessory/facial_hair) - /datum/sprite_accessory/facial_hair
var/list/fhairs = list()
for(var/x in all_fhairs)
var/datum/sprite_accessory/facial_hair/H = new x
fhairs.Add(H.name)
del(H)
new_style = input("Please select facial style", "Character Generation") as null|anything in fhairs
if(new_style)
M.f_style = new_style
for(var/x in all_fhairs)
var/datum/sprite_accessory/facial_hair/H = new x
if(H.name == new_style)
M.f_style = H
break
else
del(H)
*/
var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female")
if (new_gender)
if(new_gender == "Male")
M.gender = MALE
else
M.gender = FEMALE
//M.rebuild_appearance()
M.update_hair()
M.update_body()
M.check_dna(M)
M.real_name = commando_name
M.name = commando_name
M.age = !leader_selected ? rand(23,35) : rand(35,45)
M.dna.ready_dna(M)//Creates DNA.
//Creates mind stuff.
M.mind = new
M.mind.current = M
M.mind.original = M
M.mind.assigned_role = "MODE"
M.mind.special_role = "Response Team"
if(!(M.mind in ticker.minds))
ticker.minds += M.mind//Adds them to regular mind list.
M.loc = spawn_location
M.equip_strike_team(leader_selected)
return M
/mob/living/carbon/human/proc/equip_strike_team(leader_selected = 0)
//Special radio setup
equip_to_slot_or_del(new /obj/item/device/radio/headset/ert(src), slot_l_ear)
//Replaced with new ERT uniform
equip_to_slot_or_del(new /obj/item/clothing/under/ert(src), slot_w_uniform)
equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(src), slot_shoes)
equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(src), slot_gloves)
equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(src), slot_glasses)
/*
//Old ERT Uniform
//Basic Uniform
equip_to_slot_or_del(new /obj/item/clothing/under/syndicate/tacticool(src), slot_w_uniform)
equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_l_store)
equip_to_slot_or_del(new /obj/item/weapon/clipboard(src), slot_r_store)
equip_to_slot_or_del(new /obj/item/weapon/gun/energy/gun(src), slot_belt)
equip_to_slot_or_del(new /obj/item/clothing/mask/gas/swat(src), slot_wear_mask)
//Glasses
equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(src), slot_glasses)
//Shoes & gloves
equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(src), slot_shoes)
equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(src), slot_gloves)
//Removed
// equip_to_slot_or_del(new /obj/item/clothing/suit/armor/swat(src), slot_wear_suit)
// equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/deathsquad(src), slot_head)
//Backpack
equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(src), slot_back)
equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(src), slot_in_backpack)
equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(src), slot_in_backpack)
*/
var/obj/item/weapon/card/id/W = new(src)
W.assignment = "Emergency Response Team[leader_selected ? " Leader" : ""]"
W.registered_name = real_name
W.name = "[real_name]'s ID Card ([W.assignment])"
W.icon_state = "centcom"
W.access = get_all_accesses()
W.access += get_all_centcom_access()
equip_to_slot_or_del(W, slot_wear_id)
return 1
//debug verb (That is horribly coded, LEAVE THIS OFF UNLESS PRIVATELY TESTING. Seriously.
/*client/verb/ResponseTeam()
set category = "Admin"
if(!send_emergency_team)
send_emergency_team = 1*/
//STRIKE TEAMS
//Thanks to Kilakk for the admin-button portion of this code.
var/list/response_team_members = list()
var/global/send_emergency_team = 0 // Used for automagic response teams
// 'admin_emergency_team' for admin-spawned response teams
var/ert_base_chance = 10 // Default base chance. Will be incremented by increment ERT chance.
var/can_call_ert
/client/proc/response_team()
set name = "Dispatch Emergency Response Team"
set category = "Special Verbs"
set desc = "Send an emergency response team to the station"
if(!holder)
usr << "\red Only administrators may use this command."
return
if(!ticker)
usr << "\red The game hasn't started yet!"
return
if(ticker.current_state == 1)
usr << "\red The round hasn't started yet!"
return
if(send_emergency_team)
usr << "\red Central Command has already dispatched an emergency response team!"
return
if(alert("Do you want to dispatch an Emergency Response Team?",,"Yes","No") != "Yes")
return
if(get_security_level() != "red") // Allow admins to reconsider if the alert level isn't Red
switch(alert("The station is not in red alert. Do you still want to dispatch a response team?",,"Yes","No"))
if("No")
return
if(send_emergency_team)
usr << "\red Looks like somebody beat you to it!"
return
message_admins("[key_name_admin(usr)] is dispatching an Emergency Response Team.", 1)
log_admin("[key_name(usr)] used Dispatch Response Team.")
trigger_armed_response_team(1)
client/verb/JoinResponseTeam()
set category = "IC"
if(istype(usr,/mob/dead/observer) || istype(usr,/mob/new_player))
if(!send_emergency_team)
usr << "No emergency response team is currently being sent."
return
/* if(admin_emergency_team)
usr << "An emergency response team has already been sent."
return */
if(jobban_isbanned(usr, "Syndicate") || jobban_isbanned(usr, "Emergency Response Team") || jobban_isbanned(usr, "Security Officer"))
usr << "<font color=red><b>You are jobbanned from the emergency reponse team!"
return
if(response_team_members.len > 5) usr << "The emergency response team is already full!"
for (var/obj/effect/landmark/L in landmarks_list) if (L.name == "Commando")
L.name = null//Reserving the place.
var/new_name = input(usr, "Pick a name","Name") as null|text
if(!new_name)//Somebody changed his mind, place is available again.
L.name = "Commando"
return
var/leader_selected = isemptylist(response_team_members)
var/mob/living/carbon/human/new_commando = create_response_team(L.loc, leader_selected, new_name)
del(L)
//Creates mind stuff.
new_commando.mind.key = usr.key
new_commando.key = usr.key
new_commando << "\blue You are [!leader_selected?"a member":"the <B>LEADER</B>"] of an Emergency Response Team, a type of military division, under CentComm's service. There is a code red alert on [station_name()], you are tasked to go and fix the problem."
new_commando << "<b>You should first gear up and discuss a plan with your team. More members may be joining, don't move out before you're ready."
if(!leader_selected)
new_commando << "<b>As member of the Emergency Response Team, you answer only to your leader and CentComm officials.</b>"
else
new_commando << "<b>As leader of the Emergency Response Team, you answer only to CentComm, and have authority to override the Captain where it is necessary to achieve your mission goals. It is recommended that you attempt to cooperate with the captain where possible, however."
// By setting an explicit location the mob cannot wander off and decide change appearance elsewhere
new_commando.change_appearance(APPEARANCE_ALL, new_commando.loc, new_commando, species_whitelist = config.ert_species)
return
else
usr << "You need to be an observer or new player to use this."
// returns a number of dead players in %
proc/percentage_dead()
var/total = 0
var/deadcount = 0
for(var/mob/living/carbon/human/H in mob_list)
if(H.client) // Monkeys and mice don't have a client, amirite?
if(H.stat == 2) deadcount++
total++
if(total == 0) return 0
else return round(100 * deadcount / total)
// counts the number of antagonists in %
proc/percentage_antagonists()
var/total = 0
var/antagonists = 0
for(var/mob/living/carbon/human/H in mob_list)
if(is_special_character(H) >= 1)
antagonists++
total++
if(total == 0) return 0
else return round(100 * antagonists / total)
// Increments the ERT chance automatically, so that the later it is in the round,
// the more likely an ERT is to be able to be called.
proc/increment_ert_chance()
while(send_emergency_team == 0) // There is no ERT at the time.
if(get_security_level() == "green")
ert_base_chance += 1
if(get_security_level() == "blue")
ert_base_chance += 2
if(get_security_level() == "red")
ert_base_chance += 3
if(get_security_level() == "delta")
ert_base_chance += 10 // Need those big guns
sleep(600 * 3) // Minute * Number of Minutes
proc/trigger_armed_response_team(var/force = 0)
if(!can_call_ert && !force)
return
if(send_emergency_team)
return
var/send_team_chance = ert_base_chance // Is incremented by increment_ert_chance.
send_team_chance += 2*percentage_dead() // the more people are dead, the higher the chance
send_team_chance += percentage_antagonists() // the more antagonists, the higher the chance
send_team_chance = min(send_team_chance, 100)
if(force) send_team_chance = 100
// there's only a certain chance a team will be sent
if(!prob(send_team_chance))
command_announcement.Announce("It would appear that an emergency response team was requested for [station_name()]. Unfortunately, we were unable to send one at this time.", "Central Command")
can_call_ert = 0 // Only one call per round, ladies.
return
command_announcement.Announce("It would appear that an emergency response team was requested for [station_name()]. We will prepare and send one as soon as possible.", "Central Command")
can_call_ert = 0 // Only one call per round, gentleman.
send_emergency_team = 1
sleep(600 * 5)
send_emergency_team = 0 // Can no longer join the ERT.
/* var/area/security/nuke_storage/nukeloc = locate()//To find the nuke in the vault
var/obj/machinery/nuclearbomb/nuke = locate() in nukeloc
if(!nuke)
nuke = locate() in world
var/obj/item/weapon/paper/P = new
P.info = "Your orders, Commander, are to use all means necessary to return the station to a survivable condition.<br>To this end, you have been provided with the best tools we can give in the three areas of Medicine, Engineering, and Security. The nuclear authorization code is: <b>[ nuke ? nuke.r_code : "AHH, THE NUKE IS GONE!"]</b>. Be warned, if you detonate this without good reason, we will hold you to account for damages. Memorise this code, and then burn this message."
P.name = "Emergency Nuclear Code, and ERT Orders"
for (var/obj/effect/landmark/A in world)
if (A.name == "nukecode")
P.loc = A.loc
del(A)
continue
*/
/client/proc/create_response_team(obj/spawn_location, leader_selected = 0, commando_name)
//usr << "\red ERT has been temporarily disabled. Talk to a coder."
//return
var/mob/living/carbon/human/M = new(null)
response_team_members |= M
M.real_name = commando_name
M.name = commando_name
M.age = !leader_selected ? rand(23,35) : rand(35,45)
M.check_dna(M)
M.dna.ready_dna(M)//Creates DNA.
M.mind = new
M.mind.current = M
M.mind.original = M
M.mind.assigned_role = "MODE"
M.mind.special_role = "Response Team"
if(!(M.mind in ticker.minds))
ticker.minds += M.mind//Adds them to regular mind list.
M.loc = spawn_location
M.equip_strike_team(leader_selected)
return M
/mob/living/carbon/human/proc/equip_strike_team(leader_selected = 0)
//Special radio setup
equip_to_slot_or_del(new /obj/item/device/radio/headset/ert(src), slot_l_ear)
//Replaced with new ERT uniform
equip_to_slot_or_del(new /obj/item/clothing/under/ert(src), slot_w_uniform)
equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(src), slot_shoes)
equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(src), slot_gloves)
equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(src), slot_glasses)
/*
//Old ERT Uniform
//Basic Uniform
equip_to_slot_or_del(new /obj/item/clothing/under/syndicate/tacticool(src), slot_w_uniform)
equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_l_store)
equip_to_slot_or_del(new /obj/item/weapon/clipboard(src), slot_r_store)
equip_to_slot_or_del(new /obj/item/weapon/gun/energy/gun(src), slot_belt)
equip_to_slot_or_del(new /obj/item/clothing/mask/gas/swat(src), slot_wear_mask)
//Glasses
equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(src), slot_glasses)
//Shoes & gloves
equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(src), slot_shoes)
equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(src), slot_gloves)
//Removed
// equip_to_slot_or_del(new /obj/item/clothing/suit/armor/swat(src), slot_wear_suit)
// equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/deathsquad(src), slot_head)
//Backpack
equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(src), slot_back)
equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(src), slot_in_backpack)
equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(src), slot_in_backpack)
*/
var/obj/item/weapon/card/id/W = new(src)
W.assignment = "Emergency Response Team[leader_selected ? " Leader" : ""]"
W.registered_name = real_name
W.name = "[real_name]'s ID Card ([W.assignment])"
W.icon_state = "centcom"
W.access = get_all_accesses()
W.access += get_all_centcom_access()
equip_to_slot_or_del(W, slot_wear_id)
return 1
//debug verb (That is horribly coded, LEAVE THIS OFF UNLESS PRIVATELY TESTING. Seriously.
/*client/verb/ResponseTeam()
set category = "Admin"
if(!send_emergency_team)
send_emergency_team = 1*/
+41 -1
View File
@@ -80,7 +80,9 @@ var/list/admin_verbs_admin = list(
/client/proc/allow_character_respawn, /* Allows a ghost to respawn */
/client/proc/event_manager_panel,
/client/proc/empty_ai_core_toggle_latejoin,
/client/proc/aooc
/client/proc/aooc,
/client/proc/change_human_appearance_admin, /* Allows an admin to change the basic appearance of human-based mobs */
/client/proc/change_human_appearance_self /* Allows the human-based mob itself change its basic appearance */
)
var/list/admin_verbs_ban = list(
/client/proc/unban_panel,
@@ -718,6 +720,9 @@ var/list/admin_verbs_mentor = list(
set name = "Rename Silicon"
set category = "Admin"
if(!istype(S))
return
if(holder)
var/new_name = trim_strip_input(src, "Enter new name. Leave blank or as is to cancel.", "Enter new silicon name", S.real_name)
if(new_name && new_name != S.real_name)
@@ -725,6 +730,41 @@ var/list/admin_verbs_mentor = list(
S.SetName(new_name)
feedback_add_details("admin_verb","RAI") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/change_human_appearance_admin(mob/living/carbon/human/H in world)
set name = "Change Mob Appearance - Admin"
set desc = "Allows you to change the mob appearance"
set category = "Admin"
if(!istype(H))
return
if(holder)
admin_log_and_message_admins("is altering the appearance of [H].")
H.change_appearance(APPEARANCE_ALL, usr, usr, check_species_whitelist = 0)
feedback_add_details("admin_verb","CHAA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/change_human_appearance_self(mob/living/carbon/human/H in world)
set name = "Change Mob Appearance - Self"
set desc = "Allows the mob to change its appearance"
set category = "Admin"
if(!istype(H))
return
if(!H.client)
usr << "Only mobs with clients can alter their own appearance."
return
if(holder)
switch(alert("Do you wish for [H] to be allowed to select non-whitelisted races?","Alter Mob Appearance","Yes","No","Cancel"))
if("Yes")
admin_log_and_message_admins("has allowed [H] to change \his appearance, without whitelisting of races.")
H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 0)
if("No")
admin_log_and_message_admins("has allowed [H] to change \his appearance, with whitelisting of races.")
H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 1)
feedback_add_details("admin_verb","CMAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
//---- bs12 verbs ----
@@ -0,0 +1,187 @@
/mob/living/carbon/human/proc/change_appearance(var/flags = APPEARANCE_ALL_HAIR, var/location = src, var/mob/user = src, var/check_species_whitelist = 1, var/list/species_whitelist = list(), var/list/species_blacklist = list())
var/obj/nano_module/appearance_changer/AC = new(location, src, check_species_whitelist, species_whitelist, species_blacklist)
AC.flags = flags
AC.ui_interact(user)
/mob/living/carbon/human/proc/change_species(var/new_species)
if(!new_species)
return
if(species == new_species)
return
if(!(new_species in all_species))
return
set_species(new_species)
reset_hair()
return 1
/mob/living/carbon/human/proc/change_gender(var/gender)
if(src.gender == gender)
return
src.gender = gender
reset_hair()
update_body()
update_dna()
return 1
/mob/living/carbon/human/proc/change_hair(var/hair_style)
if(!hair_style)
return
if(h_style == hair_style)
return
if(!(hair_style in hair_styles_list))
return
h_style = hair_style
update_hair()
return 1
/mob/living/carbon/human/proc/change_facial_hair(var/facial_hair_style)
if(!facial_hair_style)
return
if(f_style == facial_hair_style)
return
if(!(facial_hair_style in facial_hair_styles_list))
return
f_style = facial_hair_style
update_hair()
return 1
/mob/living/carbon/human/proc/reset_hair()
var/list/valid_hairstyles = generate_valid_hairstyles()
var/list/valid_facial_hairstyles = generate_valid_facial_hairstyles()
if(valid_hairstyles.len)
h_style = pick(valid_hairstyles)
else
//this shouldn't happen
h_style = "Bald"
if(valid_facial_hairstyles.len)
f_style = pick(valid_facial_hairstyles)
else
//this shouldn't happen
f_style = "Shaved"
update_hair()
/mob/living/carbon/human/proc/change_eye_color(var/red, var/green, var/blue)
if(red == r_eyes && green == g_eyes && blue == b_eyes)
return
r_eyes = red
g_eyes = green
b_eyes = blue
update_body()
return 1
/mob/living/carbon/human/proc/change_hair_color(var/red, var/green, var/blue)
if(red == r_eyes && green == g_eyes && blue == b_eyes)
return
r_hair = red
g_hair = green
b_hair = blue
update_hair()
return 1
/mob/living/carbon/human/proc/change_facial_hair_color(var/red, var/green, var/blue)
if(red == r_facial && green == g_facial && blue == b_facial)
return
r_facial = red
g_facial = green
b_facial = blue
update_hair()
return 1
/mob/living/carbon/human/proc/change_skin_color(var/red, var/green, var/blue)
if(red == r_skin && green == g_skin && blue == b_skin || !(species.flags & HAS_SKIN_COLOR))
return
r_skin = red
g_skin = green
b_skin = blue
update_body()
return 1
/mob/living/carbon/human/proc/change_skin_tone(var/tone)
if(s_tone == tone || !(species.flags & HAS_SKIN_TONE))
return
s_tone = tone
update_body()
return 1
/mob/living/carbon/human/proc/update_dna()
check_dna()
dna.ready_dna(src)
/mob/living/carbon/human/proc/generate_valid_species(var/check_whitelist = 1, var/list/whitelist = list(), var/list/blacklist = list())
var/list/valid_species = new()
for(var/current_species_name in all_species)
var/datum/species/current_species = all_species[current_species_name]
if(check_whitelist && config.usealienwhitelist && !check_rights(R_ADMIN, 0, src)) //If we're using the whitelist, make sure to check it!
if(!(current_species.flags & CAN_JOIN))
continue
if(whitelist.len && !(current_species_name in whitelist))
continue
if(blacklist.len && (current_species_name in blacklist))
continue
if((current_species.flags & IS_WHITELISTED) && !is_alien_whitelisted(src, current_species_name))
continue
valid_species += current_species_name
return valid_species
/mob/living/carbon/human/proc/generate_valid_hairstyles()
var/list/valid_hairstyles = new()
for(var/hairstyle in hair_styles_list)
var/datum/sprite_accessory/S = hair_styles_list[hairstyle]
if(gender == MALE && S.gender == FEMALE)
continue
if(gender == FEMALE && S.gender == MALE)
continue
if(!(species.name in S.species_allowed))
continue
valid_hairstyles += hairstyle
return valid_hairstyles
/mob/living/carbon/human/proc/generate_valid_facial_hairstyles()
var/list/valid_facial_hairstyles = new()
for(var/facialhairstyle in facial_hair_styles_list)
var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle]
if(gender == MALE && S.gender == FEMALE)
continue
if(gender == FEMALE && S.gender == MALE)
continue
if(!(species.name in S.species_allowed))
continue
valid_facial_hairstyles += facialhairstyle
return valid_facial_hairstyles
/proc/q()
var/mob/living/carbon/human/H = usr
H.change_appearance(APPEARANCE_ALL)
@@ -188,6 +188,8 @@
del(A)
return
A.current = target
A.starting = get_turf(src)
A.original = get_turf(target)
A.yo = target:y - start:y
A.xo = target:x - start:x
spawn( 0 )
@@ -0,0 +1,163 @@
/obj/nano_module/appearance_changer
name = "Appearance Editor"
flags = APPEARANCE_ALL_HAIR
var/mob/living/carbon/human/owner = null
var/list/valid_species = list()
var/list/valid_hairstyles = list()
var/list/valid_facial_hairstyles = list()
var/check_whitelist
var/list/whitelist
var/list/blacklist
/obj/nano_module/appearance_changer/New(var/location, var/mob/living/carbon/human/H, var/check_species_whitelist = 1, var/list/species_whitelist = list(), var/list/species_blacklist = list())
..()
loc = location
owner = H
src.check_whitelist = check_species_whitelist
src.whitelist = species_whitelist
src.blacklist = species_blacklist
/obj/nano_module/appearance_changer/Topic(ref, href_list)
if(..())
return 1
if(href_list["race"])
if(can_change(APPEARANCE_RACE) && (href_list["race"] in valid_species))
if(owner.change_species(href_list["race"]))
cut_and_generate_data()
return 1
if(href_list["gender"])
if(can_change(APPEARANCE_GENDER))
if(owner.change_gender(href_list["gender"]))
cut_and_generate_data()
return 1
if(href_list["skin_tone"])
if(can_change_skin_tone())
var/new_s_tone = input(usr, "Choose your character's skin-tone:\n(Light 1 - 220 Dark)", "Skin Tone", owner.s_tone) as num|null
if(isnum(new_s_tone) && CanUseTopic(usr) == STATUS_INTERACTIVE)
new_s_tone = 35 - max(min( round(new_s_tone), 220),1)
return owner.change_skin_tone(new_s_tone)
if(href_list["skin_color"])
if(can_change_skin_color())
var/new_skin = input(usr, "Choose your character's skin colour: ", "Skin Color", rgb(owner.r_skin, owner.g_skin, owner.b_skin)) as color|null
if(new_skin && can_still_topic())
var/r_skin = hex2num(copytext(new_skin, 2, 4))
var/g_skin = hex2num(copytext(new_skin, 4, 6))
var/b_skin = hex2num(copytext(new_skin, 6, 8))
if(owner.change_skin_color(r_skin, g_skin, b_skin))
update_dna()
return 1
if(href_list["hair"])
if(can_change(APPEARANCE_HAIR) && (href_list["hair"] in valid_hairstyles))
if(owner.change_hair(href_list["hair"]))
update_dna()
return 1
if(href_list["hair_color"])
if(can_change(APPEARANCE_HAIR_COLOR))
var/new_hair = input("Please select hair color.", "Hair Color", rgb(owner.r_hair, owner.g_hair, owner.b_hair)) as color|null
if(new_hair && can_still_topic())
var/r_hair = hex2num(copytext(new_hair, 2, 4))
var/g_hair = hex2num(copytext(new_hair, 4, 6))
var/b_hair = hex2num(copytext(new_hair, 6, 8))
if(owner.change_hair_color(r_hair, g_hair, b_hair))
update_dna()
return 1
if(href_list["facial_hair"])
if(can_change(APPEARANCE_FACIAL_HAIR) && (href_list["facial_hair"] in valid_facial_hairstyles))
if(owner.change_facial_hair(href_list["facial_hair"]))
update_dna()
return 1
if(href_list["facial_hair_color"])
if(can_change(APPEARANCE_FACIAL_HAIR_COLOR))
var/new_facial = input("Please select facial hair color.", "Facial Hair Color", rgb(owner.r_facial, owner.g_facial, owner.b_facial)) as color|null
if(new_facial && can_still_topic())
var/r_facial = hex2num(copytext(new_facial, 2, 4))
var/g_facial = hex2num(copytext(new_facial, 4, 6))
var/b_facial = hex2num(copytext(new_facial, 6, 8))
if(owner.change_facial_hair_color(r_facial, g_facial, b_facial))
update_dna()
return 1
if(href_list["eye_color"])
if(can_change(APPEARANCE_EYE_COLOR))
var/new_eyes = input("Please select eye color.", "Eye Color", rgb(owner.r_eyes, owner.g_eyes, owner.b_eyes)) as color|null
if(new_eyes && can_still_topic())
var/r_eyes = hex2num(copytext(new_eyes, 2, 4))
var/g_eyes = hex2num(copytext(new_eyes, 4, 6))
var/b_eyes = hex2num(copytext(new_eyes, 6, 8))
if(owner.change_eye_color(r_eyes, g_eyes, b_eyes))
update_dna()
return 1
return 0
/obj/nano_module/appearance_changer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
generate_data(check_whitelist, whitelist, blacklist)
var/data[0]
data["specimen"] = owner.species.name
data["gender"] = owner.gender
data["change_race"] = can_change(APPEARANCE_RACE)
if(data["change_race"])
var/species[0]
for(var/specimen in valid_species)
species[++species.len] = list("specimen" = specimen)
data["species"] = species
data["change_gender"] = can_change(APPEARANCE_GENDER)
data["change_skin_tone"] = can_change_skin_tone()
data["change_skin_color"] = can_change_skin_color()
data["change_eye_color"] = can_change(APPEARANCE_EYE_COLOR)
data["change_hair"] = can_change(APPEARANCE_HAIR)
if(data["change_hair"])
var/hair_styles[0]
for(var/hair_style in valid_hairstyles)
hair_styles[++hair_styles.len] = list("hairstyle" = hair_style)
data["hair_styles"] = hair_styles
data["hair_style"] = owner.h_style
data["change_facial_hair"] = can_change(APPEARANCE_FACIAL_HAIR)
if(data["change_facial_hair"])
var/facial_hair_styles[0]
for(var/facial_hair_style in valid_facial_hairstyles)
facial_hair_styles[++facial_hair_styles.len] = list("facialhairstyle" = facial_hair_style)
data["facial_hair_styles"] = facial_hair_styles
data["facial_hair_style"] = owner.f_style
data["change_hair_color"] = can_change(APPEARANCE_HAIR_COLOR)
data["change_facial_hair_color"] = can_change(APPEARANCE_FACIAL_HAIR_COLOR)
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "appearance_changer.tmpl", "[src.name]", 800, 450)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/nano_module/appearance_changer/proc/update_dna()
if(owner && (flags & APPEARANCE_UPDATE_DNA))
owner.update_dna()
/obj/nano_module/appearance_changer/proc/can_change(var/flag)
return owner && (flags & flag)
/obj/nano_module/appearance_changer/proc/can_change_skin_tone()
return owner && (flags & APPEARANCE_SKIN) && owner.species.flags & HAS_SKIN_TONE
/obj/nano_module/appearance_changer/proc/can_change_skin_color()
return owner && (flags & APPEARANCE_SKIN) && owner.species.flags & HAS_SKIN_COLOR
/obj/nano_module/appearance_changer/proc/can_still_topic()
return CanUseTopic(usr, list(), default_state) == STATUS_INTERACTIVE
/obj/nano_module/appearance_changer/proc/cut_and_generate_data()
// Making the assumption that the available species remain constant
valid_facial_hairstyles.Cut()
valid_facial_hairstyles.Cut()
generate_data()
/obj/nano_module/appearance_changer/proc/generate_data()
if(!valid_species.len)
valid_species = owner.generate_valid_species(check_whitelist, whitelist, blacklist)
if(!valid_hairstyles.len || !valid_facial_hairstyles.len)
valid_hairstyles = owner.generate_valid_hairstyles()
valid_facial_hairstyles = owner.generate_valid_facial_hairstyles()
+2 -2
View File
@@ -1,11 +1,11 @@
/atom/movable/proc/nano_host()
/atom/proc/nano_host()
return src
/obj/nano_module/nano_host()
return loc
/atom/movable/proc/CanUseTopic(var/mob/user, href_list, var/datum/topic_state/custom_state)
/atom/proc/CanUseTopic(var/mob/user, href_list, var/datum/topic_state/custom_state)
return user.can_use_topic(nano_host(), custom_state)
+30 -33
View File
@@ -1,7 +1,7 @@
#define EMITTER_DAMAGE_POWER_TRANSFER 450 //used to transfer power to containment field generators
/obj/machinery/power/emitter
name = "Emitter"
name = "emitter"
desc = "It is a heavy duty industrial laser."
icon = 'icons/obj/singularity.dmi'
icon_state = "emitter"
@@ -60,18 +60,18 @@
/obj/machinery/power/emitter/proc/activate(mob/user as mob)
if(state == 2)
if(!powernet)
user << "The emitter isn't connected to a wire."
user << "\The [src] isn't connected to a wire."
return 1
if(!src.locked)
if(src.active==1)
src.active = 0
user << "You turn off the [src]."
user << "You turn off [src]."
message_admins("Emitter turned off by [key_name(user, user.client)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
log_game("Emitter turned off by [user.ckey]([user]) in ([x],[y],[z])")
investigate_log("turned <font color='red'>off</font> by [user.key]","singulo")
else
src.active = 1
user << "You turn on the [src]."
user << "You turn on [src]."
src.shot_number = 0
src.fire_delay = 100
message_admins("Emitter turned on by [key_name(user, user.client)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
@@ -79,9 +79,9 @@
investigate_log("turned <font color='green'>on</font> by [user.key]","singulo")
update_icon()
else
user << "\red The controls are locked!"
user << "<span class='warning'>The controls are locked!</span>"
else
user << "\red The [src] needs to be firmly secured to the floor first."
user << "<span class='warning'>\The [src] needs to be firmly secured to the floor first.</span>"
return 1
@@ -138,86 +138,83 @@
s.set_up(5, 1, src)
s.start()
A.set_dir(src.dir)
A.starting = get_turf(src)
switch(dir)
if(NORTH)
A.yo = 20
A.xo = 0
A.original = locate(x, y+1, z)
if(EAST)
A.yo = 0
A.xo = 20
A.original = locate(x+1, y, z)
if(WEST)
A.yo = 0
A.xo = -20
A.original = locate(x-1, y, z)
else // Any other
A.yo = -20
A.xo = 0
A.process() //TODO: Carn: check this out
A.original = locate(x, y-1, z)
A.process()
/obj/machinery/power/emitter/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/weapon/wrench))
if(active)
user << "Turn off the [src] first."
user << "Turn off [src] first."
return
switch(state)
if(0)
state = 1
playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
user.visible_message("[user.name] secures [src.name] to the floor.", \
user.visible_message("[user.name] secures [src] to the floor.", \
"You secure the external reinforcing bolts to the floor.", \
"You hear a ratchet")
src.anchored = 1
if(1)
state = 0
playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
user.visible_message("[user.name] unsecures [src.name] reinforcing bolts from the floor.", \
user.visible_message("[user.name] unsecures [src] reinforcing bolts from the floor.", \
"You undo the external reinforcing bolts.", \
"You hear a ratchet")
src.anchored = 0
if(2)
user << "\red The [src.name] needs to be unwelded from the floor."
user << "<span class='warning'>\The [src] needs to be unwelded from the floor.</span>"
return
if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(active)
user << "Turn off the [src] first."
user << "Turn off [src] first."
return
switch(state)
if(0)
user << "\red The [src.name] needs to be wrenched to the floor."
user << "<span class='warning'>\The [src] needs to be wrenched to the floor.</span>"
if(1)
if (WT.remove_fuel(0,user))
playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
user.visible_message("[user.name] starts to weld the [src.name] to the floor.", \
"You start to weld the [src] to the floor.", \
user.visible_message("[user.name] starts to weld [src] to the floor.", \
"You start to weld [src] to the floor.", \
"You hear welding")
if (do_after(user,20))
if(!src || !WT.isOn()) return
state = 2
user << "You weld the [src] to the floor."
user << "You weld [src] to the floor."
connect_to_network()
else
user << "\red You need more welding fuel to complete this task."
user << "<span class='warning'>You need more welding fuel to complete this task.</span>"
if(2)
if (WT.remove_fuel(0,user))
playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
user.visible_message("[user.name] starts to cut the [src.name] free from the floor.", \
"You start to cut the [src] free from the floor.", \
user.visible_message("[user.name] starts to cut [src] free from the floor.", \
"You start to cut [src] free from the floor.", \
"You hear welding")
if (do_after(user,20))
if(!src || !WT.isOn()) return
state = 1
user << "You cut the [src] free from the floor."
user << "You cut [src] free from the floor."
disconnect_from_network()
else
user << "\red You need more welding fuel to complete this task."
user << "<span class='warning'>You need more welding fuel to complete this task.</span>"
return
if(istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda))
if(emagged)
user << "\red The lock seems to be broken"
user << "<span class='warning'>The lock seems to be broken.</span>"
return
if(src.allowed(user))
if(active)
@@ -225,16 +222,16 @@
user << "The controls are now [src.locked ? "locked." : "unlocked."]"
else
src.locked = 0 //just in case it somehow gets locked
user << "\red The controls can only be locked when the [src] is online"
user << "<span class='warning'>The controls can only be locked when [src] is online.</span>"
else
user << "\red Access denied."
user << "<span class='warning'>Access denied.</span>"
return
if(istype(W, /obj/item/weapon/card/emag) && !emagged)
locked = 0
emagged = 1
user.visible_message("[user.name] emags the [src.name].","\red You short out the lock.")
user.visible_message("[user.name] emags [src].","<span class='warning'>You short out the lock.</span>")
return
..()
+126
View File
@@ -0,0 +1,126 @@
/obj/effect/projectile
icon = 'icons/effects/projectiles.dmi'
icon_state = "bolt"
layer = 20
/obj/effect/projectile/New(var/turf/location)
if(istype(location))
loc = location
/obj/effect/projectile/proc/set_transform(var/matrix/M)
if(istype(M))
transform = M
/obj/effect/projectile/proc/activate()
spawn(3)
delete() //see effect_system.dm - sets loc to null and lets GC handle removing these effects
return
//----------------------------
// Laser beam
//----------------------------
/obj/effect/projectile/laser/tracer
icon_state = "beam"
/obj/effect/projectile/laser/muzzle
icon_state = "muzzle_laser"
/obj/effect/projectile/laser/impact
icon_state = "impact_laser"
//----------------------------
// Blue laser beam
//----------------------------
/obj/effect/projectile/laser_blue/tracer
icon_state = "beam_blue"
/obj/effect/projectile/laser_blue/muzzle
icon_state = "muzzle_blue"
/obj/effect/projectile/laser_blue/impact
icon_state = "impact_blue"
//----------------------------
// Omni laser beam
//----------------------------
/obj/effect/projectile/laser_omni/tracer
icon_state = "beam_omni"
/obj/effect/projectile/laser_omni/muzzle
icon_state = "muzzle_omni"
/obj/effect/projectile/laser_omni/impact
icon_state = "impact_omni"
//----------------------------
// Xray laser beam
//----------------------------
/obj/effect/projectile/xray/tracer
icon_state = "xray"
/obj/effect/projectile/xray/muzzle
icon_state = "muzzle_xray"
/obj/effect/projectile/xray/impact
icon_state = "impact_xray"
//----------------------------
// Heavy laser beam
//----------------------------
/obj/effect/projectile/laser_heavy/tracer
icon_state = "beam_heavy"
/obj/effect/projectile/laser_heavy/muzzle
icon_state = "muzzle_beam_heavy"
/obj/effect/projectile/laser_heavy/impact
icon_state = "impact_beam_heavy"
//----------------------------
// Pulse laser beam
//----------------------------
/obj/effect/projectile/laser_pulse/tracer
icon_state = "u_laser"
/obj/effect/projectile/laser_pulse/muzzle
icon_state = "muzzle_u_laser"
/obj/effect/projectile/laser_pulse/impact
icon_state = "impact_u_laser"
//----------------------------
// Pulse muzzle effect only
//----------------------------
/obj/effect/projectile/pulse/muzzle
icon_state = "muzzle_pulse"
//----------------------------
// Emitter beam
//----------------------------
/obj/effect/projectile/emitter/tracer
icon_state = "emitter"
/obj/effect/projectile/emitter/muzzle
icon_state = "muzzle_emitter"
/obj/effect/projectile/emitter/impact
icon_state = "impact_emitter"
//----------------------------
// Stun beam
//----------------------------
/obj/effect/projectile/stun/tracer
icon_state = "stun"
/obj/effect/projectile/stun/muzzle
icon_state = "muzzle_stun"
/obj/effect/projectile/stun/impact
icon_state = "impact_stun"
//----------------------------
// Bullet
//----------------------------
/obj/effect/projectile/bullet/muzzle
icon_state = "muzzle_bullet"
@@ -6,6 +6,8 @@
embed = 1 //the dart is shot fast enough to pierce space suits, so I guess splintering inside the target can be a thing. Should be rare due to low damage.
var/reagent_amount = 15
kill_count = 15 //shorter range
muzzle_type = null
/obj/item/projectile/bullet/chemdart/New()
reagents = new/datum/reagents(reagent_amount)
+93 -7
View File
@@ -51,6 +51,18 @@
var/drowsy = 0
var/agony = 0
var/embed = 0 // whether or not the projectile can embed itself in the mob
var/hitscan = 0 // whether the projectile should be hitscan
// effect types to be used
var/muzzle_type
var/tracer_type
var/impact_type
var/datum/plot_vector/trajectory // used to plot the path of the projectile
var/datum/vector_loc/location // current location of the projectile in pixel space
var/matrix/effect_transform // matrix to rotate and scale projectile effects - putting it here so it doesn't
// have to be recreated multiple times
//TODO: make it so this is called more reliably, instead of sometimes by bullet_act() and sometimes not
/obj/item/projectile/proc/on_hit(var/atom/target, var/blocked = 0, var/def_zone = null)
@@ -63,6 +75,7 @@
//called when the projectile stops flying because it collided with something
/obj/item/projectile/proc/on_impact(var/atom/A)
impact_effect(effect_transform) // generate impact effect
return
//Checks if the projectile is eligible for embedding. Not that it necessarily will.
@@ -228,6 +241,7 @@
density = 0
invisibility = 101
del(src)
return 1
@@ -240,23 +254,86 @@
return 1
/obj/item/projectile/process()
var/first_step = 1
//plot the initial trajectory
setup_trajectory()
spawn while(src)
if(kill_count-- < 1)
on_impact(src.loc) //for any final impact behaviours
del(src)
del(src)
if((!( current ) || loc == current))
current = locate(min(max(x + xo, 1), world.maxx), min(max(y + yo, 1), world.maxy), z)
if((x == 1 || x == world.maxx || y == 1 || y == world.maxy))
del(src)
return
step_towards(src, current)
sleep(1)
trajectory.increment() // increment the current location
location = trajectory.return_location(location) // update the locally stored location data
if(!location)
del(src) // if it's left the world... kill it
Move(location.return_turf())
if(first_step)
muzzle_effect(effect_transform)
first_step = 0
else
tracer_effect(effect_transform)
if(!bumped && !isturf(original))
if(loc == get_turf(original))
if(!(original in permutated))
Bump(original)
sleep(1)
if(!hitscan)
sleep(1) //add delay between movement iterations if it's not a hitscan weapon
/obj/item/projectile/proc/setup_trajectory()
// plot the initial trajectory
trajectory = new()
trajectory.setup(starting, original, pixel_x, pixel_y)
// generate this now since all visual effects the projectile makes can use it
effect_transform = new()
effect_transform.Scale(trajectory.return_hypotenuse(), 1)
effect_transform.Turn(-trajectory.return_angle()) //no idea why this has to be inverted, but it works
/obj/item/projectile/proc/muzzle_effect(var/matrix/T)
if(silenced)
return
if(ispath(muzzle_type))
var/obj/effect/projectile/M = new muzzle_type(get_turf(src))
if(istype(M))
M.set_transform(T)
M.pixel_x = location.pixel_x
M.pixel_y = location.pixel_y
M.activate()
/obj/item/projectile/proc/tracer_effect(var/matrix/M)
if(ispath(tracer_type))
var/obj/effect/projectile/P = new tracer_type(location.loc)
if(istype(P))
P.set_transform(M)
P.pixel_x = location.pixel_x
P.pixel_y = location.pixel_y
P.activate()
/obj/item/projectile/proc/impact_effect(var/matrix/M)
if(ispath(tracer_type))
var/obj/effect/projectile/P = new impact_type(location.loc)
if(istype(P))
P.set_transform(M)
P.pixel_x = location.pixel_x
P.pixel_y = location.pixel_y
P.activate()
//"Tracing" projectile
/obj/item/projectile/test //Used to see if you can hit them.
invisibility = 101 //Nope! Can't see me!
@@ -285,12 +362,21 @@
yo = targloc.y - curloc.y
xo = targloc.x - curloc.x
target = targloc
//plot the initial trajectory
setup_trajectory()
while(src) //Loop on through!
if(result)
return (result - 1)
if((!( target ) || loc == target))
target = locate(min(max(x + xo, 1), world.maxx), min(max(y + yo, 1), world.maxy), z) //Finding the target turf at map edge
step_towards(src, target)
trajectory.increment() // increment the current location
location = trajectory.return_location(location) // update the locally stored location data
Move(location.return_turf())
var/mob/living/M = locate() in get_turf(src)
if(istype(M)) //If there is someting living...
return 1 //Return 1
@@ -310,4 +396,4 @@
trace.firer = user
var/output = trace.process() //Test it!
del(trace) //No need for it anymore
return output //Send it back to the gun!
return output //Send it back to the gun!
+36 -72
View File
@@ -1,13 +1,3 @@
var/list/beam_master = list()
//Use: Caches beam state images and holds turfs that had these images overlaid.
//Structure:
//beam_master
// icon_states/dirs of beams
// image for that beam
// references for fired beams
// icon_states/dirs for each placed beam image
// turfs that have that icon_state/dir
/obj/item/projectile/beam
name = "laser"
icon_state = "laser"
@@ -17,69 +7,11 @@ var/list/beam_master = list()
check_armour = "laser"
eyeblur = 4
var/frequency = 1
hitscan = 1
/obj/item/projectile/beam/process()
var/reference = "\ref[src]" //So we do not have to recalculate it a ton
var/first = 1 //So we don't make the overlay in the same tile as the firer
spawn while(src) //Move until we hit something
if((!( current ) || loc == current)) //If we pass our target
current = locate(min(max(x + xo, 1), world.maxx), min(max(y + yo, 1), world.maxy), z)
if((x == 1 || x == world.maxx || y == 1 || y == world.maxy))
del(src) //Delete if it passes the world edge
return
step_towards(src, current) //Move~
if(kill_count < 1)
del(src)
kill_count--
if(!bumped && !isturf(original))
if(loc == get_turf(original))
if(!(original in permutated))
Bump(original)
if(!first) //Add the overlay as we pass over tiles
var/target_dir = get_dir(src, current) //So we don't call this too much
//If the icon has not been added yet
if( !("[icon_state][target_dir]" in beam_master) )
var/image/I = image(icon,icon_state,10,target_dir) //Generate it.
beam_master["[icon_state][target_dir]"] = I //And cache it!
//Finally add the overlay
src.loc.overlays += beam_master["[icon_state][target_dir]"]
//Add the turf to a list in the beam master so they can be cleaned up easily.
if(reference in beam_master)
var/list/turf_master = beam_master[reference]
if("[icon_state][target_dir]" in turf_master)
var/list/turfs = turf_master["[icon_state][target_dir]"]
turfs += loc
else
turf_master["[icon_state][target_dir]"] = list(loc)
else
var/list/turfs = list()
turfs["[icon_state][target_dir]"] = list(loc)
beam_master[reference] = turfs
else
first = 0
cleanup(reference)
return
/obj/item/projectile/beam/Del()
cleanup("\ref[src]")
..()
/obj/item/projectile/beam/proc/cleanup(reference) //Waits .3 seconds then removes the overlay.
src = null //we're getting deleted! this will keep the code running
spawn(3)
var/list/turf_master = beam_master[reference]
for(var/laser_state in turf_master)
var/list/turfs = turf_master[laser_state]
for(var/turf/T in turfs)
T.overlays -= beam_master[laser_state]
return
muzzle_type = /obj/effect/projectile/laser/muzzle
tracer_type = /obj/effect/projectile/laser/tracer
impact_type = /obj/effect/projectile/laser/impact
/obj/item/projectile/beam/practice
name = "laser"
@@ -95,16 +27,28 @@ var/list/beam_master = list()
icon_state = "heavylaser"
damage = 60
muzzle_type = /obj/effect/projectile/laser_heavy/muzzle
tracer_type = /obj/effect/projectile/laser_heavy/tracer
impact_type = /obj/effect/projectile/laser_heavy/impact
/obj/item/projectile/beam/xray
name = "xray beam"
icon_state = "xray"
damage = 30
muzzle_type = /obj/effect/projectile/xray/muzzle
tracer_type = /obj/effect/projectile/xray/tracer
impact_type = /obj/effect/projectile/xray/impact
/obj/item/projectile/beam/pulse
name = "pulse"
icon_state = "u_laser"
damage = 50
muzzle_type = /obj/effect/projectile/laser_pulse/muzzle
tracer_type = /obj/effect/projectile/laser_pulse/tracer
impact_type = /obj/effect/projectile/laser_pulse/impact
/obj/item/projectile/beam/pulse/on_hit(var/atom/target, var/blocked = 0)
if(isturf(target))
target.ex_act(2)
@@ -115,6 +59,10 @@ var/list/beam_master = list()
icon_state = "emitter"
damage = 0 // The actual damage is computed in /code/modules/power/singularity/emitter.dm
muzzle_type = /obj/effect/projectile/emitter/muzzle
tracer_type = /obj/effect/projectile/emitter/tracer
impact_type = /obj/effect/projectile/emitter/impact
/obj/item/projectile/beam/lastertag/blue
name = "lasertag beam"
icon_state = "bluelaser"
@@ -123,6 +71,10 @@ var/list/beam_master = list()
damage_type = BURN
check_armour = "laser"
muzzle_type = /obj/effect/projectile/laser_blue/muzzle
tracer_type = /obj/effect/projectile/laser_blue/tracer
impact_type = /obj/effect/projectile/laser_blue/impact
/obj/item/projectile/beam/lastertag/blue/on_hit(var/atom/target, var/blocked = 0)
if(istype(target, /mob/living/carbon/human))
var/mob/living/carbon/human/M = target
@@ -153,6 +105,10 @@ var/list/beam_master = list()
damage_type = BURN
check_armour = "laser"
muzzle_type = /obj/effect/projectile/laser_omni/muzzle
tracer_type = /obj/effect/projectile/laser_omni/tracer
impact_type = /obj/effect/projectile/laser_omni/impact
/obj/item/projectile/beam/lastertag/omni/on_hit(var/atom/target, var/blocked = 0)
if(istype(target, /mob/living/carbon/human))
var/mob/living/carbon/human/M = target
@@ -168,6 +124,10 @@ var/list/beam_master = list()
weaken = 3
stutter = 3
muzzle_type = /obj/effect/projectile/xray/muzzle
tracer_type = /obj/effect/projectile/xray/tracer
impact_type = /obj/effect/projectile/xray/impact
/obj/item/projectile/beam/stun
name = "stun beam"
icon_state = "stun"
@@ -175,3 +135,7 @@ var/list/beam_master = list()
taser_effect = 1
agony = 40
damage_type = HALLOSS
muzzle_type = /obj/effect/projectile/stun/muzzle
tracer_type = /obj/effect/projectile/stun/tracer
impact_type = /obj/effect/projectile/stun/impact
@@ -8,6 +8,8 @@
embed = 1
sharp = 1
var/mob_passthrough_check = 0
muzzle_type = /obj/effect/projectile/bullet/muzzle
/obj/item/projectile/bullet/on_hit(var/atom/target, var/blocked = 0)
if (..(target, blocked))
+16 -1
View File
@@ -772,8 +772,23 @@ var/list/be_special_flags = list(
#define STATUS_UPDATE 1 // ORANGE Visability
#define STATUS_DISABLED 0 // RED Visability
#define STATUS_CLOSE -1 // Close the interface
//General-purpose life speed define for plants.
#define HYDRO_SPEED_MULTIPLIER 1
#define NANO_IGNORE_DISTANCE 1
#define DEFAULT_JOB_TYPE /datum/job/assistant
#define DEFAULT_JOB_TYPE /datum/job/assistant
// Appearance change flags
#define APPEARANCE_UPDATE_DNA 1
#define APPEARANCE_RACE 2|APPEARANCE_UPDATE_DNA
#define APPEARANCE_GENDER 4|APPEARANCE_UPDATE_DNA
#define APPEARANCE_SKIN 8
#define APPEARANCE_HAIR 16
#define APPEARANCE_HAIR_COLOR 32
#define APPEARANCE_FACIAL_HAIR 64
#define APPEARANCE_FACIAL_HAIR_COLOR 128
#define APPEARANCE_EYE_COLOR 256
#define APPEARANCE_ALL_HAIR APPEARANCE_HAIR|APPEARANCE_HAIR_COLOR|APPEARANCE_FACIAL_HAIR|APPEARANCE_FACIAL_HAIR_COLOR
#define APPEARANCE_ALL 511
+5 -1
View File
@@ -322,5 +322,9 @@ EVENT_CUSTOM_START_MAJOR 80;100
## Uncomment to disable respawning by default.
#DISABLE_RESPAWN
## Strength of ambient star light. Set to 0 or less to turn off.
## Strength of ambient star light. Set to 0 or less to turn off. A value of 1 is unlikely to have a noticeable effect in most lightning systems.
STARLIGHT 0
## Defines which races are allowed to join as ERT, in singular form. If unset, defaults to only human. Casing matters, separate using ;
## Example races include: Human, Tajara, Skrell, Unathi
# ERT_SPECIES Human;Skrell;Unathi
Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

+75
View File
@@ -0,0 +1,75 @@
{{if data.change_race}}
<div class="item">
<div class="itemLabelNarrow">
Species:
</div>
<div class="itemContentWide">
{{for data.species}}
{{:helper.link(value.specimen, null, { 'race' : value.specimen}, null, data.specimen == value.specimen ? 'selected' : null)}}
{{/for}}
</div>
</div>
{{/if}}
{{if data.change_gender}}
<div class="item">
<div class="itemLabelNarrow">
Gender:
</div>
<div class="itemContentWide">
{{:helper.link('Male', null, { 'gender' : 'male'}, null, data.gender == 'male' ? 'selected' : null)}}
{{:helper.link('Female', null, { 'gender' : 'female'}, null, data.gender == 'female' ? 'selected' : null)}}
</div>
</div>
{{/if}}
{{if data.change_eye_color || data.change_skin_tone || data.change_skin_color || data.change_hair_color || data.change_facial_hair_color}}
<div class="item">
<div class="itemLabelNarrow">
Colors:
</div>
<div class="itemContentWide">
{{if data.change_eye_color}}
{{:helper.link('Change eye color', null, { 'eye_color' : 1})}}
{{/if}}
{{if data.change_skin_tone}}
{{:helper.link('Change skin tone', null, { 'skin_tone' : 1})}}
{{/if}}
{{if data.change_skin_color}}
{{:helper.link('Change skin color', null, { 'skin_color' : 1})}}
{{/if}}
{{if data.change_hair_color}}
{{:helper.link('Change hair color', null, { 'hair_color' : 1})}}
{{/if}}
{{if data.change_facial_hair_color}}
{{:helper.link('Change facial hair color', null, { 'facial_hair_color' : 1})}}
{{/if}}
</div>
</div>
{{/if}}
{{if data.change_hair}}
<div class="item">
<div class="itemLabelNarrow">
Hair styles:
</div>
<div class="itemContentWide">
{{for data.hair_styles}}
{{:helper.link(value.hairstyle, null, { 'hair' : value.hairstyle}, null, data.hair_style == value.hairstyle ? 'selected' : null)}}
{{/for}}
</div>
</div>
{{/if}}
{{if data.change_facial_hair}}
<div class="item">
<div class="itemLabelNarrow">
Facial hair styles:
</div>
<div class="itemContentWide">
{{for data.facial_hair_styles}}
{{:helper.link(value.facialhairstyle, null, { 'facial_hair' : value.facialhairstyle}, null, data.facial_hair_style == value.facialhairstyle ? 'selected' : null)}}
{{/for}}
</div>
</div>
{{/if}}