Merge branch 'master' into upstream-merge-33621
This commit is contained in:
@@ -5,6 +5,10 @@
|
||||
#It can be downloaded from command line with pip:
|
||||
#pip install mysqlclient
|
||||
#
|
||||
#tgstation no longer supports MySQL which has been superseded by MariaDB, a drop-in replacement.
|
||||
#Before running this script you will need to migrate to MariaDB.
|
||||
#Migrating is very easy to do, for details on how see: https://mariadb.com/kb/en/library/upgrading-from-mysql-to-mariadb/
|
||||
#
|
||||
#You will also have to create a new feedback table for inserting converted data to per the schema:
|
||||
#CREATE TABLE `feedback_new` (
|
||||
# `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
@@ -476,11 +480,25 @@ parser.add_argument("newtable", help="Name of the new table to insert to, can't
|
||||
args = parser.parse_args()
|
||||
db=MySQLdb.connect(host=args.address, user=args.username, passwd=args.password, db=args.database)
|
||||
cursor=db.cursor()
|
||||
cursor.execute("SELECT @@GLOBAL.version_comment")
|
||||
db_version = "".join([x for x in cursor.fetchone()])
|
||||
database_mysql = False
|
||||
if 'MySQL' in db_version:
|
||||
database_mysql = True
|
||||
elif 'mariadb' not in db_version:
|
||||
choice = input("Unable to determine database version installed, are you using MySQL? Type Yes or No and press enter...").lower()
|
||||
if choice == "yes":
|
||||
database_mysql = True
|
||||
if database_mysql == True:
|
||||
print("WARNING Database detected to be MySQL: tgstation no longer supports MySQL which has been superseded by MariaDB, a drop-in replacement.\nBefore running this script you will need to migrate to MariaDB.\nMigrating is very easy to do, for details on how see: https://mariadb.com/kb/en/library/upgrading-from-mysql-to-mariadb/")
|
||||
input("Press enter to quit...")
|
||||
quit()
|
||||
current_table = args.curtable
|
||||
new_table = args.newtable
|
||||
cursor.execute("SELECT max(id) FROM {0}".format(current_table))
|
||||
cursor.execute("SELECT max(id), max(round_id) FROM {0}".format(current_table))
|
||||
query_id = cursor.fetchone()
|
||||
max_id = query_id[0]
|
||||
max_round_id = query_id[1]
|
||||
start_time = datetime.now()
|
||||
print("Beginning conversion at {0}".format(start_time.strftime("%Y-%m-%d %H:%M:%S")))
|
||||
try:
|
||||
@@ -493,7 +511,7 @@ try:
|
||||
if not query_row:
|
||||
continue
|
||||
else:
|
||||
if current_round != query_row[2]:
|
||||
if current_round != query_row[2] or current_round == max_round_id:
|
||||
multirows_completed.clear()
|
||||
if query_values:
|
||||
query_values = query_values[:-1]
|
||||
@@ -524,8 +542,11 @@ try:
|
||||
print("Conversion completed at {0}".format(datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
|
||||
print("Script duration: {0}".format(end_time - start_time))
|
||||
except Exception as e:
|
||||
cursor.execute("SELECT round_id FROM {0} WHERE id = {1}".format(current_table, current_id-1))
|
||||
query_round_id = cursor.fetchone()
|
||||
end_time = datetime.now()
|
||||
print("Error encountered on row ID {0} at {1}".format(current_id, datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
|
||||
print("Note SQL insertion errors will be due to data from round ID {0}".format(query_round_id[0])) #since data is inserted when the round id changes on a new row
|
||||
print("Script duration: {0}".format(end_time - start_time))
|
||||
cursor.execute("TRUNCATE {0} ".format(new_table))
|
||||
raise e
|
||||
|
||||
@@ -10,14 +10,11 @@
|
||||
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
|
||||
/area/lavaland/surface/outdoors)
|
||||
"d" = (
|
||||
/turf/closed/wall{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
|
||||
},
|
||||
/turf/closed/wall,
|
||||
/area/ruin/unpowered)
|
||||
"e" = (
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/plating{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -25,7 +22,6 @@
|
||||
/obj/structure/table/wood,
|
||||
/obj/item/storage/box/cups,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -36,14 +32,12 @@
|
||||
},
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
"h" = (
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -51,7 +45,6 @@
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -59,7 +52,6 @@
|
||||
/obj/item/reagent_containers/food/snacks/pizzaslice/mushroom,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/plating{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -72,7 +64,6 @@
|
||||
},
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -89,7 +80,6 @@
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/effect/decal/cleanable/cobweb/cobweb2,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -97,7 +87,6 @@
|
||||
/obj/item/chair/wood/wings,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/plating{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -105,7 +94,6 @@
|
||||
/obj/structure/glowshroom/single,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -113,7 +101,6 @@
|
||||
/obj/item/trash/plate,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -121,7 +108,6 @@
|
||||
/obj/effect/decal/remains/human,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -129,7 +115,6 @@
|
||||
/obj/item/chair/wood/wings,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -141,13 +126,11 @@
|
||||
name = "party hat"
|
||||
},
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
"s" = (
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -155,14 +138,12 @@
|
||||
/obj/structure/chair/wood/wings,
|
||||
/obj/effect/decal/remains/human,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
"u" = (
|
||||
/obj/structure/glowshroom/single,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -175,7 +156,6 @@
|
||||
/obj/item/kitchen/fork,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -187,7 +167,6 @@
|
||||
name = "pizza spawner"
|
||||
},
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -195,7 +174,6 @@
|
||||
/obj/structure/table/wood,
|
||||
/obj/item/trash/plate,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -204,7 +182,6 @@
|
||||
/obj/structure/glowshroom/single,
|
||||
/obj/item/a_gift,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -213,7 +190,6 @@
|
||||
/obj/item/trash/plate,
|
||||
/obj/item/kitchen/fork,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -224,7 +200,6 @@
|
||||
},
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/plating{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -233,7 +208,6 @@
|
||||
/obj/item/reagent_containers/food/snacks/pizzaslice/margherita,
|
||||
/obj/item/trash/plate,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -241,7 +215,6 @@
|
||||
/obj/structure/table/wood,
|
||||
/obj/item/reagent_containers/food/snacks/pizzaslice/meat,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -249,21 +222,18 @@
|
||||
/obj/structure/table/wood,
|
||||
/obj/item/reagent_containers/food/snacks/store/cake/birthday,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
"G" = (
|
||||
/obj/structure/table/wood,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
"H" = (
|
||||
/obj/item/chair/wood/wings,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -271,7 +241,6 @@
|
||||
/obj/item/kitchen/fork,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/plating{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -279,7 +248,6 @@
|
||||
/obj/structure/glowshroom/single,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/plating{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -291,7 +259,6 @@
|
||||
/obj/effect/decal/remains/human,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -299,7 +266,6 @@
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/plating{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -307,7 +273,6 @@
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/item/a_gift,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -320,7 +285,6 @@
|
||||
/obj/item/kitchen/knife,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -330,13 +294,11 @@
|
||||
},
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
"Q" = (
|
||||
/turf/open/floor/plating{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
@@ -344,7 +306,6 @@
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/effect/baseturf_helper/lava_land/surface,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/asteroid/basalt/lava_land_surface;
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered)
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
/turf/open/floor/engine,
|
||||
/area/awaymission/BMPship/Aft)
|
||||
"ap" = (
|
||||
/turf/closed/wall/mineral/titanium/overspace,
|
||||
/turf/closed/wall/mineral/titanium/nodiagonal,
|
||||
/area/awaymission/BMPship/Midship)
|
||||
"aq" = (
|
||||
/turf/closed/wall/mineral/titanium,
|
||||
@@ -2309,6 +2309,27 @@
|
||||
},
|
||||
/turf/open/floor/carpet,
|
||||
/area/awaymission/BMPship/Fore)
|
||||
"hy" = (
|
||||
/turf/closed/wall/mineral/titanium/nodiagonal,
|
||||
/area/awaymission/BMPship/Fore)
|
||||
"hz" = (
|
||||
/turf/closed/wall/mineral/titanium/nodiagonal,
|
||||
/area/awaymission/BMPship/Fore)
|
||||
"hA" = (
|
||||
/turf/closed/wall/mineral/titanium/nodiagonal,
|
||||
/area/awaymission/BMPship/Fore)
|
||||
"hB" = (
|
||||
/turf/closed/wall/mineral/titanium/nodiagonal,
|
||||
/area/awaymission/BMPship/Fore)
|
||||
"hC" = (
|
||||
/turf/closed/wall/mineral/titanium/nodiagonal,
|
||||
/area/awaymission/BMPship/Fore)
|
||||
"hD" = (
|
||||
/turf/closed/wall/mineral/titanium/nodiagonal,
|
||||
/area/awaymission/BMPship/Fore)
|
||||
"hE" = (
|
||||
/turf/closed/wall/mineral/titanium/nodiagonal,
|
||||
/area/awaymission/BMPship/Fore)
|
||||
|
||||
(1,1,1) = {"
|
||||
aa
|
||||
@@ -2684,8 +2705,8 @@ aa
|
||||
aa
|
||||
aa
|
||||
aa
|
||||
cF
|
||||
aT
|
||||
aI
|
||||
hD
|
||||
bV
|
||||
hx
|
||||
ee
|
||||
@@ -2735,7 +2756,7 @@ aa
|
||||
aa
|
||||
aa
|
||||
aI
|
||||
aH
|
||||
hC
|
||||
bV
|
||||
bV
|
||||
dH
|
||||
@@ -2785,7 +2806,7 @@ aa
|
||||
aa
|
||||
aa
|
||||
aI
|
||||
aT
|
||||
hB
|
||||
bV
|
||||
bV
|
||||
bV
|
||||
@@ -2834,8 +2855,8 @@ aH
|
||||
aQ
|
||||
bl
|
||||
bt
|
||||
aT
|
||||
aT
|
||||
hy
|
||||
hA
|
||||
bV
|
||||
bV
|
||||
cY
|
||||
@@ -2849,7 +2870,7 @@ bI
|
||||
fv
|
||||
fJ
|
||||
aH
|
||||
aH
|
||||
hE
|
||||
aQ
|
||||
gF
|
||||
gR
|
||||
@@ -2987,7 +3008,7 @@ aH
|
||||
aT
|
||||
aT
|
||||
aT
|
||||
aT
|
||||
hz
|
||||
bW
|
||||
co
|
||||
cH
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4059,14 +4059,10 @@
|
||||
/area/ruin/space/has_grav/hotel/pool)
|
||||
"li" = (
|
||||
/obj/effect/light_emitter,
|
||||
/turf/open/floor/plating/beach/water{
|
||||
baseturf = /turf/open/space
|
||||
},
|
||||
/turf/open/floor/plating/beach/water,
|
||||
/area/ruin/space/has_grav/hotel/pool)
|
||||
"lj" = (
|
||||
/turf/open/floor/plating/beach/water{
|
||||
baseturf = /turf/open/space
|
||||
},
|
||||
/turf/open/floor/plating/beach/water,
|
||||
/area/ruin/space/has_grav/hotel/pool)
|
||||
"lk" = (
|
||||
/obj/structure/chair{
|
||||
@@ -4274,9 +4270,7 @@
|
||||
/area/ruin/space/has_grav/hotel/security)
|
||||
"lP" = (
|
||||
/obj/item/bikehorn/rubberducky,
|
||||
/turf/open/floor/plating/beach/water{
|
||||
baseturf = /turf/open/space
|
||||
},
|
||||
/turf/open/floor/plating/beach/water,
|
||||
/area/ruin/space/has_grav/hotel/pool)
|
||||
"lQ" = (
|
||||
/obj/structure/table,
|
||||
@@ -4655,6 +4649,10 @@
|
||||
},
|
||||
/turf/open/floor/carpet,
|
||||
/area/ruin/space/has_grav/hotel)
|
||||
"mW" = (
|
||||
/obj/effect/baseturf_helper/space,
|
||||
/turf/closed/wall,
|
||||
/area/ruin/space/has_grav/hotel/pool)
|
||||
|
||||
(1,1,1) = {"
|
||||
aa
|
||||
@@ -7090,7 +7088,7 @@ ih
|
||||
fi
|
||||
cJ
|
||||
jt
|
||||
jQ
|
||||
mW
|
||||
jQ
|
||||
jQ
|
||||
jQ
|
||||
|
||||
@@ -91,22 +91,16 @@
|
||||
density = 0;
|
||||
pixel_y = 18
|
||||
},
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"at" = (
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"au" = (
|
||||
/obj/machinery/computer/security/telescreen/entertainment{
|
||||
pixel_y = 32
|
||||
},
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"av" = (
|
||||
/obj/structure/toilet{
|
||||
@@ -117,9 +111,7 @@
|
||||
/area/awaymission/beach)
|
||||
"aw" = (
|
||||
/obj/structure/closet/secure_closet/personal/cabinet,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"ax" = (
|
||||
/obj/item/bedsheet/rainbow,
|
||||
@@ -131,9 +123,7 @@
|
||||
pixel_x = 24;
|
||||
specialfunctions = 4
|
||||
},
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"ay" = (
|
||||
/obj/effect/overlay/palmtree_r,
|
||||
@@ -151,9 +141,7 @@
|
||||
/obj/item/reagent_containers/food/drinks/bottle/wine,
|
||||
/obj/item/reagent_containers/food/drinks/bottle/rum,
|
||||
/obj/structure/table/wood,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"aB" = (
|
||||
/obj/effect/overlay/coconut,
|
||||
@@ -174,9 +162,7 @@
|
||||
/obj/structure/mirror{
|
||||
pixel_y = 28
|
||||
},
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"aF" = (
|
||||
/obj/machinery/button/door{
|
||||
@@ -186,9 +172,7 @@
|
||||
pixel_x = 24;
|
||||
specialfunctions = 4
|
||||
},
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"aG" = (
|
||||
/obj/machinery/button/door{
|
||||
@@ -198,9 +182,7 @@
|
||||
pixel_x = 24;
|
||||
specialfunctions = 4
|
||||
},
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"aH" = (
|
||||
/obj/machinery/door/airlock/sandstone{
|
||||
@@ -238,74 +220,52 @@
|
||||
/area/awaymission/beach)
|
||||
"aM" = (
|
||||
/obj/structure/closet/gmcloset,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"aN" = (
|
||||
/obj/structure/closet/secure_closet/bar,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"aO" = (
|
||||
/obj/structure/table/wood,
|
||||
/obj/item/book/manual/barman_recipes,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"aP" = (
|
||||
/obj/structure/table/wood,
|
||||
/obj/item/reagent_containers/food/drinks/shaker,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"aQ" = (
|
||||
/obj/structure/table/wood,
|
||||
/obj/item/reagent_containers/food/drinks/beer,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"aR" = (
|
||||
/obj/structure/table/wood,
|
||||
/obj/item/clothing/glasses/sunglasses,
|
||||
/obj/item/reagent_containers/food/drinks/beer,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"aS" = (
|
||||
/obj/effect/mob_spawn/human/bartender/alive,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"aT" = (
|
||||
/obj/machinery/vending/boozeomat,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"aU" = (
|
||||
/obj/machinery/vending/cigarette,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"aV" = (
|
||||
/obj/machinery/vending/cola,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"aW" = (
|
||||
/obj/machinery/vending/snack,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"aX" = (
|
||||
/obj/structure/mineral_door/wood{
|
||||
@@ -316,29 +276,21 @@
|
||||
"aY" = (
|
||||
/obj/structure/table/wood,
|
||||
/obj/item/reagent_containers/food/drinks/ale,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"aZ" = (
|
||||
/obj/structure/table/wood,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"ba" = (
|
||||
/obj/structure/table/wood,
|
||||
/obj/item/reagent_containers/food/drinks/soda_cans/dr_gibb,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"bb" = (
|
||||
/obj/structure/table/wood,
|
||||
/obj/item/reagent_containers/food/drinks/soda_cans/lemon_lime,
|
||||
/turf/open/floor/wood{
|
||||
baseturf = /turf/open/floor/plating/beach/sand
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/beach)
|
||||
"bc" = (
|
||||
/obj/item/toy/beach_ball,
|
||||
@@ -431,6 +383,10 @@
|
||||
"bt" = (
|
||||
/turf/open/floor/plating/beach/water,
|
||||
/area/awaymission/beach)
|
||||
"bu" = (
|
||||
/obj/effect/baseturf_helper/beach/sand,
|
||||
/turf/open/floor/plating/beach/sand,
|
||||
/area/awaymission/beach)
|
||||
|
||||
(1,1,1) = {"
|
||||
aa
|
||||
@@ -43447,7 +43403,7 @@ ab
|
||||
ab
|
||||
ab
|
||||
ab
|
||||
ac
|
||||
bu
|
||||
ac
|
||||
ac
|
||||
ac
|
||||
|
||||
+161
-525
File diff suppressed because it is too large
Load Diff
+409
-1273
File diff suppressed because it is too large
Load Diff
+626
-871
File diff suppressed because it is too large
Load Diff
@@ -353,7 +353,6 @@
|
||||
name = "emergency shower"
|
||||
},
|
||||
/turf/open/floor/plasteel/whiteblue/side{
|
||||
baseturf = /turf/open/lava/smooth/lava_land_surface;
|
||||
dir = 4
|
||||
},
|
||||
/area/shuttle/escape)
|
||||
|
||||
@@ -145,6 +145,7 @@
|
||||
#define ADMIN_PUNISHMENT_GIB "Gib"
|
||||
#define ADMIN_PUNISHMENT_BSA "Bluespace Artillery Device"
|
||||
#define ADMIN_PUNISHMENT_FIREBALL "Fireball"
|
||||
#define ADMIN_PUNISHMENT_ROD "Immovable Rod"
|
||||
|
||||
#define AHELP_ACTIVE 1
|
||||
#define AHELP_CLOSED 2
|
||||
|
||||
@@ -16,3 +16,5 @@
|
||||
#define ANTAG_DATUM_ABDUCTOR /datum/antagonist/abductor
|
||||
#define ANTAG_DATUM_ABDUCTOR_SCIENTIST /datum/antagonist/abductor/scientist
|
||||
#define ANTAG_DATUM_ABDUCTOR_AGENT /datum/antagonist/abductor/agent
|
||||
#define ANTAG_DATUM_MONKEY /datum/antagonist/monkey
|
||||
#define ANTAG_DATUM_MONKEY_LEADER /datum/antagonist/monkey/leader
|
||||
|
||||
@@ -12,6 +12,12 @@
|
||||
|
||||
//ATMOS
|
||||
//stuff you should probably leave well alone!
|
||||
#define R_IDEAL_GAS_EQUATION 8.31 //kPa*L/(K*mol)
|
||||
#define ONE_ATMOSPHERE 101.325 //kPa
|
||||
#define T0C 273.15 // 0degC
|
||||
#define T20C 293.15 // 20degC
|
||||
#define TCMB 2.7 // -270.3degC
|
||||
|
||||
#define MOLES_CELLSTANDARD (ONE_ATMOSPHERE*CELL_VOLUME/(T20C*R_IDEAL_GAS_EQUATION)) //moles in a 2.5 m^3 cell at 101.325 Pa and 20 degC
|
||||
#define M_CELL_WITH_RATIO (MOLES_CELLSTANDARD * 0.005) //compared against for superconductivity
|
||||
#define O2STANDARD 0.21 //percentage of oxygen in a normal mixture of air
|
||||
@@ -170,6 +176,4 @@
|
||||
#define ADD_GAS(gas_id, out_list)\
|
||||
var/list/tmp_gaslist = GLOB.gaslist_cache[gas_id]; out_list[gas_id] = tmp_gaslist.Copy();
|
||||
|
||||
//ASSERT_GAS(gas_id, gas_mixture) - used to guarantee that the gas list for this id exists in gas_mixture.gases.
|
||||
//Must be used before adding to a gas. May be used before reading from a gas.
|
||||
#define ASSERT_GAS(gas_id, gas_mixture) if (!gas_mixture.gases[gas_id]) { ADD_GAS(gas_id, gas_mixture.gases) };
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#define HIEROPHANT_ANSIBLE "hierophant_ansible" //Use this for construction-related scripture!
|
||||
|
||||
GLOBAL_VAR_INIT(clockwork_construction_value, 0) //The total value of all structures built by the clockwork cult
|
||||
GLOBAL_VAR_INIT(clockwork_caches, 0) //How many clockwork caches exist in the world (not each individual)
|
||||
GLOBAL_VAR_INIT(clockwork_vitality, 0) //How much Vitality is stored, total
|
||||
GLOBAL_VAR_INIT(clockwork_power, 0) //How many watts of power are globally available to the clockwork cult
|
||||
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
|
||||
// How multiple components of the exact same type are handled in the same datum
|
||||
|
||||
#define COMPONENT_DUPE_HIGHLANDER 0 //old component is deleted (default)
|
||||
#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed
|
||||
#define COMPONENT_DUPE_UNIQUE 2 //new component is deleted
|
||||
#define COMPONENT_DUPE_HIGHLANDER 0 //old component is deleted (default)
|
||||
#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed
|
||||
#define COMPONENT_DUPE_UNIQUE 2 //new component is deleted
|
||||
#define COMPONENT_DUPE_UNIQUE_PASSARGS 4 //old component is given the initialization args of the new
|
||||
|
||||
// All signals. Format:
|
||||
// When the signal is called: (signal arguments)
|
||||
@@ -61,6 +62,8 @@
|
||||
#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user)
|
||||
#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (/mob)
|
||||
#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //from base of obj/item/attack_obj(): (/obj, /mob)
|
||||
#define COMSIG_ITEM_EQUIPPED "item_equip" //from base of obj/item/equipped(): (/mob/equipper, slot)
|
||||
#define COMSIG_ITEM_DROPPED "item_drop" //from base of obj/item/dropped(): (/mob/dropper)
|
||||
|
||||
// /obj/item/clothing signals
|
||||
#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): ()
|
||||
@@ -77,10 +80,10 @@
|
||||
#define COMSIG_MACHINE_PROCESS "machine_process" //from machinery subsystem fire(): ()
|
||||
#define COMSIG_MACHINE_PROCESS_ATMOS "machine_process_atmos" //from air subsystem process_atmos_machinery(): ()
|
||||
|
||||
|
||||
// /mob/living/carbon/human signals
|
||||
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target)
|
||||
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" //from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker)
|
||||
#define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit" //Hit by successful disarm attack (mob/living/carbon/human/attacker,zone_targeted)
|
||||
|
||||
#define CALTROP_BYPASS_SHOES 1
|
||||
#define CALTROP_IGNORE_WALKERS 2
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
//config files
|
||||
#define CONFIG_DEF(X) /datum/config_entry/##X { resident_file = CURRENT_RESIDENT_FILE }; /datum/config_entry/##X
|
||||
#define CONFIG_GET(X) global.config.Get(/datum/config_entry/##X)
|
||||
#define CONFIG_SET(X, Y) global.config.Set(/datum/config_entry/##X, ##Y)
|
||||
#define CONFIG_TWEAK(X) /datum/config_entry/##X
|
||||
|
||||
#define CONFIG_MAPS_FILE "maps.txt"
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#define PI 3.1415
|
||||
#define SPEED_OF_LIGHT 3e8 //not exact but hey!
|
||||
#define SPEED_OF_LIGHT_SQ 9e+16
|
||||
#define INFINITY 1e31 //closer then enough
|
||||
|
||||
//atmos
|
||||
#define R_IDEAL_GAS_EQUATION 8.31 //kPa*L/(K*mol)
|
||||
#define ONE_ATMOSPHERE 101.325 //kPa
|
||||
#define T0C 273.15 // 0degC
|
||||
#define T20C 293.15 // 20degC
|
||||
#define TCMB 2.7 // -270.3degC
|
||||
|
||||
#define SHORT_REAL_LIMIT 16777216
|
||||
|
||||
//"fancy" math for calculating time in ms from tick_usage percentage and the length of ticks
|
||||
//percent_of_tick_used * (ticklag * 100(to convert to ms)) / 100(percent ratio)
|
||||
//collapsed to percent_of_tick_used * tick_lag
|
||||
#define TICK_DELTA_TO_MS(percent_of_tick_used) ((percent_of_tick_used) * world.tick_lag)
|
||||
#define TICK_USAGE_TO_MS(starting_tickusage) (TICK_DELTA_TO_MS(TICK_USAGE_REAL - starting_tickusage))
|
||||
|
||||
#define PERCENT(val) (round(val*100, 0.1))
|
||||
#define CLAMP01(x) (Clamp(x, 0, 1))
|
||||
|
||||
//time of day but automatically adjusts to the server going into the next day within the same round.
|
||||
//for when you need a reliable time number that doesn't depend on byond time.
|
||||
#define REALTIMEOFDAY (world.timeofday + (MIDNIGHT_ROLLOVER * MIDNIGHT_ROLLOVER_CHECK))
|
||||
#define MIDNIGHT_ROLLOVER_CHECK ( GLOB.rollovercheck_last_timeofday != world.timeofday ? update_midnight_rollover() : GLOB.midnight_rollovers )
|
||||
@@ -0,0 +1,209 @@
|
||||
// Credits to Nickr5 for the useful procs I've taken from his library resource.
|
||||
// This file is quadruple wrapped for your pleasure
|
||||
// (
|
||||
|
||||
#define NUM_E 2.71828183
|
||||
#define NUM_SQRT2 1.41421356
|
||||
|
||||
#define PI 3.1415
|
||||
#define SPEED_OF_LIGHT 3e8 //not exact but hey!
|
||||
#define SPEED_OF_LIGHT_SQ 9e+16
|
||||
#define INFINITY 1e31 //closer then enough
|
||||
|
||||
#define SHORT_REAL_LIMIT 16777216
|
||||
|
||||
//"fancy" math for calculating time in ms from tick_usage percentage and the length of ticks
|
||||
//percent_of_tick_used * (ticklag * 100(to convert to ms)) / 100(percent ratio)
|
||||
//collapsed to percent_of_tick_used * tick_lag
|
||||
#define TICK_DELTA_TO_MS(percent_of_tick_used) ((percent_of_tick_used) * world.tick_lag)
|
||||
#define TICK_USAGE_TO_MS(starting_tickusage) (TICK_DELTA_TO_MS(TICK_USAGE_REAL - starting_tickusage))
|
||||
|
||||
#define PERCENT(val) (round((val)*100, 0.1))
|
||||
#define CLAMP01(x) (CLAMP(x, 0, 1))
|
||||
|
||||
//time of day but automatically adjusts to the server going into the next day within the same round.
|
||||
//for when you need a reliable time number that doesn't depend on byond time.
|
||||
#define REALTIMEOFDAY (world.timeofday + (MIDNIGHT_ROLLOVER * MIDNIGHT_ROLLOVER_CHECK))
|
||||
#define MIDNIGHT_ROLLOVER_CHECK ( GLOB.rollovercheck_last_timeofday != world.timeofday ? update_midnight_rollover() : GLOB.midnight_rollovers )
|
||||
|
||||
#define SIGN(x) ( (x)!=0 ? (x) / abs(x) : 0 )
|
||||
|
||||
#define CEILING(x, y) ( -round(-(x) / (y)) * (y) )
|
||||
|
||||
// round() acts like floor(x, 1) by default but can't handle other values
|
||||
#define FLOOR(x, y) ( round((x) / (y)) * (y) )
|
||||
|
||||
#define CLAMP(CLVALUE,CLMIN,CLMAX) ( max( (CLMIN), min((CLVALUE), (CLMAX)) ) )
|
||||
|
||||
// Similar to clamp but the bottom rolls around to the top and vice versa. min is inclusive, max is exclusive
|
||||
#define WRAP(val, min, max) ( min == max ? min : (val) - (round(((val) - (min))/((max) - (min))) * ((max) - (min))) )
|
||||
|
||||
// Real modulus that handles decimals
|
||||
#define MODULUS(x, y) ( (x) - (y) * round((x) / (y)) )
|
||||
|
||||
// Tangent
|
||||
#define TAN(x) (sin(x) / cos(x))
|
||||
|
||||
// Cotangent
|
||||
#define COT(x) (1 / TAN(x))
|
||||
|
||||
// Secant
|
||||
#define SEC(x) (1 / cos(x))
|
||||
|
||||
// Cosecant
|
||||
#define CSC(x) (1 / sin(x))
|
||||
|
||||
#define ATAN2(x, y) ( !(x) && !(y) ? 0 : (y) >= 0 ? arccos((x) / sqrt((x)*(x) + (y)*(y))) : -arccos((x) / sqrt((x)*(x) + (y)*(y))) )
|
||||
|
||||
// Greatest Common Divisor - Euclid's algorithm
|
||||
/proc/Gcd(a, b)
|
||||
return b ? Gcd(b, (a) % (b)) : a
|
||||
|
||||
// Least Common Multiple
|
||||
#define Lcm(a, b) (abs(a) / Gcd(a, b) * abs(b))
|
||||
|
||||
#define INVERSE(x) ( 1/(x) )
|
||||
|
||||
// Used for calculating the radioactive strength falloff
|
||||
#define INVERSE_SQUARE(initial_strength,cur_distance,initial_distance) ( (initial_strength)*((initial_distance)**2/(cur_distance)**2) )
|
||||
|
||||
#define ISABOUTEQUAL(a, b, deviation) (deviation ? abs((a) - (b)) <= deviation : abs((a) - (b)) <= 0.1)
|
||||
|
||||
#define ISEVEN(x) (x % 2 == 0)
|
||||
|
||||
#define ISODD(x) (x % 2 != 0)
|
||||
|
||||
// Returns true if val is from min to max, inclusive.
|
||||
#define ISINRANGE(val, min, max) (min <= val && val <= max)
|
||||
|
||||
// Same as above, exclusive.
|
||||
#define ISINRANGE_EX(val, min, max) (min < val && val > max)
|
||||
|
||||
#define ISINTEGER(x) (round(x) == x)
|
||||
|
||||
#define ISMULTIPLE(x, y) ((x) % (y) == 0)
|
||||
|
||||
// Performs a linear interpolation between a and b.
|
||||
// Note that amount=0 returns a, amount=1 returns b, and
|
||||
// amount=0.5 returns the mean of a and b.
|
||||
#define LERP(a, b, amount) (amount ? ((a) + ((b) - (a)) * (amount)) : ((a) + ((b) - (a)) * 0.5)
|
||||
|
||||
// Returns the nth root of x.
|
||||
#define ROOT(n, x) ((x) ** (1 / (n)))
|
||||
|
||||
// The quadratic formula. Returns a list with the solutions, or an empty list
|
||||
// if they are imaginary.
|
||||
/proc/SolveQuadratic(a, b, c)
|
||||
ASSERT(a)
|
||||
. = list()
|
||||
var/d = b*b - 4 * a * c
|
||||
var/bottom = 2 * a
|
||||
if(d < 0)
|
||||
return
|
||||
var/root = sqrt(d)
|
||||
. += (-b + root) / bottom
|
||||
if(!d)
|
||||
return
|
||||
. += (-b - root) / bottom
|
||||
|
||||
#define TODEGREES(radians) ((radians) * 57.2957795)
|
||||
|
||||
#define TORADIANS(degrees) ((degrees) * 0.0174532925)
|
||||
|
||||
// Will filter out extra rotations and negative rotations
|
||||
// E.g: 540 becomes 180. -180 becomes 180.
|
||||
#define SIMPLIFY_DEGREES(degrees) (MODULUS((degrees), 360))
|
||||
|
||||
#define GET_ANGLE_OF_INCIDENCE(face, input) (MODULUS((face) - (input), 360))
|
||||
|
||||
//A logarithm that converts an integer to a number scaled between 0 and 1.
|
||||
//Currently, this is used for hydroponics-produce sprite transforming, but could be useful for other transform functions.
|
||||
#define TRANSFORM_USING_VARIABLE(input, max) ( sin((90*(input))/(max))**2 )
|
||||
|
||||
//converts a uniform distributed random number into a normal distributed one
|
||||
//since this method produces two random numbers, one is saved for subsequent calls
|
||||
//(making the cost negligble for every second call)
|
||||
//This will return +/- decimals, situated about mean with standard deviation stddev
|
||||
//68% chance that the number is within 1stddev
|
||||
//95% chance that the number is within 2stddev
|
||||
//98% chance that the number is within 3stddev...etc
|
||||
#define ACCURACY 10000
|
||||
/proc/gaussian(mean, stddev)
|
||||
var/static/gaussian_next
|
||||
var/R1;var/R2;var/working
|
||||
if(gaussian_next != null)
|
||||
R1 = gaussian_next
|
||||
gaussian_next = null
|
||||
else
|
||||
do
|
||||
R1 = rand(-ACCURACY,ACCURACY)/ACCURACY
|
||||
R2 = rand(-ACCURACY,ACCURACY)/ACCURACY
|
||||
working = R1*R1 + R2*R2
|
||||
while(working >= 1 || working==0)
|
||||
working = sqrt(-2 * log(working) / working)
|
||||
R1 *= working
|
||||
gaussian_next = R2 * working
|
||||
return (mean + stddev * R1)
|
||||
#undef ACCURACY
|
||||
|
||||
/proc/mouse_angle_from_client(client/client)
|
||||
var/list/mouse_control = params2list(client.mouseParams)
|
||||
if(mouse_control["screen-loc"] && client)
|
||||
var/list/screen_loc_params = splittext(mouse_control["screen-loc"], ",")
|
||||
var/list/screen_loc_X = splittext(screen_loc_params[1],":")
|
||||
var/list/screen_loc_Y = splittext(screen_loc_params[2],":")
|
||||
var/x = (text2num(screen_loc_X[1]) * 32 + text2num(screen_loc_X[2]) - 32)
|
||||
var/y = (text2num(screen_loc_Y[1]) * 32 + text2num(screen_loc_Y[2]) - 32)
|
||||
var/list/screenview = getviewsize(client.view)
|
||||
var/screenviewX = screenview[1] * world.icon_size
|
||||
var/screenviewY = screenview[2] * world.icon_size
|
||||
var/ox = round(screenviewX/2) - client.pixel_x //"origin" x
|
||||
var/oy = round(screenviewY/2) - client.pixel_y //"origin" y
|
||||
var/angle = SIMPLIFY_DEGREES(ATAN2(y - oy, x - ox))
|
||||
return angle
|
||||
|
||||
/proc/get_turf_in_angle(angle, turf/starting, increments)
|
||||
var/pixel_x = 0
|
||||
var/pixel_y = 0
|
||||
for(var/i in 1 to increments)
|
||||
pixel_x += sin(angle)+16*sin(angle)*2
|
||||
pixel_y += cos(angle)+16*cos(angle)*2
|
||||
var/new_x = starting.x
|
||||
var/new_y = starting.y
|
||||
while(pixel_x > 16)
|
||||
pixel_x -= 32
|
||||
new_x++
|
||||
while(pixel_x < -16)
|
||||
pixel_x += 32
|
||||
new_x--
|
||||
while(pixel_y > 16)
|
||||
pixel_y -= 32
|
||||
new_y++
|
||||
while(pixel_y < -16)
|
||||
pixel_y += 32
|
||||
new_y--
|
||||
new_x = CLAMP(new_x, 0, world.maxx)
|
||||
new_y = CLAMP(new_y, 0, world.maxy)
|
||||
return locate(new_x, new_y, starting.z)
|
||||
|
||||
// Returns a list where [1] is all x values and [2] is all y values that overlap between the given pair of rectangles
|
||||
/proc/get_overlap(x1, y1, x2, y2, x3, y3, x4, y4)
|
||||
var/list/region_x1 = list()
|
||||
var/list/region_y1 = list()
|
||||
var/list/region_x2 = list()
|
||||
var/list/region_y2 = list()
|
||||
|
||||
// These loops create loops filled with x/y values that the boundaries inhabit
|
||||
// ex: list(5, 6, 7, 8, 9)
|
||||
for(var/i in min(x1, x2) to max(x1, x2))
|
||||
region_x1["[i]"] = TRUE
|
||||
for(var/i in min(y1, y2) to max(y1, y2))
|
||||
region_y1["[i]"] = TRUE
|
||||
for(var/i in min(x3, x4) to max(x3, x4))
|
||||
region_x2["[i]"] = TRUE
|
||||
for(var/i in min(y3, y4) to max(y3, y4))
|
||||
region_y2["[i]"] = TRUE
|
||||
|
||||
return list(region_x1 & region_x2, region_y1 & region_y2)
|
||||
|
||||
// )
|
||||
@@ -334,9 +334,9 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Consider these images/atoms as part of the UI/HUD
|
||||
// Consider these images/atoms as part of the UI/HUD
|
||||
#define APPEARANCE_UI_IGNORE_ALPHA RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|RESET_ALPHA|PIXEL_SCALE
|
||||
#define APPEARANCE_UI RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR
|
||||
#define APPEARANCE_UI RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|PIXEL_SCALE
|
||||
|
||||
//Just space
|
||||
#define SPACE_ICON_STATE "[((x + y) ^ ~(x * y) + z) % 25]"
|
||||
@@ -444,6 +444,7 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
|
||||
#define GIBTONITE_ACTIVE 1
|
||||
#define GIBTONITE_STABLE 2
|
||||
#define GIBTONITE_DETONATE 3
|
||||
|
||||
//for obj explosion block calculation
|
||||
#define EXPLOSION_BLOCK_PROC -1
|
||||
|
||||
@@ -452,8 +453,6 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
|
||||
#define BEAT_SLOW 2
|
||||
#define BEAT_NONE 0
|
||||
|
||||
#define BEAT_CHANNEL 150
|
||||
|
||||
//http://www.byond.com/docs/ref/info.html#/atom/var/mouse_opacity
|
||||
#define MOUSE_OPACITY_TRANSPARENT 0
|
||||
#define MOUSE_OPACITY_ICON 1
|
||||
@@ -484,9 +483,6 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
|
||||
#define SYRINGE_DRAW 0
|
||||
#define SYRINGE_INJECT 1
|
||||
|
||||
#define RESEARCH_MATERIAL_RECLAMATION_ID "0"
|
||||
|
||||
|
||||
//gold slime core spawning
|
||||
#define NO_SPAWN 0
|
||||
#define HOSTILE_SPAWN 1
|
||||
@@ -495,7 +491,7 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
|
||||
#define RIDING_OFFSET_ALL "ALL"
|
||||
|
||||
//text files
|
||||
#define BRAIN_DAMAGE_FILE "brain_damage_lines.json"
|
||||
#define BRAIN_DAMAGE_FILE "traumas.json"
|
||||
|
||||
//Fullscreen overlay resolution in tiles.
|
||||
#define FULLSCREEN_OVERLAY_RESOLUTION_X 15
|
||||
|
||||
@@ -52,8 +52,8 @@
|
||||
/*see __DEFINES/inventory.dm for bodypart bitflag defines*/
|
||||
|
||||
//Brain Damage defines
|
||||
#define BRAIN_DAMAGE_MILD 50
|
||||
#define BRAIN_DAMAGE_SEVERE 120
|
||||
#define BRAIN_DAMAGE_MILD 20
|
||||
#define BRAIN_DAMAGE_SEVERE 100
|
||||
#define BRAIN_DAMAGE_DEATH 200
|
||||
|
||||
#define BRAIN_TRAUMA_MILD /datum/brain_trauma/mild
|
||||
|
||||
+26
-15
@@ -1,19 +1,30 @@
|
||||
#define SOLID 1
|
||||
#define LIQUID 2
|
||||
#define GAS 3
|
||||
#define SOLID 1
|
||||
#define LIQUID 2
|
||||
#define GAS 3
|
||||
|
||||
#define INJECTABLE_1 1024 //Makes reagents addable through droppers and syringes
|
||||
#define DRAWABLE_1 2048 //If a syringe can draw from it
|
||||
#define OPENCONTAINER_1 4096 //Is an open container for chemistry purposes
|
||||
#define TRANSPARENT_1 8192 //Used for non-open containers which you still want to be able to see the reagents off.
|
||||
|
||||
#define TOUCH 1 //splashing
|
||||
#define INGEST 2 //ingestion
|
||||
#define VAPOR 3 //foam, spray, blob attack
|
||||
#define PATCH 4 //patches
|
||||
#define INJECT 5 //injection
|
||||
// container_type defines
|
||||
#define INJECTABLE 1 // Makes it possible to add reagents through droppers and syringes.
|
||||
#define DRAWABLE 2 // Makes it possible to remove reagents through syringes.
|
||||
|
||||
#define REFILLABLE 4 // Makes it possible to add reagents through any reagent container.
|
||||
#define DRAINABLE 8 // Makes it possible to remove reagents through any reagent container.
|
||||
|
||||
#define TRANSPARENT 16 // Used on containers which you want to be able to see the reagents off.
|
||||
#define AMOUNT_VISIBLE 32 // For non-transparent containers that still have the general amount of reagents in them visible.
|
||||
|
||||
// Is an open container for all intents and purposes.
|
||||
#define OPENCONTAINER REFILLABLE | DRAINABLE | TRANSPARENT
|
||||
|
||||
|
||||
#define TOUCH 1 // splashing
|
||||
#define INGEST 2 // ingestion
|
||||
#define VAPOR 3 // foam, spray, blob attack
|
||||
#define PATCH 4 // patches
|
||||
#define INJECT 5 // injection
|
||||
|
||||
|
||||
//defines passed through to the on_reagent_change proc
|
||||
#define DEL_REAGENT 1 //reagent deleted (fully cleared)
|
||||
#define ADD_REAGENT 2 // reagent added
|
||||
#define REM_REAGENT 3 // reagent removed (may still exist)
|
||||
#define DEL_REAGENT 1 // reagent deleted (fully cleared)
|
||||
#define ADD_REAGENT 2 // reagent added
|
||||
#define REM_REAGENT 3 // reagent removed (may still exist)
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
|
||||
#define RDCONSOLE_UI_MODE_NORMAL 1
|
||||
#define RDCONSOLE_UI_MODE_EXPERT 2
|
||||
#define RDCONSOLE_UI_MODE_LIST 3
|
||||
|
||||
//RDSCREEN screens
|
||||
#define RDSCREEN_MENU 0
|
||||
#define RDSCREEN_TECHDISK 1
|
||||
@@ -59,3 +63,5 @@
|
||||
//#define DEPARTMENTAL_FLAG_MINING 128
|
||||
|
||||
#define DESIGN_ID_IGNORE "IGNORE_THIS_DESIGN"
|
||||
|
||||
#define RESEARCH_MATERIAL_RECLAMATION_ID "__materials"
|
||||
|
||||
@@ -75,3 +75,9 @@
|
||||
#define SHUTTLE_DOCKER_LANDING_CLEAR 1
|
||||
#define SHUTTLE_DOCKER_BLOCKED_BY_HIDDEN_PORT 2
|
||||
#define SHUTTLE_DOCKER_BLOCKED 3
|
||||
|
||||
//Shuttle defaults
|
||||
#define SHUTTLE_DEFAULT_TURF_TYPE /turf/open/space
|
||||
#define SHUTTLE_DEFAULT_BASETURF_TYPE /turf/open/space
|
||||
#define SHUTTLE_DEFAULT_SHUTTLE_AREA_TYPE /area/shuttle
|
||||
#define SHUTTLE_DEFAULT_UNDERLYING_AREA /area/space
|
||||
+22
-10
@@ -10,16 +10,28 @@
|
||||
|
||||
//mob disabilities stat
|
||||
|
||||
#define BLIND 1
|
||||
#define MUTE 2
|
||||
#define DEAF 4
|
||||
#define NEARSIGHT 8
|
||||
#define FAT 32
|
||||
#define HUSK 64
|
||||
#define NOCLONE 128
|
||||
#define CLUMSY 256
|
||||
#define DUMB 512
|
||||
#define MONKEYLIKE 1024 //sets IsAdvancedToolUser to FALSE
|
||||
#define DISABILITY_BLIND "blind"
|
||||
#define DISABILITY_MUTE "mute"
|
||||
#define DISABILITY_DEAF "deaf"
|
||||
#define DISABILITY_NEARSIGHT "nearsighted"
|
||||
#define DISABILITY_FAT "fat"
|
||||
#define DISABILITY_HUSK "husk"
|
||||
#define DISABILITY_NOCLONE "noclone"
|
||||
#define DISABILITY_CLUMSY "clumsy"
|
||||
#define DISABILITY_DUMB "dumb"
|
||||
#define DISABILITY_MONKEYLIKE "monkeylike" //sets IsAdvancedToolUser to FALSE
|
||||
#define DISABILITY_PACIFISM "pacifism"
|
||||
|
||||
// common disability sources
|
||||
#define EYE_DAMAGE "eye_damage"
|
||||
#define GENETIC_MUTATION "genetic"
|
||||
#define STATUE_MUTE "statue"
|
||||
#define CHANGELING_DRAIN "drain"
|
||||
#define OBESITY "obesity"
|
||||
#define MAGIC_DISABILITY "magic"
|
||||
#define STASIS_MUTE "stasis"
|
||||
#define GENETICS_SPELL "genetics_spell"
|
||||
#define TRAUMA_DISABILITY "trauma"
|
||||
|
||||
// bitflags for machine stat variable
|
||||
#define BROKEN 1
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
#define CHANGETURF_DEFER_CHANGE 1
|
||||
#define CHANGETURF_IGNORE_AIR 2
|
||||
#define CHANGETURF_FORCEOP 4
|
||||
@@ -43,8 +43,8 @@
|
||||
//Returns list element or null. Should prevent "index out of bounds" error.
|
||||
/proc/listgetindex(list/L, index)
|
||||
if(LAZYLEN(L))
|
||||
if(isnum(index) && IsInteger(index))
|
||||
if(IsInRange(index,1,L.len))
|
||||
if(isnum(index) && ISINTEGER(index))
|
||||
if(ISINRANGE(index,1,L.len))
|
||||
return L[index]
|
||||
else if(index in L)
|
||||
return L[index]
|
||||
|
||||
@@ -267,6 +267,13 @@
|
||||
if(!target_turf)
|
||||
return NULLTURF_BORDER
|
||||
|
||||
var/area/target_area = get_area(target_turf)
|
||||
var/area/source_area = get_area(source)
|
||||
if(source_area.canSmoothWithAreas && !is_type_in_typecache(target_area, source_area.canSmoothWithAreas))
|
||||
return null
|
||||
if(target_area.canSmoothWithAreas && !is_type_in_typecache(source_area, target_area.canSmoothWithAreas))
|
||||
return null
|
||||
|
||||
if(source.canSmoothWith)
|
||||
var/atom/A
|
||||
if(source.smooth & SMOOTH_MORE)
|
||||
|
||||
@@ -1,257 +0,0 @@
|
||||
// Credits to Nickr5 for the useful procs I've taken from his library resource.
|
||||
|
||||
GLOBAL_VAR_INIT(E, 2.71828183)
|
||||
GLOBAL_VAR_INIT(Sqrt2, 1.41421356)
|
||||
|
||||
// List of square roots for the numbers 1-100.
|
||||
GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10))
|
||||
|
||||
/proc/sign(x)
|
||||
return x!=0?x/abs(x):0
|
||||
|
||||
/proc/Atan2(x, y)
|
||||
if(!x && !y)
|
||||
return 0
|
||||
var/a = arccos(x / sqrt(x*x + y*y))
|
||||
return y >= 0 ? a : -a
|
||||
|
||||
/proc/Ceiling(x, y=1)
|
||||
return -round(-x / y) * y
|
||||
|
||||
/proc/Floor(x, y=1)
|
||||
return round(x / y) * y
|
||||
|
||||
#define Clamp(CLVALUE,CLMIN,CLMAX) ( max( (CLMIN), min((CLVALUE), (CLMAX)) ) )
|
||||
|
||||
/proc/Modulus(x, y) //Byond's modulus doesn't work with decimals.
|
||||
return x - y * round(x / y)
|
||||
|
||||
// cotangent
|
||||
/proc/Cot(x)
|
||||
return 1 / Tan(x)
|
||||
|
||||
// cosecant
|
||||
/proc/Csc(x)
|
||||
return 1 / sin(x)
|
||||
|
||||
/proc/Default(a, b)
|
||||
return a ? a : b
|
||||
|
||||
// Greatest Common Divisor - Euclid's algorithm
|
||||
/proc/Gcd(a, b)
|
||||
return b ? Gcd(b, a % b) : a
|
||||
|
||||
/proc/Inverse(x)
|
||||
return 1 / x
|
||||
|
||||
#define InverseSquareLaw(initial_strength,cur_distance,initial_distance) (initial_strength*(initial_distance**2/cur_distance**2))
|
||||
|
||||
/proc/IsAboutEqual(a, b, deviation = 0.1)
|
||||
return abs(a - b) <= deviation
|
||||
|
||||
/proc/IsEven(x)
|
||||
return x % 2 == 0
|
||||
|
||||
// Returns true if val is from min to max, inclusive.
|
||||
/proc/IsInRange(val, min, max)
|
||||
return min <= val && val <= max
|
||||
|
||||
/proc/IsInteger(x)
|
||||
return round(x) == x
|
||||
|
||||
/proc/IsOdd(x)
|
||||
return !IsEven(x)
|
||||
|
||||
/proc/IsMultiple(x, y)
|
||||
return x % y == 0
|
||||
|
||||
// Least Common Multiple
|
||||
/proc/Lcm(a, b)
|
||||
return abs(a) / Gcd(a, b) * abs(b)
|
||||
|
||||
// Performs a linear interpolation between a and b.
|
||||
// Note that amount=0 returns a, amount=1 returns b, and
|
||||
// amount=0.5 returns the mean of a and b.
|
||||
/proc/Lerp(a, b, amount = 0.5)
|
||||
return a + (b - a) * amount
|
||||
|
||||
//Calculates the sum of a list of numbers.
|
||||
/proc/Sum(var/list/data)
|
||||
. = 0
|
||||
for(var/val in data)
|
||||
.+= val
|
||||
|
||||
//Calculates the mean of a list of numbers.
|
||||
/proc/Mean(var/list/data)
|
||||
. = Sum(data) / (data.len)
|
||||
|
||||
|
||||
// Returns the nth root of x.
|
||||
/proc/Root(n, x)
|
||||
return x ** (1 / n)
|
||||
|
||||
// secant
|
||||
/proc/Sec(x)
|
||||
return 1 / cos(x)
|
||||
|
||||
// The quadratic formula. Returns a list with the solutions, or an empty list
|
||||
// if they are imaginary.
|
||||
/proc/SolveQuadratic(a, b, c)
|
||||
ASSERT(a)
|
||||
. = list()
|
||||
var/d = b*b - 4 * a * c
|
||||
var/bottom = 2 * a
|
||||
if(d < 0)
|
||||
return
|
||||
var/root = sqrt(d)
|
||||
. += (-b + root) / bottom
|
||||
if(!d)
|
||||
return
|
||||
. += (-b - root) / bottom
|
||||
|
||||
// tangent
|
||||
/proc/Tan(x)
|
||||
return sin(x) / cos(x)
|
||||
|
||||
/proc/ToDegrees(radians)
|
||||
// 180 / Pi
|
||||
return radians * 57.2957795
|
||||
|
||||
/proc/ToRadians(degrees)
|
||||
// Pi / 180
|
||||
return degrees * 0.0174532925
|
||||
|
||||
// Will filter out extra rotations and negative rotations
|
||||
// E.g: 540 becomes 180. -180 becomes 180.
|
||||
/proc/SimplifyDegrees(degrees)
|
||||
degrees = degrees % 360
|
||||
if(degrees < 0)
|
||||
degrees += 360
|
||||
return degrees
|
||||
|
||||
// min is inclusive, max is exclusive
|
||||
/proc/Wrap(val, min, max)
|
||||
var/d = max - min
|
||||
var/t = round((val - min) / d)
|
||||
return val - (t * d)
|
||||
|
||||
#define NORM_ROT(rot) ((((rot % 360) + (rot - round(rot, 1))) >= 0) ? ((rot % 360) + (rot - round(rot, 1))) : (((rot % 360) + (rot - round(rot, 1))) + 360))
|
||||
|
||||
/proc/get_angle_of_incidence(face_angle, angle_in, auto_normalize = TRUE)
|
||||
|
||||
var/angle_in_s = NORM_ROT(angle_in)
|
||||
var/face_angle_s = NORM_ROT(face_angle)
|
||||
var/incidence = face_angle_s - angle_in_s
|
||||
var/incidence_s = incidence
|
||||
while(incidence_s < -90)
|
||||
incidence_s += 180
|
||||
while(incidence_s > 90)
|
||||
incidence_s -= 180
|
||||
if(auto_normalize)
|
||||
return incidence_s
|
||||
else
|
||||
return incidence
|
||||
|
||||
//A logarithm that converts an integer to a number scaled between 0 and 1 (can be tweaked to be higher).
|
||||
//Currently, this is used for hydroponics-produce sprite transforming, but could be useful for other transform functions.
|
||||
/proc/TransformUsingVariable(input, inputmaximum, scaling_modifier = 0)
|
||||
|
||||
var/inputToDegrees = (input/inputmaximum)*180 //Converting from a 0 -> 100 scale to a 0 -> 180 scale. The 0 -> 180 scale corresponds to degrees
|
||||
var/size_factor = ((-cos(inputToDegrees) +1) /2) //returns a value from 0 to 1
|
||||
|
||||
return size_factor + scaling_modifier //scale mod of 0 results in a number from 0 to 1. A scale modifier of +0.5 returns 0.5 to 1.5
|
||||
|
||||
//converts a uniform distributed random number into a normal distributed one
|
||||
//since this method produces two random numbers, one is saved for subsequent calls
|
||||
//(making the cost negligble for every second call)
|
||||
//This will return +/- decimals, situated about mean with standard deviation stddev
|
||||
//68% chance that the number is within 1stddev
|
||||
//95% chance that the number is within 2stddev
|
||||
//98% chance that the number is within 3stddev...etc
|
||||
#define ACCURACY 10000
|
||||
/proc/gaussian(mean, stddev)
|
||||
var/static/gaussian_next
|
||||
var/R1;var/R2;var/working
|
||||
if(gaussian_next != null)
|
||||
R1 = gaussian_next
|
||||
gaussian_next = null
|
||||
else
|
||||
do
|
||||
R1 = rand(-ACCURACY,ACCURACY)/ACCURACY
|
||||
R2 = rand(-ACCURACY,ACCURACY)/ACCURACY
|
||||
working = R1*R1 + R2*R2
|
||||
while(working >= 1 || working==0)
|
||||
working = sqrt(-2 * log(working) / working)
|
||||
R1 *= working
|
||||
gaussian_next = R2 * working
|
||||
return (mean + stddev * R1)
|
||||
#undef ACCURACY
|
||||
|
||||
/proc/mouse_angle_from_client(client/client)
|
||||
var/list/mouse_control = params2list(client.mouseParams)
|
||||
if(mouse_control["screen-loc"] && client)
|
||||
var/list/screen_loc_params = splittext(mouse_control["screen-loc"], ",")
|
||||
var/list/screen_loc_X = splittext(screen_loc_params[1],":")
|
||||
var/list/screen_loc_Y = splittext(screen_loc_params[2],":")
|
||||
var/x = (text2num(screen_loc_X[1]) * 32 + text2num(screen_loc_X[2]) - 32)
|
||||
var/y = (text2num(screen_loc_Y[1]) * 32 + text2num(screen_loc_Y[2]) - 32)
|
||||
var/list/screenview = getviewsize(client.view)
|
||||
var/screenviewX = screenview[1] * world.icon_size
|
||||
var/screenviewY = screenview[2] * world.icon_size
|
||||
var/ox = round(screenviewX/2) - client.pixel_x //"origin" x
|
||||
var/oy = round(screenviewY/2) - client.pixel_y //"origin" y
|
||||
var/angle = NORM_ROT(Atan2(y - oy, x - ox))
|
||||
return angle
|
||||
|
||||
/proc/get_turf_in_angle(angle, turf/starting, increments)
|
||||
var/pixel_x = 0
|
||||
var/pixel_y = 0
|
||||
for(var/i in 1 to increments)
|
||||
pixel_x += sin(angle)+16*sin(angle)*2
|
||||
pixel_y += cos(angle)+16*cos(angle)*2
|
||||
var/new_x = starting.x
|
||||
var/new_y = starting.y
|
||||
while(pixel_x > 16)
|
||||
pixel_x -= 32
|
||||
new_x++
|
||||
while(pixel_x < -16)
|
||||
pixel_x += 32
|
||||
new_x--
|
||||
while(pixel_y > 16)
|
||||
pixel_y -= 32
|
||||
new_y++
|
||||
while(pixel_y < -16)
|
||||
pixel_y += 32
|
||||
new_y--
|
||||
new_x = Clamp(new_x, 0, world.maxx)
|
||||
new_y = Clamp(new_y, 0, world.maxy)
|
||||
return locate(new_x, new_y, starting.z)
|
||||
|
||||
/proc/round_down(num)
|
||||
if(round(num) != num)
|
||||
return round(num--)
|
||||
else return num
|
||||
|
||||
//proc/get_overlap()
|
||||
// Returns a list where [1] is all x values and [2] is all y values that overlap between the given pair of rectangles
|
||||
/proc/get_overlap(x1, y1, x2, y2, x3, y3, x4, y4)
|
||||
var/list/region_x1 = list()
|
||||
var/list/region_y1 = list()
|
||||
var/list/region_x2 = list()
|
||||
var/list/region_y2 = list()
|
||||
|
||||
// These loops create loops filled with x/y values that the boundaries inhabit
|
||||
// ex: list(5, 6, 7, 8, 9)
|
||||
for(var/i in min(x1, x2) to max(x1, x2))
|
||||
region_x1["[i]"] = TRUE
|
||||
for(var/i in min(y1, y2) to max(y1, y2))
|
||||
region_y1["[i]"] = TRUE
|
||||
for(var/i in min(x3, x4) to max(x3, x4))
|
||||
region_x2["[i]"] = TRUE
|
||||
for(var/i in min(y3, y4) to max(y3, y4))
|
||||
region_y2["[i]"] = TRUE
|
||||
|
||||
return list(region_x1 & region_x2, region_y1 & region_y2)
|
||||
@@ -121,9 +121,6 @@ GLOBAL_VAR(command_name)
|
||||
return new_station_name
|
||||
|
||||
/proc/syndicate_name()
|
||||
var/static/syndicate_name
|
||||
if (syndicate_name)
|
||||
return syndicate_name
|
||||
|
||||
var/name = ""
|
||||
|
||||
@@ -146,8 +143,7 @@ GLOBAL_VAR(command_name)
|
||||
else
|
||||
name += pick("-", "*", "")
|
||||
name += pick("Tech", "Sun", "Co", "Tek", "X", "Inc", "Gen", "Star", "Dyne", "Code", "Hive")
|
||||
|
||||
syndicate_name = name
|
||||
|
||||
return name
|
||||
|
||||
|
||||
|
||||
+14
-14
@@ -1,14 +1,14 @@
|
||||
// Ensure the frequency is within bounds of what it should be sending/recieving at
|
||||
/proc/sanitize_frequency(frequency, free = FALSE)
|
||||
. = round(frequency)
|
||||
if(free)
|
||||
. = Clamp(frequency, MIN_FREE_FREQ, MAX_FREE_FREQ)
|
||||
else
|
||||
. = Clamp(frequency, MIN_FREQ, MAX_FREQ)
|
||||
if(!(. % 2)) // Ensure the last digit is an odd number
|
||||
. += 1
|
||||
|
||||
// Format frequency by moving the decimal.
|
||||
/proc/format_frequency(frequency)
|
||||
frequency = text2num(frequency)
|
||||
return "[round(frequency / 10)].[frequency % 10]"
|
||||
// Ensure the frequency is within bounds of what it should be sending/recieving at
|
||||
/proc/sanitize_frequency(frequency, free = FALSE)
|
||||
. = round(frequency)
|
||||
if(free)
|
||||
. = CLAMP(frequency, MIN_FREE_FREQ, MAX_FREE_FREQ)
|
||||
else
|
||||
. = CLAMP(frequency, MIN_FREQ, MAX_FREQ)
|
||||
if(!(. % 2)) // Ensure the last digit is an odd number
|
||||
. += 1
|
||||
|
||||
// Format frequency by moving the decimal.
|
||||
/proc/format_frequency(frequency)
|
||||
frequency = text2num(frequency)
|
||||
return "[round(frequency / 10)].[frequency % 10]"
|
||||
|
||||
@@ -0,0 +1,423 @@
|
||||
#define POPCOUNT_SURVIVORS "survivors" //Not dead at roundend
|
||||
#define POPCOUNT_ESCAPEES "escapees" //Not dead and on centcomm/shuttles marked as escaped
|
||||
#define POPCOUNT_GHOSTS "ghosts" //Ghosts on roundend
|
||||
#define POPCOUNT_HUMAN_ESCAPEES "human_escapees" //Same as escapees but human only
|
||||
#define POPCOUNT_HUMAN_SURVIVORS "human_survivors" //Same as survivors but human only
|
||||
#define POPCOUNT_SHUTTLE_ESCAPEES "shuttle_escapees" //Emergency shuttle only.
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/gather_roundend_feedback()
|
||||
//Survivor numbers
|
||||
var/clients = GLOB.player_list.len
|
||||
var/popcount = count_survivors()
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", clients, list("clients"))
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", popcount[POPCOUNT_GHOSTS], list("ghosts"))
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", popcount[POPCOUNT_HUMAN_SURVIVORS], list("survivors", "human"))
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", popcount[POPCOUNT_SURVIVORS], list("survivors", "total"))
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", popcount[POPCOUNT_HUMAN_ESCAPEES], list("escapees", "human"))
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", popcount[POPCOUNT_ESCAPEES], list("escapees", "total"))
|
||||
//Antag information
|
||||
gather_antag_data()
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/gather_antag_data()
|
||||
var/team_gid = 1
|
||||
var/list/team_ids = list()
|
||||
|
||||
for(var/datum/antagonist/A in GLOB.antagonists)
|
||||
var/list/antag_info = list()
|
||||
antag_info["key"] = A.owner.key
|
||||
antag_info["name"] = A.owner.name
|
||||
antag_info["antagonist_type"] = A.type
|
||||
antag_info["antagonist_name"] = A.name //For auto and custom roles
|
||||
antag_info["objectives"] = list()
|
||||
antag_info["team"] = list()
|
||||
var/datum/team/T = A.get_team()
|
||||
if(T)
|
||||
antag_info["team"]["type"] = T.type
|
||||
antag_info["team"]["name"] = T.name
|
||||
if(!team_ids[T])
|
||||
team_ids[T] = team_gid++
|
||||
antag_info["team"]["id"] = team_ids[T]
|
||||
|
||||
if(!A.owner)
|
||||
continue
|
||||
if(A.objectives.len)
|
||||
for(var/datum/objective/O in A.objectives)
|
||||
var/result = O.check_completion() ? "SUCCESS" : "FAIL"
|
||||
antag_info["objectives"] += list(list("objective_type"=O.type,"text"=O.explanation_text,"result"=result))
|
||||
SSblackbox.record_feedback("associative", "antagonists", 1, antag_info)
|
||||
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/declare_completion()
|
||||
set waitfor = FALSE
|
||||
|
||||
to_chat(world, "<BR><BR><BR><FONT size=3><B>The round has ended.</B></FONT>")
|
||||
if(LAZYLEN(GLOB.round_end_notifiees))
|
||||
send2irc("Notice", "[GLOB.round_end_notifiees.Join(", ")] the round has ended.")
|
||||
|
||||
/*for(var/client/C in GLOB.clients)
|
||||
if(!C.credits)
|
||||
C.RollCredits()
|
||||
C.playtitlemusic(40)*/
|
||||
|
||||
display_report()
|
||||
|
||||
gather_roundend_feedback()
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
// Add AntagHUD to everyone, see who was really evil the whole time!
|
||||
for(var/datum/atom_hud/antag/H in GLOB.huds)
|
||||
for(var/m in GLOB.player_list)
|
||||
var/mob/M = m
|
||||
H.add_hud_to(M)
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//Set news report and mode result
|
||||
mode.set_round_result()
|
||||
|
||||
send2irc("Server", "Round just ended.")
|
||||
|
||||
if(CONFIG_GET(string/cross_server_address))
|
||||
send_news_report()
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//These need update to actually reflect the real antagonists
|
||||
//Print a list of antagonists to the server log
|
||||
var/list/total_antagonists = list()
|
||||
//Look into all mobs in world, dead or alive
|
||||
for(var/datum/mind/Mind in minds)
|
||||
var/temprole = Mind.special_role
|
||||
if(temprole) //if they are an antagonist of some sort.
|
||||
if(temprole in total_antagonists) //If the role exists already, add the name to it
|
||||
total_antagonists[temprole] += ", [Mind.name]([Mind.key])"
|
||||
else
|
||||
total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob
|
||||
total_antagonists[temprole] += ": [Mind.name]([Mind.key])"
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//Now print them all into the log!
|
||||
log_game("Antagonists at round end were...")
|
||||
for(var/i in total_antagonists)
|
||||
log_game("[i]s[total_antagonists[i]].")
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//Collects persistence features
|
||||
if(mode.allow_persistence_save)
|
||||
SSpersistence.CollectData()
|
||||
|
||||
//stop collecting feedback during grifftime
|
||||
SSblackbox.Seal()
|
||||
|
||||
sleep(50)
|
||||
ready_for_reboot = TRUE
|
||||
standard_reboot()
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/standard_reboot()
|
||||
if(ready_for_reboot)
|
||||
if(mode.station_was_nuked)
|
||||
Reboot("Station destroyed by Nuclear Device.", "nuke")
|
||||
else
|
||||
Reboot("Round ended.", "proper completion")
|
||||
else
|
||||
CRASH("Attempted standard reboot without ticker roundend completion")
|
||||
|
||||
//Common part of the report
|
||||
/datum/controller/subsystem/ticker/proc/build_roundend_report()
|
||||
var/list/parts = list()
|
||||
|
||||
//Gamemode specific things. Should be empty most of the time.
|
||||
parts += mode.special_report()
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//AI laws
|
||||
parts += law_report()
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//Antagonists
|
||||
parts += antag_report()
|
||||
|
||||
CHECK_TICK
|
||||
//Medals
|
||||
parts += medal_report()
|
||||
//Station Goals
|
||||
parts += goal_report()
|
||||
|
||||
listclearnulls(parts)
|
||||
|
||||
return parts.Join()
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/count_survivors()
|
||||
. = list()
|
||||
var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED
|
||||
var/num_survivors = 0
|
||||
var/num_escapees = 0
|
||||
var/num_shuttle_escapees = 0
|
||||
var/num_ghosts = 0
|
||||
var/num_human_survivors = 0
|
||||
var/num_human_escapees = 0
|
||||
|
||||
//Player status report
|
||||
for(var/i in GLOB.mob_list)
|
||||
var/mob/Player = i
|
||||
if(Player.mind && !isnewplayer(Player))
|
||||
if(isobserver(Player))
|
||||
num_ghosts++
|
||||
if(Player.stat != DEAD && !isbrain(Player))
|
||||
num_survivors++
|
||||
if(ishuman(Player))
|
||||
num_human_survivors++
|
||||
if(station_evacuated) //If the shuttle has already left the station
|
||||
var/list/area/shuttle_areas
|
||||
if(SSshuttle && SSshuttle.emergency)
|
||||
shuttle_areas = SSshuttle.emergency.shuttle_areas
|
||||
if(Player.onCentCom() || Player.onSyndieBase())
|
||||
num_escapees++
|
||||
if(ishuman(Player))
|
||||
num_human_escapees++
|
||||
if(shuttle_areas[get_area(Player)])
|
||||
num_shuttle_escapees++
|
||||
|
||||
.[POPCOUNT_SURVIVORS] = num_survivors
|
||||
.[POPCOUNT_ESCAPEES] = num_escapees
|
||||
.[POPCOUNT_SHUTTLE_ESCAPEES] = num_shuttle_escapees
|
||||
.[POPCOUNT_HUMAN_SURVIVORS] = num_human_survivors
|
||||
.[POPCOUNT_HUMAN_ESCAPEES] = num_human_escapees
|
||||
.[POPCOUNT_GHOSTS] = num_ghosts
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/survivor_report()
|
||||
var/list/parts = list()
|
||||
var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED
|
||||
var/popcount = count_survivors()
|
||||
|
||||
//Round statistics report
|
||||
var/datum/station_state/end_state = new /datum/station_state()
|
||||
end_state.count()
|
||||
var/station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100)
|
||||
|
||||
parts += "[GLOB.TAB]Shift Duration: <B>[DisplayTimeText(world.time - SSticker.round_start_time)]</B>"
|
||||
parts += "[GLOB.TAB]Station Integrity: <B>[mode.station_was_nuked ? "<span class='redtext'>Destroyed</span>" : "[station_integrity]%"]</B>"
|
||||
var/total_players = GLOB.joined_player_list.len
|
||||
if(total_players)
|
||||
parts+= "[GLOB.TAB]Total Population: <B>[total_players]</B>"
|
||||
if(station_evacuated)
|
||||
parts += "<BR>[GLOB.TAB]Evacuation Rate: <B>[popcount[POPCOUNT_ESCAPEES]] ([PERCENT(popcount[POPCOUNT_ESCAPEES]/total_players)]%)</B>"
|
||||
parts += "[GLOB.TAB](on emergency shuttle): <B>[popcount[POPCOUNT_SHUTTLE_ESCAPEES]] ([PERCENT(popcount[POPCOUNT_SHUTTLE_ESCAPEES]/total_players)]%)</B>"
|
||||
parts += "[GLOB.TAB]Survival Rate: <B>[popcount[POPCOUNT_SURVIVORS]] ([PERCENT(popcount[POPCOUNT_SURVIVORS]/total_players)]%)</B>"
|
||||
return parts.Join("<br>")
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/show_roundend_report(client/C,common_report)
|
||||
var/list/report_parts = list()
|
||||
|
||||
report_parts += personal_report(C)
|
||||
report_parts += common_report
|
||||
|
||||
var/datum/browser/roundend_report = new(C, "roundend")
|
||||
roundend_report.width = 800
|
||||
roundend_report.height = 600
|
||||
roundend_report.set_content(report_parts.Join())
|
||||
roundend_report.stylesheets = list()
|
||||
roundend_report.add_stylesheet("roundend",'html/browser/roundend.css')
|
||||
|
||||
roundend_report.open(0)
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/personal_report(client/C)
|
||||
var/list/parts = list()
|
||||
var/mob/M = C.mob
|
||||
if(M.mind && !isnewplayer(M))
|
||||
if(M.stat != DEAD && !isbrain(M))
|
||||
if(EMERGENCY_ESCAPED_OR_ENDGAMED)
|
||||
if(!M.onCentCom() || !M.onSyndieBase())
|
||||
parts += "<div class='panel stationborder'>"
|
||||
parts += "<span class='marooned'>You managed to survive, but were marooned on [station_name()]...</span>"
|
||||
else
|
||||
parts += "<div class='panel greenborder'>"
|
||||
parts += "<span class='greentext'>You managed to survive the events on [station_name()] as [M.real_name].</span>"
|
||||
else
|
||||
parts += "<div class='panel greenborder'>"
|
||||
parts += "<span class='greentext'>You managed to survive the events on [station_name()] as [M.real_name].</span>"
|
||||
|
||||
else
|
||||
parts += "<div class='panel redborder'>"
|
||||
parts += "<span class='redtext'>You did not survive the events on [station_name()]...</span>"
|
||||
else
|
||||
parts += "<div class='panel stationborder'>"
|
||||
parts += "<br>"
|
||||
if(GLOB.survivor_report)
|
||||
parts += GLOB.survivor_report
|
||||
else
|
||||
parts += survivor_report()
|
||||
|
||||
parts += "</div>"
|
||||
|
||||
return parts.Join()
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/display_report()
|
||||
GLOB.common_report = build_roundend_report()
|
||||
for(var/client/C in GLOB.clients)
|
||||
show_roundend_report(C,GLOB.common_report)
|
||||
give_show_report_button(C)
|
||||
CHECK_TICK
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/law_report()
|
||||
var/list/parts = list()
|
||||
//Silicon laws report
|
||||
for (var/i in GLOB.ai_list)
|
||||
var/mob/living/silicon/ai/aiPlayer = i
|
||||
if(aiPlayer.mind)
|
||||
parts += "<b>[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws [aiPlayer.stat != DEAD ? "at the end of the round" : "when it was deactivated"] were:</b>"
|
||||
parts += aiPlayer.laws.get_law_list(include_zeroth=TRUE)
|
||||
|
||||
parts += "<b>Total law changes: [aiPlayer.law_change_counter]</b>"
|
||||
|
||||
if (aiPlayer.connected_robots.len)
|
||||
var/robolist = "<b>[aiPlayer.real_name]'s minions were:</b> "
|
||||
for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots)
|
||||
if(robo.mind)
|
||||
robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.mind.key]), ":" (Played by: [robo.mind.key]), "]"
|
||||
parts += "[robolist]"
|
||||
|
||||
for (var/mob/living/silicon/robot/robo in GLOB.silicon_mobs)
|
||||
if (!robo.connected_ai && robo.mind)
|
||||
if (robo.stat != DEAD)
|
||||
parts += "<b>[robo.name] (Played by: [robo.mind.key]) survived as an AI-less borg! Its laws were:</b>"
|
||||
else
|
||||
parts += "<b>[robo.name] (Played by: [robo.mind.key]) was unable to survive the rigors of being a cyborg without an AI. Its laws were:</b>"
|
||||
|
||||
if(robo) //How the hell do we lose robo between here and the world messages directly above this?
|
||||
parts += robo.laws.get_law_list(include_zeroth=TRUE)
|
||||
if(parts.len)
|
||||
return "<div class='panel stationborder'>[parts.Join("<br>")]</div>"
|
||||
else
|
||||
return ""
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/goal_report()
|
||||
var/list/parts = list()
|
||||
if(mode.station_goals.len)
|
||||
for(var/V in mode.station_goals)
|
||||
var/datum/station_goal/G = V
|
||||
parts += G.get_result()
|
||||
return "<div class='panel stationborder'><ul>[parts.Join()]</ul></div>"
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/medal_report()
|
||||
if(GLOB.commendations.len)
|
||||
var/list/parts = list()
|
||||
parts += "<span class='header'>Medal Commendations:</span>"
|
||||
for (var/com in GLOB.commendations)
|
||||
parts += com
|
||||
return "<div class='panel stationborder'>[parts.Join("<br>")]</div>"
|
||||
return ""
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/antag_report()
|
||||
var/list/result = list()
|
||||
var/list/all_teams = list()
|
||||
var/list/all_antagonists = list()
|
||||
|
||||
for(var/datum/antagonist/A in GLOB.antagonists)
|
||||
all_teams |= A.get_team()
|
||||
all_antagonists += A
|
||||
|
||||
for(var/datum/team/T in all_teams)
|
||||
result += T.roundend_report()
|
||||
for(var/datum/antagonist/X in all_antagonists)
|
||||
if(X.get_team() == T)
|
||||
all_antagonists -= X
|
||||
result += " "//newline between teams
|
||||
|
||||
var/currrent_category
|
||||
var/datum/antagonist/previous_category
|
||||
|
||||
sortTim(all_antagonists, /proc/cmp_antag_category)
|
||||
|
||||
for(var/datum/antagonist/A in all_antagonists)
|
||||
if(!A.show_in_roundend)
|
||||
continue
|
||||
if(A.roundend_category != currrent_category)
|
||||
if(previous_category)
|
||||
result += previous_category.roundend_report_footer()
|
||||
result += "</div>"
|
||||
result += "<div class='panel redborder'>"
|
||||
result += A.roundend_report_header()
|
||||
currrent_category = A.roundend_category
|
||||
previous_category = A
|
||||
result += A.roundend_report()
|
||||
result += "<br>"
|
||||
|
||||
if(all_antagonists.len)
|
||||
var/datum/antagonist/last = all_antagonists[all_antagonists.len]
|
||||
result += last.roundend_report_footer()
|
||||
result += "</div>"
|
||||
|
||||
return result.Join()
|
||||
|
||||
/proc/cmp_antag_category(datum/antagonist/A,datum/antagonist/B)
|
||||
return sorttext(B.roundend_category,A.roundend_category)
|
||||
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/give_show_report_button(client/C)
|
||||
var/datum/action/report/R = new
|
||||
C.player_details.player_actions += R
|
||||
R.Grant(C.mob)
|
||||
to_chat(C,"<a href='?src=[REF(R)];report=1'>Show roundend report again</a>")
|
||||
|
||||
/datum/action/report
|
||||
name = "Show roundend report"
|
||||
button_icon_state = "vote"
|
||||
|
||||
/datum/action/report/Trigger()
|
||||
if(owner && GLOB.common_report && SSticker.current_state == GAME_STATE_FINISHED)
|
||||
SSticker.show_roundend_report(owner.client,GLOB.common_report)
|
||||
|
||||
/datum/action/report/IsAvailable()
|
||||
return 1
|
||||
|
||||
/datum/action/report/Topic(href,href_list)
|
||||
if(usr != owner)
|
||||
return
|
||||
if(href_list["report"])
|
||||
Trigger()
|
||||
return
|
||||
|
||||
|
||||
/proc/printplayer(datum/mind/ply, fleecheck)
|
||||
var/text = "<b>[ply.key]</b> was <b>[ply.name]</b> the <b>[ply.assigned_role]</b> and"
|
||||
if(ply.current)
|
||||
if(ply.current.stat == DEAD)
|
||||
text += " <span class='redtext'>died</span>"
|
||||
else
|
||||
text += " <span class='greentext'>survived</span>"
|
||||
if(fleecheck)
|
||||
var/turf/T = get_turf(ply.current)
|
||||
if(!T || !(T.z in GLOB.station_z_levels))
|
||||
text += " while <span class='redtext'>fleeing the station</span>"
|
||||
if(ply.current.real_name != ply.name)
|
||||
text += " as <b>[ply.current.real_name]</b>"
|
||||
else
|
||||
text += " <span class='redtext'>had their body destroyed</span>"
|
||||
return text
|
||||
|
||||
/proc/printplayerlist(list/players,fleecheck)
|
||||
var/list/parts = list()
|
||||
|
||||
parts += "<ul class='playerlist'>"
|
||||
for(var/datum/mind/M in players)
|
||||
parts += "<li>[printplayer(M,fleecheck)]</li>"
|
||||
parts += "</ul>"
|
||||
return parts.Join()
|
||||
|
||||
|
||||
/proc/printobjectives(datum/mind/ply)
|
||||
var/list/objective_parts = list()
|
||||
var/count = 1
|
||||
for(var/datum/objective/objective in ply.objectives)
|
||||
if(objective.check_completion())
|
||||
objective_parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='greentext'>Success!</span>"
|
||||
else
|
||||
objective_parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
count++
|
||||
return objective_parts.Join("<br>")
|
||||
@@ -60,7 +60,7 @@ GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0)
|
||||
if(!second)
|
||||
return "0 seconds"
|
||||
if(second >= 60)
|
||||
minute = round_down(second/60)
|
||||
minute = FLOOR(second/60, 1)
|
||||
second = round(second - (minute*60), 0.1)
|
||||
second_rounded = TRUE
|
||||
if(second) //check if we still have seconds remaining to format, or if everything went into minute.
|
||||
@@ -91,7 +91,7 @@ GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0)
|
||||
if(!minute)
|
||||
return "[second]"
|
||||
if(minute >= 60)
|
||||
hour = round_down(minute/60,1)
|
||||
hour = FLOOR(minute/60, 1)
|
||||
minute = (minute - (hour*60))
|
||||
if(minute) //alot simpler from here since you don't have to worry about fractions
|
||||
if(minute != 1)
|
||||
@@ -114,7 +114,7 @@ GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0)
|
||||
if(!hour)
|
||||
return "[minute][second]"
|
||||
if(hour >= 24)
|
||||
day = round_down(hour/24,1)
|
||||
day = FLOOR(hour/24, 1)
|
||||
hour = (hour - (day*24))
|
||||
if(hour)
|
||||
if(hour != 1)
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
//Converts an angle (degrees) into an ss13 direction
|
||||
/proc/angle2dir(degree)
|
||||
|
||||
degree = SimplifyDegrees(degree)
|
||||
degree = SIMPLIFY_DEGREES(degree)
|
||||
switch(degree)
|
||||
if(0 to 22.5) //north requires two angle ranges
|
||||
return NORTH
|
||||
|
||||
@@ -147,10 +147,10 @@ Turf and target are separate in case you want to teleport some distance from a t
|
||||
var/line[] = list(locate(px,py,M.z))
|
||||
var/dx=N.x-px //x distance
|
||||
var/dy=N.y-py
|
||||
var/dxabs=abs(dx)//Absolute value of x distance
|
||||
var/dyabs=abs(dy)
|
||||
var/sdx=sign(dx) //Sign of x distance (+ or -)
|
||||
var/sdy=sign(dy)
|
||||
var/dxabs = abs(dx)//Absolute value of x distance
|
||||
var/dyabs = abs(dy)
|
||||
var/sdx = SIGN(dx) //Sign of x distance (+ or -)
|
||||
var/sdy = SIGN(dy)
|
||||
var/x=dxabs>>1 //Counters for steps taken, setting to distance/2
|
||||
var/y=dyabs>>1 //Bit-shifting makes me l33t. It also makes getline() unnessecarrily fast.
|
||||
var/j //Generic integer for counting
|
||||
@@ -953,8 +953,8 @@ GLOBAL_LIST_INIT(WALLITEMS_INVERSE, typecacheof(list(
|
||||
tY = tY[1]
|
||||
tX = splittext(tX[1], ":")
|
||||
tX = tX[1]
|
||||
tX = Clamp(origin.x + text2num(tX) - world.view - 1, 1, world.maxx)
|
||||
tY = Clamp(origin.y + text2num(tY) - world.view - 1, 1, world.maxy)
|
||||
tX = CLAMP(origin.x + text2num(tX) - world.view - 1, 1, world.maxx)
|
||||
tY = CLAMP(origin.y + text2num(tY) - world.view - 1, 1, world.maxy)
|
||||
return locate(tX, tY, tZ)
|
||||
|
||||
/proc/screen_loc2turf(text, turf/origin)
|
||||
@@ -966,8 +966,8 @@ GLOBAL_LIST_INIT(WALLITEMS_INVERSE, typecacheof(list(
|
||||
tX = splittext(tZ[2], "-")
|
||||
tX = text2num(tX[2])
|
||||
tZ = origin.z
|
||||
tX = Clamp(origin.x + 7 - tX, 1, world.maxx)
|
||||
tY = Clamp(origin.y + 7 - tY, 1, world.maxy)
|
||||
tX = CLAMP(origin.x + 7 - tX, 1, world.maxx)
|
||||
tY = CLAMP(origin.y + 7 - tY, 1, world.maxy)
|
||||
return locate(tX, tY, tZ)
|
||||
|
||||
/proc/IsValidSrc(datum/D)
|
||||
@@ -1272,7 +1272,7 @@ proc/pick_closest_path(value, list/matches = get_fancy_list_of_atom_types())
|
||||
. = 0
|
||||
var/i = DS2TICKS(initial_delay)
|
||||
do
|
||||
. += Ceiling(i*DELTA_CALC)
|
||||
. += CEILING(i*DELTA_CALC, 1)
|
||||
sleep(i*world.tick_lag*DELTA_CALC)
|
||||
i *= 2
|
||||
while (TICK_USAGE > min(TICK_LIMIT_TO_RUN, Master.current_ticklimit))
|
||||
@@ -1508,9 +1508,34 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
|
||||
return "\[[url_encode(thing.tag)]\]"
|
||||
return "\ref[input]"
|
||||
|
||||
// Makes a call in the context of a different usr
|
||||
// Use sparingly
|
||||
/world/proc/PushUsr(mob/M, datum/callback/CB)
|
||||
var/temp = usr
|
||||
usr = M
|
||||
. = CB.Invoke()
|
||||
usr = temp
|
||||
|
||||
//Returns a list of all servants of Ratvar and observers.
|
||||
/proc/servants_and_ghosts()
|
||||
. = list()
|
||||
for(var/V in GLOB.player_list)
|
||||
if(is_servant_of_ratvar(V) || isobserver(V))
|
||||
. += V
|
||||
|
||||
//datum may be null, but it does need to be a typed var
|
||||
#define NAMEOF(datum, X) (list(##datum.##X, #X)[2])
|
||||
|
||||
#define VARSET_LIST_CALLBACK(target, var_name, var_value) CALLBACK(GLOBAL_PROC, /proc/___callbackvarset, ##target, ##var_name, ##var_value)
|
||||
//dupe code because dm can't handle 3 level deep macros
|
||||
#define VARSET_CALLBACK(datum, var, var_value) CALLBACK(GLOBAL_PROC, /proc/___callbackvarset, ##datum, NAMEOF(##datum, ##var), ##var_value)
|
||||
|
||||
/proc/___callbackvarset(list_or_datum, var_name, var_value)
|
||||
if(length(list_or_datum))
|
||||
list_or_datum[var_name] = var_value
|
||||
return
|
||||
var/datum/D = list_or_datum
|
||||
if(IsAdminAdvancedProcCall())
|
||||
D.vv_edit_var(var_name, var_value) //same result generally, unless badmemes
|
||||
else
|
||||
D.vars[var_name] = var_value
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
GLOBAL_VAR_INIT(master_mode, "traitor") //"extended"
|
||||
GLOBAL_VAR_INIT(secret_force_mode, "secret") // if this is anything but "secret", the secret rotation will forceably choose this mode
|
||||
GLOBAL_VAR(common_report) //Contains commmon part of roundend report
|
||||
GLOBAL_VAR(survivor_report) //Contains shared surivor report for roundend report (part of personal report)
|
||||
|
||||
|
||||
GLOBAL_VAR_INIT(wavesecret, 0) // meteor mode, delays wave progression, terrible name
|
||||
GLOBAL_DATUM(start_state, /datum/station_state) // Used in round-end report
|
||||
|
||||
// Cult, needs to be global so admin cultists are functional
|
||||
GLOBAL_VAR_INIT(blood_target, null) // Cult Master's target or Construct's Master
|
||||
GLOBAL_DATUM(blood_target_image, /image)
|
||||
GLOBAL_VAR_INIT(blood_target_reset_timer, null)
|
||||
GLOBAL_DATUM(sac_mind, /datum/mind)
|
||||
GLOBAL_VAR_INIT(sac_image, null)
|
||||
GLOBAL_VAR_INIT(cult_vote_called, FALSE)
|
||||
GLOBAL_VAR_INIT(cult_mastered, FALSE)
|
||||
GLOBAL_VAR_INIT(reckoning_complete, FALSE)
|
||||
GLOBAL_VAR_INIT(sac_complete, FALSE)
|
||||
GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult)
|
||||
GLOBAL_LIST_EMPTY(summon_spots)
|
||||
|
||||
//TODO clear this one up too
|
||||
GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult)
|
||||
@@ -16,3 +16,5 @@ GLOBAL_VAR_INIT(CHARGELEVEL, 0.001) // Cap for how fast cells charge, as a perce
|
||||
GLOBAL_LIST_EMPTY(powernets)
|
||||
|
||||
GLOBAL_VAR_INIT(bsa_unlock, FALSE) //BSA unlocked by head ID swipes
|
||||
|
||||
GLOBAL_LIST_EMPTY(player_details) // ckey -> /datum/player_details
|
||||
@@ -23,8 +23,7 @@
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/ai/AI = usr
|
||||
var/camera = input(AI, "Choose which camera you want to view", "Cameras") as null|anything in AI.get_camera_list()
|
||||
AI.ai_camera_list(camera)
|
||||
AI.show_camera_list()
|
||||
|
||||
/obj/screen/ai/camera_track
|
||||
name = "Track With Camera"
|
||||
|
||||
+21
-10
@@ -302,32 +302,41 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
|
||||
/obj/screen/alert/bloodsense/process()
|
||||
var/atom/blood_target
|
||||
if(GLOB.blood_target)
|
||||
if(!get_turf(GLOB.blood_target))
|
||||
GLOB.blood_target = null
|
||||
|
||||
var/datum/antagonist/cult/antag = mob_viewer.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
|
||||
if(!antag)
|
||||
return
|
||||
var/datum/objective/sacrifice/sac_objective = locate() in antag.cult_team.objectives
|
||||
|
||||
if(antag.cult_team.blood_target)
|
||||
if(!get_turf(antag.cult_team.blood_target))
|
||||
antag.cult_team.blood_target = null
|
||||
else
|
||||
blood_target = GLOB.blood_target
|
||||
blood_target = antag.cult_team.blood_target
|
||||
if(Cviewer && Cviewer.seeking && Cviewer.master)
|
||||
blood_target = Cviewer.master
|
||||
desc = "Your blood sense is leading you to [Cviewer.master]"
|
||||
if(!blood_target)
|
||||
if(!GLOB.sac_complete)
|
||||
if(sac_objective && !sac_objective.check_completion())
|
||||
if(icon_state == "runed_sense0")
|
||||
return
|
||||
animate(src, transform = null, time = 1, loop = 0)
|
||||
angle = 0
|
||||
cut_overlays()
|
||||
icon_state = "runed_sense0"
|
||||
desc = "Nar-Sie demands that [GLOB.sac_mind] be sacrificed before the summoning ritual can begin."
|
||||
add_overlay(GLOB.sac_image)
|
||||
desc = "Nar-Sie demands that [sac_objective.target] be sacrificed before the summoning ritual can begin."
|
||||
add_overlay(sac_objective.sac_image)
|
||||
else
|
||||
var/datum/objective/eldergod/summon_objective = locate() in antag.cult_team.objectives
|
||||
if(!summon_objective)
|
||||
return
|
||||
if(icon_state == "runed_sense1")
|
||||
return
|
||||
animate(src, transform = null, time = 1, loop = 0)
|
||||
angle = 0
|
||||
cut_overlays()
|
||||
icon_state = "runed_sense1"
|
||||
desc = "The sacrifice is complete, summon Nar-Sie! The summoning can only take place in [english_list(GLOB.summon_spots)]!"
|
||||
desc = "The sacrifice is complete, summon Nar-Sie! The summoning can only take place in [english_list(summon_objective.summon_spots)]!"
|
||||
add_overlay(narnar)
|
||||
return
|
||||
var/turf/P = get_turf(blood_target)
|
||||
@@ -388,11 +397,13 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
desc = "<font size=3><b>CHETR<br>NYY<br>HAGEHUGF-NAQ-UBABE<br>RATVAR.</b></font>"
|
||||
else
|
||||
var/servants = 0
|
||||
var/list/textlist
|
||||
var/list/textlist = list()
|
||||
for(var/mob/living/L in GLOB.alive_mob_list)
|
||||
if(is_servant_of_ratvar(L))
|
||||
servants++
|
||||
textlist = list("[SSticker.mode.eminence ? "There is an Eminence." : "<b>There is no Eminence! Get one ASAP!</b>"]<br>")
|
||||
var/datum/antagonist/clockcult/C = mob_viewer.mind.has_antag_datum(/datum/antagonist/clockcult,TRUE)
|
||||
if(C && C.clock_team)
|
||||
textlist += "[C.clock_team.eminence ? "There is an Eminence." : "<b>There is no Eminence! Get one ASAP!</b>"]<br>"
|
||||
textlist += "There are currently <b>[servants]</b> servant[servants > 1 ? "s" : ""] of Ratvar.<br>"
|
||||
for(var/i in SSticker.scripture_states)
|
||||
if(i != SCRIPTURE_DRIVER) //ignore the always-unlocked stuff
|
||||
|
||||
@@ -257,8 +257,8 @@
|
||||
view = world.view
|
||||
|
||||
var/list/viewscales = getviewsize(view)
|
||||
var/countx = Ceiling((viewscales[1]/2)/(480/world.icon_size))+1
|
||||
var/county = Ceiling((viewscales[2]/2)/(480/world.icon_size))+1
|
||||
var/countx = CEILING((viewscales[1]/2)/(480/world.icon_size), 1)+1
|
||||
var/county = CEILING((viewscales[2]/2)/(480/world.icon_size), 1)+1
|
||||
var/list/new_overlays = new
|
||||
for(var/x in -countx to countx)
|
||||
for(var/y in -county to county)
|
||||
|
||||
+277
-277
@@ -1,277 +1,277 @@
|
||||
/obj/screen/robot
|
||||
icon = 'icons/mob/screen_cyborg.dmi'
|
||||
|
||||
/obj/screen/robot/module
|
||||
name = "cyborg module"
|
||||
icon_state = "nomod"
|
||||
|
||||
/obj/screen/robot/Click()
|
||||
if(isobserver(usr))
|
||||
return 1
|
||||
|
||||
/obj/screen/robot/module/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
if(R.module.type != /obj/item/robot_module)
|
||||
R.hud_used.toggle_show_robot_modules()
|
||||
return 1
|
||||
R.pick_module()
|
||||
|
||||
/obj/screen/robot/module1
|
||||
name = "module1"
|
||||
icon_state = "inv1"
|
||||
|
||||
/obj/screen/robot/module1/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.toggle_module(1)
|
||||
|
||||
/obj/screen/robot/module2
|
||||
name = "module2"
|
||||
icon_state = "inv2"
|
||||
|
||||
/obj/screen/robot/module2/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.toggle_module(2)
|
||||
|
||||
/obj/screen/robot/module3
|
||||
name = "module3"
|
||||
icon_state = "inv3"
|
||||
|
||||
/obj/screen/robot/module3/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.toggle_module(3)
|
||||
|
||||
/obj/screen/robot/radio
|
||||
name = "radio"
|
||||
icon_state = "radio"
|
||||
|
||||
/obj/screen/robot/radio/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.radio.interact(R)
|
||||
|
||||
/obj/screen/robot/store
|
||||
name = "store"
|
||||
icon_state = "store"
|
||||
|
||||
/obj/screen/robot/store/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.uneq_active()
|
||||
|
||||
/obj/screen/robot/lamp
|
||||
name = "headlamp"
|
||||
icon_state = "lamp0"
|
||||
|
||||
/obj/screen/robot/lamp/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.control_headlamp()
|
||||
|
||||
/obj/screen/robot/thrusters
|
||||
name = "ion thrusters"
|
||||
icon_state = "ionpulse0"
|
||||
|
||||
/obj/screen/robot/thrusters/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.toggle_ionpulse()
|
||||
|
||||
/datum/hud/robot
|
||||
ui_style_icon = 'icons/mob/screen_cyborg.dmi'
|
||||
|
||||
/datum/hud/robot/New(mob/owner, ui_style = 'icons/mob/screen_cyborg.dmi')
|
||||
..()
|
||||
var/mob/living/silicon/robot/mymobR = mymob
|
||||
var/obj/screen/using
|
||||
|
||||
using = new/obj/screen/language_menu
|
||||
using.screen_loc = ui_borg_language_menu
|
||||
static_inventory += using
|
||||
|
||||
//Radio
|
||||
using = new /obj/screen/robot/radio()
|
||||
using.screen_loc = ui_borg_radio
|
||||
static_inventory += using
|
||||
|
||||
//Module select
|
||||
using = new /obj/screen/robot/module1()
|
||||
using.screen_loc = ui_inv1
|
||||
static_inventory += using
|
||||
mymobR.inv1 = using
|
||||
|
||||
using = new /obj/screen/robot/module2()
|
||||
using.screen_loc = ui_inv2
|
||||
static_inventory += using
|
||||
mymobR.inv2 = using
|
||||
|
||||
using = new /obj/screen/robot/module3()
|
||||
using.screen_loc = ui_inv3
|
||||
static_inventory += using
|
||||
mymobR.inv3 = using
|
||||
|
||||
//End of module select
|
||||
|
||||
//Photography stuff
|
||||
using = new /obj/screen/ai/image_take()
|
||||
using.screen_loc = ui_borg_camera
|
||||
static_inventory += using
|
||||
|
||||
using = new /obj/screen/ai/image_view()
|
||||
using.screen_loc = ui_borg_album
|
||||
static_inventory += using
|
||||
|
||||
//Sec/Med HUDs
|
||||
using = new /obj/screen/ai/sensors()
|
||||
using.screen_loc = ui_borg_sensor
|
||||
static_inventory += using
|
||||
|
||||
//Headlamp control
|
||||
using = new /obj/screen/robot/lamp()
|
||||
using.screen_loc = ui_borg_lamp
|
||||
static_inventory += using
|
||||
mymobR.lamp_button = using
|
||||
|
||||
//Thrusters
|
||||
using = new /obj/screen/robot/thrusters()
|
||||
using.screen_loc = ui_borg_thrusters
|
||||
static_inventory += using
|
||||
mymobR.thruster_button = using
|
||||
|
||||
//Intent
|
||||
action_intent = new /obj/screen/act_intent/robot()
|
||||
action_intent.icon_state = mymob.a_intent
|
||||
static_inventory += action_intent
|
||||
|
||||
//Health
|
||||
healths = new /obj/screen/healths/robot()
|
||||
infodisplay += healths
|
||||
|
||||
//Installed Module
|
||||
mymobR.hands = new /obj/screen/robot/module()
|
||||
mymobR.hands.screen_loc = ui_borg_module
|
||||
static_inventory += mymobR.hands
|
||||
|
||||
//Store
|
||||
module_store_icon = new /obj/screen/robot/store()
|
||||
module_store_icon.screen_loc = ui_borg_store
|
||||
|
||||
pull_icon = new /obj/screen/pull()
|
||||
pull_icon.icon = 'icons/mob/screen_cyborg.dmi'
|
||||
pull_icon.update_icon(mymob)
|
||||
pull_icon.screen_loc = ui_borg_pull
|
||||
hotkeybuttons += pull_icon
|
||||
|
||||
|
||||
zone_select = new /obj/screen/zone_sel/robot()
|
||||
zone_select.update_icon(mymob)
|
||||
static_inventory += zone_select
|
||||
|
||||
|
||||
/datum/hud/proc/toggle_show_robot_modules()
|
||||
if(!iscyborg(mymob))
|
||||
return
|
||||
|
||||
var/mob/living/silicon/robot/R = mymob
|
||||
|
||||
R.shown_robot_modules = !R.shown_robot_modules
|
||||
update_robot_modules_display()
|
||||
|
||||
/datum/hud/proc/update_robot_modules_display(mob/viewer)
|
||||
if(!iscyborg(mymob))
|
||||
return
|
||||
|
||||
var/mob/living/silicon/robot/R = mymob
|
||||
|
||||
var/mob/screenmob = viewer || R
|
||||
|
||||
if(!R.module)
|
||||
return
|
||||
|
||||
if(!R.client)
|
||||
return
|
||||
|
||||
if(R.shown_robot_modules && screenmob.hud_used.hud_shown)
|
||||
//Modules display is shown
|
||||
screenmob.client.screen += module_store_icon //"store" icon
|
||||
|
||||
if(!R.module.modules)
|
||||
to_chat(usr, "<span class='danger'>Selected module has no modules to select</span>")
|
||||
return
|
||||
|
||||
if(!R.robot_modules_background)
|
||||
return
|
||||
|
||||
var/display_rows = Ceiling(length(R.module.get_inactive_modules()) / 8)
|
||||
R.robot_modules_background.screen_loc = "CENTER-4:16,SOUTH+1:7 to CENTER+3:16,SOUTH+[display_rows]:7"
|
||||
screenmob.client.screen += R.robot_modules_background
|
||||
|
||||
var/x = -4 //Start at CENTER-4,SOUTH+1
|
||||
var/y = 1
|
||||
|
||||
for(var/atom/movable/A in R.module.get_inactive_modules())
|
||||
//Module is not currently active
|
||||
screenmob.client.screen += A
|
||||
if(x < 0)
|
||||
A.screen_loc = "CENTER[x]:16,SOUTH+[y]:7"
|
||||
else
|
||||
A.screen_loc = "CENTER+[x]:16,SOUTH+[y]:7"
|
||||
A.layer = ABOVE_HUD_LAYER
|
||||
A.plane = ABOVE_HUD_PLANE
|
||||
|
||||
x++
|
||||
if(x == 4)
|
||||
x = -4
|
||||
y++
|
||||
|
||||
else
|
||||
//Modules display is hidden
|
||||
screenmob.client.screen -= module_store_icon //"store" icon
|
||||
|
||||
for(var/atom/A in R.module.get_inactive_modules())
|
||||
//Module is not currently active
|
||||
screenmob.client.screen -= A
|
||||
R.shown_robot_modules = 0
|
||||
screenmob.client.screen -= R.robot_modules_background
|
||||
|
||||
/mob/living/silicon/robot/create_mob_hud()
|
||||
if(client && !hud_used)
|
||||
hud_used = new /datum/hud/robot(src)
|
||||
|
||||
|
||||
/datum/hud/robot/persistent_inventory_update(mob/viewer)
|
||||
if(!mymob)
|
||||
return
|
||||
var/mob/living/silicon/robot/R = mymob
|
||||
|
||||
var/mob/screenmob = viewer || R
|
||||
|
||||
if(screenmob.hud_used)
|
||||
if(screenmob.hud_used.hud_shown)
|
||||
for(var/i in 1 to R.held_items.len)
|
||||
var/obj/item/I = R.held_items[i]
|
||||
if(I)
|
||||
switch(i)
|
||||
if(1)
|
||||
I.screen_loc = ui_inv1
|
||||
if(2)
|
||||
I.screen_loc = ui_inv2
|
||||
if(3)
|
||||
I.screen_loc = ui_inv3
|
||||
else
|
||||
return
|
||||
screenmob.client.screen += I
|
||||
else
|
||||
for(var/obj/item/I in R.held_items)
|
||||
screenmob.client.screen -= I
|
||||
/obj/screen/robot
|
||||
icon = 'icons/mob/screen_cyborg.dmi'
|
||||
|
||||
/obj/screen/robot/module
|
||||
name = "cyborg module"
|
||||
icon_state = "nomod"
|
||||
|
||||
/obj/screen/robot/Click()
|
||||
if(isobserver(usr))
|
||||
return 1
|
||||
|
||||
/obj/screen/robot/module/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
if(R.module.type != /obj/item/robot_module)
|
||||
R.hud_used.toggle_show_robot_modules()
|
||||
return 1
|
||||
R.pick_module()
|
||||
|
||||
/obj/screen/robot/module1
|
||||
name = "module1"
|
||||
icon_state = "inv1"
|
||||
|
||||
/obj/screen/robot/module1/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.toggle_module(1)
|
||||
|
||||
/obj/screen/robot/module2
|
||||
name = "module2"
|
||||
icon_state = "inv2"
|
||||
|
||||
/obj/screen/robot/module2/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.toggle_module(2)
|
||||
|
||||
/obj/screen/robot/module3
|
||||
name = "module3"
|
||||
icon_state = "inv3"
|
||||
|
||||
/obj/screen/robot/module3/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.toggle_module(3)
|
||||
|
||||
/obj/screen/robot/radio
|
||||
name = "radio"
|
||||
icon_state = "radio"
|
||||
|
||||
/obj/screen/robot/radio/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.radio.interact(R)
|
||||
|
||||
/obj/screen/robot/store
|
||||
name = "store"
|
||||
icon_state = "store"
|
||||
|
||||
/obj/screen/robot/store/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.uneq_active()
|
||||
|
||||
/obj/screen/robot/lamp
|
||||
name = "headlamp"
|
||||
icon_state = "lamp0"
|
||||
|
||||
/obj/screen/robot/lamp/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.control_headlamp()
|
||||
|
||||
/obj/screen/robot/thrusters
|
||||
name = "ion thrusters"
|
||||
icon_state = "ionpulse0"
|
||||
|
||||
/obj/screen/robot/thrusters/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.toggle_ionpulse()
|
||||
|
||||
/datum/hud/robot
|
||||
ui_style_icon = 'icons/mob/screen_cyborg.dmi'
|
||||
|
||||
/datum/hud/robot/New(mob/owner, ui_style = 'icons/mob/screen_cyborg.dmi')
|
||||
..()
|
||||
var/mob/living/silicon/robot/mymobR = mymob
|
||||
var/obj/screen/using
|
||||
|
||||
using = new/obj/screen/language_menu
|
||||
using.screen_loc = ui_borg_language_menu
|
||||
static_inventory += using
|
||||
|
||||
//Radio
|
||||
using = new /obj/screen/robot/radio()
|
||||
using.screen_loc = ui_borg_radio
|
||||
static_inventory += using
|
||||
|
||||
//Module select
|
||||
using = new /obj/screen/robot/module1()
|
||||
using.screen_loc = ui_inv1
|
||||
static_inventory += using
|
||||
mymobR.inv1 = using
|
||||
|
||||
using = new /obj/screen/robot/module2()
|
||||
using.screen_loc = ui_inv2
|
||||
static_inventory += using
|
||||
mymobR.inv2 = using
|
||||
|
||||
using = new /obj/screen/robot/module3()
|
||||
using.screen_loc = ui_inv3
|
||||
static_inventory += using
|
||||
mymobR.inv3 = using
|
||||
|
||||
//End of module select
|
||||
|
||||
//Photography stuff
|
||||
using = new /obj/screen/ai/image_take()
|
||||
using.screen_loc = ui_borg_camera
|
||||
static_inventory += using
|
||||
|
||||
using = new /obj/screen/ai/image_view()
|
||||
using.screen_loc = ui_borg_album
|
||||
static_inventory += using
|
||||
|
||||
//Sec/Med HUDs
|
||||
using = new /obj/screen/ai/sensors()
|
||||
using.screen_loc = ui_borg_sensor
|
||||
static_inventory += using
|
||||
|
||||
//Headlamp control
|
||||
using = new /obj/screen/robot/lamp()
|
||||
using.screen_loc = ui_borg_lamp
|
||||
static_inventory += using
|
||||
mymobR.lamp_button = using
|
||||
|
||||
//Thrusters
|
||||
using = new /obj/screen/robot/thrusters()
|
||||
using.screen_loc = ui_borg_thrusters
|
||||
static_inventory += using
|
||||
mymobR.thruster_button = using
|
||||
|
||||
//Intent
|
||||
action_intent = new /obj/screen/act_intent/robot()
|
||||
action_intent.icon_state = mymob.a_intent
|
||||
static_inventory += action_intent
|
||||
|
||||
//Health
|
||||
healths = new /obj/screen/healths/robot()
|
||||
infodisplay += healths
|
||||
|
||||
//Installed Module
|
||||
mymobR.hands = new /obj/screen/robot/module()
|
||||
mymobR.hands.screen_loc = ui_borg_module
|
||||
static_inventory += mymobR.hands
|
||||
|
||||
//Store
|
||||
module_store_icon = new /obj/screen/robot/store()
|
||||
module_store_icon.screen_loc = ui_borg_store
|
||||
|
||||
pull_icon = new /obj/screen/pull()
|
||||
pull_icon.icon = 'icons/mob/screen_cyborg.dmi'
|
||||
pull_icon.update_icon(mymob)
|
||||
pull_icon.screen_loc = ui_borg_pull
|
||||
hotkeybuttons += pull_icon
|
||||
|
||||
|
||||
zone_select = new /obj/screen/zone_sel/robot()
|
||||
zone_select.update_icon(mymob)
|
||||
static_inventory += zone_select
|
||||
|
||||
|
||||
/datum/hud/proc/toggle_show_robot_modules()
|
||||
if(!iscyborg(mymob))
|
||||
return
|
||||
|
||||
var/mob/living/silicon/robot/R = mymob
|
||||
|
||||
R.shown_robot_modules = !R.shown_robot_modules
|
||||
update_robot_modules_display()
|
||||
|
||||
/datum/hud/proc/update_robot_modules_display(mob/viewer)
|
||||
if(!iscyborg(mymob))
|
||||
return
|
||||
|
||||
var/mob/living/silicon/robot/R = mymob
|
||||
|
||||
var/mob/screenmob = viewer || R
|
||||
|
||||
if(!R.module)
|
||||
return
|
||||
|
||||
if(!R.client)
|
||||
return
|
||||
|
||||
if(R.shown_robot_modules && screenmob.hud_used.hud_shown)
|
||||
//Modules display is shown
|
||||
screenmob.client.screen += module_store_icon //"store" icon
|
||||
|
||||
if(!R.module.modules)
|
||||
to_chat(usr, "<span class='danger'>Selected module has no modules to select</span>")
|
||||
return
|
||||
|
||||
if(!R.robot_modules_background)
|
||||
return
|
||||
|
||||
var/display_rows = CEILING(length(R.module.get_inactive_modules()) / 8, 1)
|
||||
R.robot_modules_background.screen_loc = "CENTER-4:16,SOUTH+1:7 to CENTER+3:16,SOUTH+[display_rows]:7"
|
||||
screenmob.client.screen += R.robot_modules_background
|
||||
|
||||
var/x = -4 //Start at CENTER-4,SOUTH+1
|
||||
var/y = 1
|
||||
|
||||
for(var/atom/movable/A in R.module.get_inactive_modules())
|
||||
//Module is not currently active
|
||||
screenmob.client.screen += A
|
||||
if(x < 0)
|
||||
A.screen_loc = "CENTER[x]:16,SOUTH+[y]:7"
|
||||
else
|
||||
A.screen_loc = "CENTER+[x]:16,SOUTH+[y]:7"
|
||||
A.layer = ABOVE_HUD_LAYER
|
||||
A.plane = ABOVE_HUD_PLANE
|
||||
|
||||
x++
|
||||
if(x == 4)
|
||||
x = -4
|
||||
y++
|
||||
|
||||
else
|
||||
//Modules display is hidden
|
||||
screenmob.client.screen -= module_store_icon //"store" icon
|
||||
|
||||
for(var/atom/A in R.module.get_inactive_modules())
|
||||
//Module is not currently active
|
||||
screenmob.client.screen -= A
|
||||
R.shown_robot_modules = 0
|
||||
screenmob.client.screen -= R.robot_modules_background
|
||||
|
||||
/mob/living/silicon/robot/create_mob_hud()
|
||||
if(client && !hud_used)
|
||||
hud_used = new /datum/hud/robot(src)
|
||||
|
||||
|
||||
/datum/hud/robot/persistent_inventory_update(mob/viewer)
|
||||
if(!mymob)
|
||||
return
|
||||
var/mob/living/silicon/robot/R = mymob
|
||||
|
||||
var/mob/screenmob = viewer || R
|
||||
|
||||
if(screenmob.hud_used)
|
||||
if(screenmob.hud_used.hud_shown)
|
||||
for(var/i in 1 to R.held_items.len)
|
||||
var/obj/item/I = R.held_items[i]
|
||||
if(I)
|
||||
switch(i)
|
||||
if(1)
|
||||
I.screen_loc = ui_inv1
|
||||
if(2)
|
||||
I.screen_loc = ui_inv2
|
||||
if(3)
|
||||
I.screen_loc = ui_inv3
|
||||
else
|
||||
return
|
||||
screenmob.client.screen += I
|
||||
else
|
||||
for(var/obj/item/I in R.held_items)
|
||||
screenmob.client.screen -= I
|
||||
|
||||
@@ -58,6 +58,9 @@
|
||||
SendSignal(COMSIG_ITEM_ATTACK, M, user)
|
||||
if(flags_1 & NOBLUDGEON_1)
|
||||
return
|
||||
|
||||
if(user.has_disability(DISABILITY_PACIFISM))
|
||||
return
|
||||
if(!force)
|
||||
playsound(loc, 'sound/weapons/tap.ogg', get_clamped_volume(), 1, -1)
|
||||
else if(hitsound)
|
||||
@@ -119,9 +122,9 @@
|
||||
/obj/item/proc/get_clamped_volume()
|
||||
if(w_class)
|
||||
if(force)
|
||||
return Clamp((force + w_class) * 4, 30, 100)// Add the item's force to its weight class and multiply by 4, then clamp the value between 30 and 100
|
||||
return CLAMP((force + w_class) * 4, 30, 100)// Add the item's force to its weight class and multiply by 4, then clamp the value between 30 and 100
|
||||
else
|
||||
return Clamp(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100
|
||||
return CLAMP(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100
|
||||
|
||||
/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area)
|
||||
var/message_verb = "attacked"
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
|
||||
/atom/proc/attack_animal(mob/user)
|
||||
return
|
||||
|
||||
/mob/living/RestrainedClickOn(atom/A)
|
||||
return
|
||||
|
||||
|
||||
@@ -62,14 +62,14 @@
|
||||
/mob/living/proc/adjustArousalLoss(amount, updating_arousal=1)
|
||||
if(status_flags & GODMODE || !canbearoused)
|
||||
return 0
|
||||
arousalloss = Clamp(arousalloss + amount, min_arousal, max_arousal)
|
||||
arousalloss = CLAMP(arousalloss + amount, min_arousal, max_arousal)
|
||||
if(updating_arousal)
|
||||
updatearousal()
|
||||
|
||||
/mob/living/proc/setArousalLoss(amount, updating_arousal=1)
|
||||
if(status_flags & GODMODE || !canbearoused)
|
||||
return 0
|
||||
arousalloss = Clamp(amount, min_arousal, max_arousal)
|
||||
arousalloss = CLAMP(amount, min_arousal, max_arousal)
|
||||
if(updating_arousal)
|
||||
updatearousal()
|
||||
|
||||
|
||||
@@ -260,7 +260,7 @@
|
||||
for(var/L in relevant_layers) //Less hardcode
|
||||
H.remove_overlay(L)
|
||||
|
||||
if(H.disabilities & HUSK)
|
||||
if(H.has_disability(DISABILITY_HUSK))
|
||||
return
|
||||
//start scanning for genitals
|
||||
//var/list/worn_stuff = H.get_equipped_items()//cache this list so it's not built again
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
var/value
|
||||
var/default //read-only, just set value directly
|
||||
|
||||
var/resident_file //the file which this belongs to, must be set
|
||||
var/resident_file //the file which this was loaded from, if any
|
||||
var/modified = FALSE //set to TRUE if the default has been overridden by a config entry
|
||||
|
||||
var/protection = NONE
|
||||
@@ -18,8 +18,6 @@
|
||||
var/dupes_allowed = FALSE
|
||||
|
||||
/datum/config_entry/New()
|
||||
if(!resident_file)
|
||||
CRASH("Config entry [type] has no resident_file set")
|
||||
if(type == abstract_type)
|
||||
CRASH("Abstract config entry [type] instatiated!")
|
||||
name = lowertext(type2top(type))
|
||||
@@ -110,7 +108,7 @@
|
||||
/datum/config_entry/number/ValidateAndSet(str_val)
|
||||
var/temp = text2num(trim(str_val))
|
||||
if(!isnull(temp))
|
||||
value = Clamp(integer ? round(temp) : temp, min_val, max_val)
|
||||
value = CLAMP(integer ? round(temp) : temp, min_val, max_val)
|
||||
if(value != temp && !var_edited)
|
||||
log_config("Changing [name] from [temp] to [value]!")
|
||||
return TRUE
|
||||
|
||||
@@ -20,10 +20,13 @@ GLOBAL_PROTECT(config_dir)
|
||||
|
||||
/datum/controller/configuration/New()
|
||||
config = src
|
||||
var/list/config_files = InitEntries()
|
||||
InitEntries()
|
||||
LoadModes()
|
||||
for(var/I in config_files)
|
||||
LoadEntries(I)
|
||||
if(LoadEntries("config.txt") <= 1)
|
||||
log_config("No $include directives found in config.txt! Loading legacy game_options/dbconfig/comms files...")
|
||||
LoadEntries("game_options.txt")
|
||||
LoadEntries("dbconfig.txt")
|
||||
LoadEntries("comms.txt")
|
||||
loadmaplist(CONFIG_MAPS_FILE)
|
||||
|
||||
/datum/controller/configuration/Destroy()
|
||||
@@ -42,8 +45,6 @@ GLOBAL_PROTECT(config_dir)
|
||||
var/list/_entries_by_type = list()
|
||||
entries_by_type = _entries_by_type
|
||||
|
||||
. = list()
|
||||
|
||||
for(var/I in typesof(/datum/config_entry)) //typesof is faster in this case
|
||||
var/datum/config_entry/E = I
|
||||
if(initial(E.abstract_type) == I)
|
||||
@@ -57,24 +58,30 @@ GLOBAL_PROTECT(config_dir)
|
||||
continue
|
||||
_entries[esname] = E
|
||||
_entries_by_type[I] = E
|
||||
.[E.resident_file] = TRUE
|
||||
|
||||
/datum/controller/configuration/proc/RemoveEntry(datum/config_entry/CE)
|
||||
entries -= CE.name
|
||||
entries_by_type -= CE.type
|
||||
|
||||
/datum/controller/configuration/proc/LoadEntries(filename)
|
||||
/datum/controller/configuration/proc/LoadEntries(filename, list/stack = list())
|
||||
var/filename_to_test = world.system_type == MS_WINDOWS ? lowertext(filename) : filename
|
||||
if(filename_to_test in stack)
|
||||
log_config("Warning: Config recursion detected ([english_list(stack)]), breaking!")
|
||||
return
|
||||
stack = stack + filename_to_test
|
||||
|
||||
log_config("Loading config file [filename]...")
|
||||
var/list/lines = world.file2list("[GLOB.config_dir][filename]")
|
||||
var/list/_entries = entries
|
||||
for(var/L in lines)
|
||||
if(!L)
|
||||
continue
|
||||
|
||||
if(copytext(L, 1, 2) == "#")
|
||||
|
||||
var/firstchar = copytext(L, 1, 2)
|
||||
if(firstchar == "#")
|
||||
continue
|
||||
|
||||
var/lockthis = copytext(L, 1, 2) == "@"
|
||||
var/lockthis = firstchar == "@"
|
||||
if(lockthis)
|
||||
L = copytext(L, 2)
|
||||
|
||||
@@ -90,15 +97,25 @@ GLOBAL_PROTECT(config_dir)
|
||||
|
||||
if(!entry)
|
||||
continue
|
||||
if(entry == "$include")
|
||||
if(!value)
|
||||
log_config("Warning: Invalid $include directive: [value]")
|
||||
else
|
||||
LoadEntries(value, stack)
|
||||
++.
|
||||
continue
|
||||
|
||||
if(entry == "$include")
|
||||
if(!value)
|
||||
log_config("Warning: Invalid $include directive: [value]")
|
||||
else
|
||||
LoadEntries(value, stack)
|
||||
continue
|
||||
|
||||
var/datum/config_entry/E = _entries[entry]
|
||||
if(!E)
|
||||
log_config("Unknown setting in configuration: '[entry]'")
|
||||
continue
|
||||
|
||||
if(filename != E.resident_file)
|
||||
log_config("Found [entry] in [filename] when it should have been in [E.resident_file]! Ignoring.")
|
||||
continue
|
||||
|
||||
if(lockthis)
|
||||
E.protection |= CONFIG_ENTRY_LOCKED
|
||||
@@ -107,10 +124,14 @@ GLOBAL_PROTECT(config_dir)
|
||||
if(!validated)
|
||||
log_config("Failed to validate setting \"[value]\" for [entry]")
|
||||
else if(E.modified && !E.dupes_allowed)
|
||||
log_config("Duplicate setting for [entry] ([value]) detected! Using latest.")
|
||||
log_config("Duplicate setting for [entry] ([value], [E.resident_file]) detected! Using latest.")
|
||||
|
||||
E.resident_file = filename
|
||||
|
||||
if(validated)
|
||||
E.modified = TRUE
|
||||
|
||||
++.
|
||||
|
||||
/datum/controller/configuration/can_vv_get(var_name)
|
||||
return (var_name != "entries_by_type" || !hiding_entries_by_type) && ..()
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
#define CURRENT_RESIDENT_FILE "comms.txt"
|
||||
|
||||
CONFIG_DEF(string/comms_key)
|
||||
/datum/config_entry/string/comms_key
|
||||
protection = CONFIG_ENTRY_HIDDEN
|
||||
|
||||
/datum/config_entry/string/comms_key/ValidateAndSet(str_val)
|
||||
return str_val != "default_pwd" && length(str_val) > 6 && ..()
|
||||
|
||||
CONFIG_DEF(string/cross_server_address)
|
||||
/datum/config_entry/keyed_string_list/cross_server
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
/datum/config_entry/string/cross_server_address/ValidateAndSet(str_val)
|
||||
return str_val != "byond:\\address:port" && ..()
|
||||
|
||||
CONFIG_DEF(string/cross_comms_name)
|
||||
/datum/config_entry/string/cross_comms_name
|
||||
|
||||
GLOBAL_VAR_INIT(medals_enabled, TRUE) //will be auto set to false if the game fails contacting the medal hub to prevent unneeded calls.
|
||||
|
||||
CONFIG_DEF(string/medal_hub_address)
|
||||
/datum/config_entry/string/medal_hub_address
|
||||
|
||||
CONFIG_DEF(string/medal_hub_password)
|
||||
protection = CONFIG_ENTRY_HIDDEN
|
||||
/datum/config_entry/string/medal_hub_password
|
||||
protection = CONFIG_ENTRY_HIDDEN
|
||||
|
||||
@@ -1,390 +0,0 @@
|
||||
#define CURRENT_RESIDENT_FILE "config.txt"
|
||||
|
||||
CONFIG_DEF(flag/autoadmin) // if autoadmin is enabled
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(string/autoadmin_rank) // the rank for autoadmins
|
||||
value = "Game Master"
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(string/servername) // server name (the name of the game window)
|
||||
|
||||
CONFIG_DEF(string/serversqlname) // short form server name used for the DB
|
||||
|
||||
CONFIG_DEF(string/stationname) // station name (the name of the station in-game)
|
||||
|
||||
CONFIG_DEF(number/lobby_countdown) // In between round countdown.
|
||||
value = 120
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/round_end_countdown) // Post round murder death kill countdown
|
||||
value = 25
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/hub) // if the game appears on the hub or not
|
||||
|
||||
CONFIG_DEF(flag/log_ooc) // log OOC channel
|
||||
|
||||
CONFIG_DEF(flag/log_access) // log login/logout
|
||||
|
||||
CONFIG_DEF(flag/log_say) // log client say
|
||||
|
||||
CONFIG_DEF(flag/log_admin) // log admin actions
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/log_prayer) // log prayers
|
||||
|
||||
CONFIG_DEF(flag/log_law) // log lawchanges
|
||||
|
||||
CONFIG_DEF(flag/log_game) // log game events
|
||||
|
||||
CONFIG_DEF(flag/log_vote) // log voting
|
||||
|
||||
CONFIG_DEF(flag/log_whisper) // log client whisper
|
||||
|
||||
CONFIG_DEF(flag/log_attack) // log attack messages
|
||||
|
||||
CONFIG_DEF(flag/log_emote) // log emotes
|
||||
|
||||
CONFIG_DEF(flag/log_adminchat) // log admin chat messages
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/log_pda) // log pda messages
|
||||
|
||||
CONFIG_DEF(flag/log_twitter) // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
|
||||
|
||||
CONFIG_DEF(flag/log_world_topic) // log all world.Topic() calls
|
||||
|
||||
CONFIG_DEF(flag/log_manifest) // log crew manifest to seperate file
|
||||
|
||||
CONFIG_DEF(flag/allow_admin_ooccolor) // Allows admins with relevant permissions to have their own ooc colour
|
||||
|
||||
CONFIG_DEF(flag/allow_vote_restart) // allow votes to restart
|
||||
|
||||
CONFIG_DEF(flag/allow_vote_mode) // allow votes to change mode
|
||||
|
||||
CONFIG_DEF(number/vote_delay) // minimum time between voting sessions (deciseconds, 10 minute default)
|
||||
value = 6000
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/vote_period) // length of voting period (deciseconds, default 1 minute)
|
||||
value = 600
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/default_no_vote) // vote does not default to nochange/norestart
|
||||
|
||||
CONFIG_DEF(flag/no_dead_vote) // dead people can't vote
|
||||
|
||||
CONFIG_DEF(flag/allow_metadata) // Metadata is supported.
|
||||
|
||||
CONFIG_DEF(flag/popup_admin_pm) // adminPMs to non-admins show in a pop-up 'reply' window when set
|
||||
|
||||
CONFIG_DEF(number/fps)
|
||||
value = 20
|
||||
min_val = 1
|
||||
max_val = 100 //byond will start crapping out at 50, so this is just ridic
|
||||
var/sync_validate = FALSE
|
||||
|
||||
/datum/config_entry/number/fps/ValidateAndSet(str_val)
|
||||
. = ..()
|
||||
if(.)
|
||||
sync_validate = TRUE
|
||||
var/datum/config_entry/number/ticklag/TL = config.entries_by_type[/datum/config_entry/number/ticklag]
|
||||
if(!TL.sync_validate)
|
||||
TL.ValidateAndSet(10 / value)
|
||||
sync_validate = FALSE
|
||||
|
||||
CONFIG_DEF(number/ticklag)
|
||||
integer = FALSE
|
||||
var/sync_validate = FALSE
|
||||
|
||||
/datum/config_entry/number/ticklag/New() //ticklag weirdly just mirrors fps
|
||||
var/datum/config_entry/CE = /datum/config_entry/number/fps
|
||||
value = 10 / initial(CE.value)
|
||||
..()
|
||||
|
||||
/datum/config_entry/number/ticklag/ValidateAndSet(str_val)
|
||||
. = text2num(str_val) > 0 && ..()
|
||||
if(.)
|
||||
sync_validate = TRUE
|
||||
var/datum/config_entry/number/fps/FPS = config.entries_by_type[/datum/config_entry/number/fps]
|
||||
if(!FPS.sync_validate)
|
||||
FPS.ValidateAndSet(10 / value)
|
||||
sync_validate = FALSE
|
||||
|
||||
CONFIG_DEF(flag/allow_holidays)
|
||||
|
||||
CONFIG_DEF(number/tick_limit_mc_init) //SSinitialization throttling
|
||||
value = TICK_LIMIT_MC_INIT_DEFAULT
|
||||
min_val = 0 //oranges warned us
|
||||
integer = FALSE
|
||||
|
||||
CONFIG_DEF(flag/admin_legacy_system) //Defines whether the server uses the legacy admin system with admins.txt or the SQL system
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(string/hostedby)
|
||||
|
||||
CONFIG_DEF(flag/norespawn)
|
||||
|
||||
CONFIG_DEF(flag/guest_jobban)
|
||||
|
||||
CONFIG_DEF(flag/usewhitelist)
|
||||
|
||||
CONFIG_DEF(flag/ban_legacy_system) //Defines whether the server uses the legacy banning system with the files in /data or the SQL system.
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/use_age_restriction_for_jobs) //Do jobs use account age restrictions? --requires database
|
||||
|
||||
CONFIG_DEF(flag/use_account_age_for_jobs) //Uses the time they made the account for the job restriction stuff. New player joining alerts should be unaffected.
|
||||
|
||||
CONFIG_DEF(flag/use_exp_tracking)
|
||||
|
||||
CONFIG_DEF(flag/use_exp_restrictions_heads)
|
||||
|
||||
CONFIG_DEF(number/use_exp_restrictions_heads_hours)
|
||||
value = 0
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/use_exp_restrictions_heads_department)
|
||||
|
||||
CONFIG_DEF(flag/use_exp_restrictions_other)
|
||||
|
||||
CONFIG_DEF(flag/use_exp_restrictions_admin_bypass)
|
||||
|
||||
CONFIG_DEF(string/server)
|
||||
|
||||
CONFIG_DEF(string/banappeals)
|
||||
|
||||
CONFIG_DEF(string/wikiurl)
|
||||
value = "http://www.tgstation13.org/wiki"
|
||||
|
||||
CONFIG_DEF(string/forumurl)
|
||||
value = "http://tgstation13.org/phpBB/index.php"
|
||||
|
||||
CONFIG_DEF(string/rulesurl)
|
||||
value = "http://www.tgstation13.org/wiki/Rules"
|
||||
|
||||
CONFIG_DEF(string/githuburl)
|
||||
value = "https://www.github.com/tgstation/-tg-station"
|
||||
|
||||
CONFIG_DEF(number/githubrepoid)
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/guest_ban)
|
||||
|
||||
CONFIG_DEF(number/id_console_jobslot_delay)
|
||||
value = 30
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/inactivity_period) //time in ds until a player is considered inactive)
|
||||
value = 3000
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/inactivity_period/ValidateAndSet(str_val)
|
||||
. = ..()
|
||||
if(.)
|
||||
value *= 10 //documented as seconds in config.txt
|
||||
|
||||
CONFIG_DEF(number/afk_period) //time in ds until a player is considered inactive)
|
||||
value = 3000
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/afk_period/ValidateAndSet(str_val)
|
||||
. = ..()
|
||||
if(.)
|
||||
value *= 10 //documented as seconds in config.txt
|
||||
|
||||
CONFIG_DEF(flag/kick_inactive) //force disconnect for inactive players
|
||||
|
||||
CONFIG_DEF(flag/load_jobs_from_txt)
|
||||
|
||||
CONFIG_DEF(flag/forbid_singulo_possession)
|
||||
|
||||
CONFIG_DEF(flag/automute_on) //enables automuting/spam prevention
|
||||
|
||||
CONFIG_DEF(string/panic_server_name)
|
||||
|
||||
/datum/config_entry/string/panic_server_name/ValidateAndSet(str_val)
|
||||
return str_val != "\[Put the name here\]" && ..()
|
||||
|
||||
CONFIG_DEF(string/panic_server_address) //Reconnect a player this linked server if this server isn't accepting new players
|
||||
|
||||
/datum/config_entry/string/panic_server_address/ValidateAndSet(str_val)
|
||||
return str_val != "byond://address:port" && ..()
|
||||
|
||||
CONFIG_DEF(string/invoke_youtubedl)
|
||||
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
|
||||
|
||||
CONFIG_DEF(flag/show_irc_name)
|
||||
|
||||
CONFIG_DEF(flag/see_own_notes) //Can players see their own admin notes (read-only)?
|
||||
|
||||
CONFIG_DEF(number/note_fresh_days)
|
||||
value = null
|
||||
min_val = 0
|
||||
integer = FALSE
|
||||
|
||||
CONFIG_DEF(number/note_stale_days)
|
||||
value = null
|
||||
min_val = 0
|
||||
integer = FALSE
|
||||
|
||||
CONFIG_DEF(flag/maprotation)
|
||||
|
||||
CONFIG_DEF(number/maprotatechancedelta)
|
||||
value = 0.75
|
||||
min_val = 0
|
||||
max_val = 1
|
||||
integer = FALSE
|
||||
|
||||
CONFIG_DEF(number/soft_popcap)
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/hard_popcap)
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/extreme_popcap)
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(string/soft_popcap_message)
|
||||
value = "Be warned that the server is currently serving a high number of users, consider using alternative game servers."
|
||||
|
||||
CONFIG_DEF(string/hard_popcap_message)
|
||||
value = "The server is currently serving a high number of users, You cannot currently join. You may wait for the number of living crew to decline, observe, or find alternative servers."
|
||||
|
||||
CONFIG_DEF(string/extreme_popcap_message)
|
||||
value = "The server is currently serving a high number of users, find alternative servers."
|
||||
|
||||
CONFIG_DEF(flag/panic_bunker) // prevents people the server hasn't seen before from connecting
|
||||
|
||||
CONFIG_DEF(number/notify_new_player_age) // how long do we notify admins of a new player
|
||||
min_val = -1
|
||||
|
||||
CONFIG_DEF(number/notify_new_player_account_age) // how long do we notify admins of a new byond account
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/irc_first_connection_alert) // do we notify the irc channel when somebody is connecting for the first time?
|
||||
|
||||
CONFIG_DEF(flag/check_randomizer)
|
||||
|
||||
CONFIG_DEF(string/ipintel_email)
|
||||
|
||||
/datum/config_entry/string/ipintel_email/ValidateAndSet(str_val)
|
||||
return str_val != "ch@nge.me" && ..()
|
||||
|
||||
CONFIG_DEF(number/ipintel_rating_bad)
|
||||
value = 1
|
||||
integer = FALSE
|
||||
min_val = 0
|
||||
max_val = 1
|
||||
|
||||
CONFIG_DEF(number/ipintel_save_good)
|
||||
value = 12
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/ipintel_save_bad)
|
||||
value = 1
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(string/ipintel_domain)
|
||||
value = "check.getipintel.net"
|
||||
|
||||
CONFIG_DEF(flag/aggressive_changelog)
|
||||
|
||||
CONFIG_DEF(flag/autoconvert_notes) //if all connecting player's notes should attempt to be converted to the database
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(flag/allow_webclient)
|
||||
|
||||
CONFIG_DEF(flag/webclient_only_byond_members)
|
||||
|
||||
CONFIG_DEF(flag/announce_admin_logout)
|
||||
|
||||
CONFIG_DEF(flag/announce_admin_login)
|
||||
|
||||
CONFIG_DEF(flag/allow_map_voting)
|
||||
|
||||
CONFIG_DEF(flag/generate_minimaps)
|
||||
|
||||
CONFIG_DEF(number/client_warn_version)
|
||||
value = null
|
||||
min_val = 500
|
||||
max_val = DM_VERSION - 1
|
||||
|
||||
CONFIG_DEF(string/client_warn_message)
|
||||
value = "Your version of byond may have issues or be blocked from accessing this server in the future."
|
||||
|
||||
CONFIG_DEF(flag/client_warn_popup)
|
||||
|
||||
CONFIG_DEF(number/client_error_version)
|
||||
value = null
|
||||
min_val = 500
|
||||
max_val = DM_VERSION - 1
|
||||
|
||||
CONFIG_DEF(string/client_error_message)
|
||||
value = "Your version of byond is too old, may have issues, and is blocked from accessing this server."
|
||||
|
||||
CONFIG_DEF(number/minute_topic_limit)
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/second_topic_limit)
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/error_cooldown) // The "cooldown" time for each occurrence of a unique error)
|
||||
value = 600
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/error_limit) // How many occurrences before the next will silence them
|
||||
value = 50
|
||||
|
||||
CONFIG_DEF(number/error_silence_time) // How long a unique error will be silenced for
|
||||
value = 6000
|
||||
|
||||
CONFIG_DEF(number/error_msg_delay) // How long to wait between messaging admins about occurrences of a unique error
|
||||
value = 50
|
||||
|
||||
CONFIG_DEF(flag/irc_announce_new_game)
|
||||
|
||||
CONFIG_DEF(flag/debug_admin_hrefs)
|
||||
|
||||
CONFIG_DEF(number/mc_tick_rate/base_mc_tick_rate)
|
||||
integer = FALSE
|
||||
value = 1
|
||||
|
||||
CONFIG_DEF(number/mc_tick_rate/high_pop_mc_tick_rate)
|
||||
integer = FALSE
|
||||
value = 1.1
|
||||
|
||||
CONFIG_DEF(number/mc_tick_rate/high_pop_mc_mode_amount)
|
||||
value = 65
|
||||
|
||||
CONFIG_DEF(number/mc_tick_rate/disable_high_pop_mc_mode_amount)
|
||||
value = 60
|
||||
|
||||
CONFIG_TWEAK(number/mc_tick_rate)
|
||||
abstract_type = /datum/config_entry/number/mc_tick_rate
|
||||
|
||||
CONFIG_TWEAK(number/mc_tick_rate/ValidateAndSet(str_val))
|
||||
. = ..()
|
||||
if (.)
|
||||
Master.UpdateTickRate()
|
||||
|
||||
CONFIG_DEF(flag/resume_after_initializations)
|
||||
|
||||
CONFIG_TWEAK(flag/resume_after_initializations/ValidateAndSet(str_val))
|
||||
. = ..()
|
||||
if(. && Master.current_runlevel)
|
||||
world.sleep_offline = !value
|
||||
|
||||
CONFIG_DEF(number/rounds_until_hard_restart)
|
||||
value = -1
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(string/default_view)
|
||||
value = "15x15"
|
||||
@@ -1,28 +1,26 @@
|
||||
#define CURRENT_RESIDENT_FILE "dbconfig.txt"
|
||||
|
||||
CONFIG_DEF(flag/sql_enabled) // for sql switching
|
||||
/datum/config_entry/flag/sql_enabled // for sql switching
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
CONFIG_DEF(string/address)
|
||||
/datum/config_entry/string/address
|
||||
value = "localhost"
|
||||
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
|
||||
|
||||
CONFIG_DEF(number/port)
|
||||
/datum/config_entry/number/port
|
||||
value = 3306
|
||||
min_val = 0
|
||||
max_val = 65535
|
||||
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
|
||||
|
||||
CONFIG_DEF(string/feedback_database)
|
||||
/datum/config_entry/string/feedback_database
|
||||
value = "test"
|
||||
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
|
||||
|
||||
CONFIG_DEF(string/feedback_login)
|
||||
/datum/config_entry/string/feedback_login
|
||||
value = "root"
|
||||
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
|
||||
|
||||
CONFIG_DEF(string/feedback_password)
|
||||
/datum/config_entry/string/feedback_password
|
||||
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
|
||||
|
||||
CONFIG_DEF(string/feedback_tableprefix)
|
||||
/datum/config_entry/string/feedback_tableprefix
|
||||
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
|
||||
|
||||
@@ -1,253 +1,255 @@
|
||||
#define CURRENT_RESIDENT_FILE "game_options.txt"
|
||||
/datum/config_entry/number_list/repeated_mode_adjust
|
||||
|
||||
CONFIG_DEF(number_list/repeated_mode_adjust)
|
||||
|
||||
CONFIG_DEF(keyed_number_list/probability)
|
||||
/datum/config_entry/keyed_number_list/probability
|
||||
|
||||
/datum/config_entry/keyed_number_list/probability/ValidateKeyName(key_name)
|
||||
return key_name in config.modes
|
||||
|
||||
CONFIG_DEF(keyed_number_list/max_pop)
|
||||
/datum/config_entry/keyed_number_list/max_pop
|
||||
|
||||
/datum/config_entry/keyed_number_list/max_pop/ValidateKeyName(key_name)
|
||||
return key_name in config.modes
|
||||
|
||||
CONFIG_DEF(keyed_number_list/min_pop)
|
||||
/datum/config_entry/keyed_number_list/min_pop
|
||||
|
||||
/datum/config_entry/keyed_number_list/min_pop/ValidateKeyName(key_name)
|
||||
return key_name in config.modes
|
||||
|
||||
CONFIG_DEF(keyed_flag_list/continuous) // which roundtypes continue if all antagonists die
|
||||
/datum/config_entry/keyed_flag_list/continuous // which roundtypes continue if all antagonists die
|
||||
|
||||
/datum/config_entry/keyed_flag_list/continuous/ValidateKeyName(key_name)
|
||||
return key_name in config.modes
|
||||
|
||||
CONFIG_DEF(keyed_flag_list/midround_antag) // which roundtypes use the midround antagonist system
|
||||
/datum/config_entry/keyed_flag_list/midround_antag // which roundtypes use the midround antagonist system
|
||||
|
||||
/datum/config_entry/keyed_flag_list/midround_antag/ValidateKeyName(key_name)
|
||||
return key_name in config.modes
|
||||
|
||||
CONFIG_DEF(keyed_string_list/policy)
|
||||
/datum/config_entry/keyed_string_list/policy
|
||||
|
||||
CONFIG_DEF(number/damage_multiplier)
|
||||
/datum/config_entry/number/damage_multiplier
|
||||
value = 1
|
||||
integer = FALSE
|
||||
|
||||
CONFIG_DEF(number/minimal_access_threshold) //If the number of players is larger than this threshold, minimal access will be turned on.
|
||||
/datum/config_entry/number/minimal_access_threshold //If the number of players is larger than this threshold, minimal access will be turned on.
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/jobs_have_minimal_access) //determines whether jobs use minimal access or expanded access.
|
||||
/datum/config_entry/flag/jobs_have_minimal_access //determines whether jobs use minimal access or expanded access.
|
||||
|
||||
CONFIG_DEF(flag/assistants_have_maint_access)
|
||||
/datum/config_entry/flag/assistants_have_maint_access
|
||||
|
||||
CONFIG_DEF(flag/security_has_maint_access)
|
||||
/datum/config_entry/flag/security_has_maint_access
|
||||
|
||||
CONFIG_DEF(flag/everyone_has_maint_access)
|
||||
/datum/config_entry/flag/everyone_has_maint_access
|
||||
|
||||
CONFIG_DEF(flag/sec_start_brig) //makes sec start in brig instead of dept sec posts
|
||||
/datum/config_entry/flag/sec_start_brig //makes sec start in brig instead of dept sec posts
|
||||
|
||||
CONFIG_DEF(flag/force_random_names)
|
||||
/datum/config_entry/flag/force_random_names
|
||||
|
||||
CONFIG_DEF(flag/humans_need_surnames)
|
||||
/datum/config_entry/flag/humans_need_surnames
|
||||
|
||||
CONFIG_DEF(flag/allow_ai) // allow ai job
|
||||
/datum/config_entry/flag/allow_ai // allow ai job
|
||||
|
||||
CONFIG_DEF(flag/disable_secborg) // disallow secborg module to be chosen.
|
||||
/datum/config_entry/flag/disable_secborg // disallow secborg module to be chosen.
|
||||
|
||||
CONFIG_DEF(flag/disable_peaceborg)
|
||||
/datum/config_entry/flag/disable_peaceborg
|
||||
|
||||
CONFIG_DEF(number/traitor_scaling_coeff) //how much does the amount of players get divided by to determine traitors
|
||||
/datum/config_entry/number/traitor_scaling_coeff //how much does the amount of players get divided by to determine traitors
|
||||
value = 6
|
||||
min_val = 1
|
||||
|
||||
CONFIG_DEF(number/brother_scaling_coeff) //how many players per brother team
|
||||
/datum/config_entry/number/brother_scaling_coeff //how many players per brother team
|
||||
value = 25
|
||||
min_val = 1
|
||||
|
||||
CONFIG_DEF(number/changeling_scaling_coeff) //how much does the amount of players get divided by to determine changelings
|
||||
/datum/config_entry/number/changeling_scaling_coeff //how much does the amount of players get divided by to determine changelings
|
||||
value = 6
|
||||
min_val = 1
|
||||
|
||||
CONFIG_DEF(number/security_scaling_coeff) //how much does the amount of players get divided by to determine open security officer positions
|
||||
/datum/config_entry/number/security_scaling_coeff //how much does the amount of players get divided by to determine open security officer positions
|
||||
value = 8
|
||||
min_val = 1
|
||||
|
||||
CONFIG_DEF(number/abductor_scaling_coeff) //how many players per abductor team
|
||||
/datum/config_entry/number/abductor_scaling_coeff //how many players per abductor team
|
||||
value = 15
|
||||
min_val = 1
|
||||
|
||||
CONFIG_DEF(number/traitor_objectives_amount)
|
||||
/datum/config_entry/number/traitor_objectives_amount
|
||||
value = 2
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/brother_objectives_amount)
|
||||
/datum/config_entry/number/brother_objectives_amount
|
||||
value = 2
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/reactionary_explosions) //If we use reactionary explosions, explosions that react to walls and doors
|
||||
/datum/config_entry/flag/reactionary_explosions //If we use reactionary explosions, explosions that react to walls and doors
|
||||
|
||||
CONFIG_DEF(flag/protect_roles_from_antagonist) //If security and such can be traitor/cult/other
|
||||
/datum/config_entry/flag/protect_roles_from_antagonist //If security and such can be traitor/cult/other
|
||||
|
||||
CONFIG_DEF(flag/protect_assistant_from_antagonist) //If assistants can be traitor/cult/other
|
||||
/datum/config_entry/flag/protect_assistant_from_antagonist //If assistants can be traitor/cult/other
|
||||
|
||||
CONFIG_DEF(flag/enforce_human_authority) //If non-human species are barred from joining as a head of staff
|
||||
/datum/config_entry/flag/enforce_human_authority //If non-human species are barred from joining as a head of staff
|
||||
|
||||
CONFIG_DEF(flag/allow_latejoin_antagonists) // If late-joining players can be traitor/changeling
|
||||
/datum/config_entry/flag/allow_latejoin_antagonists // If late-joining players can be traitor/changeling
|
||||
|
||||
CONFIG_DEF(number/midround_antag_time_check) // How late (in minutes) you want the midround antag system to stay on, setting this to 0 will disable the system
|
||||
/datum/config_entry/number/midround_antag_time_check // How late (in minutes you want the midround antag system to stay on, setting this to 0 will disable the system)
|
||||
value = 60
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/midround_antag_life_check) // A ratio of how many people need to be alive in order for the round not to immediately end in midround antagonist
|
||||
/datum/config_entry/number/midround_antag_life_check // A ratio of how many people need to be alive in order for the round not to immediately end in midround antagonist
|
||||
value = 0.7
|
||||
integer = FALSE
|
||||
min_val = 0
|
||||
max_val = 1
|
||||
|
||||
CONFIG_DEF(number/shuttle_refuel_delay)
|
||||
/datum/config_entry/number/shuttle_refuel_delay
|
||||
value = 12000
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/show_game_type_odds) //if set this allows players to see the odds of each roundtype on the get revision screen
|
||||
/datum/config_entry/flag/show_game_type_odds //if set this allows players to see the odds of each roundtype on the get revision screen
|
||||
|
||||
CONFIG_DEF(keyed_flag_list/roundstart_races) //races you can play as from the get go.
|
||||
/datum/config_entry/keyed_flag_list/roundstart_races //races you can play as from the get go.
|
||||
|
||||
CONFIG_DEF(flag/join_with_mutant_humans) //players can pick mutant bodyparts for humans before joining the game
|
||||
/datum/config_entry/flag/join_with_mutant_humans //players can pick mutant bodyparts for humans before joining the game
|
||||
|
||||
CONFIG_DEF(flag/no_summon_guns) //No
|
||||
/datum/config_entry/flag/no_summon_guns //No
|
||||
|
||||
CONFIG_DEF(flag/no_summon_magic) //Fun
|
||||
/datum/config_entry/flag/no_summon_magic //Fun
|
||||
|
||||
CONFIG_DEF(flag/no_summon_events) //Allowed
|
||||
/datum/config_entry/flag/no_summon_events //Allowed
|
||||
|
||||
CONFIG_DEF(flag/no_intercept_report) //Whether or not to send a communications intercept report roundstart. This may be overriden by gamemodes.
|
||||
/datum/config_entry/flag/no_intercept_report //Whether or not to send a communications intercept report roundstart. This may be overriden by gamemodes.
|
||||
|
||||
CONFIG_DEF(number/arrivals_shuttle_dock_window) //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station
|
||||
/datum/config_entry/number/arrivals_shuttle_dock_window //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station
|
||||
value = 55
|
||||
min_val = 30
|
||||
|
||||
CONFIG_DEF(flag/arrivals_shuttle_require_undocked) //Require the arrivals shuttle to be undocked before latejoiners can join
|
||||
/datum/config_entry/flag/arrivals_shuttle_require_undocked //Require the arrivals shuttle to be undocked before latejoiners can join
|
||||
|
||||
CONFIG_DEF(flag/arrivals_shuttle_require_safe_latejoin) //Require the arrivals shuttle to be operational in order for latejoiners to join
|
||||
/datum/config_entry/flag/arrivals_shuttle_require_safe_latejoin //Require the arrivals shuttle to be operational in order for latejoiners to join
|
||||
|
||||
CONFIG_DEF(string/alert_green)
|
||||
/datum/config_entry/string/alert_green
|
||||
value = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced."
|
||||
|
||||
CONFIG_DEF(string/alert_blue_upto)
|
||||
/datum/config_entry/string/alert_blue_upto
|
||||
value = "The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible, random searches are permitted."
|
||||
|
||||
CONFIG_DEF(string/alert_blue_downto)
|
||||
/datum/config_entry/string/alert_blue_downto
|
||||
value = "The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed."
|
||||
|
||||
CONFIG_DEF(string/alert_red_upto)
|
||||
/datum/config_entry/string/alert_red_upto
|
||||
value = "There is an immediate serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised."
|
||||
|
||||
CONFIG_DEF(string/alert_red_downto)
|
||||
/datum/config_entry/string/alert_red_downto
|
||||
value = "The station's destruction has been averted. There is still however an immediate serious threat to the station. Security may have weapons unholstered at all times, random searches are allowed and advised."
|
||||
|
||||
CONFIG_DEF(string/alert_delta)
|
||||
/datum/config_entry/string/alert_delta
|
||||
value = "Destruction of the station is imminent. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill."
|
||||
|
||||
CONFIG_DEF(flag/revival_pod_plants)
|
||||
/datum/config_entry/flag/revival_pod_plants
|
||||
|
||||
CONFIG_DEF(flag/revival_cloning)
|
||||
/datum/config_entry/flag/revival_cloning
|
||||
|
||||
CONFIG_DEF(number/revival_brain_life)
|
||||
/datum/config_entry/number/revival_brain_life
|
||||
value = -1
|
||||
min_val = -1
|
||||
|
||||
CONFIG_DEF(flag/rename_cyborg)
|
||||
/datum/config_entry/flag/rename_cyborg
|
||||
|
||||
CONFIG_DEF(flag/ooc_during_round)
|
||||
/datum/config_entry/flag/ooc_during_round
|
||||
|
||||
CONFIG_DEF(flag/emojis)
|
||||
/datum/config_entry/flag/emojis
|
||||
|
||||
CONFIG_DEF(number/run_delay) //Used for modifying movement speed for mobs.
|
||||
/datum/config_entry/number/run_delay //Used for modifying movement speed for mobs.
|
||||
var/static/value_cache = 0
|
||||
|
||||
CONFIG_TWEAK(number/run_delay/ValidateAndSet())
|
||||
/datum/config_entry/number/run_delay/ValidateAndSet()
|
||||
. = ..()
|
||||
if(.)
|
||||
value_cache = value
|
||||
|
||||
CONFIG_DEF(number/walk_delay)
|
||||
/datum/config_entry/number/walk_delay
|
||||
var/static/value_cache = 0
|
||||
|
||||
CONFIG_TWEAK(number/walk_delay/ValidateAndSet())
|
||||
/datum/config_entry/number/walk_delay/ValidateAndSet()
|
||||
. = ..()
|
||||
if(.)
|
||||
value_cache = value
|
||||
|
||||
CONFIG_DEF(number/human_delay) //Mob specific modifiers. NOTE: These will affect different mob types in different ways
|
||||
CONFIG_DEF(number/robot_delay)
|
||||
CONFIG_DEF(number/monkey_delay)
|
||||
CONFIG_DEF(number/alien_delay)
|
||||
CONFIG_DEF(number/slime_delay)
|
||||
CONFIG_DEF(number/animal_delay)
|
||||
/datum/config_entry/number/human_delay //Mob specific modifiers. NOTE: These will affect different mob types in different ways
|
||||
/datum/config_entry/number/robot_delay
|
||||
/datum/config_entry/number/monkey_delay
|
||||
/datum/config_entry/number/alien_delay
|
||||
/datum/config_entry/number/slime_delay
|
||||
/datum/config_entry/number/animal_delay
|
||||
|
||||
CONFIG_DEF(number/gateway_delay) //How long the gateway takes before it activates. Default is half an hour.
|
||||
/datum/config_entry/number/gateway_delay //How long the gateway takes before it activates. Default is half an hour.
|
||||
value = 18000
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/ghost_interaction)
|
||||
/datum/config_entry/flag/ghost_interaction
|
||||
|
||||
CONFIG_DEF(flag/silent_ai)
|
||||
CONFIG_DEF(flag/silent_borg)
|
||||
/datum/config_entry/flag/silent_ai
|
||||
/datum/config_entry/flag/silent_borg
|
||||
|
||||
CONFIG_DEF(flag/sandbox_autoclose) // close the sandbox panel after spawning an item, potentially reducing griff
|
||||
/datum/config_entry/flag/sandbox_autoclose // close the sandbox panel after spawning an item, potentially reducing griff
|
||||
|
||||
CONFIG_DEF(number/default_laws) //Controls what laws the AI spawns with.
|
||||
/datum/config_entry/number/default_laws //Controls what laws the AI spawns with.
|
||||
value = 0
|
||||
min_val = 0
|
||||
max_val = 3
|
||||
|
||||
CONFIG_DEF(number/silicon_max_law_amount)
|
||||
/datum/config_entry/number/silicon_max_law_amount
|
||||
value = 12
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(keyed_flag_list/random_laws)
|
||||
/datum/config_entry/keyed_flag_list/random_laws
|
||||
|
||||
CONFIG_DEF(keyed_number_list/law_weight)
|
||||
/datum/config_entry/keyed_number_list/law_weight
|
||||
splitter = ","
|
||||
|
||||
CONFIG_DEF(number/assistant_cap)
|
||||
/datum/config_entry/number/assistant_cap
|
||||
value = -1
|
||||
min_val = -1
|
||||
|
||||
CONFIG_DEF(flag/starlight)
|
||||
CONFIG_DEF(flag/grey_assistants)
|
||||
/datum/config_entry/flag/starlight
|
||||
/datum/config_entry/flag/grey_assistants
|
||||
|
||||
CONFIG_DEF(number/lavaland_budget)
|
||||
/datum/config_entry/number/lavaland_budget
|
||||
value = 60
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/space_budget)
|
||||
/datum/config_entry/number/space_budget
|
||||
value = 16
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(flag/allow_random_events) // Enables random events mid-round when set
|
||||
/datum/config_entry/flag/allow_random_events // Enables random events mid-round when set
|
||||
|
||||
CONFIG_DEF(number/events_min_time_mul) // Multipliers for random events minimal starting time and minimal players amounts
|
||||
/datum/config_entry/number/events_min_time_mul // Multipliers for random events minimal starting time and minimal players amounts
|
||||
value = 1
|
||||
min_val = 0
|
||||
integer = FALSE
|
||||
|
||||
CONFIG_DEF(number/events_min_players_mul)
|
||||
/datum/config_entry/number/events_min_players_mul
|
||||
value = 1
|
||||
min_val = 0
|
||||
integer = FALSE
|
||||
|
||||
CONFIG_DEF(number/mice_roundstart)
|
||||
/datum/config_entry/number/mice_roundstart
|
||||
value = 10
|
||||
min_val = 0
|
||||
|
||||
CONFIG_DEF(number/bombcap)
|
||||
/datum/config_entry/number/bombcap
|
||||
value = 14
|
||||
min_val = 4
|
||||
|
||||
CONFIG_DEF(flag/allow_crew_objectives)
|
||||
CONFIG_DEF(flag/allow_miscreants)
|
||||
CONFIG_DEF(flag/allow_extended_miscreants)
|
||||
//Cit changes - Adds config options for crew objectives and miscreants
|
||||
/datum/config_entry/flag/allow_crew_objectives
|
||||
|
||||
/datum/config_entry/flag/allow_miscreants
|
||||
|
||||
/datum/config_entry/flag/allow_extended_miscreants
|
||||
//End of Cit changes
|
||||
|
||||
/datum/config_entry/number/bombcap/ValidateAndSet(str_val)
|
||||
. = ..()
|
||||
@@ -258,9 +260,9 @@ CONFIG_DEF(flag/allow_extended_miscreants)
|
||||
GLOB.MAX_EX_FLASH_RANGE = value
|
||||
GLOB.MAX_EX_FLAME_RANGE = value
|
||||
|
||||
CONFIG_DEF(number/emergency_shuttle_autocall_threshold)
|
||||
/datum/config_entry/number/emergency_shuttle_autocall_threshold
|
||||
min_val = 0
|
||||
max_val = 1
|
||||
integer = FALSE
|
||||
|
||||
CONFIG_DEF(flag/ic_printing)
|
||||
/datum/config_entry/flag/ic_printing
|
||||
|
||||
@@ -0,0 +1,388 @@
|
||||
/datum/config_entry/flag/autoadmin // if autoadmin is enabled
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
/datum/config_entry/string/autoadmin_rank // the rank for autoadmins
|
||||
value = "Game Master"
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
/datum/config_entry/string/servername // server name (the name of the game window)
|
||||
|
||||
/datum/config_entry/string/serversqlname // short form server name used for the DB
|
||||
|
||||
/datum/config_entry/string/stationname // station name (the name of the station in-game)
|
||||
|
||||
/datum/config_entry/number/lobby_countdown // In between round countdown.
|
||||
value = 120
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/round_end_countdown // Post round murder death kill countdown
|
||||
value = 25
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/flag/hub // if the game appears on the hub or not
|
||||
|
||||
/datum/config_entry/flag/log_ooc // log OOC channel
|
||||
|
||||
/datum/config_entry/flag/log_access // log login/logout
|
||||
|
||||
/datum/config_entry/flag/log_say // log client say
|
||||
|
||||
/datum/config_entry/flag/log_admin // log admin actions
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
/datum/config_entry/flag/log_prayer // log prayers
|
||||
|
||||
/datum/config_entry/flag/log_law // log lawchanges
|
||||
|
||||
/datum/config_entry/flag/log_game // log game events
|
||||
|
||||
/datum/config_entry/flag/log_vote // log voting
|
||||
|
||||
/datum/config_entry/flag/log_whisper // log client whisper
|
||||
|
||||
/datum/config_entry/flag/log_attack // log attack messages
|
||||
|
||||
/datum/config_entry/flag/log_emote // log emotes
|
||||
|
||||
/datum/config_entry/flag/log_adminchat // log admin chat messages
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
/datum/config_entry/flag/log_pda // log pda messages
|
||||
|
||||
/datum/config_entry/flag/log_twitter // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
|
||||
|
||||
/datum/config_entry/flag/log_world_topic // log all world.Topic() calls
|
||||
|
||||
/datum/config_entry/flag/log_manifest // log crew manifest to seperate file
|
||||
|
||||
/datum/config_entry/flag/allow_admin_ooccolor // Allows admins with relevant permissions to have their own ooc colour
|
||||
|
||||
/datum/config_entry/flag/allow_vote_restart // allow votes to restart
|
||||
|
||||
/datum/config_entry/flag/allow_vote_mode // allow votes to change mode
|
||||
|
||||
/datum/config_entry/number/vote_delay // minimum time between voting sessions (deciseconds, 10 minute default)
|
||||
value = 6000
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/vote_period // length of voting period (deciseconds, default 1 minute)
|
||||
value = 600
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/flag/default_no_vote // vote does not default to nochange/norestart
|
||||
|
||||
/datum/config_entry/flag/no_dead_vote // dead people can't vote
|
||||
|
||||
/datum/config_entry/flag/allow_metadata // Metadata is supported.
|
||||
|
||||
/datum/config_entry/flag/popup_admin_pm // adminPMs to non-admins show in a pop-up 'reply' window when set
|
||||
|
||||
/datum/config_entry/number/fps
|
||||
value = 20
|
||||
min_val = 1
|
||||
max_val = 100 //byond will start crapping out at 50, so this is just ridic
|
||||
var/sync_validate = FALSE
|
||||
|
||||
/datum/config_entry/number/fps/ValidateAndSet(str_val)
|
||||
. = ..()
|
||||
if(.)
|
||||
sync_validate = TRUE
|
||||
var/datum/config_entry/number/ticklag/TL = config.entries_by_type[/datum/config_entry/number/ticklag]
|
||||
if(!TL.sync_validate)
|
||||
TL.ValidateAndSet(10 / value)
|
||||
sync_validate = FALSE
|
||||
|
||||
/datum/config_entry/number/ticklag
|
||||
integer = FALSE
|
||||
var/sync_validate = FALSE
|
||||
|
||||
/datum/config_entry/number/ticklag/New() //ticklag weirdly just mirrors fps
|
||||
var/datum/config_entry/CE = /datum/config_entry/number/fps
|
||||
value = 10 / initial(CE.value)
|
||||
..()
|
||||
|
||||
/datum/config_entry/number/ticklag/ValidateAndSet(str_val)
|
||||
. = text2num(str_val) > 0 && ..()
|
||||
if(.)
|
||||
sync_validate = TRUE
|
||||
var/datum/config_entry/number/fps/FPS = config.entries_by_type[/datum/config_entry/number/fps]
|
||||
if(!FPS.sync_validate)
|
||||
FPS.ValidateAndSet(10 / value)
|
||||
sync_validate = FALSE
|
||||
|
||||
/datum/config_entry/flag/allow_holidays
|
||||
|
||||
/datum/config_entry/number/tick_limit_mc_init //SSinitialization throttling
|
||||
value = TICK_LIMIT_MC_INIT_DEFAULT
|
||||
min_val = 0 //oranges warned us
|
||||
integer = FALSE
|
||||
|
||||
/datum/config_entry/flag/admin_legacy_system //Defines whether the server uses the legacy admin system with admins.txt or the SQL system
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
/datum/config_entry/string/hostedby
|
||||
|
||||
/datum/config_entry/flag/norespawn
|
||||
|
||||
/datum/config_entry/flag/guest_jobban
|
||||
|
||||
/datum/config_entry/flag/usewhitelist
|
||||
|
||||
/datum/config_entry/flag/ban_legacy_system //Defines whether the server uses the legacy banning system with the files in /data or the SQL system.
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
/datum/config_entry/flag/use_age_restriction_for_jobs //Do jobs use account age restrictions? --requires database
|
||||
|
||||
/datum/config_entry/flag/use_account_age_for_jobs //Uses the time they made the account for the job restriction stuff. New player joining alerts should be unaffected.
|
||||
|
||||
/datum/config_entry/flag/use_exp_tracking
|
||||
|
||||
/datum/config_entry/flag/use_exp_restrictions_heads
|
||||
|
||||
/datum/config_entry/number/use_exp_restrictions_heads_hours
|
||||
value = 0
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/flag/use_exp_restrictions_heads_department
|
||||
|
||||
/datum/config_entry/flag/use_exp_restrictions_other
|
||||
|
||||
/datum/config_entry/flag/use_exp_restrictions_admin_bypass
|
||||
|
||||
/datum/config_entry/string/server
|
||||
|
||||
/datum/config_entry/string/banappeals
|
||||
|
||||
/datum/config_entry/string/wikiurl
|
||||
value = "http://www.tgstation13.org/wiki"
|
||||
|
||||
/datum/config_entry/string/forumurl
|
||||
value = "http://tgstation13.org/phpBB/index.php"
|
||||
|
||||
/datum/config_entry/string/rulesurl
|
||||
value = "http://www.tgstation13.org/wiki/Rules"
|
||||
|
||||
/datum/config_entry/string/githuburl
|
||||
value = "https://www.github.com/tgstation/-tg-station"
|
||||
|
||||
/datum/config_entry/number/githubrepoid
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/flag/guest_ban
|
||||
|
||||
/datum/config_entry/number/id_console_jobslot_delay
|
||||
value = 30
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/inactivity_period //time in ds until a player is considered inactive
|
||||
value = 3000
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/inactivity_period/ValidateAndSet(str_val)
|
||||
. = ..()
|
||||
if(.)
|
||||
value *= 10 //documented as seconds in config.txt
|
||||
|
||||
/datum/config_entry/number/afk_period //time in ds until a player is considered inactive
|
||||
value = 3000
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/afk_period/ValidateAndSet(str_val)
|
||||
. = ..()
|
||||
if(.)
|
||||
value *= 10 //documented as seconds in config.txt
|
||||
|
||||
/datum/config_entry/flag/kick_inactive //force disconnect for inactive players
|
||||
|
||||
/datum/config_entry/flag/load_jobs_from_txt
|
||||
|
||||
/datum/config_entry/flag/forbid_singulo_possession
|
||||
|
||||
/datum/config_entry/flag/automute_on //enables automuting/spam prevention
|
||||
|
||||
/datum/config_entry/string/panic_server_name
|
||||
|
||||
/datum/config_entry/string/panic_server_name/ValidateAndSet(str_val)
|
||||
return str_val != "\[Put the name here\]" && ..()
|
||||
|
||||
/datum/config_entry/string/panic_server_address //Reconnect a player this linked server if this server isn't accepting new players
|
||||
|
||||
/datum/config_entry/string/panic_server_address/ValidateAndSet(str_val)
|
||||
return str_val != "byond://address:port" && ..()
|
||||
|
||||
/datum/config_entry/string/invoke_youtubedl
|
||||
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
|
||||
|
||||
/datum/config_entry/flag/show_irc_name
|
||||
|
||||
/datum/config_entry/flag/see_own_notes //Can players see their own admin notes
|
||||
|
||||
/datum/config_entry/number/note_fresh_days
|
||||
value = null
|
||||
min_val = 0
|
||||
integer = FALSE
|
||||
|
||||
/datum/config_entry/number/note_stale_days
|
||||
value = null
|
||||
min_val = 0
|
||||
integer = FALSE
|
||||
|
||||
/datum/config_entry/flag/maprotation
|
||||
|
||||
/datum/config_entry/number/maprotatechancedelta
|
||||
value = 0.75
|
||||
min_val = 0
|
||||
max_val = 1
|
||||
integer = FALSE
|
||||
|
||||
/datum/config_entry/number/soft_popcap
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/hard_popcap
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/extreme_popcap
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/string/soft_popcap_message
|
||||
value = "Be warned that the server is currently serving a high number of users, consider using alternative game servers."
|
||||
|
||||
/datum/config_entry/string/hard_popcap_message
|
||||
value = "The server is currently serving a high number of users, You cannot currently join. You may wait for the number of living crew to decline, observe, or find alternative servers."
|
||||
|
||||
/datum/config_entry/string/extreme_popcap_message
|
||||
value = "The server is currently serving a high number of users, find alternative servers."
|
||||
|
||||
/datum/config_entry/flag/panic_bunker // prevents people the server hasn't seen before from connecting
|
||||
|
||||
/datum/config_entry/number/notify_new_player_age // how long do we notify admins of a new player
|
||||
min_val = -1
|
||||
|
||||
/datum/config_entry/number/notify_new_player_account_age // how long do we notify admins of a new byond account
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/flag/irc_first_connection_alert // do we notify the irc channel when somebody is connecting for the first time?
|
||||
|
||||
/datum/config_entry/flag/check_randomizer
|
||||
|
||||
/datum/config_entry/string/ipintel_email
|
||||
|
||||
/datum/config_entry/string/ipintel_email/ValidateAndSet(str_val)
|
||||
return str_val != "ch@nge.me" && ..()
|
||||
|
||||
/datum/config_entry/number/ipintel_rating_bad
|
||||
value = 1
|
||||
integer = FALSE
|
||||
min_val = 0
|
||||
max_val = 1
|
||||
|
||||
/datum/config_entry/number/ipintel_save_good
|
||||
value = 12
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/ipintel_save_bad
|
||||
value = 1
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/string/ipintel_domain
|
||||
value = "check.getipintel.net"
|
||||
|
||||
/datum/config_entry/flag/aggressive_changelog
|
||||
|
||||
/datum/config_entry/flag/autoconvert_notes //if all connecting player's notes should attempt to be converted to the database
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
/datum/config_entry/flag/allow_webclient
|
||||
|
||||
/datum/config_entry/flag/webclient_only_byond_members
|
||||
|
||||
/datum/config_entry/flag/announce_admin_logout
|
||||
|
||||
/datum/config_entry/flag/announce_admin_login
|
||||
|
||||
/datum/config_entry/flag/allow_map_voting
|
||||
|
||||
/datum/config_entry/flag/generate_minimaps
|
||||
|
||||
/datum/config_entry/number/client_warn_version
|
||||
value = null
|
||||
min_val = 500
|
||||
max_val = DM_VERSION - 1
|
||||
|
||||
/datum/config_entry/string/client_warn_message
|
||||
value = "Your version of byond may have issues or be blocked from accessing this server in the future."
|
||||
|
||||
/datum/config_entry/flag/client_warn_popup
|
||||
|
||||
/datum/config_entry/number/client_error_version
|
||||
value = null
|
||||
min_val = 500
|
||||
max_val = DM_VERSION - 1
|
||||
|
||||
/datum/config_entry/string/client_error_message
|
||||
value = "Your version of byond is too old, may have issues, and is blocked from accessing this server."
|
||||
|
||||
/datum/config_entry/number/minute_topic_limit
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/second_topic_limit
|
||||
value = null
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/error_cooldown // The "cooldown" time for each occurrence of a unique error
|
||||
value = 600
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/error_limit // How many occurrences before the next will silence them
|
||||
value = 50
|
||||
|
||||
/datum/config_entry/number/error_silence_time // How long a unique error will be silenced for
|
||||
value = 6000
|
||||
|
||||
/datum/config_entry/number/error_msg_delay // How long to wait between messaging admins about occurrences of a unique error
|
||||
value = 50
|
||||
|
||||
/datum/config_entry/flag/irc_announce_new_game
|
||||
|
||||
/datum/config_entry/flag/debug_admin_hrefs
|
||||
|
||||
/datum/config_entry/number/mc_tick_rate/base_mc_tick_rate
|
||||
integer = FALSE
|
||||
value = 1
|
||||
|
||||
/datum/config_entry/number/mc_tick_rate/high_pop_mc_tick_rate
|
||||
integer = FALSE
|
||||
value = 1.1
|
||||
|
||||
/datum/config_entry/number/mc_tick_rate/high_pop_mc_mode_amount
|
||||
value = 65
|
||||
|
||||
/datum/config_entry/number/mc_tick_rate/disable_high_pop_mc_mode_amount
|
||||
value = 60
|
||||
|
||||
/datum/config_entry/number/mc_tick_rate
|
||||
abstract_type = /datum/config_entry/number/mc_tick_rate
|
||||
|
||||
/datum/config_entry/number/mc_tick_rate/ValidateAndSet(str_val)
|
||||
. = ..()
|
||||
if (.)
|
||||
Master.UpdateTickRate()
|
||||
|
||||
/datum/config_entry/flag/resume_after_initializations
|
||||
|
||||
/datum/config_entry/flag/resume_after_initializations/ValidateAndSet(str_val)
|
||||
. = ..()
|
||||
if(. && Master.current_runlevel)
|
||||
world.sleep_offline = !value
|
||||
|
||||
/datum/config_entry/number/rounds_until_hard_restart
|
||||
value = -1
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/string/default_view
|
||||
value = "15x15"
|
||||
@@ -53,6 +53,8 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
var/static/restart_clear = 0
|
||||
var/static/restart_timeout = 0
|
||||
var/static/restart_count = 0
|
||||
|
||||
var/static/random_seed
|
||||
|
||||
//current tick limit, assigned before running a subsystem.
|
||||
//used by CHECK_TICK as well so that the procs subsystems call can obey that SS's tick limits
|
||||
@@ -60,6 +62,11 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
|
||||
/datum/controller/master/New()
|
||||
// Highlander-style: there can only be one! Kill off the old and replace it with the new.
|
||||
|
||||
if(!random_seed)
|
||||
random_seed = rand(1, 1e9)
|
||||
rand_seed(random_seed)
|
||||
|
||||
var/list/_subsystems = list()
|
||||
subsystems = _subsystems
|
||||
if (Master != src)
|
||||
@@ -301,7 +308,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
continue
|
||||
|
||||
//Byond resumed us late. assume it might have to do the same next tick
|
||||
if (last_run + Ceiling(world.tick_lag * (processing * sleep_delta), world.tick_lag) < world.time)
|
||||
if (last_run + CEILING(world.tick_lag * (processing * sleep_delta), world.tick_lag) < world.time)
|
||||
sleep_delta += 1
|
||||
|
||||
sleep_delta = MC_AVERAGE_FAST(sleep_delta, 1) //decay sleep_delta
|
||||
|
||||
@@ -10,11 +10,13 @@ SUBSYSTEM_DEF(blackbox)
|
||||
var/sealed = FALSE //time to stop tracking stats?
|
||||
var/list/research_levels = list() //list of highest tech levels attained that isn't lost lost by destruction of RD computers
|
||||
var/list/versions = list("time_dilation_current" = 2,
|
||||
"science_techweb_unlock" = 2) //associative list of any feedback variables that have had their format changed since creation and their current version, remember to update this
|
||||
"science_techweb_unlock" = 2,
|
||||
"antagonists" = 3) //associative list of any feedback variables that have had their format changed since creation and their current version, remember to update this
|
||||
|
||||
|
||||
/datum/controller/subsystem/blackbox/Initialize()
|
||||
triggertime = world.time
|
||||
record_feedback("amount", "random_seed", Master.random_seed)
|
||||
. = ..()
|
||||
|
||||
//poll population
|
||||
@@ -225,7 +227,10 @@ Versioning
|
||||
var/pos = length(FV.json["data"]) + 1
|
||||
FV.json["data"]["[pos]"] = list() //in 512 "pos" can be replaced with "[FV.json["data"].len+1]"
|
||||
for(var/i in data)
|
||||
FV.json["data"]["[pos]"]["[i]"] = "[data[i]]" //and here with "[FV.json["data"].len]"
|
||||
if(islist(data[i]))
|
||||
FV.json["data"]["[pos]"]["[i]"] = data[i] //and here with "[FV.json["data"].len]"
|
||||
else
|
||||
FV.json["data"]["[pos]"]["[i]"] = "[data[i]]"
|
||||
else
|
||||
CRASH("Invalid feedback key_type: [key_type]")
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ SUBSYSTEM_DEF(parallax)
|
||||
return
|
||||
continue
|
||||
var/atom/movable/A = C.eye
|
||||
if(!A)
|
||||
return
|
||||
if(!istype(A))
|
||||
continue
|
||||
for (A; isloc(A.loc) && !isturf(A.loc); A = A.loc);
|
||||
|
||||
if(A != C.movingmob)
|
||||
|
||||
@@ -20,7 +20,7 @@ SUBSYSTEM_DEF(research)
|
||||
var/list/techweb_point_items = list() //path = value
|
||||
var/list/errored_datums = list()
|
||||
//----------------------------------------------
|
||||
var/single_server_income = 40.7
|
||||
var/single_server_income = 54.3
|
||||
var/multiserver_calculation = FALSE
|
||||
var/last_income = 0
|
||||
//^^^^^^^^ ALL OF THESE ARE PER SECOND! ^^^^^^^^
|
||||
|
||||
@@ -400,7 +400,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
if(M.request(getDock(destination)))
|
||||
return 2
|
||||
else
|
||||
if(M.dock(getDock(destination)) != DOCKING_SUCCESS)
|
||||
if(M.initiate_docking(getDock(destination)) != DOCKING_SUCCESS)
|
||||
return 2
|
||||
return 0 //dock successful
|
||||
|
||||
@@ -415,7 +415,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
if(M.request(D))
|
||||
return 2
|
||||
else
|
||||
if(M.dock(D) != DOCKING_SUCCESS)
|
||||
if(M.initiate_docking(D) != DOCKING_SUCCESS)
|
||||
return 2
|
||||
return 0 //dock successful
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ SUBSYSTEM_DEF(throwing)
|
||||
last_move = world.time
|
||||
|
||||
//calculate how many tiles to move, making up for any missed ticks.
|
||||
var/tilestomove = Ceiling(min(((((world.time+world.tick_lag) - start_time + delayed_time) * speed) - (dist_travelled ? dist_travelled : -1)), speed*MAX_TICKS_TO_MAKE_UP) * (world.tick_lag * SSthrowing.wait))
|
||||
var/tilestomove = CEILING(min(((((world.time+world.tick_lag) - start_time + delayed_time) * speed) - (dist_travelled ? dist_travelled : -1)), speed*MAX_TICKS_TO_MAKE_UP) * (world.tick_lag * SSthrowing.wait), 1)
|
||||
while (tilestomove-- > 0)
|
||||
if ((dist_travelled >= maxrange || AM.loc == target_turf) && AM.has_gravity(AM.loc))
|
||||
finalize()
|
||||
|
||||
@@ -398,204 +398,6 @@ SUBSYSTEM_DEF(ticker)
|
||||
var/mob/living/L = I
|
||||
L.notransform = FALSE
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/declare_completion()
|
||||
set waitfor = FALSE
|
||||
var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED
|
||||
var/num_survivors = 0
|
||||
var/num_escapees = 0
|
||||
var/num_shuttle_escapees = 0
|
||||
var/list/successfulCrew = list()
|
||||
var/list/miscreants = list()
|
||||
|
||||
to_chat(world, "<BR><BR><BR><FONT size=3><B>The round has ended.</B></FONT>")
|
||||
if(LAZYLEN(GLOB.round_end_notifiees))
|
||||
send2irc("Notice", "[GLOB.round_end_notifiees.Join(", ")] the round has ended.")
|
||||
|
||||
/* var/nocredits = config.no_credits_round_end
|
||||
for(var/client/C in GLOB.clients)
|
||||
if(!C.credits && !nocredits)
|
||||
C.RollCredits()
|
||||
C.playtitlemusic(40)*/
|
||||
|
||||
//Player status report
|
||||
for(var/i in GLOB.mob_list)
|
||||
var/mob/Player = i
|
||||
if(Player.mind && !isnewplayer(Player))
|
||||
if(Player.stat != DEAD && !isbrain(Player))
|
||||
num_survivors++
|
||||
if(station_evacuated) //If the shuttle has already left the station
|
||||
var/list/area/shuttle_areas
|
||||
if(SSshuttle && SSshuttle.emergency)
|
||||
shuttle_areas = SSshuttle.emergency.shuttle_areas
|
||||
if(!Player.onCentCom() && !Player.onSyndieBase())
|
||||
to_chat(Player, "<font color='blue'><b>You managed to survive, but were marooned on [station_name()]...</b></FONT>")
|
||||
else
|
||||
num_escapees++
|
||||
to_chat(Player, "<font color='green'><b>You managed to survive the events on [station_name()] as [Player.real_name].</b></FONT>")
|
||||
if(shuttle_areas[get_area(Player)])
|
||||
num_shuttle_escapees++
|
||||
else
|
||||
to_chat(Player, "<font color='green'><b>You managed to survive the events on [station_name()] as [Player.real_name].</b></FONT>")
|
||||
else
|
||||
to_chat(Player, "<font color='red'><b>You did not survive the events on [station_name()]...</b></FONT>")
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//Round statistics report
|
||||
var/datum/station_state/end_state = new /datum/station_state()
|
||||
end_state.count()
|
||||
var/station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100)
|
||||
|
||||
to_chat(world, "<BR>[GLOB.TAB]Shift Duration: <B>[DisplayTimeText(world.time - SSticker.round_start_time)]</B>")
|
||||
to_chat(world, "<BR>[GLOB.TAB]Station Integrity: <B>[mode.station_was_nuked ? "<font color='red'>Destroyed</font>" : "[station_integrity]%"]</B>")
|
||||
if(mode.station_was_nuked)
|
||||
SSticker.news_report = STATION_DESTROYED_NUKE
|
||||
var/total_players = GLOB.joined_player_list.len
|
||||
if(total_players)
|
||||
to_chat(world, "<BR>[GLOB.TAB]Total Population: <B>[total_players]</B>")
|
||||
if(station_evacuated)
|
||||
to_chat(world, "<BR>[GLOB.TAB]Evacuation Rate: <B>[num_escapees] ([PERCENT(num_escapees/total_players)]%)</B>")
|
||||
to_chat(world, "<BR>[GLOB.TAB](on emergency shuttle): <B>[num_shuttle_escapees] ([PERCENT(num_shuttle_escapees/total_players)]%)</B>")
|
||||
news_report = STATION_EVACUATED
|
||||
if(SSshuttle.emergency.is_hijacked())
|
||||
news_report = SHUTTLE_HIJACK
|
||||
to_chat(world, "<BR>[GLOB.TAB]Survival Rate: <B>[num_survivors] ([PERCENT(num_survivors/total_players)]%)</B>")
|
||||
to_chat(world, "<BR>")
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//Silicon laws report
|
||||
for (var/i in GLOB.ai_list)
|
||||
var/mob/living/silicon/ai/aiPlayer = i
|
||||
if (aiPlayer.stat != DEAD && aiPlayer.mind)
|
||||
to_chat(world, "<b>[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws at the end of the round were:</b>")
|
||||
aiPlayer.show_laws(1)
|
||||
else if (aiPlayer.mind) //if the dead ai has a mind, use its key instead
|
||||
to_chat(world, "<b>[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws when it was deactivated were:</b>")
|
||||
aiPlayer.show_laws(1)
|
||||
|
||||
to_chat(world, "<b>Total law changes: [aiPlayer.law_change_counter]</b>")
|
||||
|
||||
if (aiPlayer.connected_robots.len)
|
||||
var/robolist = "<b>[aiPlayer.real_name]'s minions were:</b> "
|
||||
for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots)
|
||||
if(robo.mind)
|
||||
robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.mind.key]), ":" (Played by: [robo.mind.key]), "]"
|
||||
to_chat(world, "[robolist]")
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
for (var/mob/living/silicon/robot/robo in GLOB.silicon_mobs)
|
||||
if (!robo.connected_ai && robo.mind)
|
||||
if (robo.stat != DEAD)
|
||||
to_chat(world, "<b>[robo.name] (Played by: [robo.mind.key]) survived as an AI-less borg! Its laws were:</b>")
|
||||
else
|
||||
to_chat(world, "<b>[robo.name] (Played by: [robo.mind.key]) was unable to survive the rigors of being a cyborg without an AI. Its laws were:</b>")
|
||||
|
||||
if(robo) //How the hell do we lose robo between here and the world messages directly above this?
|
||||
robo.laws.show_laws(world)
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
mode.declare_completion()//To declare normal completion.
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//calls auto_declare_completion_* for all modes
|
||||
for(var/handler in typesof(/datum/game_mode/proc))
|
||||
if (findtext("[handler]","auto_declare_completion_"))
|
||||
call(mode, handler)(force_ending)
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
if(CONFIG_GET(string/cross_server_address))
|
||||
send_news_report()
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//Print a list of antagonists to the server log
|
||||
var/list/total_antagonists = list()
|
||||
//Look into all mobs in world, dead or alive
|
||||
for(var/datum/mind/Mind in minds)
|
||||
var/temprole = Mind.special_role
|
||||
if(temprole) //if they are an antagonist of some sort.
|
||||
if(temprole in total_antagonists) //If the role exists already, add the name to it
|
||||
total_antagonists[temprole] += ", [Mind.name]([Mind.key])"
|
||||
else
|
||||
total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob
|
||||
total_antagonists[temprole] += ": [Mind.name]([Mind.key])"
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//Now print them all into the log!
|
||||
log_game("Antagonists at round end were...")
|
||||
for(var/i in total_antagonists)
|
||||
log_game("[i]s[total_antagonists[i]].")
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
for(var/datum/mind/crewMind in minds)
|
||||
if(!crewMind.current || !crewMind.objectives.len)
|
||||
continue
|
||||
for(var/datum/objective/miscreant/MO in crewMind.objectives)
|
||||
miscreants += "<B>[crewMind.current.real_name]</B> (Played by: <B>[crewMind.key]</B>)<BR><B>Objective</B>: [MO.explanation_text] <font color='grey'>(Optional)</font>"
|
||||
for(var/datum/objective/crew/CO in crewMind.objectives)
|
||||
if(CO.check_completion())
|
||||
to_chat(crewMind.current, "<br><B>Your optional objective</B>: [CO.explanation_text] <font color='green'><B>Success!</B></font>")
|
||||
successfulCrew += "<B>[crewMind.current.real_name]</B> (Played by: <B>[crewMind.key]</B>)<BR><B>Objective</B>: [CO.explanation_text] <font color='green'><B>Success!</B></font> <font color='grey'>(Optional)</font>"
|
||||
else
|
||||
to_chat(crewMind.current, "<br><B>Your optional objective</B>: [CO.explanation_text] <font color='red'><B>Failed.</B></font>")
|
||||
|
||||
if (successfulCrew.len)
|
||||
var/completedObjectives = "<B>The following crew members completed their Crew Objectives:</B><BR>"
|
||||
for(var/i in successfulCrew)
|
||||
completedObjectives += "[i]<BR>"
|
||||
to_chat(world, "[completedObjectives]<BR>")
|
||||
else
|
||||
if(CONFIG_GET(flag/allow_crew_objectives))
|
||||
to_chat(world, "<B>Nobody completed their Crew Objectives!</B><BR>")
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
if (miscreants.len)
|
||||
var/miscreantObjectives = "<B>The following crew members were miscreants:</B><BR>"
|
||||
for(var/i in miscreants)
|
||||
miscreantObjectives += "[i]<BR>"
|
||||
to_chat(world, "[miscreantObjectives]<BR>")
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
mode.declare_station_goal_completion()
|
||||
|
||||
CHECK_TICK
|
||||
//medals, placed far down so that people can actually see the commendations.
|
||||
if(GLOB.commendations.len)
|
||||
to_chat(world, "<b><font size=3>Medal Commendations:</font></b>")
|
||||
for (var/com in GLOB.commendations)
|
||||
to_chat(world, com)
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//Collects persistence features
|
||||
if(mode.allow_persistence_save)
|
||||
SSpersistence.CollectData()
|
||||
|
||||
//stop collecting feedback during grifftime
|
||||
SSblackbox.Seal()
|
||||
|
||||
sleep(50)
|
||||
ready_for_reboot = TRUE
|
||||
standard_reboot()
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/standard_reboot()
|
||||
if(ready_for_reboot)
|
||||
if(mode.station_was_nuked)
|
||||
Reboot("Station destroyed by Nuclear Device.", "nuke")
|
||||
else
|
||||
Reboot("Round ended.", "proper completion")
|
||||
else
|
||||
CRASH("Attempted standard reboot without ticker roundend completion")
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/send_tip_of_the_round()
|
||||
var/m
|
||||
if(selected_tip)
|
||||
|
||||
@@ -206,6 +206,7 @@ SUBSYSTEM_DEF(vote)
|
||||
var/datum/action/vote/V = new
|
||||
if(question)
|
||||
V.name = "Vote: [question]"
|
||||
C.player_details.player_actions += V
|
||||
V.Grant(C.mob)
|
||||
generated_actions += V
|
||||
return 1
|
||||
@@ -299,6 +300,7 @@ SUBSYSTEM_DEF(vote)
|
||||
for(var/v in generated_actions)
|
||||
var/datum/action/vote/V = v
|
||||
if(!QDELETED(V))
|
||||
V.remove_from_client()
|
||||
V.Remove(V.owner)
|
||||
generated_actions = list()
|
||||
|
||||
@@ -318,7 +320,16 @@ SUBSYSTEM_DEF(vote)
|
||||
/datum/action/vote/Trigger()
|
||||
if(owner)
|
||||
owner.vote()
|
||||
remove_from_client()
|
||||
Remove(owner)
|
||||
|
||||
/datum/action/vote/IsAvailable()
|
||||
return 1
|
||||
|
||||
/datum/action/vote/proc/remove_from_client()
|
||||
if(owner.client)
|
||||
owner.client.player_details.player_actions -= src
|
||||
else if(owner.ckey)
|
||||
var/datum/player_details/P = GLOB.player_details[owner.ckey]
|
||||
if(P)
|
||||
P.player_actions -= src
|
||||
@@ -477,6 +477,8 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/spell_action/spell
|
||||
|
||||
/datum/action/spell_action/spell/IsAvailable()
|
||||
if(!target)
|
||||
return FALSE
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
/datum/action/item_action/zoom_speed_action
|
||||
name = "Toggle Zooming Speed"
|
||||
icon_icon = 'icons/mob/actions/actions_spells.dmi'
|
||||
button_icon_state = "projectile"
|
||||
background_icon_state = "bg_tech"
|
||||
|
||||
/datum/action/item_action/zoom_lock_action
|
||||
name = "Switch Zoom Mode"
|
||||
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
||||
button_icon_state = "zoom_mode"
|
||||
background_icon_state = "bg_tech"
|
||||
+3
-26
@@ -373,32 +373,9 @@
|
||||
ion = list()
|
||||
|
||||
/datum/ai_laws/proc/show_laws(who)
|
||||
|
||||
if (devillaws && devillaws.len) //Yes, devil laws go in FRONT of zeroth laws, as the devil must still obey it's ban/obligation.
|
||||
for(var/i in devillaws)
|
||||
to_chat(who, "666. [i]")
|
||||
|
||||
if (zeroth)
|
||||
to_chat(who, "0. [zeroth]")
|
||||
|
||||
for (var/index = 1, index <= ion.len, index++)
|
||||
var/law = ion[index]
|
||||
var/num = ionnum()
|
||||
to_chat(who, "[num]. [law]")
|
||||
|
||||
var/number = 1
|
||||
for (var/index = 1, index <= inherent.len, index++)
|
||||
var/law = inherent[index]
|
||||
|
||||
if (length(law) > 0)
|
||||
to_chat(who, "[number]. [law]")
|
||||
number++
|
||||
|
||||
for (var/index = 1, index <= supplied.len, index++)
|
||||
var/law = supplied[index]
|
||||
if (length(law) > 0)
|
||||
to_chat(who, "[number]. [law]")
|
||||
number++
|
||||
var/list/printable_laws = get_law_list(include_zeroth = TRUE)
|
||||
for(var/law in printable_laws)
|
||||
to_chat(who,law)
|
||||
|
||||
/datum/ai_laws/proc/clear_zeroth_law(force) //only removes zeroth from antag ai if force is 1
|
||||
if(force)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/datum/antagonist/abductor
|
||||
name = "Abductor"
|
||||
roundend_category = "abductors"
|
||||
job_rank = ROLE_ABDUCTOR
|
||||
var/datum/objective_team/abductor_team/team
|
||||
var/datum/team/abductor_team/team
|
||||
var/sub_role
|
||||
var/outfit
|
||||
var/landmark_type
|
||||
@@ -19,7 +20,7 @@
|
||||
landmark_type = /obj/effect/landmark/abductor/scientist
|
||||
greet_text = "Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve."
|
||||
|
||||
/datum/antagonist/abductor/create_team(datum/objective_team/abductor_team/new_team)
|
||||
/datum/antagonist/abductor/create_team(datum/team/abductor_team/new_team)
|
||||
if(!new_team)
|
||||
return
|
||||
if(!istype(new_team))
|
||||
@@ -70,3 +71,65 @@
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
var/datum/species/abductor/A = H.dna.species
|
||||
A.scientist = TRUE
|
||||
|
||||
|
||||
/datum/team/abductor_team
|
||||
member_name = "abductor"
|
||||
var/team_number
|
||||
var/list/datum/mind/abductees = list()
|
||||
|
||||
/datum/team/abductor_team/is_solo()
|
||||
return FALSE
|
||||
|
||||
/datum/team/abductor_team/proc/add_objective(datum/objective/O)
|
||||
O.team = src
|
||||
O.update_explanation_text()
|
||||
objectives += O
|
||||
|
||||
/datum/team/abductor_team/roundend_report()
|
||||
var/list/result = list()
|
||||
|
||||
var/won = TRUE
|
||||
for(var/datum/objective/O in objectives)
|
||||
if(!O.check_completion())
|
||||
won = FALSE
|
||||
if(won)
|
||||
result += "<span class='greentext big'>[name] team fulfilled its mission!</span>"
|
||||
else
|
||||
result += "<span class='redtext big'>[name] team failed its mission.</span>"
|
||||
|
||||
result += "<span class='header'>The abductors of [name] were:</span>"
|
||||
for(var/datum/mind/abductor_mind in members)
|
||||
result += printplayer(abductor_mind)
|
||||
result += printobjectives(abductor_mind)
|
||||
|
||||
return result.Join("<br>")
|
||||
|
||||
|
||||
/datum/antagonist/abductee
|
||||
name = "Abductee"
|
||||
roundend_category = "abductees"
|
||||
|
||||
/datum/antagonist/abductee/on_gain()
|
||||
give_objective()
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/abductee/greet()
|
||||
to_chat(owner, "<span class='warning'><b>Your mind snaps!</b></span>")
|
||||
to_chat(owner, "<big><span class='warning'><b>You can't remember how you got here...</b></span></big>")
|
||||
owner.announce_objectives()
|
||||
|
||||
/datum/antagonist/abductee/proc/give_objective()
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
if(istype(H))
|
||||
H.gain_trauma_type(BRAIN_TRAUMA_MILD)
|
||||
var/objtype = (prob(75) ? /datum/objective/abductee/random : pick(subtypesof(/datum/objective/abductee/) - /datum/objective/abductee/random))
|
||||
var/datum/objective/abductee/O = new objtype()
|
||||
objectives += O
|
||||
owner.objectives += objectives
|
||||
|
||||
/datum/antagonist/abductee/apply_innate_effects(mob/living/mob_override)
|
||||
SSticker.mode.update_abductor_icons_added(mob_override ? mob_override.mind : owner)
|
||||
|
||||
/datum/antagonist/abductee/remove_innate_effects(mob/living/mob_override)
|
||||
SSticker.mode.update_abductor_icons_removed(mob_override ? mob_override.mind : owner)
|
||||
@@ -2,6 +2,8 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
|
||||
/datum/antagonist
|
||||
var/name = "Antagonist"
|
||||
var/roundend_category = "other antagonists" //Section of roundend report, datums with same category will be displayed together, also default header for the section
|
||||
var/show_in_roundend = TRUE //Set to false to hide the antagonists from roundend report
|
||||
var/datum/mind/owner //Mind that owns this datum
|
||||
var/silent = FALSE //Silent will prevent the gain/lose texts to show
|
||||
var/can_coexist_with_others = TRUE //Whether or not the person will be able to have more than one datum
|
||||
@@ -9,6 +11,7 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
var/delete_on_mind_deletion = TRUE
|
||||
var/job_rank
|
||||
var/replace_banned = TRUE //Should replace jobbaned player with ghosts if granted.
|
||||
var/list/objectives = list()
|
||||
|
||||
/datum/antagonist/New(datum/mind/new_owner)
|
||||
GLOB.antagonists += src
|
||||
@@ -46,7 +49,7 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
return
|
||||
|
||||
//Assign default team and creates one for one of a kind team antagonists
|
||||
/datum/antagonist/proc/create_team(datum/objective_team/team)
|
||||
/datum/antagonist/proc/create_team(datum/team/team)
|
||||
return
|
||||
|
||||
//Proc called when the datum is given to a mind.
|
||||
@@ -81,7 +84,7 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
LAZYREMOVE(owner.antag_datums, src)
|
||||
if(!silent && owner.current)
|
||||
farewell()
|
||||
var/datum/objective_team/team = get_team()
|
||||
var/datum/team/team = get_team()
|
||||
if(team)
|
||||
team.remove_member(owner)
|
||||
qdel(src)
|
||||
@@ -96,9 +99,62 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
/datum/antagonist/proc/get_team()
|
||||
return
|
||||
|
||||
//Individual roundend report
|
||||
/datum/antagonist/proc/roundend_report()
|
||||
var/list/report = list()
|
||||
|
||||
if(!owner)
|
||||
CRASH("antagonist datum without owner")
|
||||
|
||||
report += printplayer(owner)
|
||||
|
||||
var/objectives_complete = TRUE
|
||||
if(owner.objectives.len)
|
||||
report += printobjectives(owner)
|
||||
for(var/datum/objective/objective in owner.objectives)
|
||||
if(!objective.check_completion())
|
||||
objectives_complete = FALSE
|
||||
break
|
||||
|
||||
if(owner.objectives.len == 0 || objectives_complete)
|
||||
report += "<span class='greentext big'>The [name] was successful!</span>"
|
||||
else
|
||||
report += "<span class='redtext big'>The [name] has failed!</span>"
|
||||
|
||||
return report.Join("<br>")
|
||||
|
||||
//Displayed at the start of roundend_category section, default to roundend_category header
|
||||
/datum/antagonist/proc/roundend_report_header()
|
||||
return "<span class='header'>The [roundend_category] were:</span><br>"
|
||||
|
||||
//Displayed at the end of roundend_category section
|
||||
/datum/antagonist/proc/roundend_report_footer()
|
||||
return
|
||||
|
||||
//Should probably be on ticker or job ss ?
|
||||
/proc/get_antagonists(antag_type,specific = FALSE)
|
||||
. = list()
|
||||
for(var/datum/antagonist/A in GLOB.antagonists)
|
||||
if(!specific && istype(A,antag_type) || specific && A.type == antag_type)
|
||||
. += A.owner
|
||||
. += A.owner
|
||||
|
||||
|
||||
|
||||
//This datum will autofill the name with special_role
|
||||
//Used as placeholder for minor antagonists, please create proper datums for these
|
||||
/datum/antagonist/auto_custom
|
||||
|
||||
/datum/antagonist/auto_custom/on_gain()
|
||||
..()
|
||||
name = owner.special_role
|
||||
//Add all objectives not already owned by other datums to this one.
|
||||
var/list/already_registered_objectives = list()
|
||||
for(var/datum/antagonist/A in owner.antag_datums)
|
||||
if(A == src)
|
||||
continue
|
||||
else
|
||||
already_registered_objectives |= A.objectives
|
||||
objectives = owner.objectives - already_registered_objectives
|
||||
|
||||
//This one is created by admin tools for custom objectives
|
||||
/datum/antagonist/custom
|
||||
@@ -2,12 +2,12 @@
|
||||
name = "Brother"
|
||||
job_rank = ROLE_BROTHER
|
||||
var/special_role = "blood brother"
|
||||
var/datum/objective_team/brother_team/team
|
||||
var/datum/team/brother_team/team
|
||||
|
||||
/datum/antagonist/brother/New(datum/mind/new_owner)
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/brother/create_team(datum/objective_team/brother_team/new_team)
|
||||
/datum/antagonist/brother/create_team(datum/team/brother_team/new_team)
|
||||
if(!new_team)
|
||||
return
|
||||
if(!istype(new_team))
|
||||
@@ -55,3 +55,71 @@
|
||||
|
||||
/datum/antagonist/brother/proc/finalize_brother()
|
||||
SSticker.mode.update_brother_icons_added(owner)
|
||||
|
||||
|
||||
/datum/team/brother_team
|
||||
name = "brotherhood"
|
||||
member_name = "blood brother"
|
||||
var/meeting_area
|
||||
|
||||
/datum/team/brother_team/is_solo()
|
||||
return FALSE
|
||||
|
||||
/datum/team/brother_team/proc/update_name()
|
||||
var/list/last_names = list()
|
||||
for(var/datum/mind/M in members)
|
||||
var/list/split_name = splittext(M.name," ")
|
||||
last_names += split_name[split_name.len]
|
||||
|
||||
name = last_names.Join(" & ")
|
||||
|
||||
/datum/team/brother_team/roundend_report()
|
||||
var/list/parts = list()
|
||||
|
||||
parts += "<span class='header'>The blood brothers of [name] were:</span>"
|
||||
for(var/datum/mind/M in members)
|
||||
parts += printplayer(M)
|
||||
var/win = TRUE
|
||||
var/objective_count = 1
|
||||
for(var/datum/objective/objective in objectives)
|
||||
if(objective.check_completion())
|
||||
parts += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
|
||||
else
|
||||
parts += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
win = FALSE
|
||||
objective_count++
|
||||
if(win)
|
||||
parts += "<span class='greentext'>The blood brothers were successful!</span>"
|
||||
else
|
||||
parts += "<span class='redtext'>The blood brothers have failed!</span>"
|
||||
|
||||
return "<div class='panel redborder'>[parts.Join("<br>")]</div>"
|
||||
|
||||
/datum/team/brother_team/proc/add_objective(datum/objective/O, needs_target = FALSE)
|
||||
O.team = src
|
||||
if(needs_target)
|
||||
O.find_target()
|
||||
O.update_explanation_text()
|
||||
objectives += O
|
||||
|
||||
/datum/team/brother_team/proc/forge_brother_objectives()
|
||||
objectives = list()
|
||||
var/is_hijacker = prob(10)
|
||||
for(var/i = 1 to max(1, CONFIG_GET(number/brother_objectives_amount) + (members.len > 2) - is_hijacker))
|
||||
forge_single_objective()
|
||||
if(is_hijacker)
|
||||
if(!locate(/datum/objective/hijack) in objectives)
|
||||
add_objective(new/datum/objective/hijack)
|
||||
else if(!locate(/datum/objective/escape) in objectives)
|
||||
add_objective(new/datum/objective/escape)
|
||||
|
||||
/datum/team/brother_team/proc/forge_single_objective()
|
||||
if(prob(50))
|
||||
if(LAZYLEN(active_ais()) && prob(100/GLOB.joined_player_list.len))
|
||||
add_objective(new/datum/objective/destroy, TRUE)
|
||||
else if(prob(30))
|
||||
add_objective(new/datum/objective/maroon, TRUE)
|
||||
else
|
||||
add_objective(new/datum/objective/assassinate, TRUE)
|
||||
else
|
||||
add_objective(new/datum/objective/steal, TRUE)
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
/datum/antagonist/changeling
|
||||
name = "Changeling"
|
||||
roundend_category = "changelings"
|
||||
job_rank = ROLE_CHANGELING
|
||||
|
||||
var/you_are_greet = TRUE
|
||||
var/give_objectives = TRUE
|
||||
var/list/objectives = list()
|
||||
var/team_mode = FALSE //Should assign team objectives ?
|
||||
|
||||
//Changeling Stuff
|
||||
@@ -223,7 +223,8 @@
|
||||
if(verbose)
|
||||
to_chat(user, "<span class='warning'>[target] is not compatible with our biology.</span>")
|
||||
return
|
||||
if((target.disabilities & NOCLONE) || (target.disabilities & HUSK))
|
||||
|
||||
if((target.has_disability(DISABILITY_NOCLONE)) || (target.has_disability(DISABILITY_NOCLONE)))
|
||||
if(verbose)
|
||||
to_chat(user, "<span class='warning'>DNA of [target] is ruined beyond usability!</span>")
|
||||
return
|
||||
@@ -478,4 +479,35 @@
|
||||
/datum/antagonist/changeling/xenobio
|
||||
name = "Xenobio Changeling"
|
||||
give_objectives = FALSE
|
||||
show_in_roundend = FALSE //These are here for admin tracking purposes only
|
||||
you_are_greet = FALSE
|
||||
|
||||
/datum/antagonist/changeling/roundend_report()
|
||||
var/list/parts = list()
|
||||
|
||||
var/changelingwin = 1
|
||||
if(!owner.current)
|
||||
changelingwin = 0
|
||||
|
||||
parts += printplayer(owner)
|
||||
|
||||
//Removed sanity if(changeling) because we -want- a runtime to inform us that the changelings list is incorrect and needs to be fixed.
|
||||
parts += "<b>Changeling ID:</b> [changelingID]."
|
||||
parts += "<b>Genomes Extracted:</b> [absorbedcount]"
|
||||
parts += " "
|
||||
if(objectives.len)
|
||||
var/count = 1
|
||||
for(var/datum/objective/objective in objectives)
|
||||
if(objective.check_completion())
|
||||
parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='greentext'>Success!</b></span>"
|
||||
else
|
||||
parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
changelingwin = 0
|
||||
count++
|
||||
|
||||
if(changelingwin)
|
||||
parts += "<span class='greentext'>The changeling was successful!</span>"
|
||||
else
|
||||
parts += "<span class='redtext'>The changeling has failed.</span>"
|
||||
|
||||
return parts.Join("<br>")
|
||||
@@ -1,8 +1,11 @@
|
||||
//CLOCKCULT PROOF OF CONCEPT
|
||||
/datum/antagonist/clockcult
|
||||
name = "Clock Cultist"
|
||||
var/datum/action/innate/hierophant/hierophant_network = new()
|
||||
roundend_category = "clock cultists"
|
||||
job_rank = ROLE_SERVANT_OF_RATVAR
|
||||
var/datum/action/innate/hierophant/hierophant_network = new()
|
||||
var/datum/team/clockcult/clock_team
|
||||
var/make_team = TRUE //This should be only false for tutorial scarabs
|
||||
|
||||
/datum/antagonist/clockcult/silent
|
||||
silent = TRUE
|
||||
@@ -11,6 +14,22 @@
|
||||
qdel(hierophant_network)
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/clockcult/get_team()
|
||||
return clock_team
|
||||
|
||||
/datum/antagonist/clockcult/create_team(datum/team/clockcult/new_team)
|
||||
if(!new_team && make_team)
|
||||
//TODO blah blah same as the others, allow multiple
|
||||
for(var/datum/antagonist/clockcult/H in GLOB.antagonists)
|
||||
if(H.clock_team)
|
||||
clock_team = H.clock_team
|
||||
return
|
||||
clock_team = new /datum/team/clockcult
|
||||
return
|
||||
if(make_team && !istype(new_team))
|
||||
stack_trace("Wrong team type passed to [type] initialization.")
|
||||
clock_team = new_team
|
||||
|
||||
/datum/antagonist/clockcult/can_be_owned(datum/mind/new_owner)
|
||||
. = ..()
|
||||
if(.)
|
||||
@@ -156,7 +175,7 @@
|
||||
SSticker.mode.servants_of_ratvar -= owner
|
||||
SSticker.mode.update_servant_icons_removed(owner)
|
||||
if(!silent)
|
||||
owner.current.visible_message("<span class='big'>[owner] seems to have remembered their true allegiance!</span>", ignored_mob = owner.current)
|
||||
owner.current.visible_message("<span class='deconversion_message'>[owner] seems to have remembered their true allegiance!</span>", ignored_mob = owner.current)
|
||||
to_chat(owner, "<span class='userdanger'>A cold, cold darkness flows through your mind, extinguishing the Justiciar's light and all of your memories as his servant.</span>")
|
||||
owner.current.log_message("<font color=#BE8700>Has renounced the cult of Ratvar!</font>", INDIVIDUAL_ATTACK_LOG)
|
||||
owner.wipe_memory()
|
||||
@@ -164,3 +183,35 @@
|
||||
if(iscyborg(owner.current))
|
||||
to_chat(owner.current, "<span class='warning'>Despite your freedom from Ratvar's influence, you are still irreparably damaged and no longer possess certain functions such as AI linking.</span>")
|
||||
. = ..()
|
||||
|
||||
|
||||
/datum/team/clockcult
|
||||
name = "Clockcult"
|
||||
var/list/objective
|
||||
var/datum/mind/eminence
|
||||
|
||||
/datum/team/clockcult/proc/check_clockwork_victory()
|
||||
if(GLOB.clockwork_gateway_activated)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/team/clockcult/roundend_report()
|
||||
var/list/parts = list()
|
||||
|
||||
if(check_clockwork_victory())
|
||||
parts += "<span class='greentext big'>Ratvar's servants defended the Ark until its activation!</span>"
|
||||
else
|
||||
parts += "<span class='redtext big'>The Ark was destroyed! Ratvar will rust away for all eternity!</span>"
|
||||
parts += " "
|
||||
parts += "<b>The servants' objective was:</b> [CLOCKCULT_OBJECTIVE]."
|
||||
parts += "<b>Construction Value(CV)</b> was: <b>[GLOB.clockwork_construction_value]</b>"
|
||||
for(var/i in SSticker.scripture_states)
|
||||
if(i != SCRIPTURE_DRIVER)
|
||||
parts += "<b>[i] scripture</b> was: <b>[SSticker.scripture_states[i] ? "UN":""]LOCKED</b>"
|
||||
if(eminence)
|
||||
parts += "<span class='header'>The Eminence was:</span> [printplayer(eminence)]"
|
||||
if(members.len)
|
||||
parts += "<span class='header'>Ratvar's servants were:</span>"
|
||||
parts += printplayerlist(members - eminence)
|
||||
|
||||
return "<div class='panel clockborder'>[parts.Join("<br>")]</div>"
|
||||
+197
-62
@@ -2,84 +2,103 @@
|
||||
|
||||
/datum/antagonist/cult
|
||||
name = "Cultist"
|
||||
roundend_category = "cultists"
|
||||
var/datum/action/innate/cult/comm/communion = new
|
||||
var/datum/action/innate/cult/mastervote/vote = new
|
||||
job_rank = ROLE_CULTIST
|
||||
var/ignore_implant = FALSE
|
||||
var/give_equipment = FALSE
|
||||
|
||||
var/datum/team/cult/cult_team
|
||||
|
||||
/datum/antagonist/cult/get_team()
|
||||
return cult_team
|
||||
|
||||
/datum/antagonist/cult/create_team(datum/team/cult/new_team)
|
||||
if(!new_team)
|
||||
//todo remove this and allow admin buttons to create more than one cult
|
||||
for(var/datum/antagonist/cult/H in GLOB.antagonists)
|
||||
if(H.cult_team)
|
||||
cult_team = H.cult_team
|
||||
return
|
||||
cult_team = new /datum/team/cult
|
||||
cult_team.setup_objectives()
|
||||
return
|
||||
if(!istype(new_team))
|
||||
stack_trace("Wrong team type passed to [type] initialization.")
|
||||
cult_team = new_team
|
||||
|
||||
/datum/antagonist/cult/proc/add_objectives()
|
||||
objectives |= cult_team.objectives
|
||||
owner.objectives |= objectives
|
||||
|
||||
/datum/antagonist/cult/proc/remove_objectives()
|
||||
owner.objectives -= objectives
|
||||
|
||||
/datum/antagonist/cult/Destroy()
|
||||
QDEL_NULL(communion)
|
||||
QDEL_NULL(vote)
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/cult/proc/add_objectives()
|
||||
var/list/target_candidates = list()
|
||||
for(var/mob/living/carbon/human/player in GLOB.player_list)
|
||||
if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && !is_convertable_to_cult(player) && (player != owner) && player.stat != DEAD)
|
||||
target_candidates += player.mind
|
||||
if(target_candidates.len == 0)
|
||||
message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.")
|
||||
for(var/mob/living/carbon/human/player in GLOB.player_list)
|
||||
if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && (player != owner) && player.stat != DEAD)
|
||||
target_candidates += player.mind
|
||||
listclearnulls(target_candidates)
|
||||
if(LAZYLEN(target_candidates))
|
||||
GLOB.sac_mind = pick(target_candidates)
|
||||
if(!GLOB.sac_mind)
|
||||
message_admins("Cult Sacrifice: ERROR - Null target chosen!")
|
||||
else
|
||||
var/datum/job/sacjob = SSjob.GetJob(GLOB.sac_mind.assigned_role)
|
||||
var/datum/preferences/sacface = GLOB.sac_mind.current.client.prefs
|
||||
var/icon/reshape = get_flat_human_icon(null, sacjob, sacface)
|
||||
reshape.Shift(SOUTH, 4)
|
||||
reshape.Shift(EAST, 1)
|
||||
reshape.Crop(7,4,26,31)
|
||||
reshape.Crop(-5,-3,26,30)
|
||||
GLOB.sac_image = reshape
|
||||
else
|
||||
message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!")
|
||||
GLOB.sac_complete = TRUE
|
||||
SSticker.mode.cult_objectives += "sacrifice"
|
||||
if(!GLOB.summon_spots.len)
|
||||
while(GLOB.summon_spots.len < SUMMON_POSSIBILITIES)
|
||||
var/area/summon = pick(GLOB.sortedAreas - GLOB.summon_spots)
|
||||
if(summon && (summon.z in GLOB.station_z_levels) && summon.valid_territory)
|
||||
GLOB.summon_spots += summon
|
||||
SSticker.mode.cult_objectives += "eldergod"
|
||||
|
||||
/datum/antagonist/cult/proc/cult_memorization(datum/mind/cult_mind)
|
||||
var/mob/living/current = cult_mind.current
|
||||
for(var/obj_count = 1,obj_count <= SSticker.mode.cult_objectives.len,obj_count++)
|
||||
var/explanation
|
||||
switch(SSticker.mode.cult_objectives[obj_count])
|
||||
if("sacrifice")
|
||||
if(GLOB.sac_mind)
|
||||
explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role] via invoking a Sacrifice rune with them on it and three acolytes around it."
|
||||
else
|
||||
explanation = "The veil has already been weakened here, proceed to the final objective."
|
||||
GLOB.sac_complete = TRUE
|
||||
if("eldergod")
|
||||
explanation = "Summon Nar-Sie by invoking the rune 'Summon Nar-Sie'. <b>The summoning can only be accomplished in [english_list(GLOB.summon_spots)] - where the veil is weak enough for the ritual to begin.</b>"
|
||||
if(!silent)
|
||||
to_chat(current, "<B>Objective #[obj_count]</B>: [explanation]")
|
||||
cult_mind.memory += "<B>Objective #[obj_count]</B>: [explanation]<BR>"
|
||||
|
||||
/datum/antagonist/cult/can_be_owned(datum/mind/new_owner)
|
||||
. = ..()
|
||||
if(. && !ignore_implant)
|
||||
. = is_convertable_to_cult(new_owner.current)
|
||||
. = is_convertable_to_cult(new_owner.current,cult_team)
|
||||
|
||||
/datum/antagonist/cult/greet()
|
||||
to_chat(owner, "<span class='userdanger'>You are a member of the cult!</span>")
|
||||
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/bloodcult.ogg', 100, FALSE, pressure_affected = FALSE)//subject to change
|
||||
owner.announce_objectives()
|
||||
|
||||
/datum/antagonist/cult/on_gain()
|
||||
. = ..()
|
||||
var/mob/living/current = owner.current
|
||||
if(!LAZYLEN(SSticker.mode.cult_objectives))
|
||||
add_objectives()
|
||||
add_objectives()
|
||||
if(give_equipment)
|
||||
equip_cultist()
|
||||
SSticker.mode.cult += owner // Only add after they've been given objectives
|
||||
cult_memorization(owner)
|
||||
SSticker.mode.update_cult_icons_added(owner)
|
||||
current.log_message("<font color=#960000>Has been converted to the cult of Nar'Sie!</font>", INDIVIDUAL_ATTACK_LOG)
|
||||
if(GLOB.blood_target && GLOB.blood_target_image && current.client)
|
||||
current.client.images += GLOB.blood_target_image
|
||||
|
||||
if(cult_team.blood_target && cult_team.blood_target_image && current.client)
|
||||
current.client.images += cult_team.blood_target_image
|
||||
|
||||
|
||||
/datum/antagonist/cult/proc/equip_cultist(tome=FALSE)
|
||||
var/mob/living/carbon/H = owner.current
|
||||
if(!istype(H))
|
||||
return
|
||||
if (owner.assigned_role == "Clown")
|
||||
to_chat(owner, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.")
|
||||
H.dna.remove_mutation(CLOWNMUT)
|
||||
|
||||
if(tome)
|
||||
. += cult_give_item(/obj/item/tome, H)
|
||||
else
|
||||
. += cult_give_item(/obj/item/paper/talisman/supply, H)
|
||||
to_chat(owner, "These will help you start the cult on this station. Use them well, and remember - you are not the only one.</span>")
|
||||
|
||||
|
||||
/datum/antagonist/cult/proc/cult_give_item(obj/item/item_path, mob/living/carbon/human/mob)
|
||||
var/list/slots = list(
|
||||
"backpack" = slot_in_backpack,
|
||||
"left pocket" = slot_l_store,
|
||||
"right pocket" = slot_r_store
|
||||
)
|
||||
|
||||
var/T = new item_path(mob)
|
||||
var/item_name = initial(item_path.name)
|
||||
var/where = mob.equip_in_one_of_slots(T, slots)
|
||||
if(!where)
|
||||
to_chat(mob, "<span class='userdanger'>Unfortunately, you weren't able to get a [item_name]. This is very bad and you should adminhelp immediately (press F1).</span>")
|
||||
return 0
|
||||
else
|
||||
to_chat(mob, "<span class='danger'>You have a [item_name] in your [where].</span>")
|
||||
if(where == "backpack")
|
||||
var/obj/item/storage/B = mob.back
|
||||
B.orient2hud(mob)
|
||||
B.show_to(mob)
|
||||
return 1
|
||||
|
||||
/datum/antagonist/cult/apply_innate_effects(mob/living/mob_override)
|
||||
. = ..()
|
||||
@@ -89,7 +108,7 @@
|
||||
current.faction |= "cult"
|
||||
current.grant_language(/datum/language/narsie)
|
||||
current.verbs += /mob/living/proc/cult_help
|
||||
if(!GLOB.cult_mastered)
|
||||
if(!cult_team.cult_mastered)
|
||||
vote.Grant(current)
|
||||
communion.Grant(current)
|
||||
current.throw_alert("bloodsense", /obj/screen/alert/bloodsense)
|
||||
@@ -107,6 +126,7 @@
|
||||
current.clear_alert("bloodsense")
|
||||
|
||||
/datum/antagonist/cult/on_removal()
|
||||
remove_objectives()
|
||||
owner.wipe_memory()
|
||||
SSticker.mode.cult -= owner
|
||||
SSticker.mode.update_cult_icons_removed(owner)
|
||||
@@ -114,8 +134,8 @@
|
||||
owner.current.visible_message("<span class='big'>[owner.current] looks like [owner.current.p_they()] just reverted to their old faith!</span>", ignored_mob = owner.current)
|
||||
to_chat(owner.current, "<span class='userdanger'>An unfamiliar white light flashes through your mind, cleansing the taint of the Geometer and all your memories as her servant.</span>")
|
||||
owner.current.log_message("<font color=#960000>Has renounced the cult of Nar'Sie!</font>", INDIVIDUAL_ATTACK_LOG)
|
||||
if(GLOB.blood_target && GLOB.blood_target_image && owner.current.client)
|
||||
owner.current.client.images -= GLOB.blood_target_image
|
||||
if(cult_team.blood_target && cult_team.blood_target_image && owner.current.client)
|
||||
owner.current.client.images -= cult_team.blood_target_image
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/cult/master
|
||||
@@ -145,7 +165,7 @@
|
||||
var/mob/living/current = owner.current
|
||||
if(mob_override)
|
||||
current = mob_override
|
||||
if(!GLOB.reckoning_complete)
|
||||
if(!cult_team.reckoning_complete)
|
||||
reckoning.Grant(current)
|
||||
bloodmark.Grant(current)
|
||||
throwing.Grant(current)
|
||||
@@ -162,3 +182,118 @@
|
||||
throwing.Remove(current)
|
||||
current.update_action_buttons_icon()
|
||||
current.remove_status_effect(/datum/status_effect/cult_master)
|
||||
|
||||
/datum/team/cult
|
||||
name = "Cult"
|
||||
|
||||
var/blood_target
|
||||
var/image/blood_target_image
|
||||
var/blood_target_reset_timer
|
||||
|
||||
var/cult_vote_called = FALSE
|
||||
var/cult_mastered = FALSE
|
||||
var/reckoning_complete = FALSE
|
||||
|
||||
|
||||
/datum/team/cult/proc/setup_objectives()
|
||||
//SAC OBJECTIVE , todo: move this to objective internals
|
||||
var/list/target_candidates = list()
|
||||
var/datum/objective/sacrifice/sac_objective = new
|
||||
sac_objective.team = src
|
||||
|
||||
for(var/mob/living/carbon/human/player in GLOB.player_list)
|
||||
if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && !is_convertable_to_cult(player) && player.stat != DEAD)
|
||||
target_candidates += player.mind
|
||||
|
||||
if(target_candidates.len == 0)
|
||||
message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.")
|
||||
for(var/mob/living/carbon/human/player in GLOB.player_list)
|
||||
if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && player.stat != DEAD)
|
||||
target_candidates += player.mind
|
||||
listclearnulls(target_candidates)
|
||||
if(LAZYLEN(target_candidates))
|
||||
sac_objective.target = pick(target_candidates)
|
||||
sac_objective.update_explanation_text()
|
||||
|
||||
var/datum/job/sacjob = SSjob.GetJob(sac_objective.target.assigned_role)
|
||||
var/datum/preferences/sacface = sac_objective.target.current.client.prefs
|
||||
var/icon/reshape = get_flat_human_icon(null, sacjob, sacface)
|
||||
reshape.Shift(SOUTH, 4)
|
||||
reshape.Shift(EAST, 1)
|
||||
reshape.Crop(7,4,26,31)
|
||||
reshape.Crop(-5,-3,26,30)
|
||||
sac_objective.sac_image = reshape
|
||||
|
||||
objectives += sac_objective
|
||||
else
|
||||
message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!")
|
||||
|
||||
|
||||
//SUMMON OBJECTIVE
|
||||
|
||||
var/datum/objective/eldergod/summon_objective = new()
|
||||
summon_objective.team = src
|
||||
objectives += summon_objective
|
||||
|
||||
/datum/objective/sacrifice
|
||||
var/sacced = FALSE
|
||||
var/sac_image
|
||||
|
||||
/datum/objective/sacrifice/check_completion()
|
||||
return sacced || completed
|
||||
|
||||
/datum/objective/sacrifice/update_explanation_text()
|
||||
if(target && !sacced)
|
||||
explanation_text = "Sacrifice [target], the [target.assigned_role] via invoking a Sacrifice rune with them on it and three acolytes around it."
|
||||
else
|
||||
explanation_text = "The veil has already been weakened here, proceed to the final objective."
|
||||
|
||||
/datum/objective/eldergod
|
||||
var/summoned = FALSE
|
||||
var/list/summon_spots = list()
|
||||
|
||||
/datum/objective/eldergod/New()
|
||||
..()
|
||||
var/sanity = 0
|
||||
while(summon_spots.len < SUMMON_POSSIBILITIES && sanity < 100)
|
||||
var/area/summon = pick(GLOB.sortedAreas - summon_spots)
|
||||
if(summon && (summon.z in GLOB.station_z_levels) && summon.valid_territory)
|
||||
summon_spots += summon
|
||||
sanity++
|
||||
update_explanation_text()
|
||||
|
||||
/datum/objective/eldergod/update_explanation_text()
|
||||
explanation_text = "Summon Nar-Sie by invoking the rune 'Summon Nar-Sie'. <b>The summoning can only be accomplished in [english_list(summon_spots)] - where the veil is weak enough for the ritual to begin.</b>"
|
||||
|
||||
/datum/objective/eldergod/check_completion()
|
||||
return summoned || completed
|
||||
|
||||
/datum/team/cult/proc/check_cult_victory()
|
||||
for(var/datum/objective/O in objectives)
|
||||
if(!O.check_completion())
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/team/cult/roundend_report()
|
||||
var/list/parts = list()
|
||||
|
||||
if(check_cult_victory())
|
||||
parts += "<span class='greentext big'>The cult has succeeded! Nar-sie has snuffed out another torch in the void!</span>"
|
||||
else
|
||||
parts += "<span class='redtext big'>The staff managed to stop the cult! Dark words and heresy are no match for Nanotrasen's finest!</span>"
|
||||
|
||||
if(objectives.len)
|
||||
parts += "<b>The cultists' objectives were:</b>"
|
||||
var/count = 1
|
||||
for(var/datum/objective/objective in objectives)
|
||||
if(objective.check_completion())
|
||||
parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='greentext'>Success!</span>"
|
||||
else
|
||||
parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
count++
|
||||
|
||||
if(members.len)
|
||||
parts += "<span class='header'>The cultists were:</span>"
|
||||
parts += printplayerlist(members)
|
||||
|
||||
return "<div class='panel redborder'>[parts.Join("<br>")]</div>"
|
||||
@@ -1,5 +1,6 @@
|
||||
/datum/antagonist/traitor
|
||||
name = "Traitor"
|
||||
roundend_category = "traitors"
|
||||
job_rank = ROLE_TRAITOR
|
||||
var/should_specialise = FALSE //do we split into AI and human, set to true on inital assignment only
|
||||
var/ai_datum = ANTAG_DATUM_TRAITOR_AI
|
||||
@@ -8,7 +9,6 @@
|
||||
var/employer = "The Syndicate"
|
||||
var/give_objectives = TRUE
|
||||
var/should_give_codewords = TRUE
|
||||
var/list/objectives_given = list()
|
||||
|
||||
/datum/antagonist/traitor/human
|
||||
var/should_equip = TRUE
|
||||
@@ -52,9 +52,9 @@
|
||||
if(should_specialise)
|
||||
return ..()//we never did any of this anyway
|
||||
SSticker.mode.traitors -= owner
|
||||
for(var/O in objectives_given)
|
||||
for(var/O in objectives)
|
||||
owner.objectives -= O
|
||||
objectives_given = list()
|
||||
objectives = list()
|
||||
if(!silent && owner.current)
|
||||
to_chat(owner.current,"<span class='userdanger'> You are no longer the [special_role]! </span>")
|
||||
owner.special_role = null
|
||||
@@ -71,11 +71,11 @@
|
||||
|
||||
/datum/antagonist/traitor/proc/add_objective(var/datum/objective/O)
|
||||
owner.objectives += O
|
||||
objectives_given += O
|
||||
objectives += O
|
||||
|
||||
/datum/antagonist/traitor/proc/remove_objective(var/datum/objective/O)
|
||||
owner.objectives -= O
|
||||
objectives_given -= O
|
||||
objectives -= O
|
||||
|
||||
/datum/antagonist/traitor/proc/forge_traitor_objectives()
|
||||
return
|
||||
@@ -294,3 +294,53 @@
|
||||
where = "In your [equipped_slot]"
|
||||
to_chat(mob, "<BR><BR><span class='info'>[where] is a folder containing <b>secret documents</b> that another Syndicate group wants. We have set up a meeting with one of their agents on station to make an exchange. Exercise extreme caution as they cannot be trusted and may be hostile.</span><BR>")
|
||||
|
||||
//TODO Collate
|
||||
/datum/antagonist/traitor/roundend_report()
|
||||
var/list/result = list()
|
||||
|
||||
var/traitorwin = TRUE
|
||||
|
||||
result += printplayer(owner)
|
||||
|
||||
var/TC_uses = 0
|
||||
var/uplink_true = FALSE
|
||||
var/purchases = ""
|
||||
for(var/datum/component/uplink/H in GLOB.uplinks)
|
||||
if(H && H.owner && H.owner == owner.key)
|
||||
TC_uses += H.spent_telecrystals
|
||||
uplink_true = TRUE
|
||||
purchases += H.purchase_log.generate_render(FALSE)
|
||||
|
||||
var/objectives_text = ""
|
||||
if(objectives.len)//If the traitor had no objectives, don't need to process this.
|
||||
var/count = 1
|
||||
for(var/datum/objective/objective in objectives)
|
||||
if(objective.check_completion())
|
||||
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'>Success!</span>"
|
||||
else
|
||||
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
traitorwin = FALSE
|
||||
count++
|
||||
|
||||
if(uplink_true)
|
||||
var/uplink_text = "(used [TC_uses] TC) [purchases]"
|
||||
if(TC_uses==0 && traitorwin)
|
||||
var/static/icon/badass = icon('icons/badass.dmi', "badass")
|
||||
uplink_text += "<BIG>[icon2html(badass, world)]</BIG>"
|
||||
result += uplink_text
|
||||
|
||||
result += objectives_text
|
||||
|
||||
var/special_role_text = lowertext(name)
|
||||
|
||||
if(traitorwin)
|
||||
result += "<span class='greentext'>The [special_role_text] was successful!</span>"
|
||||
else
|
||||
result += "<span class='redtext'>The [special_role_text] has failed!</span>"
|
||||
SEND_SOUND(owner.current, 'sound/ambience/ambifailure.ogg')
|
||||
|
||||
return result.Join("<br>")
|
||||
|
||||
/datum/antagonist/traitor/roundend_report_footer()
|
||||
return "<br><b>The code phrases were:</b> <span class='codephrase'>[GLOB.syndicate_code_phrase]</span><br>\
|
||||
<b>The code responses were:</b> <span class='codephrase'>[GLOB.syndicate_code_response]</span><br>"
|
||||
@@ -86,6 +86,7 @@ GLOBAL_LIST_INIT(devil_syllable, list("hal", "ve", "odr", "neit", "ci", "quon",
|
||||
GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", ", the Lord of all things", ", Jr."))
|
||||
/datum/antagonist/devil
|
||||
name = "Devil"
|
||||
roundend_category = "devils"
|
||||
job_rank = ROLE_DEVIL
|
||||
//Don't delete upon mind destruction, otherwise soul re-selling will break.
|
||||
delete_on_mind_deletion = FALSE
|
||||
@@ -508,6 +509,35 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
|
||||
owner.RemoveSpell(S)
|
||||
.=..()
|
||||
|
||||
/datum/antagonist/devil/proc/printdevilinfo()
|
||||
var/list/parts = list()
|
||||
parts += "The devil's true name is: [truename]"
|
||||
parts += "The devil's bans were:"
|
||||
parts += "[GLOB.TAB][GLOB.lawlorify[LORE][ban]]"
|
||||
parts += "[GLOB.TAB][GLOB.lawlorify[LORE][bane]]"
|
||||
parts += "[GLOB.TAB][GLOB.lawlorify[LORE][obligation]]"
|
||||
parts += "[GLOB.TAB][GLOB.lawlorify[LORE][banish]]"
|
||||
return parts.Join("<br>")
|
||||
|
||||
/datum/antagonist/devil/roundend_report()
|
||||
var/list/parts = list()
|
||||
parts += printplayer(owner)
|
||||
parts += printdevilinfo()
|
||||
parts += printobjectives(owner)
|
||||
return parts.Join("<br>")
|
||||
|
||||
/datum/antagonist/devil/roundend_report_footer()
|
||||
//sintouched go here for now as a hack , TODO proper antag datum for these
|
||||
var/list/parts = list()
|
||||
if(SSticker.mode.sintouched.len)
|
||||
parts += "<span class='header'>The sintouched were:</span>"
|
||||
var/list/sintouchedUnique = uniqueList(SSticker.mode.sintouched)
|
||||
for(var/S in sintouchedUnique)
|
||||
var/datum/mind/sintouched_mind = S
|
||||
parts += printplayer(sintouched_mind)
|
||||
parts += printobjectives(sintouched_mind)
|
||||
return parts.Join("<br>")
|
||||
|
||||
//A simple super light weight datum for the codex gigas.
|
||||
/datum/fakeDevil
|
||||
var/truename
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
#define MONKEYS_ESCAPED 1
|
||||
#define MONKEYS_LIVED 2
|
||||
#define MONKEYS_DIED 3
|
||||
#define DISEASE_LIVED 4
|
||||
|
||||
/datum/antagonist/monkey
|
||||
name = "Monkey"
|
||||
job_rank = ROLE_MONKEY
|
||||
roundend_category = "monkeys"
|
||||
var/datum/team/monkey/monkey_team
|
||||
|
||||
/datum/antagonist/monkey/on_gain()
|
||||
. = ..()
|
||||
SSticker.mode.ape_infectees += owner
|
||||
owner.special_role = "Infected Monkey"
|
||||
|
||||
var/datum/disease/D = new /datum/disease/transformation/jungle_fever/monkeymode
|
||||
if(!owner.current.HasDisease(D))
|
||||
owner.current.AddDisease(D)
|
||||
else
|
||||
QDEL_NULL(D)
|
||||
|
||||
/datum/antagonist/monkey/greet()
|
||||
to_chat(owner, "<b>You are a monkey now!</b>")
|
||||
to_chat(owner, "<b>Bite humans to infect them, follow the orders of the monkey leaders, and help fellow monkeys!</b>")
|
||||
to_chat(owner, "<b>Ensure at least one infected monkey escapes on the Emergency Shuttle!</b>")
|
||||
to_chat(owner, "<b><i>As an intelligent monkey, you know how to use technology and how to ventcrawl while wearing things.</i></b>")
|
||||
to_chat(owner, "<b>You can use :k to talk to fellow monkeys!</b>")
|
||||
SEND_SOUND(owner.current, sound('sound/ambience/antag/monkey.ogg'))
|
||||
|
||||
/datum/antagonist/monkey/on_removal()
|
||||
. = ..()
|
||||
owner.special_role = null
|
||||
SSticker.mode.ape_infectees -= owner
|
||||
|
||||
var/datum/disease/D = (/datum/disease/transformation/jungle_fever in owner.current.viruses)
|
||||
if(D)
|
||||
D.cure()
|
||||
|
||||
/datum/antagonist/monkey/create_team(datum/team/monkey/new_team)
|
||||
if(!new_team)
|
||||
for(var/datum/antagonist/monkey/N in get_antagonists(/datum/antagonist/monkey, TRUE))
|
||||
if(N.monkey_team)
|
||||
monkey_team = N.monkey_team
|
||||
return
|
||||
monkey_team = new /datum/team/monkey
|
||||
monkey_team.update_objectives()
|
||||
return
|
||||
if(!istype(new_team))
|
||||
stack_trace("Wrong team type passed to [type] initialization.")
|
||||
monkey_team = new_team
|
||||
|
||||
/datum/antagonist/monkey/proc/forge_objectives()
|
||||
if(monkey_team)
|
||||
owner.objectives |= monkey_team.objectives
|
||||
|
||||
/datum/antagonist/monkey/leader
|
||||
name = "Monkey Leader"
|
||||
|
||||
/datum/antagonist/monkey/leader/on_gain()
|
||||
. = ..()
|
||||
var/obj/item/organ/heart/freedom/F = new
|
||||
F.Insert(owner.current, drop_if_replaced = FALSE)
|
||||
SSticker.mode.ape_leaders += owner
|
||||
owner.special_role = "Monkey Leader"
|
||||
|
||||
/datum/antagonist/monkey/leader/on_removal()
|
||||
. = ..()
|
||||
SSticker.mode.ape_leaders -= owner
|
||||
var/obj/item/organ/heart/H = new
|
||||
H.Insert(owner.current, drop_if_replaced = FALSE) //replace freedom heart with normal heart
|
||||
|
||||
/datum/antagonist/monkey/leader/greet()
|
||||
to_chat(owner, "<B><span class='notice'>You are the Jungle Fever patient zero!!</B></span>")
|
||||
to_chat(owner, "<b>You have been planted onto this station by the Animal Rights Consortium.</b>")
|
||||
to_chat(owner, "<b>Soon the disease will transform you into an ape. Afterwards, you will be able spread the infection to others with a bite.</b>")
|
||||
to_chat(owner, "<b>While your infection strain is undetectable by scanners, any other infectees will show up on medical equipment.</b>")
|
||||
to_chat(owner, "<b>Your mission will be deemed a success if any of the live infected monkeys reach CentCom.</b>")
|
||||
to_chat(owner, "<b>As an initial infectee, you will be considered a 'leader' by your fellow monkeys.</b>")
|
||||
to_chat(owner, "<b>You can use :k to talk to fellow monkeys!</b>")
|
||||
SEND_SOUND(owner.current, sound('sound/ambience/antag/monkey.ogg'))
|
||||
|
||||
/datum/objective/monkey
|
||||
explanation_text = "Ensure that infected monkeys escape on the emergency shuttle!"
|
||||
martyr_compatible = TRUE
|
||||
var/monkeys_to_win = 1
|
||||
var/escaped_monkeys = 0
|
||||
|
||||
/datum/objective/monkey/check_completion()
|
||||
var/datum/disease/D = new /datum/disease/transformation/jungle_fever()
|
||||
for(var/mob/living/carbon/monkey/M in GLOB.alive_mob_list)
|
||||
if (M.HasDisease(D) && (M.onCentCom() || M.onSyndieBase()))
|
||||
escaped_monkeys++
|
||||
if(escaped_monkeys >= monkeys_to_win)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/team/monkey
|
||||
name = "Monkeys"
|
||||
|
||||
/datum/team/monkey/proc/update_objectives()
|
||||
objectives = list()
|
||||
var/datum/objective/monkey/O = new /datum/objective/monkey()
|
||||
O.team = src
|
||||
objectives += O
|
||||
return
|
||||
|
||||
/datum/team/monkey/proc/infected_monkeys_alive()
|
||||
var/datum/disease/D = new /datum/disease/transformation/jungle_fever()
|
||||
for(var/mob/living/carbon/monkey/M in GLOB.alive_mob_list)
|
||||
if(M.HasDisease(D))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/team/monkey/proc/infected_monkeys_escaped()
|
||||
var/datum/disease/D = new /datum/disease/transformation/jungle_fever()
|
||||
for(var/mob/living/carbon/monkey/M in GLOB.alive_mob_list)
|
||||
if(M.HasDisease(D) && (M.onCentCom() || M.onSyndieBase()))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/team/monkey/proc/infected_humans_escaped()
|
||||
var/datum/disease/D = new /datum/disease/transformation/jungle_fever()
|
||||
for(var/mob/living/carbon/human/M in GLOB.alive_mob_list)
|
||||
if(M.HasDisease(D) && (M.onCentCom() || M.onSyndieBase()))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/team/monkey/proc/infected_humans_alive()
|
||||
var/datum/disease/D = new /datum/disease/transformation/jungle_fever()
|
||||
for(var/mob/living/carbon/human/M in GLOB.alive_mob_list)
|
||||
if(M.HasDisease(D))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/team/monkey/proc/get_result()
|
||||
if(infected_monkeys_escaped())
|
||||
return MONKEYS_ESCAPED
|
||||
if(infected_monkeys_alive())
|
||||
return MONKEYS_LIVED
|
||||
if(infected_humans_alive() || infected_humans_escaped())
|
||||
return DISEASE_LIVED
|
||||
return MONKEYS_DIED
|
||||
|
||||
/datum/team/monkey/roundend_report()
|
||||
var/list/parts = list()
|
||||
switch(get_result())
|
||||
if(MONKEYS_ESCAPED)
|
||||
parts += "<span class='greentext big'><B>Monkey Major Victory!</B></span>"
|
||||
parts += "<span class='greentext'><B>Central Command and [station_name()] were taken over by the monkeys! Ook ook!</B></span>"
|
||||
if(MONKEYS_LIVED)
|
||||
parts += "<FONT size = 3><B>Monkey Minor Victory!</B></FONT>"
|
||||
parts += "<span class='greentext'><B>[station_name()] was taken over by the monkeys! Ook ook!</B></span>"
|
||||
if(DISEASE_LIVED)
|
||||
parts += "<span class='redtext big'><B>Monkey Minor Defeat!</B></span>"
|
||||
parts += "<span class='redtext'><B>All the monkeys died, but the disease lives on! The future is uncertain.</B></span>"
|
||||
if(MONKEYS_DIED)
|
||||
parts += "<span class='redtext big'><B>Monkey Major Defeat!</B></span>"
|
||||
parts += "<span class='redtext'><B>All the monkeys died, and Jungle Fever was wiped out!</B></span>"
|
||||
var/list/leaders = get_antagonists(/datum/antagonist/monkey/leader, TRUE)
|
||||
var/list/monkeys = get_antagonists(/datum/antagonist/monkey, TRUE)
|
||||
|
||||
if(LAZYLEN(leaders))
|
||||
parts += "<span class='header'>The monkey leaders were:</span>"
|
||||
parts += printplayerlist(SSticker.mode.ape_leaders)
|
||||
if(LAZYLEN(monkeys))
|
||||
parts += "<span class='header'>The monkeys were:</span>"
|
||||
parts += printplayerlist(SSticker.mode.ape_infectees)
|
||||
return "<div class='panel redborder'>[parts.Join("<br>")]</div>"
|
||||
@@ -37,19 +37,20 @@
|
||||
else if(M.assigned_role in GLOB.command_positions)
|
||||
possible_targets[M] = 1 //good-guy
|
||||
|
||||
var/list/objectives = list(1,2,3,4)
|
||||
while(owner.objectives.len < quantity)
|
||||
switch(pick_n_take(objectives))
|
||||
var/list/possible_objectives = list(1,2,3,4)
|
||||
|
||||
while(objectives.len < quantity)
|
||||
switch(pick_n_take(possible_objectives))
|
||||
if(1) //research
|
||||
var/datum/objective/download/O = new /datum/objective/download()
|
||||
O.owner = owner
|
||||
O.gen_amount_goal()
|
||||
owner.objectives += O
|
||||
objectives += O
|
||||
|
||||
if(2) //steal
|
||||
var/datum/objective/steal/special/O = new /datum/objective/steal/special()
|
||||
O.owner = owner
|
||||
owner.objectives += O
|
||||
objectives += O
|
||||
|
||||
if(3) //protect/kill
|
||||
if(!possible_targets.len) continue
|
||||
@@ -63,13 +64,13 @@
|
||||
O.owner = owner
|
||||
O.target = M
|
||||
O.explanation_text = "Slay \the [M.current.real_name], the [M.assigned_role]."
|
||||
owner.objectives += O
|
||||
objectives += O
|
||||
else //protect
|
||||
var/datum/objective/protect/O = new /datum/objective/protect()
|
||||
O.owner = owner
|
||||
O.target = M
|
||||
O.explanation_text = "Protect \the [M.current.real_name], the [M.assigned_role], from harm."
|
||||
owner.objectives += O
|
||||
objectives += O
|
||||
if(4) //debrain/capture
|
||||
if(!possible_targets.len) continue
|
||||
var/selected = rand(1,possible_targets.len)
|
||||
@@ -82,17 +83,17 @@
|
||||
O.owner = owner
|
||||
O.target = M
|
||||
O.explanation_text = "Steal the brain of [M.current.real_name]."
|
||||
owner.objectives += O
|
||||
objectives += O
|
||||
else //capture
|
||||
var/datum/objective/capture/O = new /datum/objective/capture()
|
||||
O.owner = owner
|
||||
O.gen_amount_goal()
|
||||
owner.objectives += O
|
||||
objectives += O
|
||||
else
|
||||
break
|
||||
var/datum/objective/O = new /datum/objective/survive()
|
||||
O.owner = owner
|
||||
owner.objectives += O
|
||||
owner.objectives |= objectives
|
||||
|
||||
|
||||
/proc/remove_ninja(mob/living/L)
|
||||
|
||||
@@ -0,0 +1,322 @@
|
||||
#define NUKE_RESULT_FLUKE 0
|
||||
#define NUKE_RESULT_NUKE_WIN 1
|
||||
#define NUKE_RESULT_CREW_WIN 2
|
||||
#define NUKE_RESULT_CREW_WIN_SYNDIES_DEAD 3
|
||||
#define NUKE_RESULT_DISK_LOST 4
|
||||
#define NUKE_RESULT_DISK_STOLEN 5
|
||||
#define NUKE_RESULT_NOSURVIVORS 6
|
||||
#define NUKE_RESULT_WRONG_STATION 7
|
||||
#define NUKE_RESULT_WRONG_STATION_DEAD 8
|
||||
|
||||
/datum/antagonist/nukeop
|
||||
name = "Nuclear Operative"
|
||||
roundend_category = "syndicate operatives" //just in case
|
||||
job_rank = ROLE_OPERATIVE
|
||||
var/datum/team/nuclear/nuke_team
|
||||
var/always_new_team = FALSE //If not assigned a team by default ops will try to join existing ones, set this to TRUE to always create new team.
|
||||
var/send_to_spawnpoint = TRUE //Should the user be moved to default spawnpoint.
|
||||
var/nukeop_outfit = /datum/outfit/syndicate
|
||||
|
||||
/datum/antagonist/nukeop/proc/update_synd_icons_added(mob/living/M)
|
||||
var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS]
|
||||
opshud.join_hud(M)
|
||||
set_antag_hud(M, "synd")
|
||||
|
||||
/datum/antagonist/nukeop/proc/update_synd_icons_removed(mob/living/M)
|
||||
var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS]
|
||||
opshud.leave_hud(M)
|
||||
set_antag_hud(M, null)
|
||||
|
||||
/datum/antagonist/nukeop/apply_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/M = mob_override || owner.current
|
||||
update_synd_icons_added(M)
|
||||
|
||||
/datum/antagonist/nukeop/remove_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/M = mob_override || owner.current
|
||||
update_synd_icons_removed(M)
|
||||
|
||||
/datum/antagonist/nukeop/proc/equip_op()
|
||||
if(!ishuman(owner.current))
|
||||
return
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
|
||||
H.set_species(/datum/species/human) //Plasamen burn up otherwise, and lizards are vulnerable to asimov AIs
|
||||
|
||||
H.equipOutfit(nukeop_outfit)
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/nukeop/greet()
|
||||
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ops.ogg',100,0)
|
||||
to_chat(owner, "<span class='notice'>You are a [nuke_team ? nuke_team.syndicate_name : "syndicate"] agent!</span>")
|
||||
owner.announce_objectives()
|
||||
return
|
||||
|
||||
/datum/antagonist/nukeop/on_gain()
|
||||
give_alias()
|
||||
forge_objectives()
|
||||
. = ..()
|
||||
equip_op()
|
||||
memorize_code()
|
||||
if(send_to_spawnpoint)
|
||||
move_to_spawnpoint()
|
||||
|
||||
/datum/antagonist/nukeop/get_team()
|
||||
return nuke_team
|
||||
|
||||
/datum/antagonist/nukeop/proc/assign_nuke()
|
||||
if(nuke_team && !nuke_team.tracked_nuke)
|
||||
nuke_team.memorized_code = random_nukecode()
|
||||
var/obj/machinery/nuclearbomb/nuke = locate("syndienuke") in GLOB.nuke_list
|
||||
if(nuke)
|
||||
nuke_team.tracked_nuke = nuke
|
||||
if(nuke.r_code == "ADMIN")
|
||||
nuke.r_code = nuke_team.memorized_code
|
||||
else //Already set by admins/something else?
|
||||
nuke_team.memorized_code = nuke.r_code
|
||||
else
|
||||
stack_trace("Syndicate nuke not found during nuke team creation.")
|
||||
nuke_team.memorized_code = null
|
||||
|
||||
/datum/antagonist/nukeop/proc/give_alias()
|
||||
if(nuke_team && nuke_team.syndicate_name)
|
||||
var/number = 1
|
||||
number = nuke_team.members.Find(owner)
|
||||
owner.current.real_name = "[nuke_team.syndicate_name] Operative #[number]"
|
||||
|
||||
/datum/antagonist/nukeop/proc/memorize_code()
|
||||
if(nuke_team && nuke_team.tracked_nuke && nuke_team.memorized_code)
|
||||
owner.store_memory("<B>[nuke_team.tracked_nuke] Code</B>: [nuke_team.memorized_code]", 0, 0)
|
||||
to_chat(owner, "The nuclear authorization code is: <B>[nuke_team.memorized_code]</B>")
|
||||
else
|
||||
to_chat(owner, "Unfortunately the syndicate was unable to provide you with nuclear authorization code.")
|
||||
|
||||
/datum/antagonist/nukeop/proc/forge_objectives()
|
||||
if(nuke_team)
|
||||
owner.objectives |= nuke_team.objectives
|
||||
|
||||
/datum/antagonist/nukeop/proc/move_to_spawnpoint()
|
||||
var/team_number = 1
|
||||
if(nuke_team)
|
||||
team_number = nuke_team.members.Find(owner)
|
||||
owner.current.forceMove(GLOB.nukeop_start[((team_number - 1) % GLOB.nukeop_start.len) + 1])
|
||||
|
||||
/datum/antagonist/nukeop/leader/move_to_spawnpoint()
|
||||
owner.current.forceMove(pick(GLOB.nukeop_leader_start))
|
||||
|
||||
/datum/antagonist/nukeop/create_team(datum/team/nuclear/new_team)
|
||||
if(!new_team)
|
||||
if(!always_new_team)
|
||||
for(var/datum/antagonist/nukeop/N in GLOB.antagonists)
|
||||
if(N.nuke_team)
|
||||
nuke_team = N.nuke_team
|
||||
return
|
||||
nuke_team = new /datum/team/nuclear
|
||||
nuke_team.update_objectives()
|
||||
assign_nuke() //This is bit ugly
|
||||
return
|
||||
if(!istype(new_team))
|
||||
stack_trace("Wrong team type passed to [type] initialization.")
|
||||
nuke_team = new_team
|
||||
|
||||
/datum/antagonist/nukeop/leader
|
||||
name = "Nuclear Operative Leader"
|
||||
nukeop_outfit = /datum/outfit/syndicate/leader
|
||||
always_new_team = TRUE
|
||||
var/title
|
||||
|
||||
/datum/antagonist/nukeop/leader/memorize_code()
|
||||
..()
|
||||
if(nuke_team && nuke_team.memorized_code)
|
||||
var/obj/item/paper/P = new
|
||||
P.info = "The nuclear authorization code is: <b>[nuke_team.memorized_code]</b>"
|
||||
P.name = "nuclear bomb code"
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
if(!istype(H))
|
||||
P.forceMove(get_turf(H))
|
||||
else
|
||||
H.put_in_hands(P, TRUE)
|
||||
H.update_icons()
|
||||
|
||||
/datum/antagonist/nukeop/leader/give_alias()
|
||||
title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord")
|
||||
if(nuke_team && nuke_team.syndicate_name)
|
||||
owner.current.real_name = "[nuke_team.syndicate_name] [title]"
|
||||
else
|
||||
owner.current.real_name = "Syndicate [title]"
|
||||
|
||||
/datum/antagonist/nukeop/leader/greet()
|
||||
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ops.ogg',100,0)
|
||||
to_chat(owner, "<B>You are the Syndicate [title] for this mission. You are responsible for the distribution of telecrystals and your ID is the only one who can open the launch bay doors.</B>")
|
||||
to_chat(owner, "<B>If you feel you are not up to this task, give your ID to another operative.</B>")
|
||||
to_chat(owner, "<B>In your hand you will find a special item capable of triggering a greater challenge for your team. Examine it carefully and consult with your fellow operatives before activating it.</B>")
|
||||
owner.announce_objectives()
|
||||
addtimer(CALLBACK(src, .proc/nuketeam_name_assign), 1)
|
||||
|
||||
|
||||
/datum/antagonist/nukeop/leader/proc/nuketeam_name_assign()
|
||||
if(!nuke_team)
|
||||
return
|
||||
nuke_team.rename_team(ask_name())
|
||||
|
||||
/datum/team/nuclear/proc/rename_team(new_name)
|
||||
syndicate_name = new_name
|
||||
name = "[syndicate_name] Team"
|
||||
for(var/I in members)
|
||||
var/datum/mind/synd_mind = I
|
||||
var/mob/living/carbon/human/H = synd_mind.current
|
||||
if(!istype(H))
|
||||
continue
|
||||
var/chosen_name = H.dna.species.random_name(H.gender,0,syndicate_name)
|
||||
H.fully_replace_character_name(H.real_name,chosen_name)
|
||||
|
||||
/datum/antagonist/nukeop/leader/proc/ask_name()
|
||||
var/randomname = pick(GLOB.last_names)
|
||||
var/newname = stripped_input(owner.current,"You are the nuke operative [title]. Please choose a last name for your family.", "Name change",randomname)
|
||||
if (!newname)
|
||||
newname = randomname
|
||||
else
|
||||
newname = reject_bad_name(newname)
|
||||
if(!newname)
|
||||
newname = randomname
|
||||
|
||||
return capitalize(newname)
|
||||
|
||||
/datum/antagonist/nukeop/lone
|
||||
name = "Lone Operative"
|
||||
always_new_team = TRUE
|
||||
send_to_spawnpoint = FALSE //Handled by event
|
||||
nukeop_outfit = /datum/outfit/syndicate/full
|
||||
|
||||
/datum/antagonist/nukeop/lone/assign_nuke()
|
||||
if(nuke_team && !nuke_team.tracked_nuke)
|
||||
nuke_team.memorized_code = random_nukecode()
|
||||
var/obj/machinery/nuclearbomb/selfdestruct/nuke = locate() in GLOB.nuke_list
|
||||
if(nuke)
|
||||
nuke_team.tracked_nuke = nuke
|
||||
if(nuke.r_code == "ADMIN")
|
||||
nuke.r_code = nuke_team.memorized_code
|
||||
else //Already set by admins/something else?
|
||||
nuke_team.memorized_code = nuke.r_code
|
||||
else
|
||||
stack_trace("Station self destruct ot found during lone op team creation.")
|
||||
nuke_team.memorized_code = null
|
||||
|
||||
/datum/team/nuclear
|
||||
var/syndicate_name
|
||||
var/obj/machinery/nuclearbomb/tracked_nuke
|
||||
var/core_objective = /datum/objective/nuclear
|
||||
var/memorized_code
|
||||
|
||||
/datum/team/nuclear/New()
|
||||
..()
|
||||
syndicate_name = syndicate_name()
|
||||
|
||||
/datum/team/nuclear/proc/update_objectives()
|
||||
if(core_objective)
|
||||
var/datum/objective/O = new core_objective
|
||||
O.team = src
|
||||
objectives += O
|
||||
|
||||
/datum/team/nuclear/proc/disk_rescued()
|
||||
for(var/obj/item/disk/nuclear/D in GLOB.poi_list)
|
||||
if(!D.onCentCom())
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/team/nuclear/proc/operatives_dead()
|
||||
for(var/I in members)
|
||||
var/datum/mind/operative_mind = I
|
||||
if(ishuman(operative_mind.current) && (operative_mind.current.stat != DEAD))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/team/nuclear/proc/syndies_escaped()
|
||||
var/obj/docking_port/mobile/S = SSshuttle.getShuttle("syndicate")
|
||||
return (S && (S.z == ZLEVEL_CENTCOM || S.z == ZLEVEL_TRANSIT))
|
||||
|
||||
/datum/team/nuclear/proc/get_result()
|
||||
var/evacuation = SSshuttle.emergency.mode == SHUTTLE_ENDGAME
|
||||
var/disk_rescued = disk_rescued()
|
||||
var/syndies_didnt_escape = !syndies_escaped()
|
||||
var/station_was_nuked = SSticker.mode.station_was_nuked
|
||||
var/nuke_off_station = SSticker.mode.nuke_off_station
|
||||
|
||||
if(nuke_off_station == NUKE_SYNDICATE_BASE)
|
||||
return NUKE_RESULT_FLUKE
|
||||
else if(!disk_rescued && station_was_nuked && !syndies_didnt_escape)
|
||||
return NUKE_RESULT_NUKE_WIN
|
||||
else if (!disk_rescued && station_was_nuked && syndies_didnt_escape)
|
||||
return NUKE_RESULT_NOSURVIVORS
|
||||
else if (!disk_rescued && !station_was_nuked && nuke_off_station && !syndies_didnt_escape)
|
||||
return NUKE_RESULT_WRONG_STATION
|
||||
else if (!disk_rescued && !station_was_nuked && nuke_off_station && syndies_didnt_escape)
|
||||
return NUKE_RESULT_WRONG_STATION_DEAD
|
||||
else if ((disk_rescued || evacuation) && operatives_dead())
|
||||
return NUKE_RESULT_CREW_WIN_SYNDIES_DEAD
|
||||
else if (disk_rescued)
|
||||
return NUKE_RESULT_CREW_WIN
|
||||
else if (!disk_rescued && operatives_dead())
|
||||
return NUKE_RESULT_DISK_LOST
|
||||
else if (!disk_rescued && evacuation)
|
||||
return NUKE_RESULT_DISK_STOLEN
|
||||
else
|
||||
return //Undefined result
|
||||
|
||||
/datum/team/nuclear/roundend_report()
|
||||
var/list/parts = list()
|
||||
parts += "<span class='header'>[syndicate_name] Operatives:</span>"
|
||||
|
||||
switch(get_result())
|
||||
if(NUKE_RESULT_FLUKE)
|
||||
parts += "<span class='redtext big'>Humiliating Syndicate Defeat</span>"
|
||||
parts += "<B>The crew of [station_name()] gave [syndicate_name] operatives back their bomb! The syndicate base was destroyed!</B> Next time, don't lose the nuke!"
|
||||
if(NUKE_RESULT_NUKE_WIN)
|
||||
parts += "<span class='greentext big'>Syndicate Major Victory!</span>"
|
||||
parts += "<B>[syndicate_name] operatives have destroyed [station_name()]!</B>"
|
||||
if(NUKE_RESULT_NOSURVIVORS)
|
||||
parts += "<span class='neutraltext big'>Total Annihilation</span>"
|
||||
parts += "<B>[syndicate_name] operatives destroyed [station_name()] but did not leave the area in time and got caught in the explosion.</B> Next time, don't lose the disk!"
|
||||
if(NUKE_RESULT_WRONG_STATION)
|
||||
parts += "<span class='redtext big'>Crew Minor Victory</span>"
|
||||
parts += "<B>[syndicate_name] operatives secured the authentication disk but blew up something that wasn't [station_name()].</B> Next time, don't do that!"
|
||||
if(NUKE_RESULT_WRONG_STATION_DEAD)
|
||||
parts += "<span class='redtext big'>[syndicate_name] operatives have earned Darwin Award!</span>"
|
||||
parts += "<B>[syndicate_name] operatives blew up something that wasn't [station_name()] and got caught in the explosion.</B> Next time, don't do that!"
|
||||
if(NUKE_RESULT_CREW_WIN_SYNDIES_DEAD)
|
||||
parts += "<span class='redtext big'>Crew Major Victory!</span>"
|
||||
parts += "<B>The Research Staff has saved the disk and killed the [syndicate_name] Operatives</B>"
|
||||
if(NUKE_RESULT_CREW_WIN)
|
||||
parts += "<span class='redtext big'>Crew Major Victory</span>"
|
||||
parts += "<B>The Research Staff has saved the disk and stopped the [syndicate_name] Operatives!</B>"
|
||||
if(NUKE_RESULT_DISK_LOST)
|
||||
parts += "<span class='neutraltext big'>Neutral Victory!</span>"
|
||||
parts += "<B>The Research Staff failed to secure the authentication disk but did manage to kill most of the [syndicate_name] Operatives!</B>"
|
||||
if(NUKE_RESULT_DISK_STOLEN)
|
||||
parts += "<span class='greentext big'>Syndicate Minor Victory!</span>"
|
||||
parts += "<B>[syndicate_name] operatives survived the assault but did not achieve the destruction of [station_name()].</B> Next time, don't lose the disk!"
|
||||
else
|
||||
parts += "<span class='neutraltext big'>Neutral Victory</span>"
|
||||
parts += "<B>Mission aborted!</B>"
|
||||
|
||||
var/text = "<br><span class='header'>The syndicate operatives were:</span>"
|
||||
var/purchases = ""
|
||||
var/TC_uses = 0
|
||||
for(var/I in members)
|
||||
var/datum/mind/syndicate = I
|
||||
for(var/U in GLOB.uplinks)
|
||||
var/datum/component/uplink/H = U
|
||||
if(H.owner == syndicate.key)
|
||||
TC_uses += H.purchase_log.total_spent
|
||||
if(H.purchase_log)
|
||||
purchases += H.purchase_log.generate_render(show_key = FALSE)
|
||||
else
|
||||
stack_trace("WARNING: Nuke Op uplink with no purchase_log Owner: [H.owner]")
|
||||
text += printplayerlist(members)
|
||||
text += "<br>"
|
||||
text += "(Syndicates used [TC_uses] TC) [purchases]"
|
||||
if(TC_uses == 0 && SSticker.mode.station_was_nuked && !operatives_dead())
|
||||
text += "<BIG>[icon2html('icons/badass.dmi', world, "badass")]</BIG>"
|
||||
|
||||
parts += text
|
||||
|
||||
return "<div class='panel redborder'>[parts.Join("<br>")]</div>"
|
||||
@@ -1,7 +1,8 @@
|
||||
/datum/antagonist/pirate
|
||||
name = "Space Pirate"
|
||||
job_rank = ROLE_TRAITOR
|
||||
var/datum/objective_team/pirate/crew
|
||||
roundend_category = "space pirates"
|
||||
var/datum/team/pirate/crew
|
||||
|
||||
/datum/antagonist/pirate/greet()
|
||||
to_chat(owner, "<span class='boldannounce'>You are a Space Pirate!</span>")
|
||||
@@ -11,15 +12,16 @@
|
||||
/datum/antagonist/pirate/get_team()
|
||||
return crew
|
||||
|
||||
/datum/antagonist/pirate/create_team(datum/objective_team/pirate/new_team)
|
||||
/datum/antagonist/pirate/create_team(datum/team/pirate/new_team)
|
||||
if(!new_team)
|
||||
for(var/datum/antagonist/pirate/P in GLOB.antagonists)
|
||||
if(P.crew)
|
||||
new_team = P.crew
|
||||
crew = P.crew
|
||||
return
|
||||
if(!new_team)
|
||||
crew = new /datum/objective_team/pirate
|
||||
crew = new /datum/team/pirate
|
||||
crew.forge_objectives()
|
||||
return
|
||||
return
|
||||
if(!istype(new_team))
|
||||
stack_trace("Wrong team type passed to [type] initialization.")
|
||||
crew = new_team
|
||||
@@ -34,11 +36,10 @@
|
||||
owner.objectives -= crew.objectives
|
||||
. = ..()
|
||||
|
||||
/datum/objective_team/pirate
|
||||
/datum/team/pirate
|
||||
name = "Pirate crew"
|
||||
var/list/objectives = list()
|
||||
|
||||
/datum/objective_team/pirate/proc/forge_objectives()
|
||||
/datum/team/pirate/proc/forge_objectives()
|
||||
var/datum/objective/loot/getbooty = new()
|
||||
getbooty.team = src
|
||||
getbooty.storage_area = locate(/area/shuttle/pirate/vault) in GLOB.sortedAreas
|
||||
@@ -84,11 +85,11 @@ GLOBAL_LIST_INIT(pirate_loot_cache, typecacheof(list(
|
||||
loot_table[lootname] = count
|
||||
else
|
||||
loot_table[lootname] += count
|
||||
var/text = ""
|
||||
var/list/loot_texts = list()
|
||||
for(var/key in loot_table)
|
||||
var/amount = loot_table[key]
|
||||
text += "[amount] [key][amount > 1 ? "s":""], "
|
||||
return text
|
||||
loot_texts += "[amount] [key][amount > 1 ? "s":""]"
|
||||
return loot_texts.Join(", ")
|
||||
|
||||
/datum/objective/loot/proc/get_loot_value()
|
||||
if(!storage_area)
|
||||
@@ -104,32 +105,25 @@ GLOBAL_LIST_INIT(pirate_loot_cache, typecacheof(list(
|
||||
/datum/objective/loot/check_completion()
|
||||
return ..() || get_loot_value() >= target_value
|
||||
|
||||
/datum/team/pirate/roundend_report()
|
||||
var/list/parts = list()
|
||||
|
||||
//These need removal ASAP as everything is converted to datum antags.
|
||||
/datum/game_mode/proc/auto_declare_completion_pirates()
|
||||
var/list/datum/mind/pirates = get_antagonists(/datum/antagonist/pirate)
|
||||
var/datum/objective_team/pirate/crew
|
||||
var/text = ""
|
||||
if(pirates.len)
|
||||
text += "<br><b>Space Pirates were:</b>"
|
||||
for(var/datum/mind/M in pirates)
|
||||
text += printplayer(M)
|
||||
if(!crew)
|
||||
var/datum/antagonist/pirate/P = M.has_antag_datum(/datum/antagonist/pirate)
|
||||
crew = P.crew
|
||||
if(crew)
|
||||
text += "<br>Loot stolen: "
|
||||
var/datum/objective/loot/L = locate() in crew.objectives
|
||||
text += L.loot_listing()
|
||||
text += "<br>Total loot value : [L.get_loot_value()]/[L.target_value] credits"
|
||||
parts += "<span class='header'>Space Pirates were:</span>"
|
||||
|
||||
var/all_dead = TRUE
|
||||
for(var/datum/mind/M in crew.members)
|
||||
if(considered_alive(M))
|
||||
all_dead = FALSE
|
||||
break
|
||||
if(L.check_completion() && !all_dead)
|
||||
text += "<br><font color='green'><b>The pirate crew was successful!</b></font>"
|
||||
else
|
||||
text += "<br><span class='boldannounce'>The pirate crew has failed.</span>"
|
||||
to_chat(world, text)
|
||||
var/all_dead = TRUE
|
||||
for(var/datum/mind/M in members)
|
||||
if(considered_alive(M))
|
||||
all_dead = FALSE
|
||||
parts += printplayerlist(members)
|
||||
|
||||
parts += "Loot stolen: "
|
||||
var/datum/objective/loot/L = locate() in objectives
|
||||
parts += L.loot_listing()
|
||||
parts += "Total loot value : [L.get_loot_value()]/[L.target_value] credits"
|
||||
|
||||
if(L.check_completion() && !all_dead)
|
||||
parts += "<span class='greentext big'>The pirate crew was successful!</span>"
|
||||
else
|
||||
parts += "<span class='redtext big'>The pirate crew has failed.</span>"
|
||||
|
||||
return "<div class='panel redborder'>[parts.Join("<br>")]</div>"
|
||||
@@ -3,9 +3,10 @@
|
||||
|
||||
/datum/antagonist/rev
|
||||
name = "Revolutionary"
|
||||
roundend_category = "revolutionaries" // if by some miracle revolutionaries without revolution happen
|
||||
job_rank = ROLE_REV
|
||||
var/hud_type = "rev"
|
||||
var/datum/objective_team/revolution/rev_team
|
||||
var/datum/team/revolution/rev_team
|
||||
|
||||
/datum/antagonist/rev/can_be_owned(datum/mind/new_owner)
|
||||
. = ..()
|
||||
@@ -39,17 +40,17 @@
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/rev/greet()
|
||||
to_chat(owner, "<span class='danger'><FONT size = 3> You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!</FONT></span>")
|
||||
to_chat(owner, "<span class='userdanger'>You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!</span>")
|
||||
owner.announce_objectives()
|
||||
|
||||
/datum/antagonist/rev/create_team(datum/objective_team/revolution/new_team)
|
||||
/datum/antagonist/rev/create_team(datum/team/revolution/new_team)
|
||||
if(!new_team)
|
||||
//For now only one revolution at a time
|
||||
for(var/datum/antagonist/rev/head/H in GLOB.antagonists)
|
||||
if(H.rev_team)
|
||||
rev_team = H.rev_team
|
||||
return
|
||||
rev_team = new /datum/objective_team/revolution
|
||||
rev_team = new /datum/team/revolution
|
||||
rev_team.update_objectives()
|
||||
rev_team.update_heads()
|
||||
return
|
||||
@@ -77,7 +78,7 @@
|
||||
old_owner.add_antag_datum(new_revhead,old_team)
|
||||
new_revhead.silent = FALSE
|
||||
to_chat(old_owner, "<span class='userdanger'>You have proved your devotion to revolution! You are a head revolutionary now!</span>")
|
||||
|
||||
|
||||
|
||||
/datum/antagonist/rev/head
|
||||
name = "Head Revolutionary"
|
||||
@@ -131,14 +132,14 @@
|
||||
old_owner.add_antag_datum(new_rev,old_team)
|
||||
new_rev.silent = FALSE
|
||||
to_chat(old_owner, "<span class='userdanger'>Revolution has been disappointed of your leader traits! You are a regular revolutionary now!</span>")
|
||||
|
||||
|
||||
/datum/antagonist/rev/farewell()
|
||||
if(ishuman(owner.current))
|
||||
owner.current.visible_message("[owner.current] looks like they just remembered their real allegiance!")
|
||||
to_chat(owner, "<span class='userdanger'><FONT size = 3>You are no longer a brainwashed revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you...</FONT></span>")
|
||||
owner.current.visible_message("<span class='deconversion_message'>[owner.current] looks like they just remembered their real allegiance!</span>", ignored_mob = owner.current)
|
||||
to_chat(owner, "<span class='userdanger'>You are no longer a brainwashed revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you...</span>")
|
||||
else if(issilicon(owner.current))
|
||||
owner.current.visible_message("The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.")
|
||||
to_chat(owner, "<span class='userdanger'><FONT size = 3>The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you.</FONT></span>")
|
||||
owner.current.visible_message("<span class='deconversion_message'>The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.</span>", ignored_mob = owner.current)
|
||||
to_chat(owner, "<span class='userdanger'>The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you.</span>")
|
||||
|
||||
/datum/antagonist/rev/proc/remove_revolutionary(borged, deconverter)
|
||||
log_attack("[owner.current] (Key: [key_name(owner.current)]) has been deconverted from the revolution by [deconverter] (Key: [key_name(deconverter)])!")
|
||||
@@ -163,7 +164,7 @@
|
||||
if(remove_clumsy && owner.assigned_role == "Clown")
|
||||
to_chat(owner, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.")
|
||||
H.dna.remove_mutation(CLOWNMUT)
|
||||
|
||||
|
||||
if(give_flash)
|
||||
var/obj/item/device/assembly/flash/T = new(H)
|
||||
var/list/slots = list (
|
||||
@@ -176,18 +177,17 @@
|
||||
to_chat(H, "The Syndicate were unfortunately unable to get you a flash.")
|
||||
else
|
||||
to_chat(H, "The flash in your [where] will help you to persuade the crew to join your cause.")
|
||||
|
||||
|
||||
if(give_hud)
|
||||
var/obj/item/organ/cyberimp/eyes/hud/security/syndicate/S = new(H)
|
||||
S.Insert(H, special = FALSE, drop_if_replaced = FALSE)
|
||||
to_chat(H, "Your eyes have been implanted with a cybernetic security HUD which will help you keep track of who is mindshield-implanted, and therefore unable to be recruited.")
|
||||
|
||||
/datum/objective_team/revolution
|
||||
/datum/team/revolution
|
||||
name = "Revolution"
|
||||
var/list/objectives = list()
|
||||
var/max_headrevs = 3
|
||||
|
||||
/datum/objective_team/revolution/proc/update_objectives(initial = FALSE)
|
||||
/datum/team/revolution/proc/update_objectives(initial = FALSE)
|
||||
var/untracked_heads = SSjob.get_all_heads()
|
||||
for(var/datum/objective/mutiny/O in objectives)
|
||||
untracked_heads -= O.target
|
||||
@@ -199,16 +199,16 @@
|
||||
objectives += new_target
|
||||
for(var/datum/mind/M in members)
|
||||
M.objectives |= objectives
|
||||
|
||||
|
||||
addtimer(CALLBACK(src,.proc/update_objectives),HEAD_UPDATE_PERIOD,TIMER_UNIQUE)
|
||||
|
||||
/datum/objective_team/revolution/proc/head_revolutionaries()
|
||||
/datum/team/revolution/proc/head_revolutionaries()
|
||||
. = list()
|
||||
for(var/datum/mind/M in members)
|
||||
if(M.has_antag_datum(/datum/antagonist/rev/head))
|
||||
. += M
|
||||
|
||||
/datum/objective_team/revolution/proc/update_heads()
|
||||
/datum/team/revolution/proc/update_heads()
|
||||
if(SSticker.HasRoundStarted())
|
||||
var/list/datum/mind/head_revolutionaries = head_revolutionaries()
|
||||
var/list/datum/mind/heads = SSjob.get_all_heads()
|
||||
@@ -227,3 +227,56 @@
|
||||
rev.promote()
|
||||
|
||||
addtimer(CALLBACK(src,.proc/update_heads),HEAD_UPDATE_PERIOD,TIMER_UNIQUE)
|
||||
|
||||
|
||||
/datum/team/revolution/roundend_report()
|
||||
if(!members.len)
|
||||
return
|
||||
|
||||
var/list/result = list()
|
||||
|
||||
result += "<div class='panel redborder'>"
|
||||
|
||||
var/num_revs = 0
|
||||
var/num_survivors = 0
|
||||
for(var/mob/living/carbon/survivor in GLOB.alive_mob_list)
|
||||
if(survivor.ckey)
|
||||
num_survivors++
|
||||
if(survivor.mind)
|
||||
if(is_revolutionary(survivor))
|
||||
num_revs++
|
||||
if(num_survivors)
|
||||
result += "Command's Approval Rating: <B>[100 - round((num_revs/num_survivors)*100, 0.1)]%</B><br>"
|
||||
|
||||
|
||||
var/list/targets = list()
|
||||
var/list/datum/mind/headrevs = get_antagonists(/datum/antagonist/rev/head)
|
||||
var/list/datum/mind/revs = get_antagonists(/datum/antagonist/rev,TRUE)
|
||||
if(headrevs.len)
|
||||
var/list/headrev_part = list()
|
||||
headrev_part += "<span class='header'>The head revolutionaries were:</span>"
|
||||
headrev_part += printplayerlist(headrevs,TRUE)
|
||||
result += headrev_part.Join("<br>")
|
||||
|
||||
if(revs.len)
|
||||
var/list/rev_part = list()
|
||||
rev_part += "<span class='header'>The revolutionaries were:</span>"
|
||||
rev_part += printplayerlist(revs,TRUE)
|
||||
result += rev_part.Join("<br>")
|
||||
|
||||
var/list/heads = SSjob.get_all_heads()
|
||||
if(heads.len)
|
||||
var/head_text = "<span class='header'>The heads of staff were:</span>"
|
||||
head_text += "<ul class='playerlist'>"
|
||||
for(var/datum/mind/head in heads)
|
||||
var/target = (head in targets)
|
||||
head_text += "<li>"
|
||||
if(target)
|
||||
head_text += "<span class='redtext'>Target</span>"
|
||||
head_text += "[printplayer(head, 1)]</li>"
|
||||
head_text += "</ul><br>"
|
||||
result += head_text
|
||||
|
||||
result += "</div>"
|
||||
|
||||
return result.Join()
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
/datum/antagonist/wizard
|
||||
name = "Space Wizard"
|
||||
roundend_category = "wizards/witches"
|
||||
job_rank = ROLE_WIZARD
|
||||
var/give_objectives = TRUE
|
||||
var/strip = TRUE //strip before equipping
|
||||
var/allow_rename = TRUE
|
||||
var/hud_version = "wizard"
|
||||
var/datum/objective_team/wizard/wiz_team //Only created if wizard summons apprentices
|
||||
var/list/objectives = list() //this should be base datum antag proc and list, todo make lazy
|
||||
var/datum/team/wizard/wiz_team //Only created if wizard summons apprentices
|
||||
var/move_to_lair = TRUE
|
||||
var/outfit_type = /datum/outfit/wizard
|
||||
var/wiz_age = WIZARD_AGE_MIN /* Wizards by nature cannot be too young. */
|
||||
@@ -33,7 +33,7 @@
|
||||
/datum/antagonist/wizard/proc/unregister()
|
||||
SSticker.mode.wizards -= src
|
||||
|
||||
/datum/antagonist/wizard/create_team(datum/objective_team/wizard/new_team)
|
||||
/datum/antagonist/wizard/create_team(datum/team/wizard/new_team)
|
||||
if(!new_team)
|
||||
return
|
||||
if(!istype(new_team))
|
||||
@@ -43,12 +43,14 @@
|
||||
/datum/antagonist/wizard/get_team()
|
||||
return wiz_team
|
||||
|
||||
/datum/objective_team/wizard
|
||||
/datum/team/wizard
|
||||
name = "wizard team"
|
||||
var/datum/antagonist/wizard/master_wizard
|
||||
|
||||
/datum/antagonist/wizard/proc/create_wiz_team()
|
||||
wiz_team = new(owner)
|
||||
wiz_team.name = "[owner.current.real_name] team"
|
||||
wiz_team.master_wizard = src
|
||||
update_wiz_icons_added(owner.current)
|
||||
|
||||
/datum/antagonist/wizard/proc/send_to_lair()
|
||||
@@ -283,4 +285,46 @@
|
||||
var/datum/objective/new_objective = new("Protect Wizard Academy from the intruders")
|
||||
new_objective.owner = owner
|
||||
owner.objectives += new_objective
|
||||
objectives += new_objective
|
||||
objectives += new_objective
|
||||
|
||||
//Solo wizard report
|
||||
/datum/antagonist/wizard/roundend_report()
|
||||
var/list/parts = list()
|
||||
|
||||
parts += printplayer(owner)
|
||||
|
||||
var/count = 1
|
||||
var/wizardwin = 1
|
||||
for(var/datum/objective/objective in objectives)
|
||||
if(objective.check_completion())
|
||||
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'>Success!</span>"
|
||||
else
|
||||
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
wizardwin = 0
|
||||
count++
|
||||
|
||||
if(wizardwin)
|
||||
parts += "<span class='greentext'>The wizard was successful!</span>"
|
||||
else
|
||||
parts += "<span class='redtext'>The wizard has failed!</span>"
|
||||
|
||||
if(owner.spell_list.len>0)
|
||||
parts += "<B>[owner.name] used the following spells: </B>"
|
||||
var/list/spell_names = list()
|
||||
for(var/obj/effect/proc_holder/spell/S in owner.spell_list)
|
||||
spell_names += S.name
|
||||
parts += spell_names.Join(", ")
|
||||
|
||||
return parts.Join("<br>")
|
||||
|
||||
//Wizard with apprentices report
|
||||
/datum/team/wizard/roundend_report()
|
||||
var/list/parts = list()
|
||||
|
||||
parts += "<span class='header'>Wizards/witches of [master_wizard.owner.name] team were:</span>"
|
||||
parts += master_wizard.roundend_report()
|
||||
parts += " "
|
||||
parts += "<span class='header'>[master_wizard.owner.name] apprentices were:</span>"
|
||||
parts += printplayerlist(members - master_wizard.owner)
|
||||
|
||||
return "<div class='panel redborder'>[parts.Join("<br>")]</div>"
|
||||
+2
-2
@@ -128,11 +128,11 @@
|
||||
//Position the effect so the beam is one continous line
|
||||
var/a
|
||||
if(abs(Pixel_x)>32)
|
||||
a = Pixel_x > 0 ? round(Pixel_x/32) : Ceiling(Pixel_x/32)
|
||||
a = Pixel_x > 0 ? round(Pixel_x/32) : CEILING(Pixel_x/32, 1)
|
||||
X.x += a
|
||||
Pixel_x %= 32
|
||||
if(abs(Pixel_y)>32)
|
||||
a = Pixel_y > 0 ? round(Pixel_y/32) : Ceiling(Pixel_y/32)
|
||||
a = Pixel_y > 0 ? round(Pixel_y/32) : CEILING(Pixel_y/32, 1)
|
||||
X.y += a
|
||||
Pixel_y %= 32
|
||||
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
/datum/brain_trauma/special/imaginary_friend
|
||||
name = "Imaginary Friend"
|
||||
desc = "Patient can see and hear an imaginary person."
|
||||
scan_desc = "partial schizophrenia"
|
||||
gain_text = "<span class='notice'>You feel in good company, for some reason.</span>"
|
||||
lose_text = "<span class='warning'>You feel lonely again.</span>"
|
||||
var/mob/camera/imaginary_friend/friend
|
||||
var/friend_initialized = FALSE
|
||||
|
||||
/datum/brain_trauma/special/imaginary_friend/on_gain()
|
||||
..()
|
||||
make_friend()
|
||||
get_ghost()
|
||||
|
||||
/datum/brain_trauma/special/imaginary_friend/on_life()
|
||||
if(get_dist(owner, friend) > 9)
|
||||
friend.yank()
|
||||
if(!friend)
|
||||
qdel(src)
|
||||
return
|
||||
if(!friend.client && friend_initialized)
|
||||
addtimer(CALLBACK(src, .proc/reroll_friend), 600)
|
||||
|
||||
/datum/brain_trauma/special/imaginary_friend/on_lose()
|
||||
..()
|
||||
QDEL_NULL(friend)
|
||||
|
||||
//If the friend goes afk, make a brand new friend. Plenty of fish in the sea of imagination.
|
||||
/datum/brain_trauma/special/imaginary_friend/proc/reroll_friend()
|
||||
if(friend.client) //reconnected
|
||||
return
|
||||
friend_initialized = FALSE
|
||||
QDEL_NULL(friend)
|
||||
make_friend()
|
||||
get_ghost()
|
||||
|
||||
/datum/brain_trauma/special/imaginary_friend/proc/make_friend()
|
||||
friend = new(get_turf(src), src)
|
||||
|
||||
/datum/brain_trauma/special/imaginary_friend/proc/get_ghost()
|
||||
set waitfor = FALSE
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s imaginary friend?", ROLE_PAI, null, null, 75, friend)
|
||||
if(LAZYLEN(candidates))
|
||||
var/client/C = pick(candidates)
|
||||
friend.key = C.key
|
||||
friend_initialized = TRUE
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/mob/camera/imaginary_friend
|
||||
name = "imaginary friend"
|
||||
real_name = "imaginary friend"
|
||||
move_on_shuttle = TRUE
|
||||
desc = "A wonderful yet fake friend."
|
||||
see_in_dark = 0
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
|
||||
sight = NONE
|
||||
see_invisible = SEE_INVISIBLE_LIVING
|
||||
var/icon/human_image
|
||||
var/image/current_image
|
||||
var/mob/living/carbon/owner
|
||||
var/datum/brain_trauma/special/imaginary_friend/trauma
|
||||
|
||||
/mob/camera/imaginary_friend/Login()
|
||||
..()
|
||||
to_chat(src, "<span class='notice'><b>You are the imaginary friend of [owner]!</b></span>")
|
||||
to_chat(src, "<span class='notice'>You are absolutely loyal to your friend, no matter what.</span>")
|
||||
to_chat(src, "<span class='notice'>You cannot directly influence the world around you, but you can see what [owner] cannot.</span>")
|
||||
|
||||
/mob/camera/imaginary_friend/Initialize(mapload, _trauma)
|
||||
. = ..()
|
||||
var/gender = pick(MALE, FEMALE)
|
||||
real_name = random_unique_name(gender)
|
||||
name = real_name
|
||||
trauma = _trauma
|
||||
owner = trauma.owner
|
||||
human_image = get_flat_human_icon(null, pick(SSjob.occupations))
|
||||
Show()
|
||||
|
||||
/mob/camera/imaginary_friend/proc/Show()
|
||||
if(!client) //nobody home
|
||||
return
|
||||
|
||||
//Remove old image from owner and friend
|
||||
if(owner.client)
|
||||
owner.client.images.Remove(current_image)
|
||||
|
||||
client.images.Remove(current_image)
|
||||
|
||||
//Generate image from the static icon and the current dir
|
||||
current_image = image(human_image, src, , MOB_LAYER, dir=src.dir)
|
||||
current_image.override = TRUE
|
||||
current_image.name = name
|
||||
|
||||
//Add new image to owner and friend
|
||||
if(owner.client)
|
||||
owner.client.images |= current_image
|
||||
|
||||
client.images |= current_image
|
||||
|
||||
/mob/camera/imaginary_friend/Destroy()
|
||||
if(owner.client)
|
||||
owner.client.images.Remove(human_image)
|
||||
if(client)
|
||||
client.images.Remove(human_image)
|
||||
return ..()
|
||||
|
||||
/mob/camera/imaginary_friend/proc/yank()
|
||||
if(!client) //don't bother if the friend is braindead
|
||||
return
|
||||
forceMove(get_turf(owner))
|
||||
Show()
|
||||
|
||||
/mob/camera/imaginary_friend/say(message)
|
||||
if (!message)
|
||||
return
|
||||
|
||||
if (src.client)
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
to_chat(src, "You cannot send IC messages (muted).")
|
||||
return
|
||||
if (src.client.handle_spam_prevention(message,MUTE_IC))
|
||||
return
|
||||
|
||||
friend_talk(message)
|
||||
|
||||
/mob/camera/imaginary_friend/proc/friend_talk(message)
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
|
||||
if(!message)
|
||||
return
|
||||
|
||||
log_talk(src,"[key_name(src)] : [message]",LOGSAY)
|
||||
|
||||
var/rendered = "<span class='game say'><span class='name'>[name]</span> <span class='message'>[say_quote(message)]</span></span>"
|
||||
var/dead_rendered = "<span class='game say'><span class='name'>[name] (Imaginary friend of [owner])</span> <span class='message'>[say_quote(message)]</span></span>"
|
||||
|
||||
to_chat(owner, "[rendered]")
|
||||
to_chat(src, "[rendered]")
|
||||
|
||||
for(var/mob/M in GLOB.dead_mob_list)
|
||||
var/link = FOLLOW_LINK(M, owner)
|
||||
to_chat(M, "[link] [dead_rendered]")
|
||||
|
||||
/mob/camera/imaginary_friend/emote(act,m_type=1,message = null)
|
||||
return
|
||||
|
||||
/mob/camera/imaginary_friend/forceMove(atom/destination)
|
||||
dir = get_dir(get_turf(src), destination)
|
||||
loc = destination
|
||||
if(get_dist(src, owner) > 9)
|
||||
yank()
|
||||
return
|
||||
Show()
|
||||
|
||||
/mob/camera/imaginary_friend/movement_delay()
|
||||
return 2
|
||||
@@ -42,7 +42,7 @@
|
||||
lose_text = "<span class='notice'>You feel smart again.</span>"
|
||||
|
||||
/datum/brain_trauma/mild/dumbness/on_gain()
|
||||
owner.disabilities |= DUMB
|
||||
owner.add_disability(DISABILITY_DUMB, TRAUMA_DISABILITY)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/mild/dumbness/on_life()
|
||||
@@ -54,7 +54,7 @@
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/mild/dumbness/on_lose()
|
||||
owner.disabilities &= ~DUMB
|
||||
owner.remove_disability(DISABILITY_DUMB, TRAUMA_DISABILITY)
|
||||
owner.derpspeech = 0
|
||||
..()
|
||||
|
||||
@@ -107,6 +107,26 @@
|
||||
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/mild/healthy
|
||||
name = "Anosognosia"
|
||||
desc = "Patient always feels healthy, regardless of their condition."
|
||||
scan_desc = "self-awareness deficit"
|
||||
gain_text = "<span class='notice'>You feel great!</span>"
|
||||
lose_text = "<span class='warning'>You no longer feel perfectly healthy.</span>"
|
||||
|
||||
/datum/brain_trauma/mild/healthy/on_gain()
|
||||
owner.set_screwyhud(SCREWYHUD_HEALTHY)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/mild/healthy/on_life()
|
||||
owner.set_screwyhud(SCREWYHUD_HEALTHY) //just in case of hallucinations
|
||||
owner.adjustStaminaLoss(-5) //no pain, no fatigue
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/mild/healthy/on_lose()
|
||||
owner.set_screwyhud(SCREWYHUD_NONE)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/mild/muscle_weakness
|
||||
name = "Muscle Weakness"
|
||||
desc = "Patient experiences occasional bouts of muscle weakness."
|
||||
@@ -133,3 +153,62 @@
|
||||
to_chat(owner, "<span class='warning'>You feel a sudden weakness in your muscles!</span>")
|
||||
owner.adjustStaminaLoss(50)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/mild/muscle_spasms
|
||||
name = "Muscle Spasms"
|
||||
desc = "Patient has occasional muscle spasms, causing them to move unintentionally."
|
||||
scan_desc = "nervous fits"
|
||||
gain_text = "<span class='warning'>Your muscles feel oddly faint.</span>"
|
||||
lose_text = "<span class='notice'>You feel in control of your muscles again.</span>"
|
||||
|
||||
/datum/brain_trauma/mild/muscle_spasms/on_life()
|
||||
if(prob(7))
|
||||
switch(rand(1,5))
|
||||
if(1)
|
||||
if(owner.canmove && !isspaceturf(owner.loc))
|
||||
to_chat(owner, "<span class='warning'>Your leg spasms!</span>")
|
||||
step(owner, pick(GLOB.cardinals))
|
||||
if(2)
|
||||
if(owner.incapacitated())
|
||||
return
|
||||
var/obj/item/I = owner.get_active_held_item()
|
||||
if(I)
|
||||
to_chat(owner, "<span class='warning'>Your fingers spasm!</span>")
|
||||
log_attack("[key_name(owner)] used [I] due to a Muscle Spasm.")
|
||||
I.attack_self(owner)
|
||||
if(3)
|
||||
var/prev_intent = owner.a_intent
|
||||
owner.a_intent = INTENT_HARM
|
||||
|
||||
var/range = 1
|
||||
if(istype(owner.get_active_held_item(), /obj/item/gun)) //get targets to shoot at
|
||||
range = 7
|
||||
|
||||
var/list/mob/living/targets = list()
|
||||
for(var/mob/M in oview(owner, range))
|
||||
if(isliving(M))
|
||||
targets += M
|
||||
if(LAZYLEN(targets))
|
||||
to_chat(owner, "<span class='warning'>Your arm spasms!</span>")
|
||||
log_attack("[key_name(owner)] attacked someone due to a Muscle Spasm.") //the following attack will log itself
|
||||
owner.ClickOn(pick(targets))
|
||||
owner.a_intent = prev_intent
|
||||
if(4)
|
||||
var/prev_intent = owner.a_intent
|
||||
owner.a_intent = INTENT_HARM
|
||||
to_chat(owner, "<span class='warning'>Your arm spasms!</span>")
|
||||
log_attack("[key_name(owner)] attacked himself to a Muscle Spasm.")
|
||||
owner.ClickOn(owner)
|
||||
owner.a_intent = prev_intent
|
||||
if(5)
|
||||
if(owner.incapacitated())
|
||||
return
|
||||
var/obj/item/I = owner.get_active_held_item()
|
||||
var/list/turf/targets = list()
|
||||
for(var/turf/T in oview(owner, 3))
|
||||
targets += T
|
||||
if(LAZYLEN(targets) && I)
|
||||
to_chat(owner, "<span class='warning'>Your arm spasms!</span>")
|
||||
log_attack("[key_name(owner)] threw [I] due to a Muscle Spasm.")
|
||||
owner.throw_item(pick(targets))
|
||||
..()
|
||||
@@ -68,7 +68,7 @@
|
||||
return
|
||||
|
||||
/datum/brain_trauma/mild/phobia/on_hear(message, speaker, message_language, raw_message, radio_freq)
|
||||
if(owner.disabilities & DEAF || world.time < next_scare) //words can't trigger you if you can't hear them *taps head*
|
||||
if(owner.has_disability(DISABILITY_DEAF) || world.time < next_scare) //words can't trigger you if you can't hear them *taps head*
|
||||
return message
|
||||
for(var/word in trigger_words)
|
||||
if(findtext(message, word))
|
||||
|
||||
@@ -7,22 +7,39 @@
|
||||
/datum/brain_trauma/severe/mute
|
||||
name = "Mutism"
|
||||
desc = "Patient is completely unable to speak."
|
||||
scan_desc = "extensive damage to the brain's language center"
|
||||
scan_desc = "extensive damage to the brain's speech center"
|
||||
gain_text = "<span class='warning'>You forget how to speak!</span>"
|
||||
lose_text = "<span class='notice'>You suddenly remember how to speak.</span>"
|
||||
|
||||
/datum/brain_trauma/severe/mute/on_gain()
|
||||
owner.disabilities |= MUTE
|
||||
..()
|
||||
|
||||
//no fiddling with genetics to get out of this one
|
||||
/datum/brain_trauma/severe/mute/on_life()
|
||||
if(!(owner.disabilities & MUTE))
|
||||
on_gain()
|
||||
owner.add_disability(DISABILITY_MUTE, TRAUMA_DISABILITY)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/severe/mute/on_lose()
|
||||
owner.disabilities &= ~MUTE
|
||||
owner.remove_disability(DISABILITY_MUTE, TRAUMA_DISABILITY)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/severe/aphasia
|
||||
name = "Aphasia"
|
||||
desc = "Patient is unable to speak or understand any language."
|
||||
scan_desc = "extensive damage to the brain's language center"
|
||||
gain_text = "<span class='warning'>You have trouble forming words in your head...</span>"
|
||||
lose_text = "<span class='notice'>You suddenly remember how languages work.</span>"
|
||||
var/datum/language_holder/prev_language
|
||||
var/datum/language_holder/mob_language
|
||||
|
||||
/datum/brain_trauma/severe/aphasia/on_gain()
|
||||
mob_language = owner.get_language_holder()
|
||||
prev_language = mob_language.copy()
|
||||
mob_language.remove_all_languages()
|
||||
mob_language.grant_language(/datum/language/aphasia)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/severe/aphasia/on_lose()
|
||||
mob_language.remove_language(/datum/language/aphasia)
|
||||
mob_language.copy_known_languages_from(prev_language) //this will also preserve languages learned during the trauma
|
||||
QDEL_NULL(prev_language)
|
||||
mob_language = null
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/severe/blindness
|
||||
@@ -109,7 +126,7 @@
|
||||
stress -= 4
|
||||
|
||||
/datum/brain_trauma/severe/monophobia/proc/check_alone()
|
||||
if(owner.disabilities & BLIND)
|
||||
if(owner.has_disability(DISABILITY_BLIND))
|
||||
return TRUE
|
||||
for(var/mob/M in oview(owner, 7))
|
||||
if(!isliving(M)) //ghosts ain't people
|
||||
@@ -171,9 +188,24 @@
|
||||
lose_text = "<span class='notice'>You feel in control of your hands again.</span>"
|
||||
|
||||
/datum/brain_trauma/severe/discoordination/on_gain()
|
||||
owner.disabilities |= MONKEYLIKE
|
||||
owner.add_disability(DISABILITY_MONKEYLIKE, TRAUMA_DISABILITY)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/severe/discoordination/on_lose()
|
||||
owner.disabilities &= ~MONKEYLIKE
|
||||
owner.remove_disability(DISABILITY_MONKEYLIKE, TRAUMA_DISABILITY)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/severe/pacifism
|
||||
name = "Traumatic Non-Violence"
|
||||
desc = "Patient is extremely unwilling to harm others in violent ways."
|
||||
scan_desc = "pacific syndrome"
|
||||
gain_text = "<span class='notice'>You feel oddly peaceful.</span>"
|
||||
lose_text = "<span class='notice'>You no longer feel compelled to not harm.</span>"
|
||||
|
||||
/datum/brain_trauma/severe/pacifism/on_gain()
|
||||
owner.add_disability(DISABILITY_PACIFISM, TRAUMA_DISABILITY)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/severe/pacifism/on_lose()
|
||||
owner.remove_disability(DISABILITY_PACIFISM, TRAUMA_DISABILITY)
|
||||
..()
|
||||
@@ -9,25 +9,35 @@
|
||||
scan_desc = "god delusion"
|
||||
gain_text = "<span class='notice'>You feel a higher power inside your mind...</span>"
|
||||
lose_text = "<span class='warning'>The divine presence leaves your head, no longer interested.</span>"
|
||||
var/next_speech = 0
|
||||
var/inspiration = FALSE
|
||||
|
||||
/datum/brain_trauma/special/godwoken/on_life()
|
||||
..()
|
||||
if(!inspiration && world.time > next_speech && prob(4))
|
||||
to_chat(owner, "<span class='notice'>[pick("You feel inspired!","You feel power course through you...","You feel something within you itching to speak...")]</span>")
|
||||
inspiration = TRUE
|
||||
if(prob(4))
|
||||
if(prob(33) && (owner.IsStun() || owner.IsKnockdown() || owner.IsUnconscious()))
|
||||
speak("unstun", TRUE)
|
||||
else if(prob(60) && owner.health <= HEALTH_THRESHOLD_CRIT)
|
||||
speak("heal", TRUE)
|
||||
else if(prob(30) && owner.a_intent == INTENT_HARM)
|
||||
speak("aggressive")
|
||||
else
|
||||
speak("neutral", prob(25))
|
||||
|
||||
/datum/brain_trauma/special/godwoken/on_say(message)
|
||||
if(world.time > next_speech && inspiration)
|
||||
playsound(get_turf(owner), 'sound/magic/clockwork/invoke_general.ogg', 300, 1, 5)
|
||||
var/cooldown = voice_of_god(message, owner, list("colossus","yell"), 2)
|
||||
cooldown *= 0.33
|
||||
next_speech = world.time + cooldown
|
||||
inspiration = FALSE
|
||||
return ""
|
||||
else
|
||||
return message
|
||||
/datum/brain_trauma/special/godwoken/proc/speak(type, include_owner = FALSE)
|
||||
var/message
|
||||
switch(type)
|
||||
if("unstun")
|
||||
message = pick_list_replacements(BRAIN_DAMAGE_FILE, "god_unstun")
|
||||
if("heal")
|
||||
message = pick_list_replacements(BRAIN_DAMAGE_FILE, "god_heal")
|
||||
if("neutral")
|
||||
message = pick_list_replacements(BRAIN_DAMAGE_FILE, "god_neutral")
|
||||
if("aggressive")
|
||||
message = pick_list_replacements(BRAIN_DAMAGE_FILE, "god_aggressive")
|
||||
else
|
||||
message = pick_list_replacements(BRAIN_DAMAGE_FILE, "god_neutral")
|
||||
|
||||
playsound(get_turf(owner), 'sound/magic/clockwork/invoke_general.ogg', 200, 1, 5)
|
||||
voice_of_god(message, owner, list("colossus","yell"), 2.5, include_owner, FALSE)
|
||||
|
||||
/datum/brain_trauma/special/bluespace_prophet
|
||||
name = "Bluespace Prophecy"
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
/datum/brain_trauma/severe/split_personality/proc/get_ghost()
|
||||
set waitfor = FALSE
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s split personality?", null, null, null, 75, stranger_backseat)
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s split personality?", ROLE_PAI, null, null, 75, stranger_backseat)
|
||||
if(LAZYLEN(candidates))
|
||||
var/client/C = pick(candidates)
|
||||
stranger_backseat.key = C.key
|
||||
@@ -136,6 +136,7 @@
|
||||
/mob/living/split_personality/Login()
|
||||
..()
|
||||
to_chat(src, "<span class='notice'>As a split personality, you cannot do anything but observe. However, you will eventually gain control of your body, switching places with the current personality.</span>")
|
||||
to_chat(src, "<span class='warning'><b>Do not commit suicide or put the body in a deadly position. Behave like you care about it as much as the owner.</b></span>")
|
||||
|
||||
/mob/living/split_personality/say(message)
|
||||
to_chat(src, "<span class='warning'>You cannot speak, your other self is controlling your body!</span>")
|
||||
@@ -191,7 +192,7 @@
|
||||
return //no random switching
|
||||
|
||||
/datum/brain_trauma/severe/split_personality/brainwashing/on_hear(message, speaker, message_language, raw_message, radio_freq)
|
||||
if(owner.disabilities & DEAF || owner == speaker)
|
||||
if(owner.has_disability(DISABILITY_DEAF) || owner == speaker)
|
||||
return message
|
||||
if(findtext(message, codeword))
|
||||
message = replacetext(message, codeword, "<span class='warning'>[codeword]</span>")
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
var/datum/object = GLOBAL_PROC
|
||||
var/delegate
|
||||
var/list/arguments
|
||||
var/datum/weakref/user
|
||||
|
||||
/datum/callback/New(thingtocall, proctocall, ...)
|
||||
if (thingtocall)
|
||||
@@ -55,6 +56,8 @@
|
||||
delegate = proctocall
|
||||
if (length(args) > 2)
|
||||
arguments = args.Copy(3)
|
||||
if(usr)
|
||||
user = WEAKREF(usr)
|
||||
|
||||
/world/proc/ImmediateInvokeAsync(thingtocall, proctocall, ...)
|
||||
set waitfor = FALSE
|
||||
@@ -70,8 +73,16 @@
|
||||
call(thingtocall, proctocall)(arglist(calling_arguments))
|
||||
|
||||
/datum/callback/proc/Invoke(...)
|
||||
if(!usr)
|
||||
var/datum/weakref/W = user
|
||||
if(W)
|
||||
var/mob/M = W.resolve()
|
||||
if(M)
|
||||
return world.PushUsr(M, src)
|
||||
|
||||
if (!object)
|
||||
return
|
||||
|
||||
var/list/calling_arguments = arguments
|
||||
if (length(args))
|
||||
if (length(arguments))
|
||||
@@ -87,8 +98,17 @@
|
||||
//copy and pasted because fuck proc overhead
|
||||
/datum/callback/proc/InvokeAsync(...)
|
||||
set waitfor = FALSE
|
||||
|
||||
if(!usr)
|
||||
var/datum/weakref/W = user
|
||||
if(W)
|
||||
var/mob/M = W.resolve()
|
||||
if(M)
|
||||
return world.PushUsr(M, src)
|
||||
|
||||
if (!object)
|
||||
return
|
||||
|
||||
var/list/calling_arguments = arguments
|
||||
if (length(args))
|
||||
if (length(arguments))
|
||||
|
||||
@@ -40,6 +40,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
* `COMPONENT_DUPE_HIGHLANDER` (default): Old component will be deleted, new component will first have `/datum/component/proc/InheritComponent(datum/component/old, FALSE)` on it
|
||||
* `COMPONENT_DUPE_ALLOWED`: The components will be treated as separate, `GetComponent()` will return the first added
|
||||
* `COMPONENT_DUPE_UNIQUE`: New component will be deleted, old component will first have `/datum/component/proc/InheritComponent(datum/component/new, TRUE)` on it
|
||||
* `COMPONENT_DUPE_UNIQUE_PASSARGS`: New component will never exist and instead its initialization arguments will be passed on to the old component.
|
||||
1. `/datum/component/var/dupe_type` (protected, type)
|
||||
* Definition of a duplicate component type
|
||||
* `null` means exact match on `type` (default)
|
||||
@@ -66,6 +67,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
* All components a datum owns are deleted with the datum
|
||||
* Returns the component that was created. Or the old component in a dupe situation where `COMPONENT_DUPE_UNIQUE` was set
|
||||
* If this tries to add an component to an incompatible type, the component will be deleted and the result will be `null`. This is very unperformant, try not to do it
|
||||
* Properly handles duplicate situations based on the `dupe_mode` var
|
||||
1. `/datum/proc/LoadComponent(component_type(type), ...) -> datum/component` (public, final)
|
||||
* Equivalent to calling `GetComponent(component_type)` where, if the result would be `null`, returns `AddComponent(component_type, ...)` instead
|
||||
1. `/datum/proc/ComponentActivated(datum/component/C)` (abstract, async)
|
||||
@@ -104,9 +106,8 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
* Allows the component to react to ownership transfers
|
||||
1. `/datum/component/proc/_RemoveFromParent()` (private, final)
|
||||
* Clears `parent` and removes the component from it's component list
|
||||
1. `/datum/component/proc/_CheckDupesAndJoinParent` (private, final)
|
||||
1. `/datum/component/proc/_JoinParent` (private, final)
|
||||
* Tries to add the component to it's `parent`s `datum_components` list
|
||||
* Properly handles duplicate situations based on the `dupe_mode` var
|
||||
1. `/datum/component/proc/RegisterSignal(signal(string/list of strings), proc_ref(type), override(boolean))` (protected, final) (Consider removing for performance gainz)
|
||||
* If signal is a list it will be as if RegisterSignal was called for each of the entries with the same following arguments
|
||||
* Makes a component listen for the specified `signal` on it's `parent` datum.
|
||||
|
||||
@@ -6,54 +6,16 @@
|
||||
var/datum/parent
|
||||
|
||||
/datum/component/New(datum/P, ...)
|
||||
if(type == /datum/component)
|
||||
qdel(src)
|
||||
CRASH("[type] instantiated!")
|
||||
|
||||
//check for common mishaps
|
||||
if(!isnum(dupe_mode))
|
||||
qdel(src)
|
||||
CRASH("[type]: Invalid dupe_mode!")
|
||||
var/dt = dupe_type
|
||||
if(dt && !ispath(dt))
|
||||
qdel(src)
|
||||
CRASH("[type]: Invalid dupe_type!")
|
||||
|
||||
parent = P
|
||||
var/list/arguments = args.Copy(2)
|
||||
if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE)
|
||||
qdel(src, TRUE, TRUE)
|
||||
return
|
||||
|
||||
_CheckDupesAndJoinParent(P)
|
||||
_JoinParent(P)
|
||||
|
||||
/datum/component/proc/_CheckDupesAndJoinParent()
|
||||
/datum/component/proc/_JoinParent()
|
||||
var/datum/P = parent
|
||||
var/dm = dupe_mode
|
||||
|
||||
var/datum/component/old
|
||||
if(dm != COMPONENT_DUPE_ALLOWED)
|
||||
var/dt = dupe_type
|
||||
if(!dt)
|
||||
old = P.GetExactComponent(type)
|
||||
else
|
||||
old = P.GetComponent(dt)
|
||||
if(old)
|
||||
//One or the other has to die
|
||||
switch(dm)
|
||||
if(COMPONENT_DUPE_UNIQUE)
|
||||
old.InheritComponent(src, TRUE)
|
||||
qdel(src, TRUE, TRUE)
|
||||
return
|
||||
if(COMPONENT_DUPE_HIGHLANDER)
|
||||
InheritComponent(old, FALSE)
|
||||
qdel(old, FALSE, TRUE)
|
||||
|
||||
//provided we didn't eat someone
|
||||
if(!old)
|
||||
//let the others know
|
||||
P.SendSignal(COMSIG_COMPONENT_ADDED, src)
|
||||
|
||||
//lazy init the parent's dc list
|
||||
var/list/dc = P.datum_components
|
||||
if(!dc)
|
||||
@@ -212,10 +174,59 @@
|
||||
return list(.)
|
||||
|
||||
/datum/proc/AddComponent(new_type, ...)
|
||||
var/nt = new_type
|
||||
var/datum/component/nt = new_type
|
||||
var/dm = initial(nt.dupe_mode)
|
||||
var/dt = initial(nt.dupe_type)
|
||||
|
||||
var/datum/component/old_comp
|
||||
var/datum/component/new_comp
|
||||
|
||||
if(ispath(nt))
|
||||
if(nt == /datum/component)
|
||||
CRASH("[nt] attempted instantiation!")
|
||||
if(!isnum(dm))
|
||||
CRASH("[nt]: Invalid dupe_mode ([dm])!")
|
||||
if(dt && !ispath(dt))
|
||||
CRASH("[nt]: Invalid dupe_type ([dt])!")
|
||||
else
|
||||
new_comp = nt
|
||||
|
||||
args[1] = src
|
||||
var/datum/component/C = new nt(arglist(args))
|
||||
return QDELING(C) ? GetExactComponent(new_type) : C
|
||||
|
||||
if(dm != COMPONENT_DUPE_ALLOWED)
|
||||
if(!dt)
|
||||
old_comp = GetExactComponent(nt)
|
||||
else
|
||||
old_comp = GetComponent(dt)
|
||||
if(old_comp)
|
||||
switch(dm)
|
||||
if(COMPONENT_DUPE_UNIQUE)
|
||||
if(!new_comp)
|
||||
new_comp = new nt(arglist(args))
|
||||
if(!QDELETED(new_comp))
|
||||
old_comp.InheritComponent(new_comp, TRUE)
|
||||
qdel(new_comp)
|
||||
if(COMPONENT_DUPE_HIGHLANDER)
|
||||
if(!new_comp)
|
||||
new_comp = new nt(arglist(args))
|
||||
if(!QDELETED(new_comp))
|
||||
new_comp.InheritComponent(old_comp, FALSE)
|
||||
qdel(old_comp)
|
||||
if(COMPONENT_DUPE_UNIQUE_PASSARGS)
|
||||
if(!new_comp)
|
||||
var/list/arguments = args.Copy(2)
|
||||
old_comp.InheritComponent(null, TRUE, arguments)
|
||||
else
|
||||
old_comp.InheritComponent(new_comp, TRUE)
|
||||
else if(!new_comp)
|
||||
new_comp = new nt(arglist(args)) // There's a valid dupe mode but there's no old component, act like normal
|
||||
else if(!new_comp)
|
||||
new_comp = new nt(arglist(args)) // Dupes are allowed, act like normal
|
||||
|
||||
if(!old_comp && !QDELETED(new_comp)) // Nothing related to duplicate components happened and the new component is healthy
|
||||
SendSignal(COMSIG_COMPONENT_ADDED, new_comp)
|
||||
return new_comp
|
||||
return old_comp
|
||||
|
||||
/datum/proc/LoadComponent(component_type, ...)
|
||||
. = GetComponent(component_type)
|
||||
@@ -235,7 +246,8 @@
|
||||
C._RemoveFromParent()
|
||||
helicopter.SendSignal(COMSIG_COMPONENT_REMOVING, C)
|
||||
C.parent = src
|
||||
C._CheckDupesAndJoinParent()
|
||||
if(C == AddComponent(C))
|
||||
C._JoinParent()
|
||||
|
||||
/datum/proc/TransferComponents(datum/target)
|
||||
var/list/dc = datum_components
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
var/datum/callback/callback
|
||||
|
||||
/datum/component/archaeology/Initialize(_prob2drop, list/_archdrops = list(), datum/callback/_callback)
|
||||
prob2drop = Clamp(_prob2drop, 0, 100)
|
||||
prob2drop = CLAMP(_prob2drop, 0, 100)
|
||||
archdrops = _archdrops
|
||||
callback = _callback
|
||||
RegisterSignal(COMSIG_PARENT_ATTACKBY,.proc/Dig)
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/datum/component/cleaning
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
|
||||
|
||||
/datum/component/cleaning/Initialize()
|
||||
if(!ismovableatom(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("[type] added to a [parent.type]")
|
||||
RegisterSignal(list(COMSIG_MOVABLE_MOVED), .proc/Clean)
|
||||
|
||||
/datum/component/cleaning/proc/Clean()
|
||||
var/atom/movable/AM = parent
|
||||
var/turf/tile = AM.loc
|
||||
if(!isturf(tile))
|
||||
return
|
||||
|
||||
tile.clean_blood()
|
||||
for(var/A in tile)
|
||||
if(is_cleanable(A))
|
||||
qdel(A)
|
||||
else if(istype(A, /obj/item))
|
||||
var/obj/item/cleaned_item = A
|
||||
cleaned_item.clean_blood()
|
||||
else if(ishuman(A))
|
||||
var/mob/living/carbon/human/cleaned_human = A
|
||||
if(cleaned_human.lying)
|
||||
if(cleaned_human.head)
|
||||
cleaned_human.head.clean_blood()
|
||||
cleaned_human.update_inv_head()
|
||||
if(cleaned_human.wear_suit)
|
||||
cleaned_human.wear_suit.clean_blood()
|
||||
cleaned_human.update_inv_wear_suit()
|
||||
else if(cleaned_human.w_uniform)
|
||||
cleaned_human.w_uniform.clean_blood()
|
||||
cleaned_human.update_inv_w_uniform()
|
||||
if(cleaned_human.shoes)
|
||||
cleaned_human.shoes.clean_blood()
|
||||
cleaned_human.update_inv_shoes()
|
||||
cleaned_human.clean_blood()
|
||||
cleaned_human.wash_cream()
|
||||
to_chat(cleaned_human, "<span class='danger'>[AM] cleans your face!</span>")
|
||||
@@ -48,8 +48,7 @@
|
||||
if(old_dir == new_dir)
|
||||
return
|
||||
remove()
|
||||
var/rotation = SimplifyDegrees(dir2angle(new_dir)-dir2angle(old_dir))
|
||||
pic.dir = turn(pic.dir, rotation)
|
||||
pic.dir = turn(pic.dir, dir2angle(old_dir) - dir2angle(new_dir))
|
||||
apply()
|
||||
|
||||
/datum/component/decal/proc/clean_react(strength)
|
||||
@@ -57,4 +56,4 @@
|
||||
qdel(src)
|
||||
|
||||
/datum/component/decal/proc/examine(mob/user)
|
||||
to_chat(user, description)
|
||||
to_chat(user, description)
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/datum/component/forensics
|
||||
var/list/fingerprints //assoc print = print
|
||||
var/list/hiddenprints //assoc ckey = realname/gloves/ckey
|
||||
var/list/blood_DNA //assoc dna = bloodtype
|
||||
var/list/fibers //assoc print = print
|
||||
|
||||
/datum/component/forensics/InheritComponent(datum/component/forensics/F, original) //Use of | and |= being different here is INTENTIONAL.
|
||||
fingerprints = fingerprints | F.fingerprints
|
||||
hiddenprints = hiddenprints | F.hiddenprints
|
||||
blood_DNA = blood_DNA | F.blood_DNA
|
||||
fibers = fibers | F.fibers
|
||||
check_blood()
|
||||
return ..()
|
||||
|
||||
/datum/component/forensics/Initialize(new_fingerprints, new_hiddenprints, new_blood_DNA, new_fibers)
|
||||
if(!isatom(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("Forensics datum applied incorrectly to non-atom of type [parent.type]!")
|
||||
fingerprints = new_fingerprints
|
||||
hiddenprints = new_hiddenprints
|
||||
blood_DNA = new_blood_DNA
|
||||
fibers = new_fibers
|
||||
check_blood()
|
||||
RegisterSignal(COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_act)
|
||||
|
||||
/datum/component/forensics/proc/wipe_fingerprints()
|
||||
fingerprints = null
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/wipe_hiddenprints()
|
||||
return //no.
|
||||
|
||||
/datum/component/forensics/proc/wipe_blood_DNA()
|
||||
blood_DNA = null
|
||||
if(isitem(parent))
|
||||
qdel(parent.GetComponent(/datum/component/decal/blood))
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/wipe_fibers()
|
||||
fibers = null
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/clean_act(strength)
|
||||
if(strength >= CLEAN_STRENGTH_FINGERPRINTS)
|
||||
wipe_fingerprints()
|
||||
if(strength >= CLEAN_STRENGTH_BLOOD)
|
||||
wipe_blood_DNA()
|
||||
if(strength >= CLEAN_STRENGTH_FIBERS)
|
||||
wipe_fibers()
|
||||
|
||||
/datum/component/forensics/proc/add_fingerprint_list(list/_fingerprints) //list(text)
|
||||
if(!length(_fingerprints))
|
||||
return
|
||||
LAZYINITLIST(fingerprints)
|
||||
for(var/i in _fingerprints) //We use an associative list, make sure we don't just merge a non-associative list into ours.
|
||||
fingerprints[i] = i
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/add_fingerprint(mob/living/M, ignoregloves = FALSE)
|
||||
if(!M)
|
||||
return
|
||||
add_hiddenprint(M)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
add_fibers(H)
|
||||
if(H.gloves) //Check if the gloves (if any) hide fingerprints
|
||||
var/obj/item/clothing/gloves/G = H.gloves
|
||||
if(G.transfer_prints)
|
||||
ignoregloves = TRUE
|
||||
if(!ignoregloves)
|
||||
H.gloves.add_fingerprint(H, TRUE) //ignoregloves = 1 to avoid infinite loop.
|
||||
return
|
||||
var/full_print = md5(H.dna.uni_identity)
|
||||
LAZYSET(fingerprints, full_print, full_print)
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/add_fiber_list(list/_fibertext) //list(text)
|
||||
if(!length(_fibertext))
|
||||
return
|
||||
LAZYINITLIST(fibers)
|
||||
for(var/i in _fibertext) //We use an associative list, make sure we don't just merge a non-associative list into ours.
|
||||
fibers[i] = i
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/add_fibers(mob/living/carbon/human/M)
|
||||
var/fibertext
|
||||
var/item_multiplier = isitem(src)?1.2:1
|
||||
if(M.wear_suit)
|
||||
fibertext = "Material from \a [M.wear_suit]."
|
||||
if(prob(10*item_multiplier) && !LAZYACCESS(fibers, fibertext))
|
||||
LAZYSET(fibers, fibertext, fibertext)
|
||||
if(!(M.wear_suit.body_parts_covered & CHEST))
|
||||
if(M.w_uniform)
|
||||
fibertext = "Fibers from \a [M.w_uniform]."
|
||||
if(prob(12*item_multiplier) && !LAZYACCESS(fibers, fibertext)) //Wearing a suit means less of the uniform exposed.
|
||||
LAZYSET(fibers, fibertext, fibertext)
|
||||
if(!(M.wear_suit.body_parts_covered & HANDS))
|
||||
if(M.gloves)
|
||||
fibertext = "Material from a pair of [M.gloves.name]."
|
||||
if(prob(20*item_multiplier) && !LAZYACCESS(fibers, fibertext))
|
||||
LAZYSET(fibers, fibertext, fibertext)
|
||||
else if(M.w_uniform)
|
||||
fibertext = "Fibers from \a [M.w_uniform]."
|
||||
if(prob(15*item_multiplier) && !LAZYACCESS(fibers, fibertext))
|
||||
// "Added fibertext: [fibertext]"
|
||||
LAZYSET(fibers, fibertext, fibertext)
|
||||
if(M.gloves)
|
||||
fibertext = "Material from a pair of [M.gloves.name]."
|
||||
if(prob(20*item_multiplier) && !LAZYACCESS(fibers, fibertext))
|
||||
LAZYSET(fibers, fibertext, fibertext)
|
||||
else if(M.gloves)
|
||||
fibertext = "Material from a pair of [M.gloves.name]."
|
||||
if(prob(20*item_multiplier) && !LAZYACCESS(fibers, fibertext))
|
||||
LAZYSET(fibers, fibertext, fibertext)
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/add_hiddenprint_list(list/_hiddenprints) //list(ckey = text)
|
||||
if(!length(_hiddenprints))
|
||||
return
|
||||
LAZYINITLIST(hiddenprints)
|
||||
for(var/i in _hiddenprints) //We use an associative list, make sure we don't just merge a non-associative list into ours.
|
||||
hiddenprints[i] = _hiddenprints[i]
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/add_hiddenprint(mob/living/M)
|
||||
if(!M || !M.key)
|
||||
return
|
||||
var/hasgloves = ""
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.gloves)
|
||||
hasgloves = "(gloves)"
|
||||
var/current_time = time_stamp()
|
||||
if(!LAZYACCESS(hiddenprints, M.key))
|
||||
LAZYSET(hiddenprints, M.key, "First: [M.real_name]\[[current_time]\][hasgloves]. Ckey: [M.ckey]")
|
||||
else
|
||||
var/laststamppos = findtext(LAZYACCESS(hiddenprints, M.key), " Last: ")
|
||||
if(laststamppos)
|
||||
LAZYSET(hiddenprints, M.key, copytext(hiddenprints[M.key], 1, laststamppos))
|
||||
hiddenprints[M.key] += " Last: [M.real_name]\[[current_time]\][hasgloves]. Ckey: [M.ckey]" //made sure to be existing by if(!LAZYACCESS);else
|
||||
parent.fingerprintslast = M.ckey
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/add_blood_DNA(list/dna) //list(dna_enzymes = type)
|
||||
if(!length(dna))
|
||||
return
|
||||
LAZYINITLIST(blood_DNA)
|
||||
for(var/i in dna)
|
||||
blood_DNA[i] = dna[i]
|
||||
check_blood()
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/check_blood()
|
||||
if(!isitem(parent))
|
||||
return
|
||||
if(!length(blood_DNA))
|
||||
return
|
||||
parent.LoadComponent(/datum/component/decal/blood)
|
||||
@@ -0,0 +1,81 @@
|
||||
/datum/component/jousting
|
||||
var/current_direction = NONE
|
||||
var/max_tile_charge = 5
|
||||
var/min_tile_charge = 2 //tiles before this code gets into effect.
|
||||
var/current_tile_charge = 0
|
||||
var/movement_reset_tolerance = 2 //deciseconds
|
||||
var/unmounted_damage_boost_per_tile = 0
|
||||
var/unmounted_knockdown_chance_per_tile = 0
|
||||
var/unmounted_knockdown_time = 0
|
||||
var/mounted_damage_boost_per_tile = 2
|
||||
var/mounted_knockdown_chance_per_tile = 20
|
||||
var/mounted_knockdown_time = 20
|
||||
var/requires_mob_riding = TRUE //whether this only works if the attacker is riding a mob, rather than anything they can buckle to.
|
||||
var/requires_mount = TRUE //kinda defeats the point of jousting if you're not mounted but whatever.
|
||||
var/mob/current_holder
|
||||
var/datum/component/redirect/listener
|
||||
var/current_timerid
|
||||
|
||||
/datum/component/jousting/Initialize()
|
||||
if(!isitem(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
stack_trace("Warning: Jousting component incorrectly applied to invalid parent type [parent.type]")
|
||||
RegisterSignal(COMSIG_ITEM_EQUIPPED, .proc/on_equip)
|
||||
RegisterSignal(COMSIG_ITEM_DROPPED, .proc/on_drop)
|
||||
RegisterSignal(COMSIG_ITEM_ATTACK, .proc/on_attack)
|
||||
|
||||
/datum/component/jousting/Destroy()
|
||||
QDEL_NULL(listener)
|
||||
return ..()
|
||||
|
||||
/datum/component/jousting/proc/on_equip(mob/user, slot)
|
||||
QDEL_NULL(listener)
|
||||
current_holder = user
|
||||
listener = new(user, COMSIG_MOVABLE_MOVED, CALLBACK(src, .proc/mob_move))
|
||||
|
||||
/datum/component/jousting/proc/on_drop(mob/user)
|
||||
QDEL_NULL(listener)
|
||||
current_holder = null
|
||||
current_direction = NONE
|
||||
current_tile_charge = 0
|
||||
|
||||
/datum/component/jousting/proc/on_attack(mob/living/target, mob/user)
|
||||
if(user != current_holder)
|
||||
return
|
||||
var/current = current_tile_charge
|
||||
var/obj/item/I = parent
|
||||
var/target_buckled = target.buckled ? TRUE : FALSE //we don't need the reference of what they're buckled to, just whether they are.
|
||||
if((requires_mount && ((requires_mob_riding && !ismob(user.buckled)) || (!user.buckled))) || !current_direction || (current_tile_charge < min_tile_charge))
|
||||
return
|
||||
var/turf/target_turf = get_step(user, current_direction)
|
||||
if(target in range(1, target_turf))
|
||||
var/knockdown_chance = (target_buckled? mounted_knockdown_chance_per_tile : unmounted_knockdown_chance_per_tile) * current
|
||||
var/knockdown_time = (target_buckled? mounted_knockdown_time : unmounted_knockdown_time)
|
||||
var/damage = (target_buckled? mounted_damage_boost_per_tile : unmounted_damage_boost_per_tile) * current
|
||||
var/sharp = I.is_sharp()
|
||||
var/msg
|
||||
if(damage)
|
||||
msg += "[user] [sharp? "impales" : "slams into"] [target] [sharp? "on" : "with"] their [parent]"
|
||||
target.apply_damage(damage, BRUTE, user.zone_selected, 0)
|
||||
if(prob(knockdown_chance))
|
||||
msg += " and knocks [target] [target_buckled? "off of [target.buckled]" : "down"]"
|
||||
if(target_buckled)
|
||||
target.buckled.unbuckle_mob(target)
|
||||
target.Knockdown(knockdown_time)
|
||||
if(length(msg))
|
||||
user.visible_message("<span class='danger'>[msg]!</span>")
|
||||
|
||||
/datum/component/jousting/proc/mob_move(newloc, dir)
|
||||
if(!current_holder || (requires_mount && ((requires_mob_riding && !ismob(current_holder.buckled)) || (!current_holder.buckled))))
|
||||
return
|
||||
if(dir != current_direction)
|
||||
current_tile_charge = 0
|
||||
current_direction = dir
|
||||
if(current_tile_charge < max_tile_charge)
|
||||
current_tile_charge++
|
||||
if(current_timerid)
|
||||
deltimer(current_timerid)
|
||||
current_timerid = addtimer(CALLBACK(src, .proc/reset_charge), movement_reset_tolerance, TIMER_STOPPABLE)
|
||||
|
||||
/datum/component/jousting/proc/reset_charge()
|
||||
current_tile_charge = 0
|
||||
@@ -0,0 +1,53 @@
|
||||
//Items with these will have a chance to get knocked off when disarming
|
||||
/datum/component/knockoff
|
||||
var/knockoff_chance = 100 //Chance to knockoff
|
||||
var/list/target_zones //Aiming for these zones will cause the knockoff, null means all zones allowed
|
||||
var/list/slots_knockoffable //Can be only knocked off from these slots, null means all slots allowed
|
||||
var/datum/component/redirect/disarm_redirect
|
||||
|
||||
/datum/component/knockoff/Initialize(knockoff_chance,zone_override,slots_knockoffable)
|
||||
if(!isitem(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("Knockoff component misuse")
|
||||
RegisterSignal(COMSIG_ITEM_EQUIPPED,.proc/OnEquipped)
|
||||
RegisterSignal(COMSIG_ITEM_DROPPED,.proc/OnDropped)
|
||||
|
||||
src.knockoff_chance = knockoff_chance
|
||||
|
||||
if(zone_override)
|
||||
target_zones = zone_override
|
||||
|
||||
if(slots_knockoffable)
|
||||
src.slots_knockoffable = slots_knockoffable
|
||||
|
||||
/datum/component/knockoff/proc/Knockoff(mob/living/attacker,zone)
|
||||
var/obj/item/I = parent
|
||||
var/mob/living/carbon/human/wearer = I.loc
|
||||
if(!istype(wearer))
|
||||
return
|
||||
if(target_zones && !(zone in target_zones))
|
||||
return
|
||||
if(!prob(knockoff_chance))
|
||||
return
|
||||
if(!wearer.dropItemToGround(I))
|
||||
return
|
||||
|
||||
wearer.visible_message("<span class='warning'>[attacker] knocks off [wearer]'s [I.name]!</span>","<span class='userdanger'>[attacker] knocks off your [I.name]!</span>")
|
||||
|
||||
/datum/component/knockoff/proc/OnEquipped(mob/living/carbon/human/H,slot)
|
||||
if(!istype(H))
|
||||
return
|
||||
if(slots_knockoffable && !(slot in slots_knockoffable))
|
||||
if(disarm_redirect)
|
||||
QDEL_NULL(disarm_redirect)
|
||||
return
|
||||
if(!disarm_redirect)
|
||||
disarm_redirect = H.AddComponent(/datum/component/redirect,list(COMSIG_HUMAN_DISARM_HIT),CALLBACK(src,.proc/Knockoff))
|
||||
|
||||
/datum/component/knockoff/proc/OnDropped(mob/living/M)
|
||||
if(disarm_redirect)
|
||||
QDEL_NULL(disarm_redirect)
|
||||
|
||||
/datum/component/knockoff/Destroy()
|
||||
QDEL_NULL(disarm_redirect)
|
||||
. = ..()
|
||||
@@ -51,7 +51,7 @@
|
||||
|
||||
/datum/component/material_container/proc/OnAttackBy(obj/item/I, mob/living/user)
|
||||
var/list/tc = allowed_typecache
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
if(user.a_intent != INTENT_HELP)
|
||||
return
|
||||
if((I.flags_2 & (HOLOGRAM_2 | NO_MAT_REDEMPTION_2)) || (tc && !is_type_in_typecache(I, tc)))
|
||||
to_chat(user, "<span class='warning'>[parent] won't accept [I]!</span>")
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#define RAD_AMOUNT_EXTREME 1000
|
||||
|
||||
/datum/component/radioactive
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
|
||||
|
||||
var/source
|
||||
|
||||
@@ -47,13 +47,16 @@
|
||||
if(strength <= RAD_BACKGROUND_RADIATION)
|
||||
return PROCESS_KILL
|
||||
|
||||
/datum/component/radioactive/InheritComponent(datum/component/C, i_am_original)
|
||||
/datum/component/radioactive/InheritComponent(datum/component/C, i_am_original, list/arguments)
|
||||
if(!i_am_original)
|
||||
return
|
||||
if(!hl3_release_date) // Permanently radioactive things don't get to grow stronger
|
||||
return
|
||||
var/datum/component/radioactive/other = C
|
||||
strength = max(strength, other.strength)
|
||||
if(C)
|
||||
var/datum/component/radioactive/other = C
|
||||
strength = max(strength, other.strength)
|
||||
else
|
||||
strength = max(strength, arguments[1])
|
||||
|
||||
/datum/component/radioactive/proc/rad_examine(mob/user, atom/thing)
|
||||
var/atom/master = parent
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/datum/component/thermite
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
|
||||
var/amount
|
||||
var/overlay
|
||||
|
||||
@@ -46,10 +46,13 @@
|
||||
master.cut_overlay(overlay)
|
||||
return ..()
|
||||
|
||||
/datum/component/thermite/InheritComponent(datum/component/thermite/newC, i_am_original)
|
||||
/datum/component/thermite/InheritComponent(datum/component/thermite/newC, i_am_original, list/arguments)
|
||||
if(!i_am_original)
|
||||
return
|
||||
amount += newC.amount
|
||||
if(newC)
|
||||
amount += newC.amount
|
||||
else
|
||||
amount += arguments[1]
|
||||
|
||||
/datum/component/thermite/proc/thermite_melt(mob/user)
|
||||
var/turf/master = parent
|
||||
@@ -60,7 +63,7 @@
|
||||
|
||||
if(amount >= 50)
|
||||
var/burning_time = max(100, 100-amount)
|
||||
master = master.ChangeTurf(master.baseturf)
|
||||
master = master.ScrapeAway()
|
||||
master.burn_tile()
|
||||
if(user)
|
||||
master.add_hiddenprint(user)
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
addtimer(CALLBACK(src, .proc/charge), charge_rate)
|
||||
|
||||
/datum/action/innate/dash/proc/charge()
|
||||
current_charges = Clamp(current_charges + 1, 0, max_charges)
|
||||
current_charges = CLAMP(current_charges + 1, 0, max_charges)
|
||||
holder.update_action_buttons_icon()
|
||||
if(recharge_sound)
|
||||
playsound(dashing_item, recharge_sound, 50, 1)
|
||||
|
||||
@@ -3,29 +3,29 @@
|
||||
for(var/thing in viruses)
|
||||
var/datum/disease/DD = thing
|
||||
if(D.IsSame(DD))
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/mob/proc/CanContractDisease(datum/disease/D)
|
||||
if(stat == DEAD)
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if(D.GetDiseaseID() in resistances)
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if(HasDisease(D))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if(!(type in D.viable_mobtypes))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
|
||||
/mob/proc/ContactContractDisease(datum/disease/D)
|
||||
if(!CanContractDisease(D))
|
||||
return 0
|
||||
return FALSE
|
||||
AddDisease(D)
|
||||
|
||||
|
||||
@@ -53,12 +53,13 @@
|
||||
else
|
||||
DD.vars[V] = D.vars[V]
|
||||
|
||||
DD.after_add()
|
||||
DD.affected_mob.med_hud_set_status()
|
||||
|
||||
|
||||
/mob/living/carbon/ContactContractDisease(datum/disease/D, target_zone)
|
||||
if(!CanContractDisease(D))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
var/obj/item/clothing/Cl = null
|
||||
var/passed = TRUE
|
||||
|
||||
@@ -60,14 +60,14 @@
|
||||
|
||||
/datum/disease/proc/has_cure()
|
||||
if(!(disease_flags & CURABLE))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
. = cures.len
|
||||
for(var/C_id in cures)
|
||||
if(!affected_mob.reagents.has_reagent(C_id))
|
||||
.--
|
||||
if(!. || (needs_all_cures && . < cures.len))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
//Airborne spreading
|
||||
/datum/disease/proc/spread(force_spread = 0)
|
||||
@@ -111,8 +111,8 @@
|
||||
|
||||
/datum/disease/proc/IsSame(datum/disease/D)
|
||||
if(istype(src, D.type))
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/datum/disease/proc/Copy()
|
||||
@@ -120,6 +120,9 @@
|
||||
D.strain_data = strain_data.Copy()
|
||||
return D
|
||||
|
||||
/datum/disease/proc/after_add()
|
||||
return
|
||||
|
||||
|
||||
/datum/disease/proc/GetDiseaseID()
|
||||
return "[type]"
|
||||
|
||||
@@ -185,10 +185,10 @@
|
||||
if(properties["stealth"] >= 2)
|
||||
visibility_flags = HIDDEN_SCANNER
|
||||
|
||||
SetSpread(Clamp(2 ** (properties["transmittable"] - symptoms.len), VIRUS_SPREAD_BLOOD, VIRUS_SPREAD_AIRBORNE))
|
||||
SetSpread(CLAMP(2 ** (properties["transmittable"] - symptoms.len), VIRUS_SPREAD_BLOOD, VIRUS_SPREAD_AIRBORNE))
|
||||
|
||||
permeability_mod = max(Ceiling(0.4 * properties["transmittable"]), 1)
|
||||
cure_chance = 15 - Clamp(properties["resistance"], -5, 5) // can be between 10 and 20
|
||||
permeability_mod = max(CEILING(0.4 * properties["transmittable"], 1), 1)
|
||||
cure_chance = 15 - CLAMP(properties["resistance"], -5, 5) // can be between 10 and 20
|
||||
stage_prob = max(properties["stage_rate"], 2)
|
||||
SetSeverity(properties["severity"])
|
||||
GenerateCure(properties)
|
||||
@@ -243,7 +243,7 @@
|
||||
// Will generate a random cure, the less resistance the symptoms have, the harder the cure.
|
||||
/datum/disease/advance/proc/GenerateCure()
|
||||
if(properties && properties.len)
|
||||
var/res = Clamp(properties["resistance"] - (symptoms.len / 2), 1, advance_cures.len)
|
||||
var/res = CLAMP(properties["resistance"] - (symptoms.len / 2), 1, advance_cures.len)
|
||||
cures = list(advance_cures[res])
|
||||
|
||||
// Get the cure name from the cure_id
|
||||
|
||||
@@ -61,7 +61,7 @@ Bonus
|
||||
M.become_nearsighted()
|
||||
if(prob(eyes.eye_damage - 10 + 1))
|
||||
if(!remove_eyes)
|
||||
if(M.become_blind())
|
||||
if(!M.has_disability(DISABILITY_BLIND))
|
||||
to_chat(M, "<span class='userdanger'>You go blind!</span>")
|
||||
else
|
||||
M.visible_message("<span class='warning'>[M]'s eyes fall off their sockets!</span>", "<span class='userdanger'>Your eyes fall off their sockets!</span>")
|
||||
@@ -111,18 +111,16 @@ Bonus
|
||||
return
|
||||
switch(A.stage)
|
||||
if(4, 5) //basically oculine
|
||||
if(M.disabilities & BLIND)
|
||||
if(M.has_disability(DISABILITY_BLIND, EYE_DAMAGE))
|
||||
if(prob(20))
|
||||
to_chat(M, "<span class='warning'>Your vision slowly returns...</span>")
|
||||
M.cure_blind()
|
||||
M.cure_nearsighted()
|
||||
M.blur_eyes(35)
|
||||
|
||||
else if(M.disabilities & NEARSIGHT)
|
||||
else if(M.has_disability(DISABILITY_NEARSIGHT, EYE_DAMAGE))
|
||||
to_chat(M, "<span class='warning'>The blackness in your peripheral vision fades.</span>")
|
||||
M.cure_nearsighted()
|
||||
M.blur_eyes(10)
|
||||
|
||||
else if(M.eye_blind || M.eye_blurry)
|
||||
M.set_blindness(0)
|
||||
M.set_blurriness(0)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user