diff --git a/SQL/paradise_schema.sql b/SQL/paradise_schema.sql index 36381013065..750e15488b5 100644 --- a/SQL/paradise_schema.sql +++ b/SQL/paradise_schema.sql @@ -247,6 +247,7 @@ CREATE TABLE `player` ( `randomslot` tinyint(1) DEFAULT '0', `volume` smallint(4) DEFAULT '100', `nanoui_fancy` smallint(4) DEFAULT '1', + `show_ghostitem_attack` smallint(4) DEFAULT '1', PRIMARY KEY (`id`), UNIQUE KEY `ckey` (`ckey`) ) ENGINE=InnoDB AUTO_INCREMENT=32446 DEFAULT CHARSET=latin1; diff --git a/SQL/paradise_schema_prefixed.sql b/SQL/paradise_schema_prefixed.sql index e599326ba8e..8af09a45737 100644 --- a/SQL/paradise_schema_prefixed.sql +++ b/SQL/paradise_schema_prefixed.sql @@ -247,6 +247,7 @@ CREATE TABLE `SS13_player` ( `randomslot` tinyint(1) DEFAULT '0', `volume` smallint(4) DEFAULT '100', `nanoui_fancy` smallint(4) DEFAULT '1', + `show_ghostitem_attack` smallint(4) DEFAULT '1', PRIMARY KEY (`id`), UNIQUE KEY `ckey` (`ckey`) ) ENGINE=InnoDB AUTO_INCREMENT=32446 DEFAULT CHARSET=latin1; diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm index 00e7cc5cac1..4e12bb5b05a 100644 --- a/_maps/map_files/cyberiad/cyberiad.dmm +++ b/_maps/map_files/cyberiad/cyberiad.dmm @@ -6357,12 +6357,12 @@ "csm" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/camera{c_tag = "Mechanic's Workshop East"; dir = 2; network = list("SS13")},/obj/machinery/space_heater,/turf/simulated/floor/plasteel{icon_state = "vault"; dir = 8},/area/engine/mechanic_workshop) "csn" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/closet/emcloset,/turf/simulated/floor/plasteel{icon_state = "vault"; dir = 8},/area/engine/mechanic_workshop) "cso" = (/obj/effect/spawner/window/reinforced,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plating,/area/engine/mechanic_workshop) -"csp" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft) -"csq" = (/obj/machinery/light{dir = 1},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft) -"csr" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft) -"css" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 1; initialize_directions = 11; level = 1},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft) -"cst" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft) -"csu" = (/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft) +"csp" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 1; initialize_directions = 11; level = 1},/obj/machinery/requests_console{department = "Mechanic"; departmentType = 2; name = "Mechanic's Workshop Requests Console"; pixel_y = 30},/obj/structure/disposalpipe/trunk,/obj/machinery/disposal,/turf/simulated/floor/plasteel,/area/engine/mechanic_workshop) +"csq" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft) +"csr" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/disposalpipe/segment{dir = 4; icon_state = "pipe-c"},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft) +"css" = (/obj/machinery/light{dir = 1},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft) +"cst" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 1; initialize_directions = 11; level = 1},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft) +"csu" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft) "csv" = (/obj/structure/disposalpipe/junction{dir = 8; icon_state = "pipe-j2"; tag = "icon-pipe-j1 (WEST)"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft) "csw" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/light{dir = 1},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft) "csx" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft) @@ -6419,11 +6419,11 @@ "ctw" = (/obj/machinery/atmospherics/unary/vent_pump{on = 0},/turf/simulated/floor/engine,/area/engine/mechanic_workshop) "ctx" = (/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "mechpod"; name = "Mechanic's Workshop Inner Door"; opacity = 0},/turf/simulated/floor/engine,/area/engine/mechanic_workshop) "cty" = (/turf/simulated/floor/plasteel{dir = 8; icon_state = "warning"},/area/engine/mechanic_workshop) -"ctz" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 1; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/turf/simulated/floor/plasteel,/area/engine/mechanic_workshop) -"ctA" = (/obj/machinery/hologram/holopad,/turf/simulated/floor/plasteel{dir = 4; icon_state = "warning"},/area/engine/mechanic_workshop) +"ctz" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft) +"ctA" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/disposalpipe/junction{dir = 1; icon_state = "pipe-y"},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft) "ctB" = (/turf/simulated/floor/plasteel{icon_state = "dark"},/area/engine/mechanic_workshop) -"ctC" = (/obj/machinery/atmospherics/unary/vent_pump{on = 0},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/engine/mechanic_workshop) -"ctD" = (/obj/machinery/door/firedoor{dir = 8; name = "Firelock West"},/obj/machinery/door/airlock/glass_engineering{name = "Mechanic Workshop"; req_access_txt = "70"; req_one_access_txt = "0"},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/engine/mechanic_workshop) +"ctC" = (/obj/machinery/hologram/holopad,/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "warning"},/area/engine/mechanic_workshop) +"ctD" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 1; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/turf/simulated/floor/plasteel,/area/engine/mechanic_workshop) "ctE" = (/turf/simulated/floor/plasteel,/area/hallway/primary/aft) "ctF" = (/obj/machinery/atmospherics/unary/vent_pump{on = 0},/turf/simulated/floor/plasteel,/area/hallway/primary/aft) "ctG" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 1; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/turf/simulated/floor/plasteel{dir = 2; icon_state = "yellowcorner"},/area/hallway/primary/aft) @@ -8264,7 +8264,7 @@ "dcV" = (/obj/machinery/computer/general_air_control/large_tank_control{frequency = 1441; input_tag = "co2_in"; name = "Carbon Dioxide Supply Control"; output_tag = "co2_out"; sensors = list("co2_sensor" = "Tank")},/turf/simulated/floor/plasteel{icon_state = "caution"; dir = 4},/area/atmos) "dcW" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'HIGH VOLTAGE'"; icon_state = "shock"; name = "HIGH VOLTAGE"; pixel_y = 32},/turf/simulated/wall/r_wall,/area/engine/engineering) "dcX" = (/obj/machinery/atmospherics/pipe/simple/visible/green{dir = 4; level = 2},/turf/simulated/floor/plasteel{dir = 6; icon_state = "caution"},/area/atmos) -"dcY" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 1; initialize_directions = 11; level = 1},/obj/machinery/requests_console{department = "Mechanic"; departmentType = 2; name = "Mechanic's Workshop Requests Console"; pixel_y = 30},/turf/simulated/floor/plasteel,/area/engine/mechanic_workshop) +"dcY" = (/obj/machinery/atmospherics/unary/vent_pump{on = 0},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/engine/mechanic_workshop) "dcZ" = (/obj/item/device/radio/intercom{pixel_y = 25},/turf/simulated/floor/plasteel,/area/hallway/primary/starboard/west) "dda" = (/obj/machinery/camera/emp_proof{c_tag = "Engineering Singularity North-East"; dir = 2; network = list("Singularity","SS13")},/obj/machinery/power/grounding_rod{anchored = 1},/turf/simulated/floor/plating/airless,/area/engine/engineering) "ddb" = (/obj/item/weapon/wrench,/obj/machinery/access_button{command = "cycle_exterior"; frequency = 1379; master_tag = "engineering_east_airlock"; name = "exterior access button"; pixel_x = -20; pixel_y = 20; req_access_txt = "10;13"},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/turf/simulated/floor/plating/airless,/area/engine/engineering) @@ -8738,6 +8738,8 @@ "dmb" = (/obj/item/weapon/storage/fancy/donut_box,/obj/structure/table,/obj/item/weapon/book/manual/sop_general,/turf/simulated/floor/wood,/area/bridge/meeting_room) "dmc" = (/obj/structure/table/woodentable,/obj/item/weapon/book/manual/security_space_law,/obj/item/weapon/coin/plasma,/obj/item/device/megaphone,/obj/item/weapon/book/manual/sop_general,/turf/simulated/floor/wood,/area/crew_quarters/captain) "dmd" = (/obj/machinery/light{dir = 1},/obj/structure/bookcase,/obj/item/weapon/book/manual/sop_engineering,/obj/item/weapon/book/manual/sop_medical,/obj/item/weapon/book/manual/sop_science,/obj/item/weapon/book/manual/sop_security,/obj/item/weapon/book/manual/sop_service,/obj/item/weapon/book/manual/sop_supply,/obj/item/weapon/book/manual/sop_general,/obj/item/weapon/book/manual/sop_legal,/turf/simulated/floor/wood,/area/ntrep) +"dme" = (/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/engine/mechanic_workshop) +"dmf" = (/obj/machinery/door/firedoor{dir = 8; name = "Firelock West"},/obj/machinery/door/airlock/glass_engineering{name = "Mechanic Workshop"; req_access_txt = "70"; req_one_access_txt = "0"},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/engine/mechanic_workshop) (1,1,1) = {" bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik @@ -8902,8 +8904,8 @@ bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbi bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaahbikcnHcpccpdcpecpfcmBcpgcphcpicmBcpjcpkcplcpmcjMbikcpncjOcpocjQcppcjScjScpqcprcpscptcpucpvcwqcobcgfcpycpzcpAcpBcpCciVcpDclAclAclAcpEciWbGybGycpFcpFcpGcpHcpIcpIcpIcyFcpJcpJcpJcpKcpFcpGcpMcqQcfdcrLcEjbjVcEYdbndbmcxNclRckDcoucpNcovckDbGycuscoAcoAaabaabbikbikbikbikbikbikbikbikbikbikbikcpRcpScpTcpUcpVcpWcpXcpXcpYcpXcpXcpXcpXcpXcpZcqacqbcqccqdbwocvvbXSbwobwoaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbWhcqhcqicqjbWhbWhbXZbXZcqkbXZbXZbWhbWhaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikcnHcqlcnJcqmcnJcqncqocqpcqqcnNcqrcjKcqscelcejbikbikbikbikciEcqtcqucqvcqvciLcqwciLcqxcgdcbkcqycqzcqAcqBcqCcqCcqCcqDcqEclAcqFclAcqGciWbGybGycpFcqHcqIcqJcqKcqLcqMcpFcqLcqMcqKcqNdehcqPcpMczecyWczgcEjdbpdbodbrdbqdbsctcckDcpOcpPcpQckDbGycuscoAcvyaabaabaabbikbikbikbikbikbikbikbikbikbikcpRcqUcqVcqWcqXcqYcqZcracrbcpXcpXcrccpXcpXcpZcqbcqbcqbcrdbwocvzbxXbwoaabaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbWfcrhcribZvbWgbWhbWhbXZbYabXZbWhbWhaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikadbabLcrjcrjcrjcrjcrjcrjcrjcrjcrkcrkcrkcrkcrkcjKcjKcjKcjKcjKcjKcjKcekcrlcrmcrmcrmcrmcrmciEciLciLciLciLciLciLciLcrncgdcbkcrocrpcrqcrrcrscrtcrucrvcrwcrxcrycrzcrAciWbGybGycpFcrBcrCcqJcqKcqKcrDcpFcrEcqKcqKcqNcqKcrFcpMbGwbGwbGwcEjdbudbtdbvdbmdbxctcdbydbydbycoAcoAbGycuscoDcwpbikaabaabaabbikbikbikbikbikbikbikbikbikcpRczNczPcoBcrOcrPcrQcrRcrScpXcpXcpXcpXcrTcrUcrVcrWcrXcrYbwocvzbxXbwobikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbWfbWfbWfbWfbWgbWgbWhbWhbWhbWhbWiaabaabbikbikaahbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaahbikbikbikbikbikbikbikbikbikbikbikbikaSecsdcsecsfcsgcsgcshcsidcYcskcslcsmcsncsocspcspcspcsqcsrcsscstcstcsucsvcswcsxcsycsxcsxcsxcswcsxcsxcszcsAcsBcsCcgdcbkcsDcsEcsFcsGcgfcsHcmQcsIcsJcsKcsLcsMcsNcsObGybGycpFcsPcsQcsRcsScsTcsUcpFcsVcsTcsWcsXdlFcsYcwrbikbikbikcEjdbAdbzdbAdbAdbCdbBdbEdbDdbycwFbVibGycuscoDcwpbikbikaabaabaabbikbikbikbikbikbikbikbikctdckPcxGckSctdctfctgcthctictjctkctlcpXcpXctmctnctoctpctqbwocvzbxXcxHbikbikbikbikbikbikbikbikbikbikbikaahbikbikbikbikbikbikbikaabaabaabaabbikbikbikbikaabaabaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaSecsdctuctvctwctvctxctyctzctActBctCctBctDctEctEctFctEcgdctGcblcblctEctHctEctEctEctEctEctEctEctEctEctEctIctJctKctLctMctNctOctPctQctRctSctTctUctVctWctXciFctZcuacnqcubcuccudcuecufcugcuhcuicpFcujcqKcugcukcqKculcwrbikbikbikdbFcmkdbGdbJdbIdbCdbKdbMdbLdbOdbNceFceJdbPcoDcwpbikbikbikaabaabaabbikbikbikbikbikbikbikckPcurczQcutckPcnCcnCcnCcnCcnCcnCcuuctlcuvcuwcuxcuycnCcnCbwocvzbxXcxHbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaahbikbikbikbikbikbikbikbikbikbikbikbikaSecsdcsecsfcsgcsgcshcsicspcskcslcsmcsncsocsrcsqcsqcsscsucstctzctzctAcsvcswcsxcsycsxcsxcsxcswcsxcsxcszcsAcsBcsCcgdcbkcsDcsEcsFcsGcgfcsHcmQcsIcsJcsKcsLcsMcsNcsObGybGycpFcsPcsQcsRcsScsTcsUcpFcsVcsTcsWcsXdlFcsYcwrbikbikbikcEjdbAdbzdbAdbAdbCdbBdbEdbDdbycwFbVibGycuscoDcwpbikbikaabaabaabbikbikbikbikbikbikbikbikctdckPcxGckSctdctfctgcthctictjctkctlcpXcpXctmctnctoctpctqbwocvzbxXcxHbikbikbikbikbikbikbikbikbikbikbikaahbikbikbikbikbikbikbikaabaabaabaabbikbikbikbikaabaabaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaSecsdctuctvctwctvctxctyctDctCdmedcYdmedmfcxnctEctFctEcgdctGcblcblctEctHctEctEctEctEctEctEctEctEctEctEctIctJctKctLctMctNctOctPctQctRctSctTctUctVctWctXciFctZcuacnqcubcuccudcuecufcugcuhcuicpFcujcqKcugcukcqKculcwrbikbikbikdbFcmkdbGdbJdbIdbCdbKdbMdbLdbOdbNceFceJdbPcoDcwpbikbikbikaabaabaabbikbikbikbikbikbikbikckPcurczQcutckPcnCcnCcnCcnCcnCcnCcuuctlcuvcuwcuxcuycnCcnCbwocvzbxXcxHbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikaSecuBctvcuCcuDcuEcuFcuGcuHcuIcuJcuKcuLcuMcuNcuOcuPcuQcuRceAcuSceAcuNcuTcuNcuNcuNcuNcuNcuNcuNcuNcuNcuNcuUctEcuVcuWcuXcuYcuZcvacvbcvccvdcvecvfcvgcvhcvicvjcvkcsLceJcvlcvmcvncqKcqJcqKcqKcvocpFcvpcqKcqKcqNcqKcyGcwrbikbikbikdbFdbRdbQdbTdbSdbVdbUdbXdbWdbybGychCcyHcuscoAbikbikbikbikbikaabckPckPckPckPckPckPckPckPckPcvucxScvwckPcxOcxOcyIckPaabcnCcnCcvAcnCcvBcvCcvDcnCcyKcyJcvzbxXcxHbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikadbabLcrjcrjcrjcrjcrjcrjcvFcvGcvGcvHctBdlXcrjcrmcvJcvKcvKcvLcvKcvMcvKcvKcvNcvOcvKcvKcvOcvOcvOcvKcvKcvKcvKcvPcvQcvRcvScvTcvUcvVcvWcvXcvWcvWcvWcvWcvZcwacwbcwccwdcsObGycvrcwecwfcwgcwhcwicwjcwkcpFcwlcwjcwmcqNcqKcwocpMbikbikbikdbFdbZdbYdcadbIdccdcbdbUczRdbycyObVibVicuscoAbikbikbikbikbikbikckPcwtcwucwvcwwcwxcwycwzcwAcwBczScwDckPcxOcBZcyPckPaabaabcwGcwHcwIcwJcwKcwLcwGbxXbxXcvzczfbwobikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikacGacGacGafxafxacGafxafxafxagiafxafxaabagiaqZbikaabaabcwNcwNcwNcrjcwOcwPcwQcwRcwScwTcwUcwVcwWcwXcwYcwZcxacxbcxccxdcxecxfcxgcvKcxfcxhcxicxjcxjcxkcvKcxlcxmcxncxocbkcxpcxqcxrcxscxtcxucxtcxvcxwcxxcxycxzcxAcsOcsOcvrcwecpMcpMcxBcpMcpMcxCcxDcxEcxEcxEcxFcxEcyUcpMbikbikbikdbFdbFdbFdbFdbFdbydcedcgdcfdbybGybGyczhcuscoAbikbikbikbikbikbikckPcxOcxPcxOcxQcxRcqUcxScwAcxTczicxTckPcxOcxOcMpckPaabbikcwGcxWcxXcwJcwJcxYcwGczjbxXcvzbzNczMbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik diff --git a/_maps/map_files/cyberiad/z2.dmm b/_maps/map_files/cyberiad/z2.dmm index 46e98f30d6c..46b1662d8d6 100644 --- a/_maps/map_files/cyberiad/z2.dmm +++ b/_maps/map_files/cyberiad/z2.dmm @@ -621,9 +621,11 @@ "lW" = (/obj/structure/rack,/obj/item/clothing/under/color/red,/obj/item/clothing/shoes/brown,/obj/item/clothing/suit/armor/vest,/obj/item/clothing/head/helmet/swat,/obj/item/weapon/gun/energy/laser,/obj/item/weapon/shield/energy,/obj/machinery/recharger/wallcharger{pixel_x = 3; pixel_y = -30},/turf/unsimulated/floor{icon_state = "dark"},/area/tdome/arena_source) "lX" = (/obj/structure/rack,/obj/item/clothing/under/color/green,/obj/item/clothing/shoes/brown,/obj/item/clothing/suit/armor/vest,/obj/item/clothing/head/helmet/swat,/obj/item/weapon/gun/energy/laser,/obj/item/weapon/shield/energy,/obj/machinery/recharger/wallcharger{pixel_x = 3; pixel_y = -30},/turf/unsimulated/floor{icon_state = "dark"},/area/tdome/arena_source) "lY" = (/obj/effect/landmark/abductor/agent{team = 3},/turf/unsimulated/floor/abductor,/area/abductor_ship) +"lZ" = (/obj/structure/closet/secure_closet/guncabinet,/obj/item/ammo_box/magazine/m10mm,/obj/item/ammo_box/magazine/m10mm,/obj/item/ammo_box/magazine/m10mm,/obj/item/weapon/gun/projectile/automatic/pistol{name = "pistol"},/obj/item/weapon/gun/projectile/automatic/pistol{name = "pistol"},/obj/item/weapon/gun/projectile/automatic/pistol{name = "pistol"},/turf/simulated/floor/engine,/area/shuttle/gamma/space) "ma" = (/obj/effect/decal/cleanable/molten_item,/turf/unsimulated/floor{icon_state = "freezerfloor"; dir = 2},/area/wizard_station) "mb" = (/turf/unsimulated/wall/fakeglass,/area/wizard_station) "mc" = (/obj/item/trash/chips,/obj/machinery/light/spot,/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/wizard_station) +"md" = (/obj/machinery/computer/mech_bay_power_console,/obj/structure/cable,/turf/simulated/floor/plasteel,/area/shuttle/gamma/space) "me" = (/obj/effect/decal/cleanable/blood,/turf/unsimulated/floor{dir = 8; icon_state = "chapel"},/area/wizard_station) "mg" = (/turf/space,/turf/simulated/shuttle/wall{icon_state = "diagonalWall3"},/area/shuttle/syndicate_elite/mothership) "mh" = (/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/shuttle/syndicate_elite/mothership) @@ -694,7 +696,6 @@ "rK" = (/turf/unsimulated/wall/splashscreen,/area/start) "rP" = (/obj/structure/table/reinforced,/obj/item/weapon/grenade/clusterbuster,/obj/machinery/ai_status_display{pixel_x = 0; pixel_y = 32},/turf/simulated/floor/engine,/area/shuttle/gamma/space) "rQ" = (/obj/structure/table/reinforced,/obj/item/weapon/grenade/chem_grenade/incendiary{name = "Incendiary Grenade"},/obj/machinery/light{dir = 1},/turf/simulated/floor/engine,/area/shuttle/gamma/space) -"rT" = (/obj/structure/closet/secure_closet/guncabinet,/obj/machinery/camera/motion{c_tag = "Gamma Armory Entrance"; network = list("SS13")},/obj/item/ammo_box/magazine/m10mm,/obj/item/ammo_box/magazine/m10mm,/obj/item/ammo_box/magazine/m10mm,/obj/item/weapon/gun/projectile/automatic/pistol{name = "pistol"},/obj/item/weapon/gun/projectile/automatic/pistol{name = "pistol"},/obj/item/weapon/gun/projectile/automatic/pistol{name = "pistol"},/turf/simulated/floor/engine,/area/shuttle/gamma/space) "rU" = (/obj/structure/closet/secure_closet/guncabinet,/obj/item/weapon/gun/energy/gun/nuclear,/obj/item/weapon/gun/energy/gun/nuclear,/obj/item/weapon/gun/energy/gun/nuclear,/obj/machinery/light{dir = 1},/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/turf/simulated/floor/engine,/area/shuttle/gamma/space) "rV" = (/obj/structure/closet/secure_closet/guncabinet,/obj/item/weapon/gun/energy/sniperrifle,/obj/item/weapon/gun/energy/sniperrifle,/obj/item/weapon/gun/energy/sniperrifle,/turf/simulated/floor/engine,/area/shuttle/gamma/space) "rW" = (/obj/structure/closet/secure_closet/guncabinet,/obj/item/ammo_casing/rocket,/obj/item/ammo_casing/rocket,/obj/item/ammo_casing/rocket,/obj/item/weapon/gun/rocketlauncher,/turf/simulated/floor/engine,/area/shuttle/gamma/space) @@ -716,7 +717,6 @@ "sm" = (/obj/machinery/alarm{dir = 1; icon_state = "alarm0"; pixel_y = -22},/obj/structure/table/reinforced,/obj/machinery/recharger{pixel_y = 4},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/shuttle/gamma/space) "sn" = (/obj/structure/cable,/obj/machinery/mech_bay_recharge_port/upgraded,/turf/simulated/floor/plasteel,/area/shuttle/gamma/space) "so" = (/obj/mecha/combat/durand/loaded{operation_req_access = list(1)},/obj/machinery/light,/turf/simulated/floor/mech_bay_recharge_floor,/area/shuttle/gamma/space) -"sp" = (/obj/machinery/computer/mech_bay_power_console,/obj/machinery/camera{c_tag = "Gamma Armory Mech Bay"; dir = 1; network = list("SS13")},/obj/structure/cable,/turf/simulated/floor/plasteel,/area/shuttle/gamma/space) "sq" = (/turf/unsimulated/wall,/area/centcom/control) "sr" = (/obj/structure/table,/turf/unsimulated/floor{icon_state = "carpet"; dir = 2},/area/centcom/control) "ss" = (/turf/unsimulated/floor{icon_state = "carpet"; dir = 2},/area/centcom/control) @@ -1434,11 +1434,11 @@ aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaqaqaqaqaqaqaqaqaq aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNbZbZbZbZbZaNaNaNaNaNaNaNaNaNaNaNaNaNaNaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNbZbZbZbZbZbZrPrQdebZaNaNaNaNaNaNaNaNaNaNaNaNaNaNaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNaNbZcYrTrUrVrWrXrXrXbZaNaNaNaNaNaNaNaNaNaNaNaNaNaNaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNaNbZcYlZrUrVrWrXrXrXbZaNaNaNaNaNaNaNaNaNaNaNaNaNaNaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNbZrXrXrXrXrXrXrYrZbZaNaNaNaNaNaNaNaNaNaNaNaNaNaNaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNbZsasbsbsbscsdsesbbZaNaNaNaNaNaNaNaNaNaNaNaNaNaNaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNsfsgsgsgsgsashsisjbZaNaNaNaNaNaNaNaNaNaNaNaNaNaNaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN -aNaNaNaNaNaNaNbZsgskslsmsasnsospbZaNaNaNaNaNaNaNaNaNaNaNaNaNaNaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN +aNaNaNaNaNaNaNbZsgskslsmsasnsomdbZaNaNaNaNaNaNaNaNaNaNaNaNaNaNaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaqaNbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNbZbZbZbZbZbZbZbZbZbZaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN aNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaNaN diff --git a/code/__DEFINES/clothing.dm b/code/__DEFINES/clothing.dm index a9474044978..83a6ac5b20a 100644 --- a/code/__DEFINES/clothing.dm +++ b/code/__DEFINES/clothing.dm @@ -32,6 +32,7 @@ #define slot_r_ear 20 #define slot_wear_pda 21 #define slot_tie 22 +#define slots_amt 22 //Cant seem to find a mob bitflags area other than the powers one diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index b6fcfc104c8..7f1a33d0b33 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -220,4 +220,14 @@ #define R_HAND_LAYER 28 #define TARGETED_LAYER 29 //BS12: Layer for the target overlay from weapon targeting system #define FIRE_LAYER 30 //If you're on fire -#define TOTAL_LAYERS 30 \ No newline at end of file +#define TOTAL_LAYERS 30 + +///Access Region Codes/// +#define REGION_ALL 0 +#define REGION_GENERAL 1 +#define REGION_SECURITY 2 +#define REGION_MEDBAY 3 +#define REGION_RESEARCH 4 +#define REGION_ENGINEERING 5 +#define REGION_SUPPLY 6 +#define REGION_COMMAND 7 \ No newline at end of file diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index fffcbd09f30..96ae9ea6281 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -36,6 +36,8 @@ #define ROLE_POSIBRAIN "positronic brain" #define ROLE_GUARDIAN "guardian" #define ROLE_MORPH "morph" +#define ROLE_ERT "emergency response team" +#define ROLE_NYMPH "Dionaea" //Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR. diff --git a/code/__DEFINES/rolebans.dm b/code/__DEFINES/rolebans.dm new file mode 100644 index 00000000000..9668721d063 --- /dev/null +++ b/code/__DEFINES/rolebans.dm @@ -0,0 +1,31 @@ +// Bannable antag roles +var/global/list/antag_roles = list( + ROLE_TRAITOR, + ROLE_OPERATIVE, + ROLE_CHANGELING, + ROLE_WIZARD, + ROLE_MALF, + ROLE_REV, + ROLE_ALIEN, + ROLE_CULTIST, + ROLE_BLOB, + ROLE_NINJA, + ROLE_SHADOWLING, + ROLE_RAIDER, + ROLE_VAMPIRE, + ROLE_MUTINEER, + ROLE_BORER, + ROLE_DEMON, + ROLE_REVENANT, + ROLE_GUARDIAN, + ROLE_MORPH, +) + +// Bannable other roles +var/global/list/other_roles = list( + ROLE_SENTIENT, + ROLE_NYMPH, + ROLE_ERT, + "AntagHUD", + "Records" +) \ No newline at end of file diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index ced289358e0..0dd40091e1e 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -184,8 +184,18 @@ /proc/ui_style2icon(ui_style) switch(ui_style) - if("Midnight") return 'icons/mob/screen1_Midnight.dmi' - else return 'icons/mob/screen1_White.dmi' + if("Retro") + return 'icons/mob/screen_retro.dmi' + if("Plasmafire") + return 'icons/mob/screen_plasmafire.dmi' + if("Slimecore") + return 'icons/mob/screen_slimecore.dmi' + if("Operative") + return 'icons/mob/screen_operative.dmi' + if("White") + return 'icons/mob/screen_white.dmi' + else + return 'icons/mob/screen_midnight.dmi' //colour formats /proc/rgb2hsl(red, green, blue) diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 50527c33329..c6ad076b102 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -142,4 +142,15 @@ // Bots #define ui_bot_radio "EAST-1:28,SOUTH:7" -#define ui_bot_pull "EAST-2:26,SOUTH:7" \ No newline at end of file +#define ui_bot_pull "EAST-2:26,SOUTH:7" + +//HUD styles. Please ensure HUD_VERSIONS is the same as the maximum index. Index order defines how they are cycled in F12. +#define HUD_STYLE_STANDARD 1 +#define HUD_STYLE_REDUCED 2 +#define HUD_STYLE_NOHUD 3 + + +#define HUD_VERSIONS 3 //used in show_hud() +//1 = standard hud +//2 = reduced hud (just hands and intent switcher) +//3 = no hud (for screenshots) \ No newline at end of file diff --git a/code/_onclick/hud/ai.dm b/code/_onclick/hud/ai.dm index d98851fc443..0a3ca11f315 100644 --- a/code/_onclick/hud/ai.dm +++ b/code/_onclick/hud/ai.dm @@ -84,7 +84,7 @@ AI.ai_call_shuttle() /obj/screen/ai/state_laws - name = "State Laws" + name = "Law Manager" icon_state = "state_laws" /obj/screen/ai/state_laws/Click() @@ -129,7 +129,7 @@ AI.aiCamera.viewpictures() /obj/screen/ai/sensors - name = "Sensor Augmentation" + name = "Toggle Sensor Augmentation" icon_state = "ai_sensor" /obj/screen/ai/sensors/Click() @@ -141,146 +141,86 @@ borg.sensor_mode() -/datum/hud/proc/ai_hud() - adding = list() - other = list() +/mob/living/silicon/ai/create_mob_hud() + if(client && !hud_used) + hud_used = new /datum/hud/ai(src) + +/datum/hud/ai/New(mob/owner) + ..() var/obj/screen/using //AI core using = new /obj/screen/ai/aicore() - using.name = "AI Core" - using.icon = 'icons/mob/screen_ai.dmi' - using.icon_state = "ai_core" using.screen_loc = ui_ai_core - using.layer = 20 - adding += using + static_inventory += using //Camera list using = new /obj/screen/ai/camera_list() - using.name = "Show Camera List" - using.icon = 'icons/mob/screen_ai.dmi' - using.icon_state = "camera" using.screen_loc = ui_ai_camera_list - using.layer = 20 - adding += using + static_inventory += using //Track using = new /obj/screen/ai/camera_track() - using.name = "Track With Camera" - using.icon = 'icons/mob/screen_ai.dmi' - using.icon_state = "track" using.screen_loc = ui_ai_track_with_camera - using.layer = 20 - adding += using + static_inventory += using //Camera light using = new /obj/screen/ai/camera_light() - using.name = "Toggle Camera Light" - using.icon = 'icons/mob/screen_ai.dmi' - using.icon_state = "camera_light" using.screen_loc = ui_ai_camera_light - using.layer = 20 - adding += using + static_inventory += using //Crew Monitorting using = new /obj/screen/ai/crew_monitor() - using.name = "Crew Monitoring" - using.icon = 'icons/mob/screen_ai.dmi' - using.icon_state = "crew_monitor" using.screen_loc = ui_ai_crew_monitor - using.layer = 20 - adding += using + static_inventory += using //Crew Manifest using = new /obj/screen/ai/crew_manifest() - using.name = "Show Crew Manifest" - using.icon = 'icons/mob/screen_ai.dmi' - using.icon_state = "manifest" using.screen_loc = ui_ai_crew_manifest - using.layer = 20 - adding += using + static_inventory += using //Alerts using = new /obj/screen/ai/alerts() - using.name = "Show Alerts" - using.icon = 'icons/mob/screen_ai.dmi' - using.icon_state = "alerts" using.screen_loc = ui_ai_alerts - using.layer = 20 - adding += using + static_inventory += using //Announcement using = new /obj/screen/ai/announcement() - using.name = "Announcement" - using.icon = 'icons/mob/screen_ai.dmi' - using.icon_state = "announcement" using.screen_loc = ui_ai_announcement - using.layer = 20 - adding += using + static_inventory += using //Shuttle using = new /obj/screen/ai/call_shuttle() - using.name = "Call Emergency Shuttle" - using.icon = 'icons/mob/screen_ai.dmi' - using.icon_state = "call_shuttle" using.screen_loc = ui_ai_shuttle - using.layer = 20 - adding += using + static_inventory += using //Laws using = new /obj/screen/ai/state_laws() - using.name = "Law Manager" - using.icon = 'icons/mob/screen_ai.dmi' - using.icon_state = "state_laws" using.screen_loc = ui_ai_state_laws - using.layer = 20 - adding += using + static_inventory += using //PDA message using = new /obj/screen/ai/pda_msg_send() - using.name = "PDA - Send Message" - using.icon = 'icons/mob/screen_ai.dmi' - using.icon_state = "pda_send" using.screen_loc = ui_ai_pda_send - using.layer = 20 - adding += using + static_inventory += using //PDA log using = new /obj/screen/ai/pda_msg_show() - using.name = "PDA - Show Message Log" - using.icon = 'icons/mob/screen_ai.dmi' - using.icon_state = "pda_receive" using.screen_loc = ui_ai_pda_log - using.layer = 20 - adding += using + static_inventory += using //Take image using = new /obj/screen/ai/image_take() - using.name = "Take Image" - using.icon = 'icons/mob/screen_ai.dmi' - using.icon_state = "take_picture" using.screen_loc = ui_ai_take_picture - using.layer = 20 - adding += using + static_inventory += using //View images using = new /obj/screen/ai/image_view() - using.name = "View Images" - using.icon = 'icons/mob/screen_ai.dmi' - using.icon_state = "view_images" using.screen_loc = ui_ai_view_images - using.layer = 20 - adding += using + static_inventory += using //Medical/Security sensors using = new /obj/screen/ai/sensors() - using.name = "Set Sensor Augmentation" - using.icon = 'icons/mob/screen_ai.dmi' - using.icon_state = "ai_sensor" using.screen_loc = ui_ai_sensor - using.layer = 20 - adding += using - - mymob.client.screen += adding + other - return \ No newline at end of file + static_inventory += using diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index ca3f223c80d..a5f4a566878 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -387,7 +387,7 @@ so as to remain in compliance with the most up-to-date laws." return var/paramslist = params2list(params) if(paramslist["shift"]) // screen objects don't do the normal Click() stuff so we'll cheat - usr << "[name] - [desc]" + to_chat(usr, "[name] - [desc]") return if(master) return usr.client.Click(master, location, control, params) diff --git a/code/_onclick/hud/alien.dm b/code/_onclick/hud/alien.dm index 2842facc713..70d121a190b 100644 --- a/code/_onclick/hud/alien.dm +++ b/code/_onclick/hud/alien.dm @@ -18,143 +18,133 @@ var/mob/living/carbon/alien/humanoid/A = usr A.nightvisiontoggle() -/datum/hud/proc/embryo_hud() - return -/datum/hud/proc/alien_hud() - src.adding = list() - src.other = list() +/obj/screen/alien/plasma_display + icon = 'icons/mob/screen_gen.dmi' + icon_state = "power_display2" + name = "plasma stored" + screen_loc = ui_alienplasmadisplay + + +/mob/living/carbon/alien/humanoid/create_mob_hud() + if(client && !hud_used) + hud_used = new /datum/hud/alien(src) + +/datum/hud/alien/New(mob/living/carbon/alien/humanoid/owner) + ..() var/obj/screen/using var/obj/screen/inventory/inv_box - using = new /obj/screen/act_intent() - using.name = "act_intent" - using.dir = SOUTHWEST - using.icon = 'icons/mob/screen1_alien.dmi' + using = new /obj/screen/act_intent/alien() using.icon_state = (mymob.a_intent == "hurt" ? "harm" : mymob.a_intent) using.screen_loc = ui_acti - using.layer = 20 - src.adding += using + static_inventory += using action_intent = using using = new /obj/screen/mov_intent() - using.name = "mov_intent" - using.dir = SOUTHWEST - using.icon = 'icons/mob/screen1_alien.dmi' + using.icon = 'icons/mob/screen_alien.dmi' using.icon_state = (mymob.m_intent == "run" ? "running" : "walking") using.screen_loc = ui_movi - using.layer = 20 - src.adding += using + static_inventory += using move_intent = using if(istype(mymob, /mob/living/carbon/alien/humanoid/hunter)) mymob.leap_icon = new /obj/screen/alien/leap() - mymob.leap_icon.icon = 'icons/mob/screen1_alien.dmi' - mymob.leap_icon.name = "toggle leap" - mymob.leap_icon.icon_state = "leap_off" + mymob.leap_icon.icon = 'icons/mob/screen_alien.dmi' mymob.leap_icon.screen_loc = ui_alien_storage_r - src.adding += mymob.leap_icon + static_inventory += mymob.leap_icon //equippable shit - inv_box = new /obj/screen/inventory() + inv_box = new /obj/screen/inventory/hand() inv_box.name = "r_hand" - inv_box.dir = WEST - inv_box.icon = 'icons/mob/screen1_alien.dmi' - inv_box.icon_state = "hand_inactive" - if(mymob && !mymob.hand) //This being 0 or null means the right hand is in use - inv_box.icon_state = "hand_active" + inv_box.icon = 'icons/mob/screen_alien.dmi' + inv_box.icon_state = "hand_r" inv_box.screen_loc = ui_rhand - inv_box.layer = 19 - src.r_hand_hud_object = inv_box inv_box.slot_id = slot_r_hand - src.adding += inv_box + static_inventory += inv_box - inv_box = new /obj/screen/inventory() + inv_box = new /obj/screen/inventory/hand() inv_box.name = "l_hand" - inv_box.dir = EAST - inv_box.icon = 'icons/mob/screen1_alien.dmi' - inv_box.icon_state = "hand_inactive" - if(mymob && mymob.hand) //This being 1 means the left hand is in use - inv_box.icon_state = "hand_active" + inv_box.icon = 'icons/mob/screen_alien.dmi' + inv_box.icon_state = "hand_l" inv_box.screen_loc = ui_lhand - inv_box.layer = 19 inv_box.slot_id = slot_l_hand - src.l_hand_hud_object = inv_box - src.adding += inv_box + static_inventory += inv_box - using = new /obj/screen/inventory() + using = new /obj/screen/swap_hand() using.name = "hand" - using.dir = SOUTH - using.icon = 'icons/mob/screen1_alien.dmi' + using.icon = 'icons/mob/screen_alien.dmi' using.icon_state = "hand1" using.screen_loc = ui_swaphand1 - using.layer = 19 - src.adding += using + static_inventory += using - using = new /obj/screen/inventory() + using = new /obj/screen/swap_hand() using.name = "hand" - using.dir = SOUTH - using.icon = 'icons/mob/screen1_alien.dmi' + using.icon = 'icons/mob/screen_alien.dmi' using.icon_state = "hand2" using.screen_loc = ui_swaphand2 - using.layer = 19 - src.adding += using + static_inventory += using //end of equippable shit using = new /obj/screen/resist() using.name = "resist" - using.icon = 'icons/mob/screen1_alien.dmi' + using.icon = 'icons/mob/screen_alien.dmi' using.icon_state = "act_resist" using.screen_loc = ui_pull_resist - using.layer = 19 - src.adding += using + static_inventory += using using = new /obj/screen/drop() using.name = "drop" - using.icon = 'icons/mob/screen1_alien.dmi' + using.icon = 'icons/mob/screen_alien.dmi' using.icon_state = "act_drop" using.screen_loc = ui_drop_throw - using.layer = 19 - src.adding += using + static_inventory += using mymob.throw_icon = new /obj/screen/throw_catch() - mymob.throw_icon.icon = 'icons/mob/screen1_alien.dmi' - mymob.throw_icon.icon_state = "act_throw_off" - mymob.throw_icon.name = "throw" + mymob.throw_icon.icon = 'icons/mob/screen_alien.dmi' mymob.throw_icon.screen_loc = ui_drop_throw + static_inventory += mymob.throw_icon - mymob.healths = new /obj/screen() - mymob.healths.icon = 'icons/mob/screen1_alien.dmi' - mymob.healths.icon_state = "health0" - mymob.healths.name = "health" - mymob.healths.screen_loc = ui_alien_health + mymob.healths = new /obj/screen/healths/alien() + infodisplay += mymob.healths nightvisionicon = new /obj/screen/alien/nightvision() - nightvisionicon.icon = 'icons/mob/screen1_alien.dmi' - nightvisionicon.icon_state = "nightvision1" - nightvisionicon.name = "night vision" - nightvisionicon.screen_loc = ui_alien_nightvision + infodisplay += nightvisionicon mymob.pullin = new /obj/screen/pull() - mymob.pullin.icon = 'icons/mob/screen1_alien.dmi' + mymob.pullin.icon = 'icons/mob/screen_alien.dmi' mymob.pullin.update_icon(mymob) mymob.pullin.screen_loc = ui_pull_resist + hotkeybuttons += mymob.pullin - alien_plasma_display = new /obj/screen() - alien_plasma_display.icon = 'icons/mob/screen_gen.dmi' - alien_plasma_display.icon_state = "power_display" - alien_plasma_display.name = "plasma stored" - alien_plasma_display.screen_loc = ui_alienplasmadisplay + alien_plasma_display = new /obj/screen/alien/plasma_display() + infodisplay += alien_plasma_display - mymob.zone_sel = new /obj/screen/zone_sel() - mymob.zone_sel.icon = 'icons/mob/screen1_alien.dmi' - mymob.zone_sel.overlays.Cut() - mymob.zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[mymob.zone_sel.selecting]") + mymob.zone_sel = new /obj/screen/zone_sel/alien() + mymob.zone_sel.update_icon(mymob) + static_inventory += mymob.zone_sel - mymob.client.screen = list() + for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory)) + if(inv.slot_id) + inv.hud = src + inv_slots[inv.slot_id] = inv + inv.update_icon() - mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.healths, nightvisionicon, mymob.pullin, alien_plasma_display, mymob.pullin) //, mymob.hands, mymob.rest, mymob.sleep, mymob.mach ) - mymob.client.screen += src.adding + src.other - mymob.client.screen += mymob.client.void \ No newline at end of file +/datum/hud/alien/persistant_inventory_update() + if(!mymob) + return + var/mob/living/carbon/alien/humanoid/H = mymob + if(hud_version != HUD_STYLE_NOHUD) + if(H.r_hand) + H.r_hand.screen_loc = ui_rhand + H.client.screen += H.r_hand + if(H.l_hand) + H.l_hand.screen_loc = ui_lhand + H.client.screen += H.l_hand + else + if(H.r_hand) + H.r_hand.screen_loc = null + if(H.l_hand) + H.l_hand.screen_loc = null diff --git a/code/_onclick/hud/alien_larva.dm b/code/_onclick/hud/alien_larva.dm index dca63c7d2ae..6ab416259e7 100644 --- a/code/_onclick/hud/alien_larva.dm +++ b/code/_onclick/hud/alien_larva.dm @@ -1,53 +1,35 @@ -/datum/hud/proc/larva_hud() - src.adding = list() - src.other = list() +/mob/living/carbon/alien/larva/create_mob_hud() + if(client && !hud_used) + hud_used = new /datum/hud/larva(src) + +/datum/hud/larva/New(mob/owner) + ..() var/obj/screen/using - using = new /obj/screen/act_intent() - using.name = "act_intent" - using.dir = SOUTHWEST - using.icon = 'icons/mob/screen1_alien.dmi' - using.icon_state = (mymob.a_intent == "harm" ? "harm" : mymob.a_intent) - using.screen_loc = ui_acti - using.layer = 20 - src.adding += using + using = new /obj/screen/act_intent/alien() + using.icon_state = mymob.a_intent + static_inventory += using action_intent = using using = new /obj/screen/mov_intent() - using.name = "mov_intent" - using.dir = SOUTHWEST - using.icon = 'icons/mob/screen1_alien.dmi' + using.icon = 'icons/mob/screen_alien.dmi' using.icon_state = (mymob.m_intent == "run" ? "running" : "walking") - using.screen_loc = ui_movi - using.layer = 20 - src.adding += using + static_inventory += using move_intent = using - mymob.healths = new /obj/screen() - mymob.healths.icon = 'icons/mob/screen1_alien.dmi' - mymob.healths.icon_state = "health0" - mymob.healths.name = "health" - mymob.healths.screen_loc = ui_alien_health + mymob.healths = new /obj/screen/healths/alien() + infodisplay += mymob.healths nightvisionicon = new /obj/screen/alien/nightvision() - nightvisionicon.icon = 'icons/mob/screen1_alien.dmi' - nightvisionicon.icon_state = "nightvision1" - nightvisionicon.name = "night vision" - nightvisionicon.screen_loc = ui_alien_nightvision + infodisplay += nightvisionicon mymob.pullin = new /obj/screen/pull() - mymob.pullin.icon = 'icons/mob/screen1_alien.dmi' + mymob.pullin.icon = 'icons/mob/screen_alien.dmi' mymob.pullin.update_icon(mymob) mymob.pullin.screen_loc = ui_pull_resist + hotkeybuttons += mymob.pullin - mymob.zone_sel = new /obj/screen/zone_sel() - mymob.zone_sel.icon = 'icons/mob/screen1_alien.dmi' - mymob.zone_sel.overlays.Cut() - mymob.zone_sel.overlays += image("icon" = 'icons/mob/zone_sel.dmi', "icon_state" = text("[]", mymob.zone_sel.selecting)) - - mymob.client.screen = list() - - mymob.client.screen += list( mymob.zone_sel, mymob.healths, nightvisionicon, mymob.pullin) //, mymob.rest, mymob.sleep, mymob.mach ) - mymob.client.screen += src.adding + src.other - mymob.client.screen += mymob.client.void \ No newline at end of file + mymob.zone_sel = new /obj/screen/zone_sel/alien() + mymob.zone_sel.update_icon(mymob) + static_inventory += mymob.zone_sel \ No newline at end of file diff --git a/code/_onclick/hud/bot.dm b/code/_onclick/hud/bot.dm index 4f205b04567..5f4ddbd7622 100644 --- a/code/_onclick/hud/bot.dm +++ b/code/_onclick/hud/bot.dm @@ -1,43 +1,33 @@ /obj/screen/bot - icon = 'icons/mob/screen1_bot.dmi' + icon = 'icons/mob/screen_bot.dmi' /obj/screen/bot/radio name = "radio" icon_state = "radio" + screen_loc = ui_bot_radio /obj/screen/bot/radio/Click() if(isbot(usr)) var/mob/living/simple_animal/bot/B = usr B.Radio.interact(usr) -/datum/hud/proc/bot_hud() - src.adding = list() - src.other = list() +/mob/living/simple_animal/bot/create_mob_hud() + if(client && !hud_used) + hud_used = new /datum/hud/bot(src) +/datum/hud/bot/New(mob/owner) + ..() var/obj/screen/using using = new /obj/screen/bot/radio() - using.name = "radio" - using.dir = SOUTHWEST - using.icon_state = "radio" - using.screen_loc = ui_bot_radio - using.layer = 20 - src.adding += using + static_inventory += using - mymob.healths = new /obj/screen() - mymob.healths.icon = 'icons/mob/screen1_bot.dmi' - mymob.healths.icon_state = "health0" - mymob.healths.name = "health" + mymob.healths = new /obj/screen/healths/bot() mymob.healths.screen_loc = ui_borg_health + infodisplay += mymob.healths mymob.pullin = new /obj/screen/pull() - mymob.pullin.icon = 'icons/mob/screen1_bot.dmi' + mymob.pullin.icon = 'icons/mob/screen_bot.dmi' mymob.pullin.update_icon(mymob) mymob.pullin.screen_loc = ui_bot_pull - - mymob.client.screen = list() - - mymob.client.screen += list(mymob.healths, mymob.pullin) - mymob.client.screen += adding + other - mymob.client.screen += mymob.client.void - return \ No newline at end of file + static_inventory += mymob.pullin \ No newline at end of file diff --git a/code/_onclick/hud/guardian.dm b/code/_onclick/hud/guardian.dm new file mode 100644 index 00000000000..6da2a44b0f7 --- /dev/null +++ b/code/_onclick/hud/guardian.dm @@ -0,0 +1,89 @@ +/mob/living/simple_animal/hostile/guardian/create_mob_hud() + if(client && !hud_used) + hud_used = new /datum/hud/guardian(src) + +/datum/hud/guardian/New(mob/owner) + ..() + var/obj/screen/using + + guardianhealthdisplay = new /obj/screen/healths/guardian() + infodisplay += guardianhealthdisplay + + using = new /obj/screen/guardian/Manifest() + using.screen_loc = ui_rhand + static_inventory += using + + using = new /obj/screen/guardian/Recall() + using.screen_loc = ui_lhand + static_inventory += using + + using = new /obj/screen/guardian/ToggleMode() + using.screen_loc = ui_storage1 + static_inventory += using + + using = new /obj/screen/guardian/ToggleLight() + using.screen_loc = ui_inventory + static_inventory += using + + using = new /obj/screen/guardian/Communicate() + using.screen_loc = ui_back + static_inventory += using + + +//HUD BUTTONS + +/obj/screen/guardian + icon = 'icons/mob/guardian.dmi' + icon_state = "base" + +/obj/screen/guardian/Manifest + icon_state = "manifest" + name = "Manifest" + desc = "Spring forth into battle!" + +/obj/screen/guardian/Manifest/Click() + if(isguardian(usr)) + var/mob/living/simple_animal/hostile/guardian/G = usr + G.Manifest() + + +/obj/screen/guardian/Recall + icon_state = "recall" + name = "Recall" + desc = "Return to your user." + +/obj/screen/guardian/Recall/Click() + if(isguardian(usr)) + var/mob/living/simple_animal/hostile/guardian/G = usr + G.Recall() + +/obj/screen/guardian/ToggleMode + icon_state = "toggle" + name = "Toggle Mode" + desc = "Switch between ability modes." + +/obj/screen/guardian/ToggleMode/Click() + if(isguardian(usr)) + var/mob/living/simple_animal/hostile/guardian/G = usr + G.ToggleMode() + +/obj/screen/guardian/Communicate + icon_state = "communicate" + name = "Communicate" + desc = "Communicate telepathically with your user." + +/obj/screen/guardian/Communicate/Click() + if(isguardian(usr)) + var/mob/living/simple_animal/hostile/guardian/G = usr + G.Communicate() + + +/obj/screen/guardian/ToggleLight + icon_state = "light" + name = "Toggle Light" + desc = "Glow like star dust." + +/obj/screen/guardian/ToggleLight/Click() + if(isguardian(usr)) + var/mob/living/simple_animal/hostile/guardian/G = usr + G.ToggleLight() \ No newline at end of file diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 3c11b91a9b0..02c5bfc2ac3 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -8,6 +8,7 @@ var/mob/mymob var/hud_shown = 1 //Used for the HUD toggle (F12) + var/hud_version = 1 //Current displayed version of the HUD var/inventory_shown = 1 //the inventory var/show_intent_icons = 0 var/hotkey_ui_hidden = 0 //This is to hide the buttons that can be used via hotkeys. (hotkeybuttons list of buttons) @@ -22,182 +23,167 @@ var/obj/screen/vampire_blood_display var/obj/screen/alien_plasma_display var/obj/screen/nightvisionicon - var/obj/screen/r_hand_hud_object - var/obj/screen/l_hand_hud_object var/obj/screen/action_intent var/obj/screen/move_intent + var/obj/screen/module_store_icon - var/list/adding - var/list/other - var/list/obj/screen/hotkeybuttons + var/list/static_inventory = list() //the screen objects which are static + var/list/toggleable_inventory = list() //the screen objects which can be hidden + var/list/hotkeybuttons = list() //the buttons that can be used via hotkeys + var/list/infodisplay = list() //the screen objects that display mob info (health, alien plasma, etc...) + var/list/inv_slots[slots_amt] // /obj/screen/inventory objects, ordered by their slot ID. var/obj/screen/movable/action_button/hide_toggle/hide_actions_toggle var/action_buttons_hidden = 0 -datum/hud/New(mob/owner) +/mob/proc/create_mob_hud() + if(client && !hud_used) + hud_used = new /datum/hud(src) + +/datum/hud/New(mob/owner) mymob = owner - instantiate() - ..() +/datum/hud/Destroy() + if(mymob.hud_used == src) + mymob.hud_used = null -/datum/hud/proc/hidden_inventory_update() - if(!mymob) return - if(ishuman(mymob)) - var/mob/living/carbon/human/H = mymob - if(inventory_shown && hud_shown) - if(H.shoes) H.shoes.screen_loc = ui_shoes - if(H.gloves) H.gloves.screen_loc = ui_gloves - if(H.l_ear) H.l_ear.screen_loc = ui_l_ear - if(H.r_ear) H.r_ear.screen_loc = ui_r_ear - if(H.glasses) H.glasses.screen_loc = ui_glasses - if(H.w_uniform) H.w_uniform.screen_loc = ui_iclothing - if(H.wear_suit) H.wear_suit.screen_loc = ui_oclothing - if(H.wear_mask) H.wear_mask.screen_loc = ui_mask - if(H.head) H.head.screen_loc = ui_head - else - if(H.shoes) H.shoes.screen_loc = null - if(H.gloves) H.gloves.screen_loc = null - if(H.l_ear) H.l_ear.screen_loc = null - if(H.r_ear) H.r_ear.screen_loc = null - if(H.glasses) H.glasses.screen_loc = null - if(H.w_uniform) H.w_uniform.screen_loc = null - if(H.wear_suit) H.wear_suit.screen_loc = null - if(H.wear_mask) H.wear_mask.screen_loc = null - if(H.head) H.head.screen_loc = null + qdel(hide_actions_toggle) + hide_actions_toggle = null + qdel(module_store_icon) + module_store_icon = null -/datum/hud/proc/persistant_inventory_update() - if(!mymob) - return + if(static_inventory.len) + for(var/thing in static_inventory) + qdel(thing) + static_inventory.Cut() - if(ishuman(mymob)) - var/mob/living/carbon/human/H = mymob - if(hud_shown) - if(H.s_store) H.s_store.screen_loc = ui_sstore1 - if(H.wear_id) H.wear_id.screen_loc = ui_id - if(H.wear_pda) H.wear_pda.screen_loc = ui_pda - if(H.belt) H.belt.screen_loc = ui_belt - if(H.back) H.back.screen_loc = ui_back - if(H.l_store) H.l_store.screen_loc = ui_storage1 - if(H.r_store) H.r_store.screen_loc = ui_storage2 - else - if(H.s_store) H.s_store.screen_loc = null - if(H.wear_id) H.wear_id.screen_loc = null - if(H.wear_pda) H.wear_pda.screen_loc = null - if(H.belt) H.belt.screen_loc = null - if(H.back) H.back.screen_loc = null - if(H.l_store) H.l_store.screen_loc = null - if(H.r_store) H.r_store.screen_loc = null + inv_slots.Cut() + action_intent = null + move_intent = null + if(toggleable_inventory.len) + for(var/thing in toggleable_inventory) + qdel(thing) + toggleable_inventory.Cut() -/datum/hud/proc/instantiate() - if(!ismob(mymob)) return 0 - if(!mymob.client) return 0 - var/ui_style = ui_style2icon(mymob.client.prefs.UI_style) - var/ui_color = mymob.client.prefs.UI_style_color - var/ui_alpha = mymob.client.prefs.UI_style_alpha + if(hotkeybuttons.len) + for(var/thing in hotkeybuttons) + qdel(thing) + hotkeybuttons.Cut() - if(issmall(mymob)) - monkey_hud(ui_style, ui_color, ui_alpha) - else if(ishuman(mymob)) - human_hud(ui_style, ui_color, ui_alpha) // Pass the player the UI style chosen in preferences - else if( islarva(mymob) || isfacehugger(mymob) ) - larva_hud() - else if (isembryo(mymob)) - embryo_hud() - else if(isalien(mymob)) - alien_hud() - else if(isAI(mymob)) - ai_hud() - else if(isrobot(mymob)) - robot_hud() - else if(isbot(mymob)) - bot_hud() - else if(isobserver(mymob)) - ghost_hud() - else if(isovermind(mymob)) - blob_hud() - else if(mymob.mind && mymob.mind.vampire) - vampire_hud() - else if(isswarmer(mymob)) - swarmer_hud() - else if(isguardian(mymob)) - guardian_hud() - else if(ispet(mymob)) - corgi_hud() + if(infodisplay.len) + for(var/thing in infodisplay) + qdel(thing) + infodisplay.Cut() - reload_fullscreen() + //clear mob refs to screen objects + mymob.throw_icon = null + mymob.internals = null + mymob.healths = null + mymob.healthdoll = null + mymob.pullin = null + mymob.zone_sel = null + + //clear the rest of our reload_fullscreen + lingchemdisplay = null + lingstingdisplay = null + blobpwrdisplay = null + alien_plasma_display = null + vampire_blood_display = null + nightvisionicon = null + + mymob = null + return ..() + +/datum/hud/proc/show_hud(version = 0) + if(!ismob(mymob)) + return 0 + if(!mymob.client) + return 0 + + mymob.client.screen = list() + + var/display_hud_version = version + if(!display_hud_version) //If 0 or blank, display the next hud version + display_hud_version = hud_version + 1 + if(display_hud_version > HUD_VERSIONS) //If the requested version number is greater than the available versions, reset back to the first version + display_hud_version = 1 + + switch(display_hud_version) + if(HUD_STYLE_STANDARD) //Default HUD + hud_shown = 1 //Governs behavior of other procs + if(static_inventory.len) + mymob.client.screen += static_inventory + if(toggleable_inventory.len && inventory_shown) + mymob.client.screen += toggleable_inventory + if(hotkeybuttons.len && !hotkey_ui_hidden) + mymob.client.screen += hotkeybuttons + if(infodisplay.len) + mymob.client.screen += infodisplay + + if(action_intent) + action_intent.screen_loc = initial(action_intent.screen_loc) //Restore intent selection to the original position + + if(HUD_STYLE_REDUCED) //Reduced HUD + hud_shown = 0 //Governs behavior of other procs + if(static_inventory.len) + mymob.client.screen -= static_inventory + if(toggleable_inventory.len) + mymob.client.screen -= toggleable_inventory + if(hotkeybuttons.len) + mymob.client.screen -= hotkeybuttons + if(infodisplay.len) + mymob.client.screen += infodisplay + + //These ones are a part of 'static_inventory', 'toggleable_inventory' or 'hotkeybuttons' but we want them to stay + if(inv_slots[slot_l_hand]) + mymob.client.screen += inv_slots[slot_l_hand] //we want the hands to be visible + if(inv_slots[slot_r_hand]) + mymob.client.screen += inv_slots[slot_r_hand] //we want the hands to be visible + if(action_intent) + mymob.client.screen += action_intent //we want the intent switcher visible + action_intent.screen_loc = ui_acti_alt //move this to the alternative position, where zone_select usually is. + + if(HUD_STYLE_NOHUD) //No HUD + hud_shown = 0 //Governs behavior of other procs + if(static_inventory.len) + mymob.client.screen -= static_inventory + if(toggleable_inventory.len) + mymob.client.screen -= toggleable_inventory + if(hotkeybuttons.len) + mymob.client.screen -= hotkeybuttons + if(infodisplay.len) + mymob.client.screen -= infodisplay + + hud_version = display_hud_version persistant_inventory_update() mymob.update_action_buttons() reorganize_alerts() + reload_fullscreen() + +/datum/hud/human/show_hud(version = 0) + ..() + hidden_inventory_update() + +/datum/hud/robot/show_hud(version = 0) + ..() + update_robot_modules_display() + +/datum/hud/proc/hidden_inventory_update() + return + +/datum/hud/proc/persistant_inventory_update() + return //Triggered when F12 is pressed (Unless someone changed something in the DMF) -/mob/verb/button_pressed_F12(var/full = 0 as null) +/mob/verb/button_pressed_F12() set name = "F12" set hidden = 1 - if(hud_used) - if(ishuman(src)) - if(!client) return - if(client.view != world.view) - return - if(hud_used.hud_shown) - hud_used.hud_shown = 0 - if(src.hud_used.adding) - src.client.screen -= src.hud_used.adding - if(src.hud_used.other) - src.client.screen -= src.hud_used.other - if(src.hud_used.hotkeybuttons) - src.client.screen -= src.hud_used.hotkeybuttons - - //Due to some poor coding some things need special treatment: - //These ones are a part of 'adding', 'other' or 'hotkeybuttons' but we want them to stay - if(!full) - src.client.screen += src.hud_used.l_hand_hud_object //we want the hands to be visible - src.client.screen += src.hud_used.r_hand_hud_object //we want the hands to be visible - src.client.screen += src.hud_used.action_intent //we want the intent swticher visible - src.hud_used.action_intent.screen_loc = ui_acti_alt //move this to the alternative position, where zone_select usually is. - else - src.client.screen -= src.healths - src.client.screen -= src.internals - src.client.screen -= src.healthdoll - src.client.screen -= src.gun_setting_icon - src.client.screen -= src.hud_used.lingstingdisplay - src.client.screen -= src.hud_used.lingchemdisplay - - //These ones are not a part of 'adding', 'other' or 'hotkeybuttons' but we want them gone. - src.client.screen -= src.zone_sel //zone_sel is a mob variable for some reason. - - else - hud_used.hud_shown = 1 - if(src.hud_used.adding) - src.client.screen += src.hud_used.adding - if(src.hud_used.other && src.hud_used.inventory_shown) - src.client.screen += src.hud_used.other - if(src.hud_used.hotkeybuttons && !src.hud_used.hotkey_ui_hidden) - src.client.screen += src.hud_used.hotkeybuttons - if(src.healths) - src.client.screen |= src.healths - if(src.healthdoll) - src.client.screen |= src.healthdoll - if(src.internals) - src.client.screen |= src.internals - if(src.gun_setting_icon) - src.client.screen |= src.gun_setting_icon - if(src.hud_used.lingstingdisplay) - src.client.screen |= src.hud_used.lingstingdisplay - if(src.hud_used.lingchemdisplay) - src.client.screen |= src.hud_used.lingchemdisplay - - src.hud_used.action_intent.screen_loc = ui_acti //Restore intent selection to the original position - src.client.screen += src.zone_sel //This one is a special snowflake - - hud_used.hidden_inventory_update() - hud_used.persistant_inventory_update() - update_action_buttons() - hud_used.reorganize_alerts() - - else - to_chat(usr, "\red Inventory hiding is currently only supported for human mobs, sorry.") + if(hud_used && client) + hud_used.show_hud() //Shows the next hud preset + to_chat(usr, "Switched HUD mode. Press F12 to toggle.") else - to_chat(usr, "\red This mob type does not use a HUD.") + to_chat(usr, "This mob type does not use a HUD.") + diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index d75f7c8ad61..3a6e9df5dae 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -1,5 +1,5 @@ /obj/screen/human - icon = 'icons/mob/screen1_midnight.dmi' + icon = 'icons/mob/screen_midnight.dmi' /obj/screen/human/toggle name = "toggle" @@ -8,10 +8,10 @@ /obj/screen/human/toggle/Click() if(usr.hud_used.inventory_shown) usr.hud_used.inventory_shown = 0 - usr.client.screen -= usr.hud_used.other + usr.client.screen -= usr.hud_used.toggleable_inventory else usr.hud_used.inventory_shown = 1 - usr.client.screen += usr.hud_used.other + usr.client.screen += usr.hud_used.toggleable_inventory usr.hud_used.hidden_inventory_update() @@ -30,6 +30,7 @@ /obj/screen/ling/sting name = "current sting" + screen_loc = ui_lingstingdisplay /obj/screen/ling/sting/Click() var/mob/living/carbon/U = usr @@ -38,175 +39,147 @@ /obj/screen/ling/chems name = "chemical storage" icon_state = "power_display" + screen_loc = ui_lingchemdisplay -/datum/hud/proc/human_hud(var/ui_style='icons/mob/screen1_White.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255) - src.adding = list() - src.other = list() - src.hotkeybuttons = list() //These can be disabled for hotkey usersx +/mob/living/carbon/human/proc/remake_hud() //used for preference changes mid-round; can't change hud icons without remaking the hud. + if(hud_used) + qdel(hud_used) + hud_used = null + create_mob_hud() + if(hud_used) + hud_used.show_hud(hud_used.hud_version) + +/mob/living/carbon/human/create_mob_hud() + if(client && !hud_used) + hud_used = new /datum/hud/human(src, ui_style2icon(client.prefs.UI_style), client.prefs.UI_style_color, client.prefs.UI_style_alpha) + +/datum/hud/human/New(mob/living/carbon/human/owner, var/ui_style = 'icons/mob/screen_white.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255) + ..() var/obj/screen/using var/obj/screen/inventory/inv_box using = new /obj/screen/act_intent() - using.name = "act_intent" - using.dir = SOUTHWEST - using.icon = ui_style - using.icon_state = "intent_"+mymob.a_intent - using.screen_loc = ui_acti + using.icon_state = mymob.a_intent using.color = ui_color using.alpha = ui_alpha - using.layer = 20 - src.adding += using + static_inventory += using action_intent = using - - using = new /obj/screen/mov_intent() - using.name = "mov_intent" - using.dir = SOUTHWEST using.icon = ui_style using.icon_state = (mymob.m_intent == "run" ? "running" : "walking") using.screen_loc = ui_movi - using.layer = 20 using.color = ui_color using.alpha = ui_alpha - src.adding += using + static_inventory += using move_intent = using using = new /obj/screen/drop() - using.name = "drop" using.icon = ui_style - using.icon_state = "act_drop" using.screen_loc = ui_drop_throw - using.layer = 19 using.color = ui_color using.alpha = ui_alpha - src.hotkeybuttons += using + static_inventory += using inv_box = new /obj/screen/inventory() inv_box.name = "i_clothing" - inv_box.dir = SOUTH inv_box.icon = ui_style inv_box.slot_id = slot_w_uniform - inv_box.icon_state = "center" + inv_box.icon_state = "uniform" inv_box.screen_loc = ui_iclothing - inv_box.layer = 19 inv_box.color = ui_color inv_box.alpha = ui_alpha - src.other += inv_box + toggleable_inventory += inv_box inv_box = new /obj/screen/inventory() inv_box.name = "o_clothing" - inv_box.dir = SOUTH inv_box.icon = ui_style inv_box.slot_id = slot_wear_suit - inv_box.icon_state = "equip" + inv_box.icon_state = "suit" inv_box.screen_loc = ui_oclothing inv_box.color = ui_color inv_box.alpha = ui_alpha - inv_box.layer = 19 - src.other += inv_box + toggleable_inventory += inv_box - inv_box = new /obj/screen/inventory() + inv_box = new /obj/screen/inventory/hand() inv_box.name = "r_hand" - inv_box.dir = WEST inv_box.icon = ui_style - inv_box.icon_state = "hand_inactive" - if(mymob && !mymob.hand) //This being 0 or null means the right hand is in use - inv_box.icon_state = "hand_active" + inv_box.icon_state = "hand_r" + inv_box.color = ui_color + inv_box.alpha = ui_alpha inv_box.screen_loc = ui_rhand inv_box.slot_id = slot_r_hand - inv_box.layer = 19 + static_inventory += inv_box + + inv_box = new /obj/screen/inventory/hand() + inv_box.name = "l_hand" + inv_box.icon = ui_style + inv_box.icon_state = "hand_l" inv_box.color = ui_color inv_box.alpha = ui_alpha - src.r_hand_hud_object = inv_box - src.adding += inv_box - - inv_box = new /obj/screen/inventory() - inv_box.name = "l_hand" - inv_box.dir = EAST - inv_box.icon = ui_style - inv_box.icon_state = "hand_inactive" - if(mymob && mymob.hand) //This being 1 means the left hand is in use - inv_box.icon_state = "hand_active" inv_box.screen_loc = ui_lhand inv_box.slot_id = slot_l_hand - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.l_hand_hud_object = inv_box - src.adding += inv_box + static_inventory += inv_box - using = new /obj/screen/inventory() + using = new /obj/screen/swap_hand() using.name = "hand" - using.dir = SOUTH using.icon = ui_style - using.icon_state = "hand1" + using.icon_state = "swap_1" using.screen_loc = ui_swaphand1 - using.layer = 19 using.color = ui_color using.alpha = ui_alpha - src.adding += using + static_inventory += using - using = new /obj/screen/inventory() + using = new /obj/screen/swap_hand() using.name = "hand" - using.dir = SOUTH using.icon = ui_style - using.icon_state = "hand2" + using.icon_state = "swap_2" using.screen_loc = ui_swaphand2 - using.layer = 19 using.color = ui_color using.alpha = ui_alpha - src.adding += using + static_inventory += using inv_box = new /obj/screen/inventory() inv_box.name = "id" - inv_box.dir = NORTH inv_box.icon = ui_style inv_box.icon_state = "id" inv_box.screen_loc = ui_id inv_box.slot_id = slot_wear_id - inv_box.layer = 19 inv_box.color = ui_color inv_box.alpha = ui_alpha - src.adding += inv_box + static_inventory += inv_box inv_box = new /obj/screen/inventory() inv_box.name = "pda" - inv_box.dir = NORTH inv_box.icon = ui_style inv_box.icon_state = "pda" inv_box.screen_loc = ui_pda inv_box.slot_id = slot_wear_pda - inv_box.layer = 19 inv_box.color = ui_color inv_box.alpha = ui_alpha - src.adding += inv_box + static_inventory += inv_box inv_box = new /obj/screen/inventory() inv_box.name = "mask" - inv_box.dir = NORTH inv_box.icon = ui_style - inv_box.icon_state = "equip" + inv_box.icon_state = "mask" inv_box.screen_loc = ui_mask inv_box.slot_id = slot_wear_mask - inv_box.layer = 19 inv_box.color = ui_color inv_box.alpha = ui_alpha - src.other += inv_box + toggleable_inventory += inv_box inv_box = new /obj/screen/inventory() inv_box.name = "back" - inv_box.dir = NORTH inv_box.icon = ui_style inv_box.icon_state = "back" inv_box.screen_loc = ui_back inv_box.slot_id = slot_back - inv_box.layer = 19 inv_box.color = ui_color inv_box.alpha = ui_alpha - src.adding += inv_box + static_inventory += inv_box inv_box = new /obj/screen/inventory() inv_box.name = "storage1" @@ -214,10 +187,9 @@ inv_box.icon_state = "pocket" inv_box.screen_loc = ui_storage1 inv_box.slot_id = slot_l_store - inv_box.layer = 19 inv_box.color = ui_color inv_box.alpha = ui_alpha - src.adding += inv_box + static_inventory += inv_box inv_box = new /obj/screen/inventory() inv_box.name = "storage2" @@ -225,52 +197,40 @@ inv_box.icon_state = "pocket" inv_box.screen_loc = ui_storage2 inv_box.slot_id = slot_r_store - inv_box.layer = 19 inv_box.color = ui_color inv_box.alpha = ui_alpha - src.adding += inv_box + static_inventory += inv_box inv_box = new /obj/screen/inventory() inv_box.name = "suit storage" inv_box.icon = ui_style - inv_box.dir = 8 //The sprite at dir=8 has the background whereas the others don't. - inv_box.icon_state = "belt" - inv_box.screen_loc = ui_sstore1 - inv_box.slot_id = slot_s_store - inv_box.layer = 19 + inv_box.icon_state = "suit_storage" inv_box.color = ui_color inv_box.alpha = ui_alpha - src.adding += inv_box + inv_box.screen_loc = ui_sstore1 + inv_box.slot_id = slot_s_store + static_inventory += inv_box using = new /obj/screen/resist() - using.name = "resist" using.icon = ui_style - using.icon_state = "act_resist" - using.screen_loc = ui_pull_resist - using.layer = 19 using.color = ui_color using.alpha = ui_alpha - src.hotkeybuttons += using + using.screen_loc = ui_pull_resist + hotkeybuttons += using using = new /obj/screen/human/toggle() - using.name = "toggle" using.icon = ui_style - using.icon_state = "other" - using.screen_loc = ui_inventory - using.layer = 20 using.color = ui_color using.alpha = ui_alpha - src.adding += using + using.screen_loc = ui_inventory + static_inventory += using using = new /obj/screen/human/equip() - using.name = "equip" using.icon = ui_style - using.icon_state = "act_equip" - using.screen_loc = ui_equip - using.layer = 20 using.color = ui_color using.alpha = ui_alpha - src.adding += using + using.screen_loc = ui_equip + static_inventory += using inv_box = new /obj/screen/inventory() inv_box.name = "gloves" @@ -278,10 +238,9 @@ inv_box.icon_state = "gloves" inv_box.screen_loc = ui_gloves inv_box.slot_id = slot_gloves - inv_box.layer = 19 inv_box.color = ui_color inv_box.alpha = ui_alpha - src.other += inv_box + toggleable_inventory += inv_box inv_box = new /obj/screen/inventory() inv_box.name = "eyes" @@ -289,10 +248,9 @@ inv_box.icon_state = "glasses" inv_box.screen_loc = ui_glasses inv_box.slot_id = slot_glasses - inv_box.layer = 19 inv_box.color = ui_color inv_box.alpha = ui_alpha - src.other += inv_box + toggleable_inventory += inv_box inv_box = new /obj/screen/inventory() inv_box.name = "l_ear" @@ -300,10 +258,9 @@ inv_box.icon_state = "ears" inv_box.screen_loc = ui_l_ear inv_box.slot_id = slot_l_ear - inv_box.layer = 19 inv_box.color = ui_color inv_box.alpha = ui_alpha - src.other += inv_box + toggleable_inventory += inv_box inv_box = new /obj/screen/inventory() inv_box.name = "r_ear" @@ -311,21 +268,19 @@ inv_box.icon_state = "ears" inv_box.screen_loc = ui_r_ear inv_box.slot_id = slot_r_ear - inv_box.layer = 19 inv_box.color = ui_color inv_box.alpha = ui_alpha - src.other += inv_box + toggleable_inventory += inv_box inv_box = new /obj/screen/inventory() inv_box.name = "head" inv_box.icon = ui_style - inv_box.icon_state = "hair" + inv_box.icon_state = "head" inv_box.screen_loc = ui_head inv_box.slot_id = slot_head - inv_box.layer = 19 inv_box.color = ui_color inv_box.alpha = ui_alpha - src.other += inv_box + toggleable_inventory += inv_box inv_box = new /obj/screen/inventory() inv_box.name = "shoes" @@ -333,10 +288,9 @@ inv_box.icon_state = "shoes" inv_box.screen_loc = ui_shoes inv_box.slot_id = slot_shoes - inv_box.layer = 19 inv_box.color = ui_color inv_box.alpha = ui_alpha - src.other += inv_box + toggleable_inventory += inv_box inv_box = new /obj/screen/inventory() inv_box.name = "belt" @@ -344,85 +298,150 @@ inv_box.icon_state = "belt" inv_box.screen_loc = ui_belt inv_box.slot_id = slot_belt - inv_box.layer = 19 inv_box.color = ui_color inv_box.alpha = ui_alpha - src.adding += inv_box + static_inventory += inv_box mymob.throw_icon = new /obj/screen/throw_catch() mymob.throw_icon.icon = ui_style - mymob.throw_icon.icon_state = "act_throw_off" - mymob.throw_icon.name = "throw" mymob.throw_icon.screen_loc = ui_drop_throw mymob.throw_icon.color = ui_color mymob.throw_icon.alpha = ui_alpha - src.hotkeybuttons += mymob.throw_icon + hotkeybuttons += mymob.throw_icon mymob.internals = new /obj/screen/internals() - mymob.internals.icon = ui_style - mymob.internals.icon_state = "internal0" - mymob.internals.name = "internal" - mymob.internals.screen_loc = ui_internal + infodisplay += mymob.internals - mymob.healths = new /obj/screen() - mymob.healths.icon = ui_style - mymob.healths.icon_state = "health0" - mymob.healths.name = "health" - mymob.healths.screen_loc = ui_health + mymob.healths = new /obj/screen/healths() + infodisplay += mymob.healths - mymob.healthdoll = new /obj/screen() - mymob.healthdoll.icon = ui_style - mymob.healthdoll.icon_state = "healthdoll_DEAD" - mymob.healthdoll.name = "health doll" - mymob.healthdoll.screen_loc = ui_healthdoll + mymob.healthdoll = new /obj/screen/healthdoll() + infodisplay += mymob.healthdoll mymob.pullin = new /obj/screen/pull() mymob.pullin.icon = ui_style mymob.pullin.update_icon(mymob) mymob.pullin.screen_loc = ui_pull_resist - src.hotkeybuttons += mymob.pullin + static_inventory += mymob.pullin lingchemdisplay = new /obj/screen/ling/chems() - lingchemdisplay.screen_loc = ui_lingchemdisplay + infodisplay += lingchemdisplay lingstingdisplay = new /obj/screen/ling/sting() - lingstingdisplay.screen_loc = ui_lingstingdisplay + infodisplay += lingstingdisplay - mymob.zone_sel = new /obj/screen/zone_sel( null ) + mymob.zone_sel = new /obj/screen/zone_sel() mymob.zone_sel.icon = ui_style - mymob.zone_sel.color = ui_color - mymob.zone_sel.alpha = ui_alpha - mymob.zone_sel.overlays.Cut() - mymob.zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[mymob.zone_sel.selecting]") + mymob.zone_sel.update_icon(mymob) + static_inventory += mymob.zone_sel - //Handle the gun settings buttons - mymob.gun_setting_icon = new /obj/screen/gun/mode(null) - //mymob.gun_setting_icon.color = ui_color - mymob.gun_setting_icon.alpha = ui_alpha - - mymob.item_use_icon = new /obj/screen/gun/item(null) - //mymob.item_use_icon.color = ui_color - mymob.item_use_icon.alpha = ui_alpha - - /*mymob.gun_move_icon = new /obj/screen/gun/move(null) - //mymob.gun_move_icon.color = ui_color - mymob.gun_move_icon.alpha = ui_alpha - - mymob.gun_run_icon = new /obj/screen/gun/run(null) - //mymob.gun_run_icon.color = ui_color - mymob.gun_run_icon.alpha = ui_alpha*/ - - if (mymob.client) - if (mymob.client.gun_mode) // If in aim mode, correct the sprite - mymob.gun_setting_icon.dir = 2 - - mymob.client.screen = list() - - mymob.client.screen += list(mymob.throw_icon, mymob.zone_sel, mymob.internals, mymob.healths, mymob.healthdoll, mymob.pullin, mymob.gun_setting_icon, lingchemdisplay, lingstingdisplay) //, mymob.hands, mymob.rest, mymob.sleep) //, mymob.mach ) - mymob.client.screen += src.adding + src.hotkeybuttons - mymob.client.screen += mymob.client.void inventory_shown = 0 + for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory)) + if(inv.slot_id) + inv.hud = src + inv_slots[inv.slot_id] = inv + inv.update_icon() + +/datum/hud/human/hidden_inventory_update() + if(!mymob) + return + var/mob/living/carbon/human/H = mymob + if(inventory_shown && hud_shown) + if(H.shoes) + H.shoes.screen_loc = ui_shoes + H.client.screen += H.shoes + if(H.gloves) + H.gloves.screen_loc = ui_gloves + H.client.screen += H.gloves + if(H.l_ear) + H.l_ear.screen_loc = ui_l_ear + H.client.screen += H.l_ear + if(H.r_ear) + H.r_ear.screen_loc = ui_r_ear + H.client.screen += H.r_ear + if(H.glasses) + H.glasses.screen_loc = ui_glasses + H.client.screen += H.glasses + if(H.w_uniform) + H.w_uniform.screen_loc = ui_iclothing + H.client.screen += H.w_uniform + if(H.wear_suit) + H.wear_suit.screen_loc = ui_oclothing + H.client.screen += H.wear_suit + if(H.wear_mask) + H.wear_mask.screen_loc = ui_mask + H.client.screen += H.wear_mask + if(H.head) + H.head.screen_loc = ui_head + H.client.screen += H.head + else + if(H.shoes) H.shoes.screen_loc = null + if(H.gloves) H.gloves.screen_loc = null + if(H.l_ear) H.l_ear.screen_loc = null + if(H.r_ear) H.r_ear.screen_loc = null + if(H.glasses) H.glasses.screen_loc = null + if(H.w_uniform) H.w_uniform.screen_loc = null + if(H.wear_suit) H.wear_suit.screen_loc = null + if(H.wear_mask) H.wear_mask.screen_loc = null + if(H.head) H.head.screen_loc = null + +/datum/hud/human/persistant_inventory_update() + if(!mymob) + return + var/mob/living/carbon/human/H = mymob + if(hud_shown) + if(H.s_store) + H.s_store.screen_loc = ui_sstore1 + H.client.screen += H.s_store + if(H.wear_id) + H.wear_id.screen_loc = ui_id + H.client.screen += H.wear_id + if(H.wear_pda) + H.wear_pda.screen_loc = ui_pda + H.client.screen += H.wear_pda + if(H.belt) + H.belt.screen_loc = ui_belt + H.client.screen += H.belt + if(H.back) + H.back.screen_loc = ui_back + H.client.screen += H.back + if(H.l_store) + H.l_store.screen_loc = ui_storage1 + H.client.screen += H.l_store + if(H.r_store) + H.r_store.screen_loc = ui_storage2 + H.client.screen += H.r_store + else + if(H.s_store) + H.s_store.screen_loc = null + if(H.wear_id) + H.wear_id.screen_loc = null + if(H.wear_pda) + H.wear_pda.screen_loc = null + if(H.belt) + H.belt.screen_loc = null + if(H.back) + H.back.screen_loc = null + if(H.l_store) + H.l_store.screen_loc = null + if(H.r_store) + H.r_store.screen_loc = null + + if(hud_version != HUD_STYLE_NOHUD) + if(H.r_hand) + H.r_hand.screen_loc = ui_rhand + H.client.screen += H.r_hand + if(H.l_hand) + H.l_hand.screen_loc = ui_lhand + H.client.screen += H.l_hand + else + if(H.r_hand) + H.r_hand.screen_loc = null + if(H.l_hand) + H.l_hand.screen_loc = null + + /mob/living/carbon/human/verb/toggle_hotkey_verbs() set category = "OOC" set name = "Toggle Hotkey Buttons" diff --git a/code/_onclick/hud/monkey.dm b/code/_onclick/hud/monkey.dm index 34d26e77d6d..ef87435c79f 100644 --- a/code/_onclick/hud/monkey.dm +++ b/code/_onclick/hud/monkey.dm @@ -1,194 +1,131 @@ -/datum/hud/proc/monkey_hud(var/ui_style='icons/mob/screen1_White.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255) +/mob/living/carbon/human/monkey/create_mob_hud() + if(client && !hud_used) + hud_used = new /datum/hud/monkey(src, ui_style2icon(client.prefs.UI_style), client.prefs.UI_style_color, client.prefs.UI_style_alpha) - src.adding = list() - src.other = list() - src.hotkeybuttons = list() //These can be disabled for hotkey usersx +/datum/hud/monkey/New(mob/living/carbon/human/owner, var/ui_style = 'icons/mob/screen_white.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255) + ..() var/obj/screen/using var/obj/screen/inventory/inv_box using = new /obj/screen/act_intent() - using.name = "act_intent" - using.dir = SOUTHWEST - using.icon = ui_style - using.icon_state = "intent_"+mymob.a_intent - using.screen_loc = ui_acti + using.icon_state = mymob.a_intent using.color = ui_color using.alpha = ui_alpha - using.layer = 20 - src.adding += using + static_inventory += using action_intent = using using = new /obj/screen/mov_intent() - using.name = "mov_intent" - using.dir = SOUTHWEST using.icon = ui_style using.icon_state = (mymob.m_intent == "run" ? "running" : "walking") using.screen_loc = ui_movi - using.layer = 20 using.color = ui_color using.alpha = ui_alpha - src.adding += using + static_inventory += using move_intent = using using = new /obj/screen/drop() - using.name = "drop" using.icon = ui_style - using.icon_state = "act_drop" using.screen_loc = ui_drop_throw - using.layer = 19 using.color = ui_color using.alpha = ui_alpha - src.adding += using + static_inventory += using - inv_box = new /obj/screen/inventory() + inv_box = new /obj/screen/inventory/hand() inv_box.name = "r_hand" - inv_box.dir = WEST inv_box.icon = ui_style - inv_box.icon_state = "hand_inactive" - if(mymob && !mymob.hand) //This being 0 or null means the right hand is in use - inv_box.icon_state = "hand_active" + inv_box.icon_state = "hand_r" + inv_box.color = ui_color + inv_box.alpha = ui_alpha inv_box.screen_loc = ui_rhand inv_box.slot_id = slot_r_hand - inv_box.layer = 19 + static_inventory += inv_box + + inv_box = new /obj/screen/inventory/hand() + inv_box.name = "l_hand" + inv_box.icon = ui_style + inv_box.icon_state = "hand_l" inv_box.color = ui_color inv_box.alpha = ui_alpha - src.r_hand_hud_object = inv_box - src.adding += inv_box - - inv_box = new /obj/screen/inventory() - inv_box.name = "l_hand" - inv_box.dir = EAST - inv_box.icon = ui_style - inv_box.icon_state = "hand_inactive" - if(mymob && mymob.hand) //This being 1 means the left hand is in use - inv_box.icon_state = "hand_active" inv_box.screen_loc = ui_lhand inv_box.slot_id = slot_l_hand - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.l_hand_hud_object = inv_box - src.adding += inv_box + static_inventory += inv_box - using = new /obj/screen/inventory() + using = new /obj/screen/swap_hand() using.name = "hand" - using.dir = SOUTH using.icon = ui_style - using.icon_state = "hand1" + using.icon_state = "swap_1_m" using.screen_loc = ui_swaphand1 - using.layer = 19 using.color = ui_color using.alpha = ui_alpha - src.adding += using + static_inventory += using - using = new /obj/screen/inventory() + using = new /obj/screen/swap_hand() using.name = "hand" - using.dir = SOUTH using.icon = ui_style - using.icon_state = "hand2" + using.icon_state = "swap_2" using.screen_loc = ui_swaphand2 - using.layer = 19 using.color = ui_color using.alpha = ui_alpha - src.adding += using + static_inventory += using inv_box = new /obj/screen/inventory() inv_box.name = "mask" - inv_box.dir = NORTH inv_box.icon = ui_style - inv_box.icon_state = "equip" - inv_box.screen_loc = ui_monkey_mask + inv_box.icon_state = "mask" + inv_box.screen_loc = ui_mask inv_box.slot_id = slot_wear_mask - inv_box.layer = 19 inv_box.color = ui_color inv_box.alpha = ui_alpha - src.adding += inv_box + toggleable_inventory += inv_box inv_box = new /obj/screen/inventory() inv_box.name = "back" - inv_box.dir = NORTHEAST inv_box.icon = ui_style - inv_box.icon_state = "equip" + inv_box.icon_state = "back" inv_box.screen_loc = ui_back inv_box.slot_id = slot_back - inv_box.layer = 19 inv_box.color = ui_color inv_box.alpha = ui_alpha - src.adding += inv_box + static_inventory += inv_box mymob.throw_icon = new /obj/screen/throw_catch() mymob.throw_icon.icon = ui_style - mymob.throw_icon.icon_state = "act_throw_off" - mymob.throw_icon.name = "throw" mymob.throw_icon.screen_loc = ui_drop_throw mymob.throw_icon.color = ui_color mymob.throw_icon.alpha = ui_alpha - src.hotkeybuttons += mymob.throw_icon + hotkeybuttons += mymob.throw_icon mymob.internals = new /obj/screen/internals() - mymob.internals.icon = ui_style - mymob.internals.icon_state = "internal0" - mymob.internals.name = "internal" - mymob.internals.screen_loc = ui_internal + infodisplay += mymob.internals - mymob.healths = new /obj/screen() - mymob.healths.icon = ui_style - mymob.healths.icon_state = "health0" - mymob.healths.name = "health" - mymob.healths.screen_loc = ui_health + mymob.healths = new /obj/screen/healths() + infodisplay += mymob.healths - mymob.healthdoll = new /obj/screen() - mymob.healthdoll.icon = ui_style - mymob.healthdoll.icon_state = "healthdoll_DEAD" - mymob.healthdoll.name = "health doll" - mymob.healthdoll.screen_loc = ui_healthdoll + mymob.healthdoll = new /obj/screen/healthdoll() + infodisplay += mymob.healthdoll mymob.pullin = new /obj/screen/pull() mymob.pullin.icon = ui_style mymob.pullin.update_icon(mymob) mymob.pullin.screen_loc = ui_pull_resist - src.hotkeybuttons += mymob.pullin + static_inventory += mymob.pullin lingchemdisplay = new /obj/screen/ling/chems() - lingchemdisplay.screen_loc = ui_lingchemdisplay + infodisplay += lingchemdisplay lingstingdisplay = new /obj/screen/ling/sting() - lingstingdisplay.screen_loc = ui_lingstingdisplay + infodisplay += lingstingdisplay - mymob.zone_sel = new /obj/screen/zone_sel( null ) + mymob.zone_sel = new /obj/screen/zone_sel() mymob.zone_sel.icon = ui_style - mymob.zone_sel.color = ui_color - mymob.zone_sel.alpha = ui_alpha - mymob.zone_sel.overlays.Cut() - mymob.zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[mymob.zone_sel.selecting]") + mymob.zone_sel.update_icon(mymob) + static_inventory += mymob.zone_sel - //Handle the gun settings buttons - mymob.gun_setting_icon = new /obj/screen/gun/mode(null) - //mymob.gun_setting_icon.color = ui_color - mymob.gun_setting_icon.alpha = ui_alpha + inventory_shown = 0 - mymob.item_use_icon = new /obj/screen/gun/item(null) - //mymob.item_use_icon.color = ui_color - mymob.item_use_icon.alpha = ui_alpha - - /*mymob.gun_move_icon = new /obj/screen/gun/move(null) - //mymob.gun_move_icon.color = ui_color - mymob.gun_move_icon.alpha = ui_alpha - - mymob.gun_run_icon = new /obj/screen/gun/run(null) - //mymob.gun_run_icon.color = ui_color - mymob.gun_run_icon.alpha = ui_alpha*/ - - if (mymob.client) - if (mymob.client.gun_mode) // If in aim mode, correct the sprite - mymob.gun_setting_icon.dir = 2 - - - mymob.client.screen = list() - - mymob.client.screen += list(mymob.throw_icon, mymob.zone_sel, mymob.internals, mymob.healths, mymob.healthdoll, mymob.pullin, mymob.gun_setting_icon, lingchemdisplay, lingstingdisplay) //, mymob.hands, mymob.rest, mymob.sleep) //, mymob.mach ) - mymob.client.screen += src.adding + src.hotkeybuttons - mymob.client.screen += mymob.client.void - - return \ No newline at end of file + for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory)) + if(inv.slot_id) + inv.hud = src + inv_slots[inv.slot_id] = inv + inv.update_icon() diff --git a/code/_onclick/hud/other_mobs.dm b/code/_onclick/hud/other_mobs.dm index 331c04fc69f..29d7295feac 100644 --- a/code/_onclick/hud/other_mobs.dm +++ b/code/_onclick/hud/other_mobs.dm @@ -1,41 +1,35 @@ +/mob/living/simple_animal/pet/create_mob_hud() + if(client && !hud_used) + hud_used = new /datum/hud/corgi(src) -/datum/hud/proc/unplayer_hud() - return +/datum/hud/corgi/New(mob/user) + ..() -/datum/hud/proc/ghost_hud() - return - -/datum/hud/proc/corgi_hud(u) - mymob.healths = new /obj/screen() - mymob.healths.icon = 'icons/mob/screen1_corgi.dmi' - mymob.healths.icon_state = "health0" - mymob.healths.name = "health" - mymob.healths.screen_loc = ui_health + mymob.healths = new /obj/screen/healths/corgi() + infodisplay += mymob.healths mymob.pullin = new /obj/screen/pull() - mymob.pullin.icon = 'icons/mob/screen1_corgi.dmi' + mymob.pullin.icon = 'icons/mob/screen_corgi.dmi' mymob.pullin.update_icon(mymob) mymob.pullin.screen_loc = ui_construct_pull - - mymob.client.screen = list() - mymob.client.screen += list(mymob.healths, mymob.pullin) + static_inventory += mymob.pullin -/datum/hud/proc/blob_hud(ui_style = 'icons/mob/screen1_Midnight.dmi') +/mob/camera/blob/create_mob_hud() + if(client && !hud_used) + hud_used = new /datum/hud/blob_overmind(src) + +/datum/hud/blob_overmind/New(mob/user) + ..() blobpwrdisplay = new /obj/screen() blobpwrdisplay.name = "blob power" blobpwrdisplay.icon_state = "block" blobpwrdisplay.screen_loc = ui_health - blobpwrdisplay.layer = 20 + static_inventory += blobpwrdisplay blobhealthdisplay = new /obj/screen() blobhealthdisplay.name = "blob health" blobhealthdisplay.icon_state = "block" blobhealthdisplay.screen_loc = ui_internal - blobhealthdisplay.layer = 20 - - mymob.client.screen = list() - - mymob.client.screen += list(blobpwrdisplay, blobhealthdisplay) - mymob.client.screen += mymob.client.void \ No newline at end of file + static_inventory += blobhealthdisplay \ No newline at end of file diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index 8a0fadf4e26..7aa9839d663 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -1,5 +1,5 @@ /obj/screen/robot - icon = 'icons/mob/screen1_robot.dmi' + icon = 'icons/mob/screen_robot.dmi' /obj/screen/robot/module name = "cyborg module" @@ -61,8 +61,9 @@ R.hud_used.update_robot_modules_display() /obj/screen/robot/lamp - name = "headlamp" + name = "Toggle Headlamp" icon_state = "lamp0" + screen_loc = ui_borg_lamp /obj/screen/robot/lamp/Click() if(isrobot(usr)) @@ -78,161 +79,113 @@ var/mob/living/silicon/robot/R = usr R.installed_modules() -/datum/hud/proc/robot_hud() +/mob/living/silicon/robot/create_mob_hud() + if(client && !hud_used) + hud_used = new /datum/hud/robot(src) - src.adding = list() - src.other = list() +/datum/hud/robot/New(mob/user) + ..() var/obj/screen/using - + var/mob/living/silicon/robot/mymobR = mymob //Radio using = new /obj/screen/robot/radio() - using.name = "radio" - using.dir = SOUTHWEST - using.icon = 'icons/mob/screen1_robot.dmi' - using.icon_state = "radio" using.screen_loc = ui_borg_radio - using.layer = 20 - src.adding += using + static_inventory += using //Module select - using = new /obj/screen/robot/module1() - using.name = "module1" - using.dir = SOUTHWEST - using.icon = 'icons/mob/screen1_robot.dmi' - using.icon_state = "inv1" using.screen_loc = ui_inv1 - using.layer = 20 - src.adding += using - mymob:inv1 = using + static_inventory += using + mymobR.inv1 = using using = new /obj/screen/robot/module2() - using.name = "module2" - using.dir = SOUTHWEST - using.icon = 'icons/mob/screen1_robot.dmi' - using.icon_state = "inv2" using.screen_loc = ui_inv2 - using.layer = 20 - src.adding += using - mymob:inv2 = using + static_inventory += using + mymobR.inv2 = using using = new /obj/screen/robot/module3() - using.name = "module3" - using.dir = SOUTHWEST - using.icon = 'icons/mob/screen1_robot.dmi' - using.icon_state = "inv3" using.screen_loc = ui_inv3 - using.layer = 20 - src.adding += using - mymob:inv3 = using + static_inventory += using + mymobR.inv3 = using //End of module select //Sec/Med HUDs using = new /obj/screen/ai/sensors() - using.name = "Toggle Sensor Augmentation" - using.icon = 'icons/mob/screen_ai.dmi' - using.icon_state = "ai_sensor" using.screen_loc = ui_borg_sensor - using.layer = 20 - adding += using + static_inventory += using -//Intent - using = new /obj/screen/act_intent() - using.name = "act_intent" - using.dir = SOUTHWEST - using.icon = 'icons/mob/screen1_robot.dmi' - using.icon_state = (mymob.a_intent == "harm" ? "harm" : mymob.a_intent) - using.screen_loc = ui_borg_intents - using.layer = 20 - src.adding += using +//Intent + using = new /obj/screen/act_intent/robot() + using.icon_state = mymob.a_intent + static_inventory += using action_intent = using //Health - mymob.healths = new /obj/screen() - mymob.healths.icon = 'icons/mob/screen1_robot.dmi' - mymob.healths.icon_state = "health0" - mymob.healths.name = "health" - mymob.healths.screen_loc = ui_borg_health + mymob.healths = new /obj/screen/healths/robot() + infodisplay += mymob.healths //Installed Module mymob.hands = new /obj/screen/robot/module() - mymob.hands.icon = 'icons/mob/screen1_robot.dmi' - mymob.hands.icon_state = "nomod" - mymob.hands.name = "module" mymob.hands.screen_loc = ui_borg_module + static_inventory += mymob.hands - -//Store - mymob.throw_icon = new /obj/screen/robot/store() - mymob.throw_icon.icon = 'icons/mob/screen1_robot.dmi' - mymob.throw_icon.icon_state = "store" - mymob.throw_icon.name = "store" - mymob.throw_icon.screen_loc = ui_borg_store - -//Headlamp - mymob:lamp_button = new /obj/screen/robot/lamp() - mymob:lamp_button.icon = 'icons/mob/screen1_robot.dmi' - mymob:lamp_button.icon_state = "lamp0" - mymob:lamp_button.name = "Toggle Headlamp" - mymob:lamp_button.screen_loc = ui_borg_lamp + module_store_icon = new /obj/screen/robot/store() + module_store_icon.screen_loc = ui_borg_store mymob.pullin = new /obj/screen/pull() - mymob.pullin.icon = 'icons/mob/screen1_robot.dmi' + mymob.pullin.icon = 'icons/mob/screen_robot.dmi' mymob.pullin.update_icon(mymob) mymob.pullin.screen_loc = ui_borg_pull + hotkeybuttons += mymob.pullin - mymob.zone_sel = new /obj/screen/zone_sel() - mymob.zone_sel.icon = 'icons/mob/screen1_robot.dmi' - mymob.zone_sel.overlays.Cut() - mymob.zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[mymob.zone_sel.selecting]") + mymob.zone_sel = new /obj/screen/zone_sel/robot() + mymob.zone_sel.update_icon(mymob) + static_inventory += mymob.zone_sel - mymob.gun_setting_icon = new /obj/screen/gun/mode(null) - mymob.item_use_icon = new /obj/screen/gun/item(null) - - mymob.client.screen = list() - - mymob.client.screen += list(mymob.zone_sel, mymob.hands, mymob.healths, mymob.pullin, mymob.gun_setting_icon, mymob:lamp_button) //, mymob.rest, mymob.sleep, mymob.mach ) - mymob.client.screen += src.adding + src.other - mymob.client.screen += mymob.client.void - return +//Headlamp + mymobR.lamp_button = new /obj/screen/robot/lamp() + mymobR.lamp_button.screen_loc = ui_borg_lamp + static_inventory += mymobR.lamp_button /datum/hud/proc/toggle_show_robot_modules() - if(!isrobot(mymob)) return + if(!isrobot(mymob)) + return - var/mob/living/silicon/robot/r = mymob + var/mob/living/silicon/robot/R = mymob - r.shown_robot_modules = !r.shown_robot_modules + R.shown_robot_modules = !R.shown_robot_modules update_robot_modules_display() /datum/hud/proc/update_robot_modules_display() - if(!isrobot(mymob)) return + if(!isrobot(mymob)) + return - var/mob/living/silicon/robot/r = mymob + var/mob/living/silicon/robot/R = mymob - if(!r.client) return + if(!R.client) + return - if(r.shown_robot_modules) + if(!R.module) + return + + if(R.shown_robot_modules && hud_shown) //Modules display is shown - r.client.screen += r.throw_icon //"store" icon + R.client.screen += module_store_icon //"store" icon - if(!r.module) - to_chat(usr, "\red No module selected") + if(!R.module.modules) + to_chat(usr, "Selected module has no modules to select.") return - if(!r.module.modules) - to_chat(usr, "\red Selected module has no modules to select") + if(!R.robot_modules_background) return - if(!r.robot_modules_background) - return - - var/display_rows = round((r.module.modules.len) / 8) +1 //+1 because round() returns floor of number - r.robot_modules_background.screen_loc = "CENTER-4:16,SOUTH+1:7 to CENTER+3:16,SOUTH+[display_rows]:7" - r.client.screen += r.robot_modules_background + var/display_rows = Ceiling(R.module.modules.len / 8) + R.robot_modules_background.screen_loc = "CENTER-4:16,SOUTH+1:7 to CENTER+3:16,SOUTH+[display_rows]:7" + R.client.screen += R.robot_modules_background var/x = -4 //Start at CENTER-4,SOUTH+1 var/y = 1 @@ -240,17 +193,17 @@ //Unfortunately adding the emag module to the list of modules has to be here. This is because a borg can //be emagged before they actually select a module. - or some situation can cause them to get a new module // - or some situation might cause them to get de-emagged or something. - if(r.emagged) - if(!(r.module.emag in r.module.modules)) - r.module.modules.Add(r.module.emag) + if(R.emagged) + if(!(R.module.emag in R.module.modules)) + R.module.modules.Add(R.module.emag) else - if(r.module.emag in r.module.modules) - r.module.modules.Remove(r.module.emag) + if(R.module.emag in R.module.modules) + R.module.modules.Remove(R.module.emag) - for(var/atom/movable/A in r.module.modules) - if( (A != r.module_state_1) && (A != r.module_state_2) && (A != r.module_state_3) ) + for(var/atom/movable/A in R.module.modules) + if( (A != R.module_state_1) && (A != R.module_state_2) && (A != R.module_state_3) ) //Module is not currently active - r.client.screen += A + R.client.screen += A if(x < 0) A.screen_loc = "CENTER[x]:16,SOUTH+[y]:7" else @@ -264,11 +217,11 @@ else //Modules display is hidden - r.client.screen -= r.throw_icon //"store" icon + R.client.screen -= module_store_icon - for(var/atom/A in r.module.modules) - if( (A != r.module_state_1) && (A != r.module_state_2) && (A != r.module_state_3) ) + for(var/atom/A in R.module.modules) + if( (A != R.module_state_1) && (A != R.module_state_2) && (A != R.module_state_3) ) //Module is not currently active - r.client.screen -= A - r.shown_robot_modules = 0 - r.client.screen -= r.robot_modules_background + R.client.screen -= A + R.shown_robot_modules = 0 + R.client.screen -= R.robot_modules_background diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 3ab8f58fd99..1f0e6205200 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -8,11 +8,11 @@ */ /obj/screen name = "" - icon = 'icons/mob/screen1.dmi' - layer = 20.0 + icon = 'icons/mob/screen_gen.dmi' + layer = 20 unacidable = 1 var/obj/master = null //A reference to the object in the slot. Grabs or items, generally. - var/gun_click_time = -100 //I'm lazy. + var/datum/hud/hud = null /obj/screen/Destroy() master = null @@ -26,11 +26,6 @@ maptext_height = 480 maptext_width = 480 - -/obj/screen/inventory - var/slot_id //The indentifier for the slot. It has nothing to do with ID cards. - - /obj/screen/close name = "close" @@ -43,7 +38,6 @@ /obj/screen/drop name = "drop" - icon = 'icons/mob/screen1_midnight.dmi' icon_state = "act_drop" layer = 19 @@ -66,6 +60,7 @@ /obj/screen/act_intent name = "intent" icon_state = "help" + screen_loc = ui_acti /obj/screen/act_intent/Click(location, control, params) if(ishuman(usr)) @@ -85,9 +80,18 @@ else usr.a_intent_change("right") +/obj/screen/act_intent/alien + icon = 'icons/mob/screen_alien.dmi' + screen_loc = ui_acti + +/obj/screen/act_intent/robot + icon = 'icons/mob/screen_robot.dmi' + screen_loc = ui_borg_intents + /obj/screen/internals name = "toggle internals" icon_state = "internal0" + screen_loc = ui_internal /obj/screen/internals/Click() if(iscarbon(usr)) @@ -201,7 +205,6 @@ /obj/screen/mov_intent name = "run/walk toggle" - icon = 'icons/mob/screen1_midnight.dmi' icon_state = "running" /obj/screen/mov_intent/Click() @@ -226,7 +229,6 @@ /obj/screen/pull name = "stop pulling" - icon = 'icons/mob/screen1_Midnight.dmi' icon_state = "pull" /obj/screen/pull/Click() @@ -241,7 +243,7 @@ /obj/screen/resist name = "resist" - icon = 'icons/mob/screen1_midnight.dmi' + icon = 'icons/mob/screen_midnight.dmi' icon_state = "act_resist" layer = 19 @@ -252,7 +254,7 @@ /obj/screen/throw_catch name = "throw/catch" - icon = 'icons/mob/screen1_midnight.dmi' + icon = 'icons/mob/screen_midnight.dmi' icon_state = "act_throw_off" /obj/screen/throw_catch/Click() @@ -347,59 +349,126 @@ overlays.Cut() overlays += image('icons/mob/zone_sel.dmi', "[selecting]") -/obj/screen/gun - name = "gun" - icon = 'icons/mob/screen1.dmi' - master = null - dir = 2 +/obj/screen/zone_sel/alien + icon = 'icons/mob/screen_alien.dmi' -/obj/screen/gun/mode - name = "Toggle Gun Mode" - icon_state = "gun0" - screen_loc = ui_gun_select +/obj/screen/zone_sel/alien/update_icon(mob/user) + overlays.Cut() + overlays += image('icons/mob/screen_alien.dmi', "[selecting]") -/obj/screen/gun/mode/Click() - usr.client.ToggleGunMode() - -/obj/screen/gun/item - name = "Allow Item Use" - icon_state = "no_item0" - screen_loc = ui_gun1 - -/obj/screen/gun/item/Click() - if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes. - return - if(!istype(usr.get_active_hand(), /obj/item/weapon/gun)) - to_chat(usr, "You need your gun in your active hand to do that!") - return - usr.client.AllowTargetClick() - gun_click_time = world.time +/obj/screen/zone_sel/robot + icon = 'icons/mob/screen_robot.dmi' +/obj/screen/inventory + var/slot_id //The indentifier for the slot. It has nothing to do with ID cards. + layer = 19 /obj/screen/inventory/Click() // At this point in client Click() code we have passed the 1/10 sec check and little else // We don't even know if it's a middle click if(world.time <= usr.next_move) return 1 - if(usr.stat || usr.paralysis || usr.stunned || usr.weakened) + if(usr.incapacitated()) return 1 if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech return 1 - switch(name) - if("r_hand") - if(iscarbon(usr)) - var/mob/living/carbon/C = usr - C.activate_hand("r") - if("l_hand") - if(iscarbon(usr)) - var/mob/living/carbon/C = usr - C.activate_hand("l") - if("swap") - usr:swap_hand() - if("hand") - usr:swap_hand() - else - if(usr.attack_ui(slot_id)) - usr.update_inv_l_hand(0) - usr.update_inv_r_hand(0) + if(usr.attack_ui(slot_id)) + usr.update_inv_l_hand(0) + usr.update_inv_r_hand(0) return 1 + +/obj/screen/inventory/hand + var/image/active_overlay + var/image/handcuff_overlay + +/obj/screen/inventory/hand/update_icon() + ..() + if(!active_overlay) + active_overlay = image("icon"=icon, "icon_state"="hand_active") + if(!handcuff_overlay) + var/state = (slot_id == slot_r_hand) ? "markus" : "gabrielle" + handcuff_overlay = image("icon"='icons/mob/screen_gen.dmi', "icon_state"=state) + + overlays.Cut() + + if(hud && hud.mymob) + if(iscarbon(hud.mymob)) + var/mob/living/carbon/C = hud.mymob + if(C.handcuffed) + overlays += handcuff_overlay + + if(slot_id == slot_l_hand && hud.mymob.hand) + overlays += active_overlay + else if(slot_id == slot_r_hand && !hud.mymob.hand) + overlays += active_overlay + +/obj/screen/inventory/hand/Click() + // At this point in client Click() code we have passed the 1/10 sec check and little else + // We don't even know if it's a middle click + if(world.time <= usr.next_move) + return 1 + if(usr.incapacitated()) + return 1 + if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech + return 1 + + if(ismob(usr)) + var/mob/M = usr + switch(name) + if("right hand", "r_hand") + M.activate_hand("r") + if("left hand", "l_hand") + M.activate_hand("l") + return 1 + +/obj/screen/swap_hand + layer = 19 + name = "swap hand" + +/obj/screen/swap_hand/Click() + // At this point in client Click() code we have passed the 1/10 sec check and little else + // We don't even know if it's a middle click + if(world.time <= usr.next_move) + return 1 + + if(usr.incapacitated()) + return 1 + + if(ismob(usr)) + var/mob/M = usr + M.swap_hand() + return 1 + +/obj/screen/healths + name = "health" + icon_state = "health0" + screen_loc = ui_health + +/obj/screen/healths/alien + icon = 'icons/mob/screen_alien.dmi' + screen_loc = ui_alien_health + +/obj/screen/healths/bot + icon = 'icons/mob/screen_bot.dmi' + screen_loc = ui_borg_health + +/obj/screen/healths/robot + icon = 'icons/mob/screen_robot.dmi' + screen_loc = ui_borg_health + +/obj/screen/healths/corgi + icon = 'icons/mob/screen_corgi.dmi' + + +/obj/screen/healths/guardian + name = "summoner health" + icon = 'icons/mob/guardian.dmi' + icon_state = "base" + screen_loc = ui_health + mouse_opacity = 0 + +/obj/screen/healthdoll + name = "health doll" + icon_state = "healthdoll_DEAD" + screen_loc = ui_healthdoll + diff --git a/code/_onclick/hud/swarmer.dm b/code/_onclick/hud/swarmer.dm new file mode 100644 index 00000000000..84f5811cc8d --- /dev/null +++ b/code/_onclick/hud/swarmer.dm @@ -0,0 +1,97 @@ + +////HUD NONSENSE//// +/obj/screen/swarmer + icon = 'icons/mob/swarmer.dmi' + +/obj/screen/swarmer/FabricateTrap + icon_state = "ui_trap" + name = "Create trap (Costs 5 Resources)" + desc = "Creates a trap that will nonlethally shock any non-swarmer that attempts to cross it. (Costs 5 resources)" + +/obj/screen/swarmer/FabricateTrap/Click() + if(isswarmer(usr)) + var/mob/living/simple_animal/hostile/swarmer/S = usr + S.CreateTrap() + +/obj/screen/swarmer/Barricade + icon_state = "ui_barricade" + name = "Create barricade (Costs 5 Resources)" + desc = "Creates a destructible barricade that will stop any non swarmer from passing it. Also allows disabler beams to pass through. (Costs 5 resources)" + +/obj/screen/swarmer/Barricade/Click() + if(isswarmer(usr)) + var/mob/living/simple_animal/hostile/swarmer/S = usr + S.CreateBarricade() + +/obj/screen/swarmer/Replicate + icon_state = "ui_replicate" + name = "Replicate (Costs 50 Resources)" + desc = "Creates a another of our kind." + +/obj/screen/swarmer/Replicate/Click() + if(isswarmer(usr)) + var/mob/living/simple_animal/hostile/swarmer/S = usr + S.CreateSwarmer() + +/obj/screen/swarmer/RepairSelf + icon_state = "ui_self_repair" + name = "Repair self" + desc = "Repairs damage to our body." + +/obj/screen/swarmer/RepairSelf/Click() + if(isswarmer(usr)) + var/mob/living/simple_animal/hostile/swarmer/S = usr + S.RepairSelf() + +/obj/screen/swarmer/ToggleLight + icon_state = "ui_light" + name = "Toggle light" + desc = "Toggles our inbuilt light on or off." + +/obj/screen/swarmer/ToggleLight/Click() + if(isswarmer(usr)) + var/mob/living/simple_animal/hostile/swarmer/S = usr + S.ToggleLight() + +/obj/screen/swarmer/ContactSwarmers + icon_state = "ui_contact_swarmers" + name = "Contact swarmers" + desc = "Sends a message to all other swarmers, should they exist." + +/obj/screen/swarmer/ContactSwarmers/Click() + if(isswarmer(usr)) + var/mob/living/simple_animal/hostile/swarmer/S = usr + S.ContactSwarmers() + +/mob/living/simple_animal/hostile/swarmer/create_mob_hud() + if(client && !hud_used) + hud_used = new /datum/hud/swarmer(src) + +/datum/hud/swarmer/New(mob/owner) + ..() + var/obj/screen/using + + using = new /obj/screen/swarmer/FabricateTrap() + using.screen_loc = ui_rhand + static_inventory += using + + using = new /obj/screen/swarmer/Barricade() + using.screen_loc = ui_lhand + static_inventory += using + + using = new /obj/screen/swarmer/Replicate() + using.screen_loc = ui_zonesel + static_inventory += using + + using = new /obj/screen/swarmer/RepairSelf() + using.screen_loc = ui_storage1 + static_inventory += using + + using = new /obj/screen/swarmer/ToggleLight() + using.screen_loc = ui_back + static_inventory += using + + using = new /obj/screen/swarmer/ContactSwarmers() + using.screen_loc = ui_inventory + static_inventory += using + diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index d71d0205b89..e32637e798c 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -182,9 +182,8 @@ if (istype(location, /turf/simulated)) location.add_blood_floor(M) if("fire") - if (!(RESIST_COLD in M.mutations)) - M.take_organ_damage(0, power) - to_chat(M, "Aargh it burns!") + M.take_organ_damage(0, power) + to_chat(M, "Aargh it burns!") M.updatehealth() add_fingerprint(user) return 1 diff --git a/code/datums/martial.dm b/code/datums/martial.dm deleted file mode 100644 index 07355929572..00000000000 --- a/code/datums/martial.dm +++ /dev/null @@ -1,643 +0,0 @@ -/datum/martial_art - var/name = "Martial Art" - var/streak = "" - var/max_streak_length = 6 - var/current_target = null - var/temporary = 0 - var/datum/martial_art/base = null // The permanent style - var/deflection_chance = 0 //Chance to deflect projectiles - var/help_verb = null - -/datum/martial_art/proc/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - return 0 - -/datum/martial_art/proc/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - return 0 - -/datum/martial_art/proc/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - return 0 - -/datum/martial_art/proc/add_to_streak(var/element,var/mob/living/carbon/human/D) - if(D != current_target) - current_target = D - streak = "" - streak = streak+element - if(length(streak) > max_streak_length) - streak = copytext(streak,2) - return - -/datum/martial_art/proc/basic_hit(var/mob/living/carbon/human/A,var/mob/living/carbon/human/D) - - A.do_attack_animation(D) - var/damage = rand(A.species.punchdamagelow, A.species.punchdamagehigh) - var/datum/unarmed_attack/attack = A.species.unarmed - - var/atk_verb = "[pick(attack.attack_verb)]" - if(D.lying) - atk_verb = "kick" - - if(!damage) - playsound(D.loc, attack.miss_sound, 25, 1, -1) - D.visible_message("[A] has attempted to [atk_verb] [D]!") - return 0 - - var/obj/item/organ/external/affecting = D.get_organ(ran_zone(A.zone_sel.selecting)) - var/armor_block = D.run_armor_check(affecting, "melee") - - playsound(D.loc, attack.attack_sound, 25, 1, -1) - D.visible_message("[A] has [atk_verb]ed [D]!", \ - "[A] has [atk_verb]ed [D]!") - - D.apply_damage(damage, BRUTE, affecting, armor_block) - - add_logs(D, A, "punched") - - if((D.stat != DEAD) && damage >= A.species.punchstunthreshold) - D.visible_message("[A] has weakened [D]!!", \ - "[A] has weakened [D]!") - D.apply_effect(4, WEAKEN, armor_block) - D.forcesay(hit_appends) - else if(D.lying) - D.forcesay(hit_appends) - return 1 - -/datum/martial_art/proc/teach(var/mob/living/carbon/human/H,var/make_temporary=0) - if(help_verb) - H.verbs += help_verb - if(make_temporary) - temporary = 1 - if(temporary) - if(H.martial_art) - base = H.martial_art.base - else - base = src - H.martial_art = src - -/datum/martial_art/proc/remove(var/mob/living/carbon/human/H) - if(H.martial_art != src) - return - H.martial_art = base - if(help_verb) - H.verbs -= help_verb - -/datum/martial_art/boxing - name = "Boxing" - -/datum/martial_art/boxing/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - to_chat(A, "Can't disarm while boxing!") - return 1 - -/datum/martial_art/boxing/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - to_chat(A, "Can't grab while boxing!") - return 1 - -/datum/martial_art/boxing/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - - A.do_attack_animation(D) - - var/atk_verb = pick("left hook","right hook","straight punch") - - var/damage = rand(5, 8) + A.species.punchdamagelow - if(!damage) - playsound(D.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - D.visible_message("[A] has attempted to hit [D] with a [atk_verb]!") - add_logs(D, A, "attempted to hit", atk_verb) - return 0 - - - var/obj/item/organ/external/affecting = D.get_organ(ran_zone(A.zone_sel.selecting)) - var/armor_block = D.run_armor_check(affecting, "melee") - - playsound(D.loc, 'sound/weapons/punch1.ogg', 25, 1, -1) - - D.visible_message("[A] has hit [D] with a [atk_verb]!", \ - "[A] has hit [D] with a [atk_verb]!") - - D.apply_damage(damage, STAMINA, affecting, armor_block) - add_logs(D, A, "punched") - if(D.getStaminaLoss() > 50) - var/knockout_prob = D.getStaminaLoss() + rand(-15,15) - if((D.stat != DEAD) && prob(knockout_prob)) - D.visible_message("[A] has knocked [D] out with a haymaker!", \ - "[A] has knocked [D] out with a haymaker!") - D.apply_effect(10,WEAKEN,armor_block) - D.SetSleeping(5) - D.forcesay(hit_appends) - else if(D.lying) - D.forcesay(hit_appends) - return 1 - -/datum/martial_art/drunk_brawling - name = "Drunken Brawling" - -/datum/martial_art/drunk_brawling/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - if(prob(70)) - A.visible_message("[A] tries to grab ahold of [D], but fails!", \ - "You fail to grab ahold of [D]!") - return 1 - D.grabbedby(A,1) - var/obj/item/weapon/grab/G = A.get_active_hand() - if(G) - D.visible_message("[A] grabs ahold of [D] drunkenly!", \ - "[A] grabs ahold of [D] drunkenly!") - return 1 - -/datum/martial_art/drunk_brawling/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - add_logs(D, A, "punched") - A.do_attack_animation(D) - - var/atk_verb = pick("jab","uppercut","overhand punch","drunken right hook","drunken left hook") - - var/damage = rand(0,6) - - if(atk_verb == "uppercut") - if(prob(90)) - damage = 0 - else //10% chance to do a massive amount of damage - damage = 14 - - if(prob(50)) //they are drunk, they aren't going to land half of their hits - damage = 0 - - if(!damage) - playsound(D.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - D.visible_message("[A] has attempted to hit [D] with a [atk_verb]!") - return 1 //returns 1 so that they actually miss and don't switch to attackhand damage - - var/obj/item/organ/external/affecting = D.get_organ(ran_zone(A.zone_sel.selecting)) - var/armor_block = D.run_armor_check(affecting, "melee") - - playsound(D.loc, 'sound/weapons/punch1.ogg', 25, 1, -1) - - - D.visible_message("[A] has hit [D] with a [atk_verb]!", \ - "[A] has hit [D] with a [atk_verb]!") - - D.apply_damage(damage, BRUTE, null, armor_block) - D.apply_effect(damage, STAMINA, armor_block) - if(D.getStaminaLoss() > 50) - var/knockout_prob = D.getStaminaLoss() + rand(-15,15) - if((D.stat != DEAD) && prob(knockout_prob)) - D.visible_message("[A] has knocked [D] out with a haymaker!", \ - "[A] has knocked [D] out with a haymaker!") - D.apply_effect(10,WEAKEN,armor_block) - D.Paralyse(5) - D.forcesay(hit_appends) - else if(D.lying) - D.forcesay(hit_appends) - return 1 - -/datum/martial_art/wrestling - name = "Wrestling" - help_verb = /mob/living/carbon/human/proc/wrestling_help - -// combo refence since wrestling uses a different format to sleeping carp and plasma fist. -// Clinch "G" -// Suplex "GD" -// Advanced grab "G" - -/datum/martial_art/wrestling/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - D.grabbedby(A,1) - var/obj/item/weapon/grab/G = A.get_active_hand() - if(G && prob(50)) - G.state = GRAB_AGGRESSIVE - D.visible_message("[A] has [D] in a clinch!", \ - "[A] has [D] in a clinch!") - else - D.visible_message("[A] fails to get [D] in a clinch!", \ - "[A] fails to get [D] in a clinch!") - return 1 - - -/datum/martial_art/wrestling/proc/Suplex(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - - D.visible_message("[A] suplexes [D]!", \ - "[A] suplexes [D]!") - D.forceMove(A.loc) - var/armor_block = D.run_armor_check(null, "melee") - D.apply_damage(30, BRUTE, null, armor_block) - D.apply_effect(6, WEAKEN, armor_block) - add_logs(D, A, "suplexed") - - A.SpinAnimation(10,1) - - D.SpinAnimation(10,1) - spawn(3) - armor_block = A.run_armor_check(null, "melee") - A.apply_effect(4, WEAKEN, armor_block) - return - -/datum/martial_art/wrestling/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - if(istype(A.get_inactive_hand(),/obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = A.get_inactive_hand() - if(G.affecting == D) - Suplex(A,D) - return 1 - harm_act(A,D) - return 1 - -/datum/martial_art/wrestling/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - D.grabbedby(A,1) - D.visible_message("[A] holds [D] down!", \ - "[A] holds [D] down!") - var/obj/item/organ/external/affecting = D.get_organ(ran_zone(A.zone_sel.selecting)) - var/armor_block = D.run_armor_check(affecting, "melee") - D.apply_damage(10, STAMINA, affecting, armor_block) - return 1 - -/mob/living/carbon/human/proc/wrestling_help() - set name = "Recall Teachings" - set desc = "Remember how to wrestle." - set category = "Wrestling" - - to_chat(usr, "You flex your muscles and have a revelation...") - to_chat(usr, "Clinch: Grab. Passively gives you a chance to immediately aggressively grab someone. Not always successful.") - to_chat(usr, "Suplex: Disarm someone you are grabbing. Suplexes your target to the floor. Greatly injures them and leaves both you and your target on the floor.") - to_chat(usr, "Advanced grab: Grab. Passively causes stamina damage when grabbing someone.") - -#define TORNADO_COMBO "HHD" -#define THROWBACK_COMBO "DHD" -#define PLASMA_COMBO "HDDDH" - -/datum/martial_art/plasma_fist - name = "Plasma Fist" - help_verb = /mob/living/carbon/human/proc/plasma_fist_help - - -/datum/martial_art/plasma_fist/proc/check_streak(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - if(findtext(streak,TORNADO_COMBO)) - streak = "" - Tornado(A,D) - return 1 - if(findtext(streak,THROWBACK_COMBO)) - streak = "" - Throwback(A,D) - return 1 - if(findtext(streak,PLASMA_COMBO)) - streak = "" - Plasma(A,D) - return 1 - return 0 - -/datum/martial_art/plasma_fist/proc/Tornado(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - A.say("TORNADO SWEEP!") - spawn(0) - for(var/i in list(NORTH,SOUTH,EAST,WEST,EAST,SOUTH,NORTH,SOUTH,EAST,WEST,EAST,SOUTH)) - A.dir = i - playsound(A.loc, 'sound/weapons/punch1.ogg', 15, 1, -1) - sleep(1) - var/obj/effect/proc_holder/spell/aoe_turf/repulse/R = new(null) - var/list/turfs = list() - for(var/turf/T in range(1,A)) - turfs.Add(T) - R.cast(turfs) - return - -/datum/martial_art/plasma_fist/proc/Throwback(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - D.visible_message("[A] has hit [D] with Plasma Punch!", \ - "[A] has hit [D] with Plasma Punch!") - playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1) - var/atom/throw_target = get_edge_target_turf(D, get_dir(D, get_step_away(D, A))) - D.throw_at(throw_target, 200, 4,A) - A.say("HYAH!") - return - -/datum/martial_art/plasma_fist/proc/Plasma(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - A.do_attack_animation(D) - playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1) - A.say("PLASMA FIST!") - D.visible_message("[A] has hit [D] with THE PLASMA FIST TECHNIQUE!", \ - "[A] has hit [D] with THE PLASMA FIST TECHNIQUE!") - D.gib() - return - -/datum/martial_art/plasma_fist/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - add_to_streak("H",D) - if(check_streak(A,D)) - return 1 - basic_hit(A,D) - return 1 - -/datum/martial_art/plasma_fist/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - add_to_streak("D",D) - if(check_streak(A,D)) - return 1 - basic_hit(A,D) - return 1 - -/datum/martial_art/plasma_fist/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - add_to_streak("G",D) - if(check_streak(A,D)) - return 1 - basic_hit(A,D) - return 1 - -/mob/living/carbon/human/proc/plasma_fist_help() - set name = "Recall Teachings" - set desc = "Remember the martial techniques of the Plasma Fist." - set category = "Plasma Fist" - - to_chat(usr, "You clench your fists and have a flashback of knowledge...") - to_chat(usr, "Tornado Sweep: Harm Harm Disarm. Repulses target and everyone back.") - to_chat(usr, "Throwback: Disarm Harm Disarm. Throws the target and an item at them.") - to_chat(usr, "The Plasma Fist: Harm Disarm Disarm Disarm Harm. Knocks the brain out of the opponent and gibs their body.") - -//Used by the gang of the same name. Uses combos. Basic attacks bypass armor and never miss -#define WRIST_WRENCH_COMBO "DD" -#define BACK_KICK_COMBO "HG" -#define STOMACH_KNEE_COMBO "GH" -#define HEAD_KICK_COMBO "DHH" -#define ELBOW_DROP_COMBO "HDHDH" -/datum/martial_art/the_sleeping_carp - name = "The Sleeping Carp" - deflection_chance = 100 - help_verb = /mob/living/carbon/human/proc/sleeping_carp_help - -/datum/martial_art/the_sleeping_carp/proc/check_streak(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - if(findtext(streak,WRIST_WRENCH_COMBO)) - streak = "" - wristWrench(A,D) - return 1 - if(findtext(streak,BACK_KICK_COMBO)) - streak = "" - backKick(A,D) - return 1 - if(findtext(streak,STOMACH_KNEE_COMBO)) - streak = "" - kneeStomach(A,D) - return 1 - if(findtext(streak,HEAD_KICK_COMBO)) - streak = "" - headKick(A,D) - return 1 - if(findtext(streak,ELBOW_DROP_COMBO)) - streak = "" - elbowDrop(A,D) - return 1 - return 0 - -/datum/martial_art/the_sleeping_carp/proc/wristWrench(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - if(!D.stat && !D.stunned && !D.weakened) - A.do_attack_animation(D) - D.visible_message("[A] grabs [D]'s wrist and wrenches it sideways!", \ - "[A] grabs your wrist and violently wrenches it to the side!") - playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - D.emote("scream") - D.drop_item() - D.apply_damage(5, BRUTE, pick("l_arm", "r_arm")) - D.Stun(3) - return 1 - return basic_hit(A,D) - -/datum/martial_art/the_sleeping_carp/proc/backKick(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - if(A.dir == D.dir && !D.stat && !D.weakened) - A.do_attack_animation(D) - D.visible_message("[A] kicks [D] in the back!", \ - "[A] kicks you in the back, making you stumble and fall!") - step_to(D,get_step(D,D.dir),1) - D.Weaken(4) - playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1) - return 1 - return basic_hit(A,D) - -/datum/martial_art/the_sleeping_carp/proc/kneeStomach(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - if(!D.stat && !D.weakened) - A.do_attack_animation(D) - D.visible_message("[A] knees [D] in the stomach!", \ - "[A] winds you with a knee in the stomach!") - D.audible_message("[D] gags!") - D.losebreath += 3 - D.Stun(2) - playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1) - return 1 - return basic_hit(A,D) - -/datum/martial_art/the_sleeping_carp/proc/headKick(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - if(!D.stat && !D.weakened) - A.do_attack_animation(D) - D.visible_message("[A] kicks [D] in the head!", \ - "[A] kicks you in the jaw!") - D.apply_damage(20, BRUTE, "head") - D.drop_item() - playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1) - D.Stun(4) - return 1 - return basic_hit(A,D) - -/datum/martial_art/the_sleeping_carp/proc/elbowDrop(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - if(D.weakened || D.resting || D.stat) - A.do_attack_animation(D) - D.visible_message("[A] elbow drops [D]!", \ - "[A] piledrives you with their elbow!") - if(D.stat) - D.death() //FINISH HIM! - D.apply_damage(50, BRUTE, "chest") - playsound(get_turf(D), 'sound/weapons/punch1.ogg', 75, 1, -1) - return 1 - return basic_hit(A,D) - -/datum/martial_art/the_sleeping_carp/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - add_to_streak("G",D) - if(check_streak(A,D)) - return 1 - D.grabbedby(A,1) - var/obj/item/weapon/grab/G = A.get_active_hand() - if(G) - G.state = GRAB_AGGRESSIVE //Instant aggressive grab - -/datum/martial_art/the_sleeping_carp/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) - add_to_streak("H",D) - if(check_streak(A,D)) - return 1 - A.do_attack_animation(D) - var/atk_verb = pick("punches", "kicks", "chops", "hits", "slams") - D.visible_message("[A] [atk_verb] [D]!", \ - "[A] [atk_verb] you!") - D.apply_damage(rand(10,15), BRUTE) - playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, 1, -1) - if(prob(D.getBruteLoss()) && !D.lying) - D.visible_message("[D] stumbles and falls!", "The blow sends you to the ground!") - D.Weaken(4) - return 1 - - -/datum/martial_art/the_sleeping_carp/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) - add_to_streak("D",D) - if(check_streak(A,D)) - return 1 - return ..() - -/mob/living/carbon/human/proc/sleeping_carp_help() - set name = "Recall Teachings" - set desc = "Remember the martial techniques of the Sleeping Carp clan." - set category = "Sleeping Carp" - - to_chat(usr, "You retreat inward and recall the teachings of the Sleeping Carp...") - - to_chat(usr, "Wrist Wrench: Disarm Disarm. Forces opponent to drop item in hand.") - to_chat(usr, "Back Kick: Harm Grab. Opponent must be facing away. Knocks down.") - to_chat(usr, "Stomach Knee: Grab Harm. Knocks the wind out of opponent and stuns.") - to_chat(usr, "Head Kick: Disarm Harm Harm. Decent damage, forces opponent to drop item in hand.") - to_chat(usr, "Elbow Drop: Harm Disarm Harm Disarm Harm. Opponent must be on the ground. Deals huge damage, instantly kills anyone in critical condition.") - -//ITEMS - -/obj/item/clothing/gloves/boxing - var/datum/martial_art/boxing/style = new - -/obj/item/clothing/gloves/boxing/equipped(mob/user, slot) - if(!ishuman(user)) - return - if(slot == slot_gloves) - var/mob/living/carbon/human/H = user - style.teach(H,1) - return - -/obj/item/clothing/gloves/boxing/dropped(mob/user) - if(!ishuman(user)) - return - var/mob/living/carbon/human/H = user - if(H.get_item_by_slot(slot_gloves) == src) - style.remove(H) - return - -/obj/item/weapon/storage/belt/champion/wrestling - name = "Wrestling Belt" - var/datum/martial_art/wrestling/style = new - -/obj/item/weapon/storage/belt/champion/wrestling/equipped(mob/user, slot) - if(!ishuman(user)) - return - if(slot == slot_belt) - var/mob/living/carbon/human/H = user - style.teach(H,1) - to_chat(user, "You have an urge to flex your muscles and get into a fight. You have the knowledge of a thousand wrestlers before you. You can remember more by using the Recall teaching verb in the wrestling tab.") - return - -/obj/item/weapon/storage/belt/champion/wrestling/dropped(mob/user) - if(!ishuman(user)) - return - var/mob/living/carbon/human/H = user - if(H.get_item_by_slot(slot_belt) == src) - style.remove(H) - to_chat(user, "You no longer have an urge to flex your muscles.") - return - -/obj/item/weapon/plasma_fist_scroll - name = "frayed scroll" - desc = "An aged and frayed scrap of paper written in shifting runes. There are hand-drawn illustrations of pugilism." - icon = 'icons/obj/wizard.dmi' - icon_state ="scroll2" - var/used = 0 - -/obj/item/weapon/plasma_fist_scroll/attack_self(mob/user as mob) - if(!ishuman(user)) - return - if(!used) - var/mob/living/carbon/human/H = user - var/datum/martial_art/plasma_fist/F = new/datum/martial_art/plasma_fist(null) - F.teach(H) - to_chat(H, "You have learned the ancient martial art of Plasma Fist.") - used = 1 - desc = "It's completely blank." - name = "empty scroll" - icon_state = "blankscroll" - -/obj/item/weapon/sleeping_carp_scroll - name = "mysterious scroll" - desc = "A scroll filled with strange markings. It seems to be drawings of some sort of martial art." - icon = 'icons/obj/wizard.dmi' - icon_state = "scroll2" - -/obj/item/weapon/sleeping_carp_scroll/attack_self(mob/living/carbon/human/user as mob) - if(!istype(user) || !user) - return - to_chat(user, "You have learned the ancient martial art of the Sleeping Carp! \ - Your hand-to-hand combat has become much more effective, and you are now able to deflect any projectiles directed toward you. \ - However, you are also unable to use any ranged weaponry. \ - You can learn more about your newfound art by using the Recall Teachings verb in the Sleeping Carp tab.") - - - var/datum/martial_art/the_sleeping_carp/theSleepingCarp = new(null) - theSleepingCarp.teach(user) - user.drop_item() - visible_message("[src] lights up in fire and quickly burns to ash.") - new /obj/effect/decal/cleanable/ash(get_turf(src)) - qdel(src) - -/obj/item/weapon/twohanded/bostaff - name = "bo staff" - desc = "A long, tall staff made of polished wood. Traditionally used in ancient old-Earth martial arts. Can be wielded to both kill and incapacitate." - force = 10 - w_class = 4 - slot_flags = SLOT_BACK - force_unwielded = 10 - force_wielded = 24 - throwforce = 20 - throw_speed = 2 - attack_verb = list("smashed", "slammed", "whacked", "thwacked") - icon = 'icons/obj/weapons.dmi' - icon_state = "bostaff0" - - -/obj/item/weapon/twohanded/bostaff/update_icon() - icon_state = "bostaff[wielded]" - return - -/obj/item/weapon/twohanded/bostaff/attack(mob/target, mob/living/user) - add_fingerprint(user) - if((CLUMSY in user.disabilities) && prob(50)) - to_chat(user, "You club yourself over the head with [src].") - user.Weaken(3) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - H.apply_damage(2*force, BRUTE, "head") - else - user.take_organ_damage(2*force) - return - if(isrobot(target)) - return ..() - if(!isliving(target)) - return ..() - var/mob/living/carbon/C = target - if(C.stat) - to_chat(user, "It would be dishonorable to attack a foe while they cannot retaliate.") - return - switch(user.a_intent) - if("disarm") - if(!wielded) - return ..() - if(!ishuman(target)) - return ..() - var/mob/living/carbon/human/H = target - var/list/fluffmessages = list("[user] clubs [H] with [src]!", \ - "[user] smacks [H] with the butt of [src]!", \ - "[user] broadsides [H] with [src]!", \ - "[user] smashes [H]'s head with [src]!", \ - "[user] beats [H] with front of [src]!", \ - "[user] twirls and slams [H] with [src]!") - H.visible_message("[pick(fluffmessages)]", \ - "[pick(fluffmessages)]") - playsound(get_turf(user), 'sound/effects/woodhit.ogg', 75, 1, -1) - H.adjustStaminaLoss(rand(13,20)) - if(prob(10)) - H.visible_message("[H] collapses!", \ - "Your legs give out!") - H.Weaken(4) - if(H.staminaloss && !H.sleeping) - var/total_health = (H.health - H.staminaloss) - if(total_health <= config.health_threshold_crit && !H.stat) - H.visible_message("[user] delivers a heavy hit to [H]'s head, knocking them out cold!", \ - "[user] knocks you unconscious!") - H.SetSleeping(30) - H.adjustBrainLoss(25) - return - else - return ..() - return ..() - -/obj/item/weapon/twohanded/bostaff/IsShield() - if(wielded) - return 1 - else - return 0 diff --git a/code/datums/mind.dm b/code/datums/mind.dm index a7fb80b87fb..4221db90798 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -919,6 +919,7 @@ if(vampire) vampire.remove_vampire_powers() qdel(vampire) + vampire = null ticker.mode.update_vampire_icons_removed(src) to_chat(current, "You grow weak and lose your powers! You are no longer a vampire and are stuck in your current form!") log_admin("[key_name(usr)] has de-vampired [key_name(current)]") diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 831e7004ad6..92c894cba10 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -110,11 +110,13 @@ /atom/movable/proc/forceMove(atom/destination) var/turf/old_loc = loc - if(old_loc) - old_loc.Exited(src) - loc = destination + if(old_loc) + old_loc.Exited(src, destination) + for(var/atom/movable/AM in old_loc) + AM.Uncrossed(src) + if(destination) destination.Entered(src) for(var/atom/movable/AM in destination) diff --git a/code/game/dna/genes/monkey.dm b/code/game/dna/genes/monkey.dm index 48e7e3a580f..8ef0b7bb5f8 100644 --- a/code/game/dna/genes/monkey.dm +++ b/code/game/dna/genes/monkey.dm @@ -43,7 +43,11 @@ H.set_species(H.species.primitive_form) if(H.hud_used) - H.hud_used.instantiate() + qdel(H.hud_used) + H.hud_used = null + + if(H.client) + H.hud_used = new /datum/hud/monkey(H, ui_style2icon(H.client.prefs.UI_style), H.client.prefs.UI_style_color, H.client.prefs.UI_style_alpha) to_chat(H, "You are now a [H.species.name].") @@ -86,7 +90,11 @@ H.name = H.real_name if(H.hud_used) - H.hud_used.instantiate() + qdel(H.hud_used) + H.hud_used = null + + if(H.client) + H.hud_used = new /datum/hud/human(H, ui_style2icon(H.client.prefs.UI_style), H.client.prefs.UI_style_color, H.client.prefs.UI_style_alpha) to_chat(H, "You are now a [H.species.name].") diff --git a/code/game/gamemodes/autotraitor/autotraitor.dm b/code/game/gamemodes/autotraitor/autotraitor.dm index 5e79f387aea..a41dcb8d583 100644 --- a/code/game/gamemodes/autotraitor/autotraitor.dm +++ b/code/game/gamemodes/autotraitor/autotraitor.dm @@ -82,7 +82,7 @@ traitorcount += 1 if (player.client && player.mind && !player.mind.special_role && player.stat != DEAD) if (ishuman(player) || isrobot(player) || isAI(player)) - if (player.client && (ROLE_TRAITOR in player.client.prefs.be_special) && !jobban_isbanned(player, "traitor") && !jobban_isbanned(player, "Syndicate")) + if (player.client && (ROLE_TRAITOR in player.client.prefs.be_special) && !jobban_isbanned(player, ROLE_TRAITOR) && !jobban_isbanned(player, "Syndicate")) possible_traitors += player.mind for(var/datum/mind/player in possible_traitors) for(var/job in restricted_jobs) @@ -159,7 +159,7 @@ if(shuttle_master.emergency.mode >= SHUTTLE_ESCAPE) return //message_admins("Late Join Check") - if(character.client && (ROLE_TRAITOR in character.client.prefs.be_special) && !jobban_isbanned(character, "traitor") && !jobban_isbanned(character, "Syndicate")) + if(character.client && (ROLE_TRAITOR in character.client.prefs.be_special) && !jobban_isbanned(character, ROLE_TRAITOR) && !jobban_isbanned(character, "Syndicate")) //message_admins("Late Joiner has Be Syndicate") //message_admins("Checking number of players") var/playercount = 0 diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index cdd57853759..c62408eddd5 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -373,7 +373,7 @@ var/list/sacrificed = list() break if(!ghost) return this_rune.fizzle() - if(jobban_isbanned(ghost, "cultist") || jobban_isbanned(ghost,"Syndicate")) + if(jobban_isbanned(ghost, ROLE_CULTIST) || jobban_isbanned(ghost,"Syndicate")) return this_rune.fizzle() usr.say("Gal'h'rfikk harfrandid mud[pick("'","`")]gib!") diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 4001eba338b..3cdb5b412f5 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -297,37 +297,38 @@ //Keeps track of all living heads// /////////////////////////////////// /datum/game_mode/proc/get_living_heads() - var/list/heads = list() + . = list() for(var/mob/living/carbon/human/player in mob_list) - if(player.stat!=2 && player.mind && (player.mind.assigned_role in command_positions)) - heads += player.mind - return heads + if(player.stat != DEAD && player.mind && (player.mind.assigned_role in command_positions)) + . |= player.mind -/datum/game_mode/proc/get_extra_living_heads() - var/list/heads = list() - var/list/alt_positions = list("Warden", "Magistrate", "Blueshield", "Nanotrasen Representative") - for(var/mob/living/carbon/human/player in mob_list) - if(player.stat!=2 && player.mind && (player.mind.assigned_role in alt_positions)) - heads += player.mind - return heads //////////////////////////// //Keeps track of all heads// //////////////////////////// /datum/game_mode/proc/get_all_heads() - var/list/heads = list() + . = list() for(var/mob/player in mob_list) if(player.mind && (player.mind.assigned_role in command_positions)) - heads += player.mind - return heads + . |= player.mind -/datum/game_mode/proc/get_extra_heads() - var/list/heads = list() - var/list/alt_positions = list("Warden", "Magistrate", "Blueshield", "Nanotrasen Representative") - for(var/mob/player in mob_list) - if(player.mind && (player.mind.assigned_role in alt_positions)) - heads += player.mind - return heads +////////////////////////////////////////////// +//Keeps track of all living security members// +////////////////////////////////////////////// +/datum/game_mode/proc/get_living_sec() + . = list() + for(var/mob/living/carbon/human/player in mob_list) + if(player.stat != DEAD && player.mind && (player.mind.assigned_role in security_positions)) + . |= player.mind + +//////////////////////////////////////// +//Keeps track of all security members// +//////////////////////////////////////// +/datum/game_mode/proc/get_all_sec() + . = list() + for(var/mob/living/carbon/human/player in mob_list) + if(player.mind && (player.mind.assigned_role in security_positions)) + . |= player.mind /datum/game_mode/proc/check_antagonists_topic(href, href_list[]) return 0 diff --git a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm index b102ae8d908..5107ff7cab4 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm @@ -477,7 +477,7 @@ Congratulations! You are now trained for xenobiology research!"} if(do_mob(user, C, 30)) if(!C.handcuffed) C.handcuffed = new /obj/item/weapon/restraints/handcuffs/energy/used(C) - C.update_inv_handcuffed() + C.update_handcuffed() to_chat(user, "You handcuff [C].") add_logs(C, user, "handcuffed") else diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm index 472dea17cce..9e25a50a811 100644 --- a/code/game/gamemodes/miniantags/borer/borer.dm +++ b/code/game/gamemodes/miniantags/borer/borer.dm @@ -646,7 +646,7 @@ if(jobban_isbanned(O, "Syndicate")) continue if(O.client) - if((ROLE_BORER in O.client.prefs.be_special) && !jobban_isbanned(O, "alien")) + if((ROLE_BORER in O.client.prefs.be_special) && !jobban_isbanned(O, ROLE_BORER)) question(O.client) /mob/living/simple_animal/borer/proc/question(var/client/C) diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm index 773e81349a1..ccd498bb97f 100644 --- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm +++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm @@ -531,102 +531,3 @@ if(isswarmer(M) || (M in dead_mob_list)) to_chat(M, "Swarm communication - [src] states: [message]") - - -////HUD NONSENSE//// -/obj/screen/swarmer - icon = 'icons/mob/swarmer.dmi' - -/obj/screen/swarmer/FabricateTrap - icon_state = "ui_trap" - name = "Create trap (Costs 5 Resources)" - desc = "Creates a trap that will nonlethally shock any non-swarmer that attempts to cross it. (Costs 5 resources)" - -/obj/screen/swarmer/FabricateTrap/Click() - if(isswarmer(usr)) - var/mob/living/simple_animal/hostile/swarmer/S = usr - S.CreateTrap() - -/obj/screen/swarmer/Barricade - icon_state = "ui_barricade" - name = "Create barricade (Costs 5 Resources)" - desc = "Creates a destructible barricade that will stop any non swarmer from passing it. Also allows disabler beams to pass through. (Costs 5 resources)" - -/obj/screen/swarmer/Barricade/Click() - if(isswarmer(usr)) - var/mob/living/simple_animal/hostile/swarmer/S = usr - S.CreateBarricade() - -/obj/screen/swarmer/Replicate - icon_state = "ui_replicate" - name = "Replicate (Costs 50 Resources)" - desc = "Creates a another of our kind." - -/obj/screen/swarmer/Replicate/Click() - if(isswarmer(usr)) - var/mob/living/simple_animal/hostile/swarmer/S = usr - S.CreateSwarmer() - -/obj/screen/swarmer/RepairSelf - icon_state = "ui_self_repair" - name = "Repair self" - desc = "Repairs damage to our body." - -/obj/screen/swarmer/RepairSelf/Click() - if(isswarmer(usr)) - var/mob/living/simple_animal/hostile/swarmer/S = usr - S.RepairSelf() - -/obj/screen/swarmer/ToggleLight - icon_state = "ui_light" - name = "Toggle light" - desc = "Toggles our inbuilt light on or off." - -/obj/screen/swarmer/ToggleLight/Click() - if(isswarmer(usr)) - var/mob/living/simple_animal/hostile/swarmer/S = usr - S.ToggleLight() - -/obj/screen/swarmer/ContactSwarmers - icon_state = "ui_contact_swarmers" - name = "Contact swarmers" - desc = "Sends a message to all other swarmers, should they exist." - -/obj/screen/swarmer/ContactSwarmers/Click() - if(isswarmer(usr)) - var/mob/living/simple_animal/hostile/swarmer/S = usr - S.ContactSwarmers() - -/datum/hud/proc/swarmer_hud(ui_style = 'icons/mob/screen1_midnight.dmi') - adding = list() - - var/obj/screen/using - - using = new /obj/screen/swarmer/FabricateTrap() - using.screen_loc = ui_rhand - adding += using - - using = new /obj/screen/swarmer/Barricade() - using.screen_loc = ui_lhand - adding += using - - using = new /obj/screen/swarmer/Replicate() - using.screen_loc = ui_zonesel - adding += using - - using = new /obj/screen/swarmer/RepairSelf() - using.screen_loc = ui_storage1 - adding += using - - using = new /obj/screen/swarmer/ToggleLight() - using.screen_loc = ui_back - adding += using - - using = new /obj/screen/swarmer/ContactSwarmers() - using.screen_loc = ui_inventory - adding += using - - mymob.client.screen = list() - //mymob.client.screen += mymob.client.void - mymob.client.screen += adding - diff --git a/code/game/gamemodes/miniantags/guardian/guardian.dm b/code/game/gamemodes/miniantags/guardian/guardian.dm index b987f2eb6f6..2108e1c3147 100644 --- a/code/game/gamemodes/miniantags/guardian/guardian.dm +++ b/code/game/gamemodes/miniantags/guardian/guardian.dm @@ -29,6 +29,8 @@ var/summoned = FALSE var/cooldown = 0 var/damage_transfer = 1 //how much damage from each attack we transfer to the owner + var/light_on = 0 + var/luminosity_on = 3 var/mob/living/summoner var/range = 10 //how far from the user the spirit can be var/playstyle_string = "You are a standard Guardian. You shouldn't exist!" @@ -202,13 +204,13 @@ /mob/living/simple_animal/hostile/guardian/proc/ToggleLight() - if(!luminosity) - set_light(3) + if(!light_on) + set_light(luminosity_on) to_chat(src, "You activate your light.") else set_light(0) to_chat(src, "You deactivate your light.") - + light_on = !light_on //////////////////////////TYPES OF GUARDIANS @@ -839,99 +841,3 @@ new /obj/item/weapon/guardiancreator/tech/choose(src) new /obj/item/weapon/paper/guardian(src) return - - - -/datum/hud/proc/guardian_hud(ui_style = 'icons/mob/screen1_Midnight.dmi') - adding = list() - - var/obj/screen/using - - guardianhealthdisplay = new /obj/screen/guardian() - guardianhealthdisplay.name = "summoner health" - guardianhealthdisplay.screen_loc = ui_health - guardianhealthdisplay.mouse_opacity = 0 - adding += guardianhealthdisplay - - using = new /obj/screen/guardian/Manifest() - using.screen_loc = ui_rhand - adding += using - - using = new /obj/screen/guardian/Recall() - using.screen_loc = ui_lhand - adding += using - - using = new /obj/screen/guardian/ToggleMode() - using.screen_loc = ui_storage1 - adding += using - - using = new /obj/screen/guardian/ToggleLight() - using.screen_loc = ui_inventory - adding += using - - using = new /obj/screen/guardian/Communicate() - using.screen_loc = ui_back - adding += using - - mymob.client.screen = list() - mymob.client.screen += mymob.client.void - mymob.client.screen += adding - - -//HUD BUTTONS - -/obj/screen/guardian - icon = 'icons/mob/guardian.dmi' - icon_state = "base" - -/obj/screen/guardian/Manifest - icon_state = "manifest" - name = "Manifest" - desc = "Spring forth into battle!" - -/obj/screen/guardian/Manifest/Click() - if(isguardian(usr)) - var/mob/living/simple_animal/hostile/guardian/G = usr - G.Manifest() - - -/obj/screen/guardian/Recall - icon_state = "recall" - name = "Recall" - desc = "Return to your user." - -/obj/screen/guardian/Recall/Click() - if(isguardian(usr)) - var/mob/living/simple_animal/hostile/guardian/G = usr - G.Recall() - -/obj/screen/guardian/ToggleMode - icon_state = "toggle" - name = "Toggle Mode" - desc = "Switch between ability modes." - -/obj/screen/guardian/ToggleMode/Click() - if(isguardian(usr)) - var/mob/living/simple_animal/hostile/guardian/G = usr - G.ToggleMode() - -/obj/screen/guardian/Communicate - icon_state = "communicate" - name = "Communicate" - desc = "Communicate telepathically with your user." - -/obj/screen/guardian/Communicate/Click() - if(isguardian(usr)) - var/mob/living/simple_animal/hostile/guardian/G = usr - G.Communicate() - - -/obj/screen/guardian/ToggleLight - icon_state = "light" - name = "Toggle Light" - desc = "Glow like star dust." - -/obj/screen/guardian/ToggleLight/Click() - if(isguardian(usr)) - var/mob/living/simple_animal/hostile/guardian/G = usr - G.ToggleLight() \ No newline at end of file diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index bbf0e5c9c73..1cb05d4ac0d 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -4,31 +4,27 @@ // Just make sure the converter is a head before you call it! // To remove a rev (from brainwashing or w/e), call ticker.mode:remove_revolutionary(_THE_PLAYERS_MIND_), // this will also check they're not a head, so it can just be called freely -// If the rev icons start going wrong for some reason, ticker.mode:update_all_rev_icons() can be called to correct them. // If the game somtimes isn't registering a win properly, then ticker.mode.check_win() isn't being called somewhere. /datum/game_mode var/list/datum/mind/head_revolutionaries = list() var/list/datum/mind/revolutionaries = list() - var/extra_heads = 0 /datum/game_mode/revolution name = "revolution" config_tag = "revolution" restricted_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "AI", "Cyborg","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Magistrate", "Brig Physician") - protected_jobs = list() - required_players = 4 - required_players_secret = 15 - required_enemies = 3 + required_players = 20 + required_players_secret = 20 + required_enemies = 1 recommended_enemies = 3 - - uplink_welcome = "Revolutionary Uplink Console:" - uplink_uses = 20 - var/finished = 0 - var/checkwin_counter = 0 + var/check_counter = 0 var/max_headrevs = 3 + var/list/datum/mind/heads_to_kill = list() + var/list/possible_revolutionaries = list() + /////////////////////////// //Announces the game type// /////////////////////////// @@ -41,17 +37,17 @@ //Gets the round setup, cancelling if there's not enough players at the start// /////////////////////////////////////////////////////////////////////////////// /datum/game_mode/revolution/pre_setup() + possible_revolutionaries = get_players_for_role(ROLE_REV) if(config.protect_roles_from_antagonist) restricted_jobs += protected_jobs - var/list/datum/mind/possible_headrevs = get_players_for_role(ROLE_REV) for (var/i=1 to max_headrevs) - if(possible_headrevs.len==0) + if(possible_revolutionaries.len==0) break - var/datum/mind/lenin = pick(possible_headrevs) - possible_headrevs -= lenin + var/datum/mind/lenin = pick(possible_revolutionaries) + possible_revolutionaries -= lenin head_revolutionaries += lenin lenin.restricted_roles = restricted_jobs @@ -63,22 +59,24 @@ /datum/game_mode/revolution/post_setup() var/list/heads = get_living_heads() - if(num_players_started() >= 30) - heads += get_extra_living_heads() - extra_heads = 1 + var/list/sec = get_living_sec() + var/weighted_score = min(max(round(heads.len - ((8 - sec.len) / 3)),1),max_headrevs) + + while(weighted_score < head_revolutionaries.len) //das vi danya + var/datum/mind/trotsky = pick(head_revolutionaries) + possible_revolutionaries += trotsky + head_revolutionaries -= trotsky + update_rev_icons_removed(trotsky) for(var/datum/mind/rev_mind in head_revolutionaries) + log_game("[rev_mind.key] (ckey) has been selected as a head rev") for(var/datum/mind/head_mind in heads) - var/datum/objective/mutiny/rev_obj = new - rev_obj.owner = rev_mind - rev_obj.target = head_mind - rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]." - rev_mind.objectives += rev_obj + mark_for_death(rev_mind, head_mind) - // equip_traitor(rev_mind.current, 1) //changing how revs get assigned their uplink so they can get PDA uplinks. --NEO - // Removing revolutionary uplinks. -Pete - equip_revolutionary(rev_mind.current) - update_rev_icons_added(rev_mind) + spawn(rand(10,100)) + // equip_traitor(rev_mind.current, 1) //changing how revs get assigned their uplink so they can get PDA uplinks. --NEO + // Removing revolutionary uplinks. -Pete + equip_revolutionary(rev_mind.current) for(var/datum/mind/rev_mind in head_revolutionaries) greet_revolutionary(rev_mind) @@ -89,71 +87,29 @@ /datum/game_mode/revolution/process() - checkwin_counter++ - if(checkwin_counter >= 5) + check_counter++ + if(check_counter >= 5) if(!finished) + check_heads() ticker.mode.check_win() - checkwin_counter = 0 + check_counter = 0 return 0 -/proc/get_rev_mode() - if(!ticker || !istype(ticker.mode, /datum/game_mode/revolution)) - return null -/** - * LateSpawn hook. - * Called in newplayer.dm when a humanoid character joins the round after it started. - * Parameters: var/mob/living/carbon/human, var/rank - */ -/hook/latespawn/proc/add_latejoiner_heads(var/mob/living/carbon/human/H) - var/datum/game_mode/revolution/mode = get_rev_mode() - if (!mode) return 1 - - var/list/heads = list() - var/list/alt_positions = list("Warden", "Magistrate", "Blueshield", "Nanotrasen Representative") - - if(H.stat!=2 && H.mind && (H.mind.assigned_role in command_positions)) - heads += H - - if(mode.extra_heads) - if(H.stat!=2 && H.mind && (H.mind.assigned_role in alt_positions)) - heads += H - - for(var/datum/mind/rev_mind in mode.head_revolutionaries) - for(var/datum/mind/head_mind in heads) - var/datum/objective/mutiny/rev_obj = new - rev_obj.owner = rev_mind - rev_obj.target = head_mind - rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]." - rev_mind.objectives += rev_obj - to_chat(rev_mind.current, "Additional Objective: Assassinate [head_mind.name], the [head_mind.assigned_role].") - - for(var/datum/mind/rev_mind in mode.revolutionaries) - for(var/datum/mind/head_mind in heads) - var/datum/objective/mutiny/rev_obj = new - rev_obj.owner = rev_mind - rev_obj.target = head_mind - rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]." - rev_mind.objectives += rev_obj - to_chat(rev_mind.current, "Additional Objective: Assassinate [head_mind.name], the [head_mind.assigned_role].") - - -/datum/game_mode/proc/forge_revolutionary_objectives(var/datum/mind/rev_mind) +/datum/game_mode/proc/forge_revolutionary_objectives(datum/mind/rev_mind) var/list/heads = get_living_heads() - if(num_players_started() >= 30) - heads += get_extra_living_heads() - extra_heads = 1 for(var/datum/mind/head_mind in heads) var/datum/objective/mutiny/rev_obj = new rev_obj.owner = rev_mind rev_obj.target = head_mind - rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]." + rev_obj.explanation_text = "Assassinate or exile [head_mind.name], the [head_mind.assigned_role]." rev_mind.objectives += rev_obj -/datum/game_mode/proc/greet_revolutionary(var/datum/mind/rev_mind, var/you_are=1) +/datum/game_mode/proc/greet_revolutionary(datum/mind/rev_mind, you_are=1) var/obj_count = 1 + update_rev_icons_added(rev_mind) if (you_are) - to_chat(rev_mind.current, "\blue You are a member of the revolutionaries' leadership!") + to_chat(rev_mind.current, "You are a member of the revolutionaries' leadership!") for(var/datum/objective/objective in rev_mind.objectives) to_chat(rev_mind.current, "Objective #[obj_count]: [objective.explanation_text]") rev_mind.special_role = "Head Revolutionary" @@ -173,6 +129,8 @@ var/obj/item/device/flash/T = new(mob) + var/obj/item/toy/crayon/spraycan/R = new(mob) + var/obj/item/clothing/glasses/hud/security/chameleon/C = new(mob) var/list/slots = list ( "backpack" = slot_in_backpack, @@ -182,13 +140,67 @@ "right hand" = slot_r_hand, ) var/where = mob.equip_in_one_of_slots(T, slots) + var/where2 = mob.equip_in_one_of_slots(C, slots) + mob.equip_in_one_of_slots(R,slots) + + mob.update_icons() + + if (!where2) + to_chat(mob, "The Syndicate were unfortunately unable to get you a chameleon security HUD.") + else + to_chat(mob, "The chameleon security HUD in your [where2] will help you keep track of who is loyalty-implanted, and unable to be recruited.") + if (!where) to_chat(mob, "The Syndicate were unfortunately unable to get you a flash.") else to_chat(mob, "The flash in your [where] will help you to persuade the crew to join your cause.") - mob.update_icons() return 1 +///////////////////////////////// +//Gives head revs their targets// +///////////////////////////////// +/datum/game_mode/revolution/proc/mark_for_death(datum/mind/rev_mind, datum/mind/head_mind) + var/datum/objective/mutiny/rev_obj = new + rev_obj.owner = rev_mind + rev_obj.target = head_mind + rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]." + rev_mind.objectives += rev_obj + heads_to_kill += head_mind + +//////////////////////////////////////////// +//Checks if new heads have joined midround// +//////////////////////////////////////////// +/datum/game_mode/revolution/proc/check_heads() + var/list/heads = get_all_heads() + var/list/sec = get_all_sec() + if(heads_to_kill.len < heads.len) + var/list/new_heads = heads - heads_to_kill + for(var/datum/mind/head_mind in new_heads) + for(var/datum/mind/rev_mind in head_revolutionaries) + mark_for_death(rev_mind, head_mind) + + if(head_revolutionaries.len < max_headrevs && head_revolutionaries.len < round(heads.len - ((8 - sec.len) / 3))) + latejoin_headrev() + +/////////////////////////////// +//Adds a new headrev midround// +/////////////////////////////// +/datum/game_mode/revolution/proc/latejoin_headrev() + if(revolutionaries) //Head Revs are not in this list + var/list/promotable_revs = list() + for(var/datum/mind/khrushchev in revolutionaries) + if(khrushchev.current && khrushchev.current.client && khrushchev.current.stat != DEAD) + if(ROLE_REV in khrushchev.current.client.prefs.be_special) + promotable_revs += khrushchev + if(promotable_revs.len) + var/datum/mind/stalin = pick(promotable_revs) + revolutionaries -= stalin + head_revolutionaries += stalin + log_game("[stalin.key] (ckey) has been promoted to a head rev") + equip_revolutionary(stalin.current) + forge_revolutionary_objectives(stalin) + greet_revolutionary(stalin) + ////////////////////////////////////// //Checks if the revs have won or not// ////////////////////////////////////// @@ -205,9 +217,16 @@ /datum/game_mode/revolution/check_finished() if(config.continuous_rounds) if(finished != 0) - if(shuttle_master && shuttle_master.emergencyNoEscape) - shuttle_master.emergencyNoEscape = 0 - return finished != 0 + shuttle_master.emergencyNoEscape = 0 + if(shuttle_master.emergency.mode == SHUTTLE_STRANDED) + shuttle_master.emergency.mode = SHUTTLE_DOCKED + shuttle_master.emergency.timer = world.time + command_announcement.Announce("Hostile enviroment resolved. You have 3 minutes to board the Emergency Shuttle.", null, 'sound/AI/shuttledock.ogg') + return ..() + if(finished != 0) + return 1 + else + return ..() /////////////////////////////////////////////////// //Deals with converting players to the revolution// @@ -216,13 +235,18 @@ if(rev_mind.assigned_role in command_positions) return 0 var/mob/living/carbon/human/H = rev_mind.current//Check to see if the potential rev is implanted - for(var/obj/item/weapon/implant/loyalty/L in H)//Checking that there is a loyalty implant in the contents - if(L.imp_in == H)//Checking that it's actually implanted - return 0 + if(isloyal(H)) + return 0 if((rev_mind in revolutionaries) || (rev_mind in head_revolutionaries)) return 0 revolutionaries += rev_mind - to_chat(rev_mind.current, "\red 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!") + if(iscarbon(rev_mind.current)) + var/mob/living/carbon/carbon_mob = rev_mind.current + carbon_mob.silent = max(carbon_mob.silent, 5) + carbon_mob.flash_eyes(1, 1) + rev_mind.current.Stun(5) + to_chat(rev_mind.current, " 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!") + rev_mind.current.attack_log += "\[[time_stamp()]\] Has been converted to the revolution!" rev_mind.special_role = "Revolutionary" update_rev_icons_added(rev_mind) if(jobban_isbanned(rev_mind.current, ROLE_REV)) @@ -232,15 +256,23 @@ //Deals with players being converted from the revolution (Not a rev anymore)// // Modified to handle borged MMIs. Accepts another var if the target is being borged at the time -- Polymorph. ////////////////////////////////////////////////////////////////////////////// /datum/game_mode/proc/remove_revolutionary(datum/mind/rev_mind , beingborged) - if(rev_mind in revolutionaries) + var/remove_head = 0 + if(beingborged && (rev_mind in head_revolutionaries)) + head_revolutionaries -= rev_mind + remove_head = 1 + + if((rev_mind in revolutionaries) || remove_head) revolutionaries -= rev_mind rev_mind.special_role = null + rev_mind.current.attack_log += "\[[time_stamp()]\] Has renounced the revolution!" if(beingborged) - to_chat(rev_mind.current, "\red The frame's firmware detects and deletes your neural reprogramming! You remember nothing from the moment you were flashed until now.") - message_admins("[key_name_admin(rev_mind.current)] has been borged while being a member of the revolution.") + to_chat(rev_mind.current, "The frame's firmware detects and deletes your neural reprogramming! You remember nothing[remove_head ? "." : " but the name of the one who flashed you."]") + message_admins("[key_name_admin(rev_mind.current)] ? (FLW) has been borged while being a [remove_head ? "leader" : " member"] of the revolution.") + else - to_chat(rev_mind.current, "\red You have been brainwashed! You are no longer a 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...") + rev_mind.current.Paralyse(5) + to_chat(rev_mind.current, "You have been brainwashed! You are no longer a 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...") update_rev_icons_removed(rev_mind) for(var/mob/living/M in view(rev_mind.current)) @@ -250,7 +282,6 @@ else to_chat(M, "[rev_mind.current] looks like they just remembered their real allegiance!") - ///////////////////////////////////// //Adds the rev hud to a new convert// ///////////////////////////////////// @@ -266,6 +297,7 @@ var/datum/atom_hud/antag/revhud = huds[ANTAG_HUD_REV] revhud.leave_hud(rev_mind.current) set_antag_hud(rev_mind.current, null) + ////////////////////////// //Checks for rev victory// ////////////////////////// @@ -283,7 +315,7 @@ /datum/game_mode/revolution/proc/check_heads_victory() for(var/datum/mind/rev_mind in head_revolutionaries) var/turf/T = get_turf(rev_mind.current) - if((rev_mind) && (rev_mind.current) && (rev_mind.current.stat != 2) && rev_mind.current.client && T && (T.z in config.station_levels)) + if((rev_mind) && (rev_mind.current) && (rev_mind.current.stat != 2) && rev_mind.current.client && T && (T.z == ZLEVEL_STATION)) if(ishuman(rev_mind.current)) return 0 return 1 @@ -294,96 +326,50 @@ /datum/game_mode/revolution/declare_completion() if(finished == 1) feedback_set_details("round_end_result","win - heads killed") - to_chat(world, "\red The heads of staff were killed or abandoned the station! The revolutionaries win!") + to_chat(world, "The heads of staff were killed or exiled! The revolutionaries win!") else if(finished == 2) feedback_set_details("round_end_result","loss - rev heads killed") - to_chat(world, "\red The heads of staff managed to stop the revolution!") + to_chat(world, "The heads of staff managed to stop the revolution!") ..() return 1 /datum/game_mode/proc/auto_declare_completion_revolution() var/list/targets = list() - if(head_revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution)) - var/text = "The head revolutionaries were:" - + var/num_revs = 0 + var/num_survivors = 0 + for(var/mob/living/carbon/survivor in living_mob_list) + if(survivor.ckey) + num_survivors++ + if(survivor.mind) + if((survivor.mind in head_revolutionaries) || (survivor.mind in revolutionaries)) + num_revs++ + if(num_survivors) + to_chat(world, "[TAB]Command's Approval Rating: [100 - round((num_revs/num_survivors)*100, 0.1)]%") // % of loyal crew + var/text = "
The head revolutionaries were:" for(var/datum/mind/headrev in head_revolutionaries) - text += "
[headrev.key] was [headrev.name] (" - if(headrev.current) - if(headrev.current.stat == DEAD) - text += "died" - else if(!(headrev.current.z in config.station_levels)) - text += "fled the station" - else - text += "survived the revolution" - if(headrev.current.real_name != headrev.name) - text += " as [headrev.current.real_name]" - else - text += "body destroyed" - text += ")" - - for(var/datum/objective/mutiny/objective in headrev.objectives) - targets |= objective.target - + text += printplayer(headrev, 1) + text += "
" to_chat(world, text) if(revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution)) - var/text = "The revolutionaries were:" - + var/text = "
The revolutionaries were:" for(var/datum/mind/rev in revolutionaries) - text += "
[rev.key] was [rev.name] (" - if(rev.current) - if(rev.current.stat == DEAD) - text += "died" - else if(!(rev.current.z in config.station_levels)) - text += "fled the station" - else - text += "survived the revolution" - if(rev.current.real_name != rev.name) - text += " as [rev.current.real_name]" - else - text += "body destroyed" - text += ")" - + text += printplayer(rev, 1) + text += "
" to_chat(world, text) - if( head_revolutionaries.len || revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution) ) - var/text = "The heads of staff were:" - + var/text = "
The heads of staff were:" var/list/heads = get_all_heads() - if(extra_heads) - heads += get_extra_heads() for(var/datum/mind/head in heads) var/target = (head in targets) if(target) - text += "" - text += "
[head.key] was [head.name] (" - if(head.current) - if(head.current.stat == DEAD) - text += "died" - else if(!(head.current.z in config.station_levels)) - text += "fled the station" - else - text += "survived the revolution" - if(head.current.real_name != head.name) - text += " as [head.current.real_name]" - else - text += "body destroyed" - text += ")" - if(target) - text += "
" - + text += "Target" + text += printplayer(head, 1) + text += "
" to_chat(world, text) -/proc/is_convertable_to_rev(datum/mind/mind) - return istype(mind) && \ - istype(mind.current, /mob/living/carbon/human) && \ - !(mind.assigned_role in command_positions) && \ - !(mind.assigned_role in list("Security Officer", "Detective", "Warden", "Nanotrasen Representative")) - - - /datum/game_mode/revolution/set_scoreboard_gvars() var/foecount = 0 for(var/datum/mind/M in ticker.mode.head_revolutionaries) diff --git a/code/game/gamemodes/revolution/rp_revolution.dm b/code/game/gamemodes/revolution/rp_revolution.dm deleted file mode 100644 index 78d210159a8..00000000000 --- a/code/game/gamemodes/revolution/rp_revolution.dm +++ /dev/null @@ -1,257 +0,0 @@ -// BS12's less violent revolution mode -// Isn't this basically mutiny but without any real reason - -/datum/game_mode/revolution/rp_revolution - name = "rp-revolution" - config_tag = "rp-revolution" - required_players = 4 - required_players_secret = 12 - required_enemies = 3 - recommended_enemies = 3 - - uplink_welcome = "Revolutionary Uplink Console:" - uplink_uses = 10 - - newscaster_announcements = /datum/news_announcement/revolution_inciting_event - - var/last_command_report = 0 - var/list/heads = list() - var/tried_to_add_revheads = 0 - -/////////////////////////////////////////////////////////////////////////////// -//Gets the round setup, cancelling if there's not enough players at the start// -/////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/revolution/rp_revolution/pre_setup() - - if(config.protect_roles_from_antagonist) - restricted_jobs += protected_jobs - - var/num_players = num_players() - max_headrevs = max(num_players / 4, 3) - recommended_enemies = max_headrevs - - var/list/datum/mind/possible_headrevs = get_players_for_role(ROLE_REV) - - var/head_check = 0 - for(var/mob/new_player/player in player_list) - if(player.mind.assigned_role in command_positions) - head_check = 1 - break - - for (var/i=1 to max_headrevs) - if (possible_headrevs.len==0) - break - var/datum/mind/lenin = pick(possible_headrevs) - possible_headrevs -= lenin - head_revolutionaries += lenin - lenin.restricted_roles = restricted_jobs - - if((head_revolutionaries.len==0)||(!head_check)) - return 0 - - return 1 - - -/datum/game_mode/revolution/rp_revolution/post_setup() - heads = get_living_heads() - - for(var/datum/mind/rev_mind in head_revolutionaries) - for(var/datum/mind/head_mind in heads) - var/datum/objective/mutiny/rp/rev_obj = new - rev_obj.owner = rev_mind - rev_obj.target = head_mind - rev_obj.explanation_text = "Assassinate, convert or capture [head_mind.name], the [head_mind.assigned_role]." - rev_mind.objectives += rev_obj - - update_rev_icons_added(rev_mind) - - for(var/datum/mind/rev_mind in head_revolutionaries) - greet_revolutionary(rev_mind) - rev_mind.current.verbs += /mob/living/carbon/human/proc/RevConvert - - modePlayer += head_revolutionaries - - -/datum/game_mode/revolution/rp_revolution/greet_revolutionary(var/datum/mind/rev_mind, var/you_are=1) - var/obj_count = 1 - if (you_are) - to_chat(rev_mind.current, "\blue You are a member of the revolutionaries' leadership!") - for(var/datum/objective/objective in rev_mind.objectives) - to_chat(rev_mind.current, "Objective #[obj_count]: [objective.explanation_text]") - rev_mind.special_role = "Head Revolutionary" - obj_count++ - - // Show each head revolutionary up to 3 candidates - var/list/already_considered = list() - for(var/i = 0, i < 2, i++) - var/mob/rev_mob = rev_mind.current - already_considered += rev_mob - // Tell them about people they might want to contact. - var/mob/living/carbon/human/M = get_nt_opposed() - if(M && !(M.mind in head_revolutionaries) && !(M in already_considered)) - to_chat(rev_mob, "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them.") - rev_mob.mind.store_memory("Potential Collaborator: [M.real_name]") - -/////////////////////////////////////////////////// -//Deals with converting players to the revolution// -/////////////////////////////////////////////////// -/datum/game_mode/revolution/rp_revolution/add_revolutionary(datum/mind/rev_mind) - // overwrite this func to make it so even heads can be converted - var/mob/living/carbon/human/H = rev_mind.current//Check to see if the potential rev is implanted - if(!is_convertible(H)) - return 0 - if((rev_mind in revolutionaries) || (rev_mind in head_revolutionaries)) - return 0 - revolutionaries += rev_mind - to_chat(rev_mind.current, "\red 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, capture or convert the heads to win the revolution!") - rev_mind.special_role = "Revolutionary" - update_rev_icons_added(rev_mind) - return 1 - -///////////////////////////// -//Checks for a head victory// -///////////////////////////// -/datum/game_mode/revolution/rp_revolution/check_heads_victory() - for(var/datum/mind/rev_mind in head_revolutionaries) - var/turf/T = get_turf(rev_mind.current) - if(rev_mind.current.stat != 2) - // TODO: add a similar check that also checks whether they're without ID in the brig.. - // probably wanna export this stuff into a separate function for use by both - // revs and heads - //assume that only carbon mobs can become rev heads for now - if(!rev_mind.current:handcuffed && T && (T.z in config.station_levels)) - return 0 - return 1 - -/////////////////////////// -//Announces the game type// -/////////////////////////// -/datum/game_mode/revolution/rp_revolution/announce() - to_chat(world, "The current game mode is - Revolution!") - to_chat(world, "Some crewmembers are attempting to start a revolution!") - - -////////////////////////////////////////////////////////////////////// -//Announces the end of the game with all relavent information stated// -////////////////////////////////////////////////////////////////////// -/datum/game_mode/revolution/rp_revolution/declare_completion() - if(finished == 1) - feedback_set_details("round_end_result","win - heads overthrown") - to_chat(world, "\red The heads of staff were overthrown! The revolutionaries win!") - else if(finished == 2) - feedback_set_details("round_end_result","loss - revolution stopped") - to_chat(world, "\red The heads of staff managed to stop the revolution!") - ..() - return 1 - -/datum/game_mode/revolution/proc/is_convertible(mob/M) - for(var/obj/item/weapon/implant/loyalty/L in M)//Checking that there is a loyalty implant in the contents - if(L.imp_in == M)//Checking that it's actually implanted - return 0 - - return 1 - -/mob/living/carbon/human/proc/RevConvert() - set name = "Rev-Convert" - set category = "IC" - var/list/Possible = list() - for (var/mob/living/carbon/human/P in oview(src)) - if(!stat && P.client && P.mind && !P.mind.special_role) - Possible += P - if(!Possible.len) - to_chat(src, "\red There doesn't appear to be anyone available for you to convert here.") - return - var/mob/living/carbon/human/M = input("Select a person to convert", "Viva la revolution!", null) as mob in Possible - if(((src.mind in ticker.mode:head_revolutionaries) || (src.mind in ticker.mode:revolutionaries))) - if((M.mind in ticker.mode:head_revolutionaries) || (M.mind in ticker.mode:revolutionaries)) - to_chat(src, "\red [M] is already be a revolutionary!") - else if(!ticker.mode:is_convertible(M)) - to_chat(src, "\red [M] is implanted with a loyalty implant - Remove it first!") - else - if(world.time < M.mind.rev_cooldown) - to_chat(src, "\red Wait five seconds before reconversion attempt.") - return - to_chat(src, "\red Attempting to convert [M]...") - log_admin("[src]([src.ckey]) attempted to convert [M].") - message_admins("\red [src]([src.ckey]) attempted to convert [M].") - var/choice = alert(M,"Asked by [src]: Do you want to join the revolution?","Align Thyself with the Revolution!","No!","Yes!") - if(choice == "Yes!") - ticker.mode:add_revolutionary(M.mind) - to_chat(M, "\blue You join the revolution!") - to_chat(src, "\blue [M] joins the revolution!") - else if(choice == "No!") - to_chat(M, "\red You reject this traitorous cause!") - to_chat(src, "\red [M] does not support the revolution!") - M.mind.rev_cooldown = world.time+50 - -/datum/game_mode/revolution/rp_revolution/process() - // only perform rev checks once in a while - if(tried_to_add_revheads < world.time) - tried_to_add_revheads = world.time+50 - var/active_revs = 0 - for(var/datum/mind/rev_mind in head_revolutionaries) - if(rev_mind.current.client && rev_mind.current.client.inactivity <= 10*60*20) // 20 minutes inactivity are OK - active_revs++ - - if(active_revs == 0) - log_debug("There are zero active heads of revolution, trying to add some..") - var/added_heads = 0 - for(var/mob/living/carbon/human/H in world) if(H.client && H.mind && H.client.inactivity <= 10*60*20 && H.mind in revolutionaries) - head_revolutionaries += H.mind - for(var/datum/mind/head_mind in heads) - var/datum/objective/mutiny/rp/rev_obj = new - rev_obj.owner = H.mind - rev_obj.target = head_mind - rev_obj.explanation_text = "Assassinate or capture [head_mind.name], the [head_mind.assigned_role]." - H.mind.objectives += rev_obj - - update_rev_icons_added(H.mind) - H.verbs += /mob/living/carbon/human/proc/RevConvert - - to_chat(H, "\red Congratulations, yer heads of revolution are all gone now, so yer earned yourself a promotion.") - added_heads = 1 - break - - if(added_heads) - log_admin("Managed to add new heads of revolution.") - message_admins("Managed to add new heads of revolution.") - else - log_admin("Unable to add new heads of revolution.") - message_admins("Unable to add new heads of revolution.") - tried_to_add_revheads = world.time + 6000 // wait 10 minutes - - if(last_command_report == 0 && world.time >= 10 * 60 * 10) - src.command_report("We are regrettably announcing that your performance has been disappointing, and we are thus forced to cut down on financial support to your station. To achieve this, the pay of all personnal, except the Heads of Staff, has been halved.") - last_command_report = 1 - else if(last_command_report == 1 && world.time >= 10 * 60 * 30) - src.command_report("Statistics hint that a high amount of leisure time, and associated activities, are responsible for the poor performance of many of our stations. You are to bolt and close down any leisure facilities, such as the holodeck, the theatre and the bar. Food can be distributed through vendors and the kitchen.") - last_command_report = 2 - else if(last_command_report == 2 && world.time >= 10 * 60 * 60) - src.command_report("It is reported that merely closing down leisure facilities has not been successful. You and your Heads of Staff are to ensure that all crew are working hard, and not wasting time or energy. Any crew caught off duty without leave from their Head of Staff are to be warned, and on repeated offence, to be brigged until the next transfer shuttle arrives, which will take them to facilities where they can be of more use.") - last_command_report = 3 - - return ..() - -/datum/game_mode/revolution/rp_revolution/proc/command_report(message) - for (var/obj/machinery/computer/communications/comm in world) - if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept) - var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc ) - intercept.name = "paper- 'Cent. Com. Announcement'" - intercept.info = message - - comm.messagetitle.Add("Cent. Com. Announcement") - comm.messagetext.Add(message) - to_chat(world, sound('sound/AI/commandreport.ogg')) - -/datum/game_mode/revolution/rp_revolution/latespawn(mob/M) - if(M.mind.assigned_role in command_positions) - log_debug("Adding head kill/capture/convert objective for [M.name]") - heads += M - - for(var/datum/mind/rev_mind in head_revolutionaries) - var/datum/objective/mutiny/rp/rev_obj = new - rev_obj.owner = rev_mind - rev_obj.target = M.mind - rev_obj.explanation_text = "Assassinate, convert or capture [M.real_name], the [M.mind.assigned_role]." - rev_mind.objectives += rev_obj - to_chat(rev_mind.current, "\red A new Head of Staff, [M.real_name], the [M.mind.assigned_role] has appeared. Your objectives have been updated.") diff --git a/code/game/gamemodes/vampire/hud.dm b/code/game/gamemodes/vampire/hud.dm deleted file mode 100644 index 727ae3bdc25..00000000000 --- a/code/game/gamemodes/vampire/hud.dm +++ /dev/null @@ -1,9 +0,0 @@ -/datum/hud/proc/vampire_hud(ui_style = 'icons/mob/screen1_Midnight.dmi') - - vampire_blood_display = new /obj/screen() - vampire_blood_display.name = "Usable Blood" - vampire_blood_display.icon_state = "power_display" - vampire_blood_display.screen_loc = "WEST:6,CENTER-1:15" - vampire_blood_display.layer = 20 - - mymob.client.screen += list(vampire_blood_display) \ No newline at end of file diff --git a/code/game/gamemodes/vampire/vampire.dm b/code/game/gamemodes/vampire/vampire.dm index 1abed5ba4dd..f10e5333a46 100644 --- a/code/game/gamemodes/vampire/vampire.dm +++ b/code/game/gamemodes/vampire/vampire.dm @@ -239,12 +239,11 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha if(!get_ability(path)) force_add_ability(path) -/datum/vampire/proc/remove_ability(path) - var/A = get_ability(path) - if(A) - powers -= A - owner.mind.spell_list.Remove(A) - qdel(A) +/datum/vampire/proc/remove_ability(ability) + if(ability && (ability in powers)) + powers -= ability + owner.mind.spell_list.Remove(ability) + qdel(ability) /mob/proc/make_vampire() if(!mind) @@ -263,6 +262,10 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha /datum/vampire/proc/remove_vampire_powers() for(var/P in powers) remove_ability(P) + if(owner.hud_used) + var/datum/hud/hud = owner.hud_used + if(hud.vampire_blood_display) + hud.remove_vampire_hud() owner.alpha = 255 /datum/vampire/proc/handle_bloodsucking(mob/living/carbon/human/H) @@ -353,6 +356,9 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha update_vampire_icons_removed(vampire_mind) // to_chat(world, "Removed [vampire_mind.current.name] from vampire shit") to_chat(vampire_mind.current, "\red The fog clouding your mind clears. You remember nothing from the moment you were enthralled until now.") + if(vampire_mind.current.hud_used) + vampire_mind.current.hud_used.remove_vampire_hud() + /datum/vampire/proc/check_sun() var/ax = owner.x @@ -375,7 +381,12 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha if(owner.hud_used) var/datum/hud/hud = owner.hud_used if(!hud.vampire_blood_display) - hud.vampire_hud() + hud.vampire_blood_display = new /obj/screen() + hud.vampire_blood_display.name = "Usable Blood" + hud.vampire_blood_display.icon_state = "power_display" + hud.vampire_blood_display.screen_loc = "WEST:6,CENTER-1:15" + hud.static_inventory += hud.vampire_blood_display + hud.show_hud(hud.hud_version) hud.vampire_blood_display.maptext = "
[bloodusable]
" handle_vampire_cloak() if(istype(owner.loc, /turf/space)) @@ -429,4 +440,13 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha owner.fire_stacks++ owner.IgniteMob() owner.adjustFireLoss(3) - return \ No newline at end of file + return + +/datum/hud/proc/remove_vampire_hud() + if(!vampire_blood_display) + return + + static_inventory -= vampire_blood_display + qdel(vampire_blood_display) + vampire_blood_display = null + show_hud(hud_version) \ No newline at end of file diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index d43d5e17e8f..e3649f5e445 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -249,43 +249,43 @@ /proc/get_absolutely_all_accesses() return (get_all_accesses() | get_all_centcom_access() | get_all_syndicate_access() | get_all_misc_access()) -/proc/get_region_accesses(var/code) +/proc/get_region_accesses(code) switch(code) - if(0) + if(REGION_ALL) return get_all_accesses() - if(1) //security + if(REGION_GENERAL) //station general + return list(access_kitchen, access_bar, access_hydroponics, access_janitor, access_chapel_office, access_crematorium, access_library, access_theatre, access_lawyer, access_magistrate, access_clown, access_mime) + if(REGION_SECURITY) //security return list(access_sec_doors, access_weapons, access_security, access_brig, access_armory, access_forensics_lockers, access_court, access_pilot, access_hos) - if(2) //medbay + if(REGION_MEDBAY) //medbay return list(access_medical, access_genetics, access_morgue, access_chemistry, access_psychiatrist, access_virology, access_surgery, access_cmo, access_paramedic) - if(3) //research - return list(access_research, access_tox, access_tox_storage, access_robotics, access_xenobiology, access_xenoarch, access_minisat, access_rd) - if(4) //engineering and maintenance + if(REGION_RESEARCH) //research + return list(access_research, access_tox, access_tox_storage, access_genetics, access_robotics, access_xenobiology, access_xenoarch, access_minisat, access_rd) + if(REGION_ENGINEERING) //engineering and maintenance return list(access_construction, access_maint_tunnels, access_engine, access_engine_equip, access_external_airlocks, access_tech_storage, access_atmospherics, access_minisat, access_ce, access_mechanic) - if(5) //command - return list(access_heads, access_RC_announce, access_keycard_auth, access_change_ids, access_ai_upload, access_teleporter, access_eva, access_tcomsat, access_gateway, access_all_personal_lockers, access_heads_vault, access_blueshield, access_ntrep, access_hop, access_captain) - if(6) //station general - return list(access_kitchen,access_bar, access_hydroponics, access_janitor, access_chapel_office, access_crematorium, access_library, access_theatre, access_lawyer, access_magistrate, access_clown, access_mime) - if(7) //supply + if(REGION_SUPPLY) //supply return list(access_mailsorting, access_mining, access_mining_station, access_mineral_storeroom, access_cargo, access_qm) + if(REGION_COMMAND) //command + return list(access_heads, access_RC_announce, access_keycard_auth, access_change_ids, access_ai_upload, access_teleporter, access_eva, access_tcomsat, access_gateway, access_all_personal_lockers, access_heads_vault, access_blueshield, access_ntrep, access_hop, access_captain) -/proc/get_region_accesses_name(var/code) +/proc/get_region_accesses_name(code) switch(code) - if(0) + if(REGION_ALL) return "All" - if(1) //security + if(REGION_GENERAL) //station general + return "General" + if(REGION_SECURITY) //security return "Security" - if(2) //medbay + if(REGION_MEDBAY) //medbay return "Medbay" - if(3) //research + if(REGION_RESEARCH) //research return "Research" - if(4) //engineering and maintenance + if(REGION_ENGINEERING) //engineering and maintenance return "Engineering" - if(5) //command - return "Command" - if(6) //station general - return "Station General" - if(7) //supply + if(REGION_SUPPLY) //supply return "Supply" + if(REGION_COMMAND) //command + return "Command" /proc/get_access_desc(A) diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 200b21d441d..6b13dbe95e3 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -445,6 +445,39 @@ to destroy them and players will be able to make replacements. origin_tech = "programming=1" req_components = list( /obj/item/weapon/stock_parts/matter_bin = 1) + var/list/fridge_names_paths = list( + "\improper SmartFridge" = /obj/machinery/smartfridge, + "\improper MegaSeed Servitor" = /obj/machinery/smartfridge/seeds, + "\improper Refrigerated Medicine Storage" = /obj/machinery/smartfridge/medbay, + "\improper Slime Extract Storage" = /obj/machinery/smartfridge/secure/extract, + "\improper Secure Refrigerated Medicine Storage" = /obj/machinery/smartfridge/secure/medbay, + "\improper Smart Chemical Storage" = /obj/machinery/smartfridge/secure/chemistry, + "smart virus storage" = /obj/machinery/smartfridge/secure/chemistry/virology, + "\improper Drink Showcase" = /obj/machinery/smartfridge/drinks + ) + + + +/obj/item/weapon/circuitboard/smartfridge/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/weapon/screwdriver)) + set_type(null, user) + +/obj/item/weapon/circuitboard/smartfridge/proc/set_type(typepath, mob/user) + var/new_name = "" + if(!typepath) + new_name = input("Circuit Setting", "What would you change the board setting to?") in fridge_names_paths + typepath = fridge_names_paths[new_name] + else + for(var/name in fridge_names_paths) + if(fridge_names_paths[name] == typepath) + new_name = name + break + build_path = typepath + name = new_name + if(findtextEx(new_name, "\improper")) + new_name = replacetext(new_name, "\improper", "") + if(user) + to_chat(user, "You set the board to [new_name].") /obj/item/weapon/circuitboard/monkey_recycler name = "circuit board (Monkey Recycler)" @@ -890,6 +923,15 @@ obj/item/weapon/circuitboard/rdserver /obj/item/weapon/stock_parts/manipulator = 1, /obj/item/weapon/stock_parts/console_screen = 1) +/obj/item/weapon/circuitboard/gameboard + name = "circuit board (Virtual Gameboard)" + build_path = /obj/machinery/gameboard + board_type = "machine" + origin_tech = "programming=2" + req_components = list( + /obj/item/weapon/stock_parts/micro_laser = 1, + /obj/item/stack/cable_coil = 3, + /obj/item/stack/sheet/glass = 1) //Selectable mode board, like vending machine boards /obj/item/weapon/circuitboard/logic_gate diff --git a/code/game/machinery/gameboard.dm b/code/game/machinery/gameboard.dm new file mode 100644 index 00000000000..b331930b325 --- /dev/null +++ b/code/game/machinery/gameboard.dm @@ -0,0 +1,79 @@ +/obj/machinery/gameboard + name = "Virtual Gameboard" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "gboard_on" + desc = "A holographic table allowing the crew to have fun™ on boring shifts! One player per board." + density = 1 + anchored = 1 + use_power = 1 + +/obj/machinery/gameboard/New() + ..() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/gameboard(null) + component_parts += new /obj/item/weapon/stock_parts/micro_laser(null) + component_parts += new /obj/item/stack/cable_coil(null, 3) + component_parts += new /obj/item/stack/sheet/glass(null, 1) + RefreshParts() + +/obj/machinery/gameboard/power_change() + . = ..() + update_icon() + +/obj/machinery/gameboard/update_icon() + if(stat & NOPOWER) + icon_state = "gboard_off" + else + icon_state = "gboard_on" + +/obj/machinery/gameboard/attack_hand(mob/user) + . = ..() + if(.) + return + if(src.in_use) + to_chat(user, "This gameboard is already in use!") + return + interact(user) + +/obj/machinery/gameboard/interact(mob/user) + . = ..() + if(.) + return + + var/dat + dat = replacetext(file2text('html/chess.html'), "\[hsrc]", "\ref[src]") + var/datum/asset/simple/chess/assets = get_asset_datum(/datum/asset/simple/chess) + assets.send(user) + + var/datum/browser/popup = new(user, "SpessChess", name, 500, 800, src) + popup.set_content(dat) + popup.add_stylesheet("chess.css", 'html/browser/chess.css') + popup.add_script("garbochess.js", 'html/browser/garbochess.js') + //popup.add_script("boardui.js", 'html/browser/boardui.js') + popup.add_script("jquery-1.8.2.min.js", 'html/browser/jquery-1.8.2.min.js') + popup.add_script("jquery-ui-1.8.24.custom.min.js", 'html/browser/jquery-ui-1.8.24.custom.min.js') + popup.set_window_options("titlebar=0") + popup.open() + user.set_machine(src) + +/obj/machinery/gameboard/proc/close_game() //yes, shamelessly copied over from arcade_base + in_use = 0 + for(var/mob/user in viewers(world.view, src)) // I don't know who you are. + if(user.client && user.machine == src) // I will look for you, + user.unset_machine() // I will find you, + user << browse(null, "window=SpessChess") // And I will kill you. + return + +/obj/machinery/gameboard/Topic(var/href, var/list/href_list) + . = ..() + var/prize = /obj/item/stack/tickets + if (.) + return + + if (href_list["checkmate"]) + visible_message("[src.name] beeps, \"WINNER!\"") + new prize(get_turf(src), 80) + close_game() + + if (href_list["close"]) + close_game() \ No newline at end of file diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm index d1dda0bc558..b17b09d5419 100644 --- a/code/game/machinery/kitchen/smartfridge.dm +++ b/code/game/machinery/kitchen/smartfridge.dm @@ -26,7 +26,9 @@ /obj/machinery/smartfridge/New() ..() component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/smartfridge(null) + var/obj/item/weapon/circuitboard/smartfridge/board = new(null) + board.set_type(type) + component_parts += board component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) RefreshParts() @@ -150,10 +152,8 @@ /obj/item/weapon/reagent_containers/glass/bottle/plasma = 1, /obj/item/weapon/reagent_containers/glass/bottle/diphenhydramine = 1) -/obj/machinery/smartfridge/secure/chemistry/virology/accept_check(obj/item/O) - if(..(O)) - return 1 - if(istype(O, /obj/item/weapon/reagent_containers/syringe)) +/obj/machinery/smartfridge/secure/chemistry/virology/accept_check(var/obj/item/O as obj) + if(istype(O, /obj/item/weapon/reagent_containers/syringe) || istype(O, /obj/item/weapon/reagent_containers/glass/bottle) || istype(O, /obj/item/weapon/reagent_containers/glass/beaker)) return 1 return 0 diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index 011cd0d3c7c..f79c43068ee 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -473,6 +473,7 @@ if(M) S.icon_state = initial(S.icon_state) S.icon = initial(S.icon) + S.reagents.reaction(M, INGEST) S.reagents.trans_to(M, S.reagents.total_volume) M.take_organ_damage(2) S.visible_message(" [M] was hit by the syringe!") diff --git a/code/game/objects/effects/bump_teleporter.dm b/code/game/objects/effects/bump_teleporter.dm index 9379234ca68..bb9a34010c9 100644 --- a/code/game/objects/effects/bump_teleporter.dm +++ b/code/game/objects/effects/bump_teleporter.dm @@ -2,7 +2,7 @@ var/list/obj/effect/bump_teleporter/BUMP_TELEPORTERS = list() /obj/effect/bump_teleporter name = "bump-teleporter" - icon = 'icons/mob/screen1.dmi' + icon = 'icons/mob/screen_gen.dmi' icon_state = "x2" var/id = null //id of this bump_teleporter. var/id_target = null //id of bump_teleporter which this moves you to. diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm index 4e86d96d0fc..9445b5aa626 100644 --- a/code/game/objects/effects/decals/misc.dm +++ b/code/game/objects/effects/decals/misc.dm @@ -1,7 +1,7 @@ /obj/effect/decal/point name = "arrow" desc = "It's an arrow hanging in mid-air. There may be a wizard about." - icon = 'icons/mob/screen1.dmi' + icon = 'icons/mob/screen_gen.dmi' icon_state = "arrow" layer = 16.0 anchored = 1 diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 8d6aa799fd8..a074e269350 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -1,6 +1,6 @@ /obj/effect/landmark name = "landmark" - icon = 'icons/mob/screen1.dmi' + icon = 'icons/mob/screen_gen.dmi' icon_state = "x2" anchored = 1.0 unacidable = 1 @@ -104,7 +104,7 @@ /obj/effect/landmark/start name = "start" - icon = 'icons/mob/screen1.dmi' + icon = 'icons/mob/screen_gen.dmi' icon_state = "x" anchored = 1.0 diff --git a/code/game/objects/effects/manifest.dm b/code/game/objects/effects/manifest.dm index ec45c7a0894..4b5a2eebb7b 100644 --- a/code/game/objects/effects/manifest.dm +++ b/code/game/objects/effects/manifest.dm @@ -1,6 +1,6 @@ /obj/effect/manifest name = "manifest" - icon = 'icons/mob/screen1.dmi' + icon = 'icons/mob/screen_gen.dmi' icon_state = "x" unacidable = 1//Just to be sure. diff --git a/code/game/objects/effects/spawners/bombspawner.dm b/code/game/objects/effects/spawners/bombspawner.dm index e34b136cb45..e065941a947 100644 --- a/code/game/objects/effects/spawners/bombspawner.dm +++ b/code/game/objects/effects/spawners/bombspawner.dm @@ -1,113 +1,6 @@ -/* The old single tank bombs that dont really work anymore -/obj/effect/spawner/bomb - name = "bomb" - icon = 'icons/mob/screen1.dmi' - icon_state = "x" - var/btype = 0 //0 = radio, 1= prox, 2=time - var/explosive = 1 // 0= firebomb - var/btemp = 500 // bomb temperature (degC) - var/active = 0 - -/obj/effect/spawner/bomb/radio - btype = 0 - -/obj/effect/spawner/bomb/proximity - btype = 1 - -/obj/effect/spawner/bomb/timer - btype = 2 - -/obj/effect/spawner/bomb/timer/syndicate - btemp = 450 - -/obj/effect/spawner/bomb/suicide - btype = 3 - -/obj/effect/spawner/bomb/New() - ..() - - switch (src.btype) - // radio - if (0) - var/obj/item/assembly/r_i_ptank/R = new /obj/item/assembly/r_i_ptank(src.loc) - var/obj/item/weapon/tank/plasma/p3 = new /obj/item/weapon/tank/plasma(R) - var/obj/item/device/radio/signaler/p1 = new /obj/item/device/radio/signaler(R) - var/obj/item/device/igniter/p2 = new /obj/item/device/igniter(R) - R.part1 = p1 - R.part2 = p2 - R.part3 = p3 - p1.master = R - p2.master = R - p3.master = R - R.status = explosive - p1.b_stat = 0 - p2.secured = 1 - p3.air_contents.temperature = btemp + T0C - - // proximity - if (1) - var/obj/item/assembly/m_i_ptank/R = new /obj/item/assembly/m_i_ptank(src.loc) - var/obj/item/weapon/tank/plasma/p3 = new /obj/item/weapon/tank/plasma(R) - var/obj/item/device/prox_sensor/p1 = new /obj/item/device/prox_sensor(R) - var/obj/item/device/igniter/p2 = new /obj/item/device/igniter(R) - R.part1 = p1 - R.part2 = p2 - R.part3 = p3 - p1.master = R - p2.master = R - p3.master = R - R.status = explosive - - p3.air_contents.temperature = btemp + T0C - p2.secured = 1 - - if(src.active) - R.part1.secured = 1 - R.part1.icon_state = text("motion[]", 1) - R.c_state(1, src) - - // timer - if (2) - var/obj/item/assembly/t_i_ptank/R = new /obj/item/assembly/t_i_ptank(src.loc) - var/obj/item/weapon/tank/plasma/p3 = new /obj/item/weapon/tank/plasma(R) - var/obj/item/device/timer/p1 = new /obj/item/device/timer(R) - var/obj/item/device/igniter/p2 = new /obj/item/device/igniter(R) - R.part1 = p1 - R.part2 = p2 - R.part3 = p3 - p1.master = R - p2.master = R - p3.master = R - R.status = explosive - - p3.air_contents.temperature = btemp + T0C - p2.secured = 1 - //bombvest - if(3) - var/obj/item/clothing/suit/armor/a_i_a_ptank/R = new /obj/item/clothing/suit/armor/a_i_a_ptank(src.loc) - var/obj/item/weapon/tank/plasma/p4 = new /obj/item/weapon/tank/plasma(R) - var/obj/item/device/healthanalyzer/p1 = new /obj/item/device/healthanalyzer(R) - var/obj/item/device/igniter/p2 = new /obj/item/device/igniter(R) - var/obj/item/clothing/suit/armor/vest/p3 = new /obj/item/clothing/suit/armor/vest(R) - R.part1 = p1 - R.part2 = p2 - R.part3 = p3 - R.part4 = p4 - p1.master = R - p2.master = R - p3.master = R - p4.master = R - R.status = explosive - - p4.air_contents.temperature = btemp + T0C - p2.secured = 1 - - qdel(src) -*/ - /obj/effect/spawner/newbomb name = "bomb" - icon = 'icons/mob/screen1.dmi' + icon = 'icons/mob/screen_gen.dmi' icon_state = "x" var/btype = 0 // 0=radio, 1=prox, 2=time var/btemp1 = 1500 diff --git a/code/game/objects/items/control_wand.dm b/code/game/objects/items/control_wand.dm new file mode 100644 index 00000000000..86f6fd5a74d --- /dev/null +++ b/code/game/objects/items/control_wand.dm @@ -0,0 +1,104 @@ +#define WAND_OPEN "Open Door" +#define WAND_BOLT "Toggle Bolts" +#define WAND_EMERGENCY "Toggle Emergency Access" + +/obj/item/weapon/door_remote + icon_state = "gangtool-white" + item_state = "electronic" + icon = 'icons/obj/device.dmi' + name = "control wand" + desc = "Remotely controls airlocks." + w_class = 1 + var/mode = WAND_OPEN + var/region_access = 1 //See access.dm + var/obj/item/weapon/card/id/ID + +/obj/item/weapon/door_remote/New() + ..() + ID = new /obj/item/weapon/card/id + ID.access = get_region_accesses(region_access) + +/obj/item/weapon/door_remote/attack_self(mob/user) + switch(mode) + if(WAND_OPEN) + mode = WAND_BOLT + if(WAND_BOLT) + mode = WAND_EMERGENCY + if(WAND_EMERGENCY) + mode = WAND_OPEN + to_chat(user, "Now in mode: [mode].") + +/obj/item/weapon/door_remote/afterattack(obj/machinery/door/airlock/D, mob/user) + if(!istype(D)) + return + if(!(D.arePowerSystemsOn())) + to_chat(user, "[D] has no power!") + return + if(!D.requiresID()) + to_chat(user, "[D]'s ID scan is disabled!") + return + if(D.check_access(src.ID)) + switch(mode) + if(WAND_OPEN) + if(D.density) + D.open() + else + D.close() + if(WAND_BOLT) + if(D.locked) + D.unlock() + else + D.lock() + if(WAND_EMERGENCY) + if(D.emergency) + D.emergency = 0 + else + D.emergency = 1 + D.update_icon() + else + to_chat(user, "[src] does not have access to this door.") + +/obj/item/weapon/door_remote/omni + name = "omni door remote" + desc = "This control wand can access any door on the station." + icon_state = "gangtool-yellow" + region_access = REGION_ALL + +/obj/item/weapon/door_remote/captain + name = "command door remote" + icon_state = "gangtool-yellow" + region_access = REGION_COMMAND + +/obj/item/weapon/door_remote/chief_engineer + name = "engineering door remote" + icon_state = "gangtool-orange" + region_access = REGION_ENGINEERING + +/obj/item/weapon/door_remote/research_director + name = "research door remote" + icon_state = "gangtool-purple" + region_access = REGION_RESEARCH + +/obj/item/weapon/door_remote/head_of_security + name = "security door remote" + icon_state = "gangtool-red" + region_access = REGION_SECURITY + +/obj/item/weapon/door_remote/quartermaster + name = "supply door remote" + icon_state = "gangtool-green" + region_access = REGION_SUPPLY + +/obj/item/weapon/door_remote/chief_medical_officer + name = "medical door remote" + icon_state = "gangtool-blue" + region_access = REGION_MEDBAY + +/obj/item/weapon/door_remote/civillian + name = "civillian door remote" + icon_state = "gangtool-white" + region_access = REGION_GENERAL + +#undef WAND_OPEN +#undef WAND_BOLT +#undef WAND_EMERGENCY \ No newline at end of file diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index d2fe7d2b319..ae8c888831d 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -288,8 +288,6 @@ var/global/list/default_medbay_channels = list( if(!M.IsVocal()) return 0 - M.last_target_click = world.time - /* Quick introduction: This new radio system uses a very robust FTL signaling technology unoriginally dubbed "subspace" which is somewhat similar to 'blue-space' but can't diff --git a/code/game/objects/items/weapons/cosmetics.dm b/code/game/objects/items/weapons/cosmetics.dm index 208b93c0c53..3e2448fa8fe 100644 --- a/code/game/objects/items/weapons/cosmetics.dm +++ b/code/game/objects/items/weapons/cosmetics.dm @@ -91,14 +91,15 @@ /obj/item/weapon/razor/attack(mob/living/carbon/M as mob, mob/user as mob) if(ishuman(M)) var/mob/living/carbon/human/H = M + var/obj/item/organ/external/head/C = H.organs_by_name["head"] + var/datum/robolimb/robohead = all_robolimbs[C.model] if(user.zone_sel.selecting == "mouth") if(!get_location_accessible(H, "mouth")) to_chat(user, "The mask is in the way.") return - if(H.species && H.species.flags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, but doesn't have one... - if(!H.client.prefs.rlimb_data["head"]) - to_chat(user, "You find yourself disappointed at the appalling lack of facial hair.") - return + if((H.species && H.species.flags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'... + to_chat(user, "You find yourself disappointed at the appalling lack of facial hair.") + return if(H.f_style == "Shaved") to_chat(user, "Already clean-shaven.") return @@ -127,10 +128,9 @@ if(!get_location_accessible(H, "head")) to_chat(user, "The headgear is in the way.") return - if(H.species && H.species.flags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, but doesn't have one... - if(!H.client.prefs.rlimb_data["head"]) - to_chat(user, "You find yourself disappointed at the appalling lack of hair.") - return + if((H.species && H.species.flags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'... + to_chat(user, "You find yourself disappointed at the appalling lack of hair.") + return if(H.h_style == "Bald" || H.h_style == "Balding Hair" || H.h_style == "Skinhead") to_chat(user, "There is not enough hair left to shave...") return diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm index ce6707bcdcb..2fc12e812fe 100644 --- a/code/game/objects/items/weapons/dna_injector.dm +++ b/code/game/objects/items/weapons/dna_injector.dm @@ -100,7 +100,7 @@ /obj/item/weapon/dnainjector/attack(mob/M as mob, mob/user as mob) if(used) - user << "This injector is used up!" + to_chat(user, "This injector is used up!") return if(!M.dna) //You know what would be nice? If the mob you're injecting has DNA, and so doesn't cause runtimes. return 0 @@ -151,7 +151,7 @@ "[user] injects [M] with the syringe with [src]!") else - user << "You inject yourself with [src]." + to_chat(user, "You inject yourself with [src].") inject(M, user) used = 1 diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm index afff3a01fd3..5444110aa30 100644 --- a/code/game/objects/items/weapons/explosives.dm +++ b/code/game/objects/items/weapons/explosives.dm @@ -30,19 +30,19 @@ if(user.mind) if(user.mind.special_role) var/role = lowertext(user.mind.special_role) - if(role == "traitor" || role == "syndicate" || role == "syndicate commando") + if(role == ROLE_TRAITOR || role == "syndicate" || role == "syndicate commando") message_say = "FOR THE SYNDICATE!" - else if(role == "changeling") + else if(role == ROLE_CHANGELING) message_say = "FOR THE HIVE!" - else if(role == "cultist") + else if(role == ROLE_CULTIST) message_say = "FOR NARSIE!" - else if(role == "ninja") + else if(role == ROLE_NINJA) message_say = "FOR THE CLAN!" - else if(role == "wizard") + else if(role == ROLE_WIZARD) message_say = "FOR THE FEDERATION!" - else if(role =="revolutionary" || role == "head revolutionary") + else if(role == ROLE_REV || role == "head revolutionary") message_say = "FOR THE REVOLOUTION!" - else if(role == "death commando" || role == "emergency response team") + else if(role == "death commando" || role == ROLE_ERT) message_say = "FOR NANOTRASEN!" user.say(message_say) diff --git a/code/game/objects/items/weapons/implants/implant_krav_maga.dm b/code/game/objects/items/weapons/implants/implant_krav_maga.dm new file mode 100644 index 00000000000..0a742a9f0a9 --- /dev/null +++ b/code/game/objects/items/weapons/implants/implant_krav_maga.dm @@ -0,0 +1,40 @@ +/obj/item/weapon/implant/krav_maga + name = "krav maga implant" + desc = "Teaches you the arts of Krav Maga in 5 short instructional videos beamed directly into your eyeballs." + icon = 'icons/obj/wizard.dmi' + icon_state ="scroll2" + activated = 1 + origin_tech = "materials=2;biotech=4;combat=5;syndicate=4" + var/datum/martial_art/krav_maga/style = new + +/obj/item/weapon/implant/krav_maga/get_data() + var/dat = {"Implant Specifications:
+ Name: Krav Maga Implant
+ Life: 4 hours after death of host
+ Implant Details:
+ Function: Teaches even the clumsiest host the arts of Krav Maga."} + return dat + +/obj/item/weapon/implant/krav_maga/activate() + var/mob/living/carbon/human/H = imp_in + if(!ishuman(H)) + return + if(istype(H.martial_art, /datum/martial_art/krav_maga)) + style.remove(H) + else + style.teach(H,1) + +/obj/item/weapon/implanter/krav_maga + name = "implanter (krav maga)" + +/obj/item/weapon/implanter/krav_maga/New() + imp = new /obj/item/weapon/implant/krav_maga(src) + ..() + +/obj/item/weapon/implantcase/krav_maga + name = "implant case - 'Krav Maga'" + desc = "A glass case containing an implant that can teach the user the art of Krav Maga." + +/obj/item/weapon/implantcase/krav_maga/New() + imp = new /obj/item/weapon/implant/krav_maga(src) + ..() \ No newline at end of file diff --git a/code/game/objects/items/weapons/power_cells.dm b/code/game/objects/items/weapons/power_cells.dm index d2598a4036f..62f60a91bc4 100644 --- a/code/game/objects/items/weapons/power_cells.dm +++ b/code/game/objects/items/weapons/power_cells.dm @@ -16,10 +16,18 @@ materials = list(MAT_METAL=700, MAT_GLASS=50) var/rigged = 0 // true if rigged to explode var/minor_fault = 0 //If not 100% reliable, it will build up faults. + var/chargerate = 1000 //how much power is given every tick in a recharger + var/self_recharge = 0 //does it self recharge, over time, or not? - suicide_act(mob/user) - to_chat(viewers(user), "[user] is licking the electrodes of the [src.name]! It looks like \he's trying to commit suicide.") - return (FIRELOSS) +/obj/item/weapon/stock_parts/cell/suicide_act(mob/user) + to_chat(viewers(user), "[user] is licking the electrodes of the [src.name]! It looks like \he's trying to commit suicide.") + return (FIRELOSS) + +/obj/item/weapon/stock_parts/cell/process() + if(self_recharge) + give(chargerate * 0.25) + else + return PROCESS_KILL /obj/item/weapon/stock_parts/cell/crap name = "\improper Nanotrasen brand rechargable AA battery" @@ -51,6 +59,7 @@ maxcharge = 15000 rating = 3 materials = list(MAT_GLASS=60) + chargerate = 1500 /obj/item/weapon/stock_parts/cell/high/empty/New() ..() @@ -63,6 +72,7 @@ maxcharge = 20000 materials = list(MAT_GLASS=70) rating = 4 + chargerate = 2000 /obj/item/weapon/stock_parts/cell/super/empty/New() ..() @@ -75,6 +85,7 @@ maxcharge = 30000 rating = 5 materials = list(MAT_GLASS=80) + chargerate = 3000 /obj/item/weapon/stock_parts/cell/hyper/empty/New() ..() @@ -87,6 +98,7 @@ maxcharge = 40000 materials = list(MAT_GLASS=80) rating = 6 + chargerate = 4000 /obj/item/weapon/stock_parts/cell/bluespace/empty/New() ..() @@ -99,8 +111,10 @@ maxcharge = 30000 rating = 6 materials = list(MAT_GLASS=80) - use() - return 1 + chargerate = 30000 + +/obj/item/weapon/stock_parts/cell/infinite/use() + return 1 /obj/item/weapon/stock_parts/cell/potato name = "potato battery" @@ -122,6 +136,7 @@ icon = 'icons/mob/slimes.dmi' icon_state = "yellow slime extract" materials = list() + self_recharge = 1 // Infused slime cores self-recharge, over time /obj/item/weapon/stock_parts/cell/pulse/carbine name = "pulse carbine power cell" diff --git a/code/game/objects/items/weapons/scissors.dm b/code/game/objects/items/weapons/scissors.dm index 34b700d440d..a5e0081e723 100644 --- a/code/game/objects/items/weapons/scissors.dm +++ b/code/game/objects/items/weapons/scissors.dm @@ -30,17 +30,26 @@ //this is largely copypasted from there. //handle facial hair (if necessary) var/list/species_facial_hair = list() + var/obj/item/organ/external/head/C = H.organs_by_name["head"] + var/datum/robolimb/robohead = all_robolimbs[C.model] if(H.gender == MALE || H.get_species() == "Vulpkanin") if(H.species) for(var/i in facial_hair_styles_list) var/datum/sprite_accessory/facial_hair/tmp_facial = facial_hair_styles_list[i] if(H.species.name in tmp_facial.species_allowed) //If the species is allowed to have the style, add the style to the list. Or, if the character has a prosthetic head, give them the human hair styles. + if(H.species.flags & ALL_RPARTS) //If the character is of a species that can have full body prosthetics and their head doesn't suport human hair 'wigs', don't add the style to the list. + if(robohead.is_monitor) + to_chat(user, "You are unable to find anything on [H]'s face worth cutting. How disappointing.") + return + continue //If the head DOES support human hair wigs, make sure they don't get monitor-oriented styles. species_facial_hair += i else - if(H.species.flags & ALL_RPARTS) - if(("head" in H.client.prefs.rlimb_data) && ("Human" in tmp_facial.species_allowed)) - species_facial_hair += i - else + if(H.species.flags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, and the head supports human hair 'wigs' AND the hair-style is human-suitable, add it to the list. + if(!robohead.is_monitor) + if("Human" in tmp_facial.species_allowed) + species_facial_hair += i + else //Otherwise, they won't be getting any hairstyles. + to_chat(user, "You are unable to find anything on [H]'s face worth cutting. How disappointing.") return else species_facial_hair = facial_hair_styles_list @@ -51,14 +60,19 @@ for(var/i in hair_styles_list) var/datum/sprite_accessory/hair/tmp_hair = hair_styles_list[i] if(H.species.name in tmp_hair.species_allowed) //If the species is allowed to have the style, add the style to the list. Or, if the character has a prosthetic head, give them the human facial hair styles. - if((H.species.flags & ALL_RPARTS) && !("head" in H.client.prefs.rlimb_data)) - return + if(H.species.flags & ALL_RPARTS) //If the character is of a species that can have full body prosthetics and their head doesn't suport human hair 'wigs', don't add the style to the list. + if(robohead.is_monitor) + to_chat(user, "You are unable to find anything on [H]'s head worth cutting. How disappointing.") + return + continue //If the head DOES support human hair wigs, make sure they don't get monitor-oriented styles. species_hair += i else - if(H.species.flags & ALL_RPARTS) - if(("head" in H.client.prefs.rlimb_data) && ("Human" in tmp_hair.species_allowed)) - species_facial_hair += i - else + if(H.species.flags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, and the head supports human hair 'wigs' AND the hair-style is human-suitable, add it to the list. + if(!robohead.is_monitor) + if("Human" in tmp_hair.species_allowed) + species_hair += i + else //Otherwise, they won't be getting any hairstyles. + to_chat(user, "You are unable to find anything on [H]'s head worth cutting. How disappointing.") return else species_hair = hair_styles_list @@ -103,7 +117,7 @@ playsound(loc, "sound/items/Wirecutter.ogg", 50, 1, -1) if(do_after(user, 50, target = H)) playsound(loc, "sound/weapons/bladeslice.ogg", 50, 1, -1) - user.visible_message("[user] abruptly stops cutting [M]'s hair and slices their throat!", "You stop cutting [M]'s hair and slice their throat!") + user.visible_message("[user] abruptly stops cutting [M]'s hair and slices their throat!", "You stop cutting [M]'s hair and slice their throat!") //Just a little off the top. H.losebreath += 10 //30 Oxy damage over time H.apply_damage(18, BRUTE, "head", sharp =1, edge =1, used_weapon = "scissors") var/turf/location = get_turf(H) diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index 57e22a3eef4..e20a3af837b 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -144,20 +144,19 @@ sharp = 1 edge = 1 w_class = 3 + hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - suicide_act(mob/user) - to_chat(viewers(user), "[user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.") - return(BRUTELOSS) +/obj/item/weapon/katana/cursed + slot_flags = null + +/obj/item/weapon/katana/suicide_act(mob/user) + user.visible_message("[user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.") + return(BRUTELOSS) /obj/item/weapon/katana/IsShield() return 1 -/obj/item/weapon/katana/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) - return ..() - - /obj/item/weapon/harpoon name = "harpoon" sharp = 1 diff --git a/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm b/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm index 945f4f4d818..51f01d874a8 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm @@ -39,4 +39,5 @@ new /obj/item/weapon/tank/emergency_oxygen(src) new /obj/item/clothing/mask/gas(src) new /obj/item/clothing/glasses/meson(src) - new /obj/item/clothing/head/soft(src) \ No newline at end of file + new /obj/item/clothing/head/soft(src) + new /obj/item/weapon/door_remote/quartermaster(src) \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm index d7fd20b6d37..1746211e248 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm @@ -31,6 +31,7 @@ new /obj/item/device/flash(src) new /obj/item/taperoll/engineering(src) new /obj/item/clothing/head/beret/eng(src) + new /obj/item/weapon/door_remote/chief_engineer(src) /obj/structure/closet/secure_closet/engineering_electrical name = "electrical supplies locker" diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm index ad76cfc9409..17f208e28e9 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm @@ -175,6 +175,7 @@ new /obj/item/device/flash(src) new /obj/item/weapon/reagent_containers/hypospray/CMO(src) new /obj/item/organ/internal/cyberimp/eyes/hud/medical(src) + new /obj/item/weapon/door_remote/chief_medical_officer(src) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm index 321b71b6eaa..488a422af86 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm @@ -49,6 +49,7 @@ new /obj/item/clothing/suit/armor/reactive(src) new /obj/item/device/flash(src) new /obj/item/device/laser_pointer(src) + new /obj/item/weapon/door_remote/research_director(src) /obj/structure/closet/secure_closet/research_reagents name = "research chemical storage closet" diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 05f077e64d1..4a2ced79339 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -26,6 +26,7 @@ new /obj/item/device/radio/headset/heads/captain/alt(src) new /obj/item/clothing/gloves/color/captain(src) new /obj/item/weapon/gun/energy/gun(src) + new /obj/item/weapon/door_remote/captain(src) @@ -52,6 +53,7 @@ new /obj/item/device/flash(src) new /obj/item/weapon/mining_voucher(src) new /obj/item/clothing/accessory/petcollar(src) + new /obj/item/weapon/door_remote/civillian(src) /obj/structure/closet/secure_closet/hop2 name = "head of personnel's attire" @@ -114,6 +116,7 @@ new /obj/item/weapon/storage/belt/security/sec(src) new /obj/item/taperoll/police(src) new /obj/item/weapon/gun/energy/hos(src) + new /obj/item/weapon/door_remote/head_of_security(src) diff --git a/code/game/objects/structures/fullwindow.dm b/code/game/objects/structures/fullwindow.dm index fda64fcb740..ac6e57a4135 100644 --- a/code/game/objects/structures/fullwindow.dm +++ b/code/game/objects/structures/fullwindow.dm @@ -89,12 +89,18 @@ health = 160 reinf = 1 - New() - ..() - color = null +/obj/structure/window/full/shuttle/New() + ..() + color = null - update_icon() //icon_state has to be set manually - return +/obj/structure/window/full/shuttle/update_icon() //icon_state has to be set manually + return + +/obj/structure/window/full/shuttle/shuttleRotate(rotation) + ..() + var/matrix/M = transform + M.Turn(rotation) + transform = M /obj/structure/window/full/shuttle/dark icon = 'icons/turf/shuttle.dmi' diff --git a/code/game/response_team.dm b/code/game/response_team.dm index 89e968c23b8..14bf44ff7b5 100644 --- a/code/game/response_team.dm +++ b/code/game/response_team.dm @@ -83,7 +83,7 @@ var/send_emergency_team to_chat(usr, "No emergency response team is currently being sent.") return - if(jobban_isbanned(usr, "Emergency Response Team")) + if(jobban_isbanned(usr, ROLE_ERT)) to_chat(usr, "You are jobbanned from the emergency reponse team!") return diff --git a/code/game/shuttle_engines.dm b/code/game/shuttle_engines.dm index f0d0544bd45..820103eb2d4 100644 --- a/code/game/shuttle_engines.dm +++ b/code/game/shuttle_engines.dm @@ -2,6 +2,12 @@ name = "shuttle" icon = 'icons/turf/shuttle.dmi' +/obj/structure/shuttle/shuttleRotate(rotation) + ..() + var/matrix/M = transform + M.Turn(rotation) + transform = M + /obj/structure/shuttle/window name = "shuttle window" icon = 'icons/obj/podwindows.dmi' diff --git a/code/game/turfs/simulated/shuttle.dm b/code/game/turfs/simulated/shuttle.dm index b8d22325d7a..a169d588dd2 100644 --- a/code/game/turfs/simulated/shuttle.dm +++ b/code/game/turfs/simulated/shuttle.dm @@ -36,7 +36,8 @@ T.transform = transform //why don't shuttle walls habe smoothwall? now i gotta do rotation the dirty way -/turf/simulated/shuttle/wall/shuttleRotate(rotation) +/turf/simulated/shuttle/shuttleRotate(rotation) + ..() var/matrix/M = transform M.Turn(rotation) transform = M diff --git a/code/game/turfs/unsimulated/beach.dm b/code/game/turfs/unsimulated/beach.dm index cc3b2fcedc7..89881767844 100644 --- a/code/game/turfs/unsimulated/beach.dm +++ b/code/game/turfs/unsimulated/beach.dm @@ -52,14 +52,26 @@ /turf/unsimulated/beach/water/drop, /turf/unsimulated/beach/water/drop/dense, /turf/unsimulated/beach/water, /turf/unsimulated/beach/water/dense, /turf/unsimulated/beach/water/edge_drop) + var/obj/effect/effect/beach_drop_overlay/water_overlay /turf/unsimulated/beach/water/drop/New() ..() - spawn(1) - overlays += image(icon, "[top_left_corner]-o", MOB_LAYER + 0.1) - overlays += image(icon, "[top_right_corner]-o", MOB_LAYER + 0.1) - overlays += image(icon, "[bottom_left_corner]-o", MOB_LAYER + 0.1) - overlays += image(icon, "[bottom_right_corner]-o", MOB_LAYER + 0.1) + water_overlay = new(src) + +/turf/unsimulated/beach/water/drop/Destroy() + qdel(water_overlay) + water_overlay = null + return ..() + +/obj/effect/effect/beach_drop_overlay + name = "Water" + icon = 'icons/turf/floors/seadrop-o.dmi' + layer = MOB_LAYER + 0.1 + smooth = SMOOTH_TRUE + canSmoothWith = list( + /turf/unsimulated/beach/water/drop, /turf/unsimulated/beach/water/drop/dense, + /turf/unsimulated/beach/water, /turf/unsimulated/beach/water/dense, + /turf/unsimulated/beach/water/edge_drop) /turf/unsimulated/beach/water/drop/dense density = 1 diff --git a/code/game/vehicles/spacepods/spacepod.dm b/code/game/vehicles/spacepods/spacepod.dm index 8ed498be025..bfa4cf1dd6a 100644 --- a/code/game/vehicles/spacepods/spacepod.dm +++ b/code/game/vehicles/spacepods/spacepod.dm @@ -883,7 +883,7 @@ /obj/effect/landmark/spacepod/random name = "spacepod spawner" invisibility = 101 - icon = 'icons/mob/screen1.dmi' + icon = 'icons/mob/screen_gen.dmi' icon_state = "x" anchored = 1 diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm index dbf88292f3a..1c5365a6b96 100644 --- a/code/modules/admin/DB ban/functions.dm +++ b/code/modules/admin/DB ban/functions.dm @@ -90,7 +90,7 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = a_ckey = src.owner:ckey a_computerid = src.owner:computer_id a_ip = src.owner:address - + if(blockselfban) if(a_ckey == ckey) to_chat(usr, "You cannot apply this ban type on yourself.") @@ -111,7 +111,7 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = adminwho += ", [C]" reason = sql_sanitize_text(reason) - + if(maxadminbancheck) var/DBQuery/adm_query = dbcon.NewQuery("SELECT count(id) AS num FROM [format_table_name("ban")] WHERE (a_ckey = '[a_ckey]') AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)") adm_query.Execute() @@ -362,11 +362,11 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) output += "" for(var/j in nonhuman_positions) output += "" - for(var/j in list("Dionaea","NPC","AntagHUD","Emergency Response Team")) + for(var/j in other_roles) output += "" for(var/j in list("commanddept","securitydept","engineeringdept","medicaldept","sciencedept","supportdept","nonhumandept")) output += "" - for(var/j in list("Syndicate","traitor","changeling","operative","revolutionary","cultist","wizard","alien","ninja","raider","mutineer","blob")) + for(var/j in list("Syndicate") + antag_roles) output += "" output += "" output += "Reason:

" diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index 2a4a3e9cdeb..766cee622a0 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -466,15 +466,6 @@ dat += "[mob_loc.loc]" else dat += "Head not found!" - if(ticker.mode.num_players_started() >= 30) - for(var/datum/mind/N in ticker.mode.get_extra_living_heads()) - var/mob/M = N.current - if(M) - dat += check_antagonists_line(M) - var/turf/mob_loc = get_turf(M) - dat += "[mob_loc.loc]" - else - dat += "Head not found!" dat += "" if(istype(ticker.mode, /datum/game_mode/blob)) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index f93e8c416bf..7fb6806b5c0 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -654,120 +654,37 @@ jobs += "" jobs += "" - //Traitor - if(jobban_isbanned(M, "traitor") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Changeling - if(jobban_isbanned(M, "changeling") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Nuclear Operative - if(jobban_isbanned(M, "operative") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Revolutionary - if(jobban_isbanned(M, "revolutionary") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Cultist - if(jobban_isbanned(M, "cultist") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Shadowling - if(jobban_isbanned(M, "shadowling") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Wizard - if(jobban_isbanned(M, "wizard") || isbanned_dept) - jobs += "" - else - jobs += "" - - jobs += "" //Breaking it up so it fits nicer on the screen every 5 entries - - //Malfunctioning AI - if(jobban_isbanned(M, "malf AI") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Alien - if(jobban_isbanned(M, "alien") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Ninja - if(jobban_isbanned(M, "ninja") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Raider - if(jobban_isbanned(M, "raider") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Mutineer - if(jobban_isbanned(M, "mutineer") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Blob - if(jobban_isbanned(M, "blob") || isbanned_dept) - jobs += "" - else - jobs += "" + counter = 0 + for(var/role in antag_roles) + if(jobban_isbanned(M, role) || isbanned_dept) + jobs += "" + else + jobs += "" + counter++ + if(counter >= 5) //So things dont get squiiiiished! + jobs += "" + counter = 0 jobs += "
Antagonist Positions
[replacetext("Traitor", " ", " ")][replacetext("Traitor", " ", " ")][replacetext("Changeling", " ", " ")][replacetext("Changeling", " ", " ")][replacetext("Nuclear Operative", " ", " ")][replacetext("Nuclear Operative", " ", " ")][replacetext("Revolutionary", " ", " ")][replacetext("Revolutionary", " ", " ")][replacetext("Cultist", " ", " ")][replacetext("Cultist", " ", " ")][replacetext("Shadowling", " ", " ")][replacetext("Shadowling", " ", " ")][replacetext("Wizard", " ", " ")][replacetext("Wizard", " ", " ")]
[replacetext("Malf AI", " ", " ")][replacetext("Malf AI", " ", " ")][replacetext("Alien", " ", " ")][replacetext("Alien", " ", " ")][replacetext("Ninja", " ", " ")][replacetext("Ninja", " ", " ")][replacetext("Raider", " ", " ")][replacetext("Raider", " ", " ")][replacetext("Mutineer", " ", " ")][replacetext("Mutineer", " ", " ")][replacetext("Blob", " ", " ")][replacetext("Blob", " ", " ")][replacetext(role, " ", " ")][replacetext(role, " ", " ")]
" - - //Other races (BLUE, because I have no idea what other color to make this) + //Other races (BLUE, because I have no idea what other color to make this) jobs += "" - jobs += "" + jobs += "" - //NYMPH - if(jobban_isbanned(M, "Dionaea")) - jobs += "" - else - jobs += "" - - //NPC - if(jobban_isbanned(M, "NPC")) - jobs += "" - else - jobs += "" - - //ANTAG HUD - if(jobban_isbanned(M, "AntagHUD")) - jobs += "" - else - jobs += "" - - //ERT - if(jobban_isbanned(M, "Emergency Response Team") || isbanned_dept) - jobs += "" - else - jobs += "" + counter = 0 + for(var/role in other_roles) + if(jobban_isbanned(M, role) || isbanned_dept) + jobs += "" + else + jobs += "" + counter++ + if(counter >= 5) //So things dont get squiiiiished! + jobs += "" + counter = 0 jobs += "
Other
Other
Dionaea NymphDionaea NymphNPCNPCAntagHUDAntagHUDEmergency Response TeamEmergency Response Team[replacetext(role, " ", " ")][replacetext(role, " ", " ")]
" - //Support (Grey) + //Whitelisted positions counter = 0 jobs += "" jobs += "" diff --git a/code/modules/admin/verbs/adminjump.dm b/code/modules/admin/verbs/adminjump.dm index 2194fb20bf3..5cbb8dd26d5 100644 --- a/code/modules/admin/verbs/adminjump.dm +++ b/code/modules/admin/verbs/adminjump.dm @@ -2,8 +2,8 @@ set name = "Jump to Area" set desc = "Area to jump to" set category = "Admin" - - if(!check_rights(R_ADMIN)) + + if(!check_rights(R_ADMIN)) return if(!A) @@ -21,7 +21,7 @@ if(!T) to_chat(src, "Nowhere to jump to!") return - + admin_forcemove(usr, T) log_admin("[key_name(usr)] jumped to [A]") message_admins("[key_name_admin(usr)] jumped to [A]") @@ -30,13 +30,13 @@ /client/proc/jumptoturf(var/turf/T in world) set name = "Jump to Turf" set category = "Admin" - - if(!check_rights(R_ADMIN)) + + if(!check_rights(R_ADMIN)) return log_admin("[key_name(usr)] jumped to [T.x], [T.y], [T.z] in [T.loc]") message_admins("[key_name_admin(usr)] jumped to [T.x], [T.y], [T.z] in [T.loc]", 1) - usr.loc = T + admin_forcemove(usr, T) feedback_add_details("admin_verb","JT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! return @@ -44,7 +44,7 @@ set category = "Admin" set name = "Jump to Mob" - if(!check_rights(R_ADMIN)) + if(!check_rights(R_ADMIN)) return log_admin("[key_name(usr)] jumped to [key_name(M)]") @@ -62,14 +62,12 @@ set category = "Admin" set name = "Jump to Coordinate" - if(!check_rights(R_ADMIN)) + if(!check_rights(R_ADMIN)) return - if(src.mob) - var/mob/A = src.mob - A.x = tx - A.y = ty - A.z = tz + var/turf/T = locate(tx, ty, tz) + if(T) + admin_forcemove(usr, T) feedback_add_details("admin_verb","JC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! message_admins("[key_name_admin(usr)] jumped to coordinates [tx], [ty], [tz]") @@ -77,7 +75,7 @@ set category = "Admin" set name = "Jump to Key" - if(!check_rights(R_ADMIN)) + if(!check_rights(R_ADMIN)) return var/list/keys = list() @@ -90,7 +88,7 @@ var/mob/M = selection:mob log_admin("[key_name(usr)] jumped to [key_name(M)]") message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]", 1) - + admin_forcemove(usr, M.loc) feedback_add_details("admin_verb","JK") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -99,8 +97,8 @@ set category = "Admin" set name = "Get Mob" set desc = "Mob to teleport" - - if(!check_rights(R_ADMIN)) + + if(!check_rights(R_ADMIN)) return log_admin("[key_name(usr)] teleported [key_name(M)]") @@ -113,7 +111,7 @@ set name = "Get Key" set desc = "Key to teleport" - if(!check_rights(R_ADMIN)) + if(!check_rights(R_ADMIN)) return var/list/keys = list() @@ -130,16 +128,16 @@ message_admins("[key_name_admin(usr)] teleported [key_name(M)]", 1) if(M) admin_forcemove(M, get_turf(usr)) - usr.loc = M.loc + admin_forcemove(usr, M.loc) feedback_add_details("admin_verb","GK") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/proc/sendmob(var/mob/M in mob_list) set category = "Admin" set name = "Send Mob" - - if(!check_rights(R_ADMIN)) + + if(!check_rights(R_ADMIN)) return - + var/area/A = input(usr, "Pick an area.", "Pick an area") in return_sorted_areas() if(A) admin_forcemove(M, pick(get_area_turfs(A))) @@ -148,7 +146,7 @@ message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)] to [A]", 1) /proc/admin_forcemove(mob/mover, atom/newloc) - mover.loc = newloc + mover.forceMove(newloc) mover.on_forcemove(newloc) /mob/proc/on_forcemove(atom/newloc) diff --git a/code/modules/admin/verbs/map_template_loadverb.dm b/code/modules/admin/verbs/map_template_loadverb.dm index 4a15552a789..fc010de8a43 100644 --- a/code/modules/admin/verbs/map_template_loadverb.dm +++ b/code/modules/admin/verbs/map_template_loadverb.dm @@ -36,7 +36,7 @@ if(!map) return if(copytext("[map]",-4) != ".dmm") - usr << "Bad map file: [map]" + to_chat(usr, "Bad map file: [map]") return var/datum/map_template/M = new(map=map, rename="[map]") diff --git a/code/modules/awaymissions/loot.dm b/code/modules/awaymissions/loot.dm index 3ae2da35068..49af9a43ce6 100644 --- a/code/modules/awaymissions/loot.dm +++ b/code/modules/awaymissions/loot.dm @@ -1,5 +1,5 @@ /obj/effect/spawner/away/lootdrop - icon = 'icons/mob/screen1.dmi' + icon = 'icons/mob/screen_gen.dmi' icon_state = "x2" var/lootcount = 1 //how many items will be spawned var/lootdoubles = 0 //if the same item can be spawned twice diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm index 33254cc7d2d..ac4a426fe08 100644 --- a/code/modules/client/asset_cache.dm +++ b/code/modules/client/asset_cache.dm @@ -204,6 +204,27 @@ proc/getFilesSlow(var/client/client, var/list/files, var/register_asset = TRUE) "ntlogo.png" = 'icons/paper_icons/ntlogo.png' ) +/datum/asset/simple/chess + assets = list( + "bishop_black.png" = 'icons/chess_pieces/bishop_black.png', + "bishop_white.png" = 'icons/chess_pieces/bishop_white.png', + "king_black.png" = 'icons/chess_pieces/king_black.png', + "king_white.png" = 'icons/chess_pieces/king_white.png', + "knight_black.png" = 'icons/chess_pieces/knight_black.png', + "knight_white.png" = 'icons/chess_pieces/knight_white.png', + "pawn_black.png" = 'icons/chess_pieces/pawn_black.png', + "pawn_white.png" = 'icons/chess_pieces/pawn_white.png', + "queen_black.png" = 'icons/chess_pieces/queen_black.png', + "queen_white.png" = 'icons/chess_pieces/queen_white.png', + "rook_black.png" = 'icons/chess_pieces/rook_black.png', + "rook_white.png" = 'icons/chess_pieces/rook_white.png', + "sprites.png" = 'icons/chess_pieces/sprites.png', + "blank.gif" = 'icons/chess_pieces/blank.gif', + "background.png" = 'nano/images/uiBackground.png', + "garbochess.js" = 'html/browser/garbochess.js', + "boardui.js" = 'html/browser/boardui.js' + ) + /datum/asset/nanoui var/list/common = list() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 6de86447e09..e53af9a5014 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -84,6 +84,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts var/nanoui_fancy = TRUE var/toggles = TOGGLES_DEFAULT var/sound = SOUND_DEFAULT + var/show_ghostitem_attack = TRUE var/UI_style_color = "#ffffff" var/UI_style_alpha = 255 @@ -397,6 +398,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts dat += "

General Settings

" dat += "UI Style:[UI_style]
" dat += "Fancy NanoUI:[(nanoui_fancy) ? "Yes" : "No"]
" + dat += "Ghost-Item Attack Animation:[(show_ghostitem_attack) ? "Yes" : "No"]
" dat += "Custom UI settings:
" dat += "Color:[UI_style_color]
Whitelisted Positions
__

" dat += "Alpha (transparency): [UI_style_alpha]
" @@ -1187,8 +1189,6 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if("hair") if(species == "Human" || species == "Unathi" || species == "Tajaran" || species == "Skrell" || species == "Machine" || species == "Vulpkanin") var/input = "Choose your character's hair colour:" - if(species == "Machine" && !("head" in rlimb_data)) - input = "Choose your character's frame colour:" var/new_hair = input(user, input, "Character Preference", rgb(r_hair, g_hair, b_hair)) as color|null if(new_hair) r_hair = hex2num(copytext(new_hair, 2, 4)) @@ -1200,18 +1200,25 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts for(var/hairstyle in hair_styles_list) var/datum/sprite_accessory/S = hair_styles_list[hairstyle] if(species == "Machine") //Species that can use prosthetic heads. - if(species in S.species_allowed) - if(!rlimb_data["head"]) - valid_hairstyles[hairstyle] = S - continue - else - continue + var/obj/item/organ/external/head/H = new() + if(S.name == "Bald") + valid_hairstyles[hairstyle] = S + if(!rlimb_data["head"]) //Handle situations where the head is default. + H.model = "Morpheus Cyberkinetics" else - if(!rlimb_data["head"]) + H.model = rlimb_data["head"] + var/datum/robolimb/robohead = all_robolimbs[H.model] + if(species in S.species_allowed) + if(robohead.is_monitor && (robohead.company in S.models_allowed)) //If the Machine character has the default Morpheus screen head or another screen head + //and said head is in the hair style's allowed models list... + valid_hairstyles[hairstyle] = S //Allow them to select the hairstyle. + continue + else + if(robohead.is_monitor) //Monitors (incl. the default morpheus head) cannot have wigs (human hairstyles). continue - else if("Human" in S.species_allowed) + else if(!robohead.is_monitor && ("Human" in S.species_allowed)) valid_hairstyles[hairstyle] = S - continue + continue else if(!(species in S.species_allowed)) continue @@ -1223,7 +1230,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts h_style = new_h_style if("headaccessory") - if(species in list("Unathi", "Vulpkanin", "Tajaran", "Machine")) // Species with head accessories + if(species in list("Unathi", "Vulpkanin", "Tajaran", "Machine")) //Species with head accessories. var/input = "Choose the colour of your your character's head accessory:" var/new_head_accessory = input(user, input, "Character Preference", rgb(r_headacc, g_headacc, b_headacc)) as color|null if(new_head_accessory) @@ -1232,7 +1239,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts b_headacc = hex2num(copytext(new_head_accessory, 6, 8)) if("ha_style") - if(species in list("Unathi", "Vulpkanin", "Tajaran", "Machine")) // Species with head accessories + if(species in list("Unathi", "Vulpkanin", "Tajaran", "Machine")) //Species with head accessories. var/list/valid_head_accessory_styles = list() for(var/head_accessory_style in head_accessory_styles_list) var/datum/sprite_accessory/H = head_accessory_styles_list[head_accessory_style] @@ -1246,7 +1253,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts ha_style = new_head_accessory_style if("markings") - if(species in list("Unathi", "Vulpkanin", "Tajaran", "Machine")) // Species with markings + if(species in list("Unathi", "Vulpkanin", "Tajaran", "Machine")) //Species with markings. var/input = "Choose the colour of your your character's markings:" var/new_markings = input(user, input, "Character Preference", rgb(r_markings, g_markings, b_markings)) as color|null if(new_markings) @@ -1255,7 +1262,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts b_markings = hex2num(copytext(new_markings, 6, 8)) if("m_style") - if(species in list("Unathi", "Vulpkanin", "Tajaran")) // Species with markings + if(species in list("Unathi", "Vulpkanin", "Tajaran", "Machine")) //Species with markings. var/list/valid_markings = list() for(var/markingstyle in marking_styles_list) var/datum/sprite_accessory/M = marking_styles_list[markingstyle] @@ -1263,10 +1270,17 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts continue if(species == "Machine") //Species that can use prosthetic heads. - if(!("head" in rlimb_data) && M.name != "None") //If the character can have prosthetic heads and they have the default head (with screen), no optic markings. - continue - else if(("head" in rlimb_data) && M.name == "None") //Otherwise, if they DON'T have the default head and since they must have optics, give them a list of styles excluding the "None" option. + var/obj/item/organ/external/head/H = new() + if(!rlimb_data["head"]) //Handle situations where the head is default. + H.model = "Morpheus Cyberkinetics" + else + H.model = rlimb_data["head"] + var/datum/robolimb/robohead = all_robolimbs[H.model] + if(robohead.is_monitor && M.name != "None") //If the character can have prosthetic heads and they have the default Morpheus head (or another monitor-head), no optic markings. continue + else if(!robohead.is_monitor && M.name != "None") //Otherwise, if they DON'T have the default head and the head's not a monitor but the head's not in the style's list of allowed models, skip. + if(!(robohead.company in M.models_allowed)) + continue valid_markings[markingstyle] = marking_styles_list[markingstyle] @@ -1302,25 +1316,29 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts var/list/valid_facialhairstyles = list() for(var/facialhairstyle in facial_hair_styles_list) var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle] + if(S.name == "Shaved") + valid_facialhairstyles[facialhairstyle] = S if(gender == MALE && S.gender == FEMALE) continue if(gender == FEMALE && S.gender == MALE) continue if(species == "Machine") //Species that can use prosthetic heads. - if(species in S.species_allowed) - if(!rlimb_data["head"]) - valid_facialhairstyles[facialhairstyle] = S - continue - else - continue + var/obj/item/organ/external/head/H = new() + if(!rlimb_data["head"]) //Handle situations where the head is default. + H.model = "Morpheus Cyberkinetics" else - if(!rlimb_data["head"]) - continue - else if("Human" in S.species_allowed) + H.model = rlimb_data["head"] + var/datum/robolimb/robohead = all_robolimbs[H.model] + if(species in S.species_allowed) + if(robohead.is_monitor) //If the Machine character has the default Morpheus screen head or another screen head and they're allowed to have the style, let them have it. valid_facialhairstyles[facialhairstyle] = S + continue + else + if(robohead.is_monitor) //Monitors (incl. the default morpheus head) cannot have wigs (human facial hairstyles). continue - else - continue + else if(!robohead.is_monitor && ("Human" in S.species_allowed)) + valid_facialhairstyles[facialhairstyle] = S + continue else if(!(species in S.species_allowed)) continue @@ -1491,18 +1509,51 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts organ_data[second_limb] = "amputated" rlimb_data[second_limb] = null if("Prosthesis") - var/choice = input(user, "Which manufacturer do you wish to use for this limb?") as null|anything in chargen_robolimbs + var/choice + var/subchoice + var/datum/robolimb/R = new() + var/in_model + var/robolimb_companies = list() + for(var/limb_type in typesof(/datum/robolimb)) //This loop populates a list of companies that offer the limb the user selected previously as one of their cybernetic products. + R = new limb_type() + if(!R.unavailable_at_chargen && (limb in R.parts) && R.has_subtypes) //Ensures users can only choose companies that offer the parts they want, that singular models get added to the list as well companies that offer more than one model, and... + robolimb_companies[R.company] = R //List only main brands that have the parts we're looking for. + R = new() //Re-initialize R. + + choice = input(user, "Which manufacturer do you wish to use for this limb?") as null|anything in robolimb_companies //Choose from a list of companies that offer the part the user wants. if(!choice) return + R.company = choice + R = all_robolimbs[R.company] + if(R.has_subtypes == 1) //If the company the user selected provides more than just one base model, lets handle it. + var/list/robolimb_models = list() + for(var/limb_type in typesof(R)) //Handling the different models of parts that manufacturers can provide. + var/datum/robolimb/L = new limb_type() + if(limb in L.parts) //Make sure that only models that provide the parts the user needs populate the list. + robolimb_models[L.company] = L + if(robolimb_models.len == 1) //If there's only one model available in the list, autoselect it to avoid having to bother the user with a dialog that provides only one option. + subchoice = L.company //If there ends up being more than one model populating the list, subchoice will be overwritten later anyway, so this isn't a problem. + if(second_limb in L.parts) //If the child limb of the limb the user selected is also present in the model's parts list, state it's been found so the second limb can be set later. + in_model = 1 + if(robolimb_models.len > 1) //If there's more than one model in the list that can provide the part the user wants, let them choose. + subchoice = input(user, "Which model of [choice] [limb_name] do you wish to use?") as null|anything in robolimb_models + if(subchoice) + choice = subchoice if(limb == "head") - m_style = "Humanoid Optics" ha_style = "None" h_style = hair_styles_list["Bald"] + f_style = facial_hair_styles_list["Shaved"] + m_style = "None" rlimb_data[limb] = choice organ_data[limb] = "cyborg" if(second_limb) - rlimb_data[second_limb] = choice - organ_data[second_limb] = "cyborg" + if(subchoice) + if(in_model) + rlimb_data[second_limb] = choice + organ_data[second_limb] = "cyborg" + else + rlimb_data[second_limb] = choice + organ_data[second_limb] = "cyborg" if("organs") var/organ_name = input(user, "Which internal function do you want to change?") as null|anything in list("Heart", "Eyes") @@ -1561,23 +1612,46 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if("ui") switch(UI_style) if("Midnight") + UI_style = "Plasmafire" + if("Plasmafire") + UI_style = "Retro" + if("Retro") + UI_style = "Slimecore" + if("Slimecore") + UI_style = "Operative" + if("Operative") UI_style = "White" else UI_style = "Midnight" + if(ishuman(usr)) //mid-round preference changes, for aesthetics + var/mob/living/carbon/human/H = usr + H.remake_hud() + if("nanoui") nanoui_fancy = !nanoui_fancy + if("ghost_att_anim") + show_ghostitem_attack = !show_ghostitem_attack + if("UIcolor") var/UI_style_color_new = input(user, "Choose your UI color, dark colors are not recommended!", UI_style_color) as color|null if(!UI_style_color_new) return UI_style_color = UI_style_color_new + if(ishuman(usr)) //mid-round preference changes, for aesthetics + var/mob/living/carbon/human/H = usr + H.remake_hud() + if("UIalpha") var/UI_style_alpha_new = input(user, "Select a new alpha(transparence) parameter for UI, between 50 and 255", UI_style_alpha) as num if(!UI_style_alpha_new | !(UI_style_alpha_new <= 255 && UI_style_alpha_new >= 50)) return UI_style_alpha = UI_style_alpha_new + if(ishuman(usr)) //mid-round preference changes, for aesthetics + var/mob/living/carbon/human/H = usr + H.remake_hud() + if("be_special") var/r = href_list["role"] if(!(r in special_roles)) @@ -1666,9 +1740,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts character.name = character.real_name character.flavor_text = flavor_text - character.med_record = med_record - character.sec_record = sec_record - character.gen_record = gen_record + if(character.ckey && !jobban_isbanned(character, "Records")) + character.med_record = med_record + character.sec_record = sec_record + character.gen_record = gen_record character.change_gender(gender) character.age = age diff --git a/code/modules/client/preferences_mysql.dm b/code/modules/client/preferences_mysql.dm index 9b873baec73..cb2e3116526 100644 --- a/code/modules/client/preferences_mysql.dm +++ b/code/modules/client/preferences_mysql.dm @@ -11,7 +11,8 @@ sound, randomslot, volume, - nanoui_fancy + nanoui_fancy, + show_ghostitem_attack FROM [format_table_name("player")] WHERE ckey='[C.ckey]'"} ) @@ -36,6 +37,7 @@ randomslot = text2num(query.item[9]) volume = text2num(query.item[10]) nanoui_fancy = text2num(query.item[11]) + show_ghostitem_attack = text2num(query.item[12]) //Sanitize ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor)) @@ -49,6 +51,7 @@ randomslot = sanitize_integer(randomslot, 0, 1, initial(randomslot)) volume = sanitize_integer(volume, 0, 100, initial(volume)) nanoui_fancy = sanitize_integer(nanoui_fancy, 0, 1, initial(nanoui_fancy)) + show_ghostitem_attack = sanitize_integer(show_ghostitem_attack, 0, 1, initial(show_ghostitem_attack)) return 1 /datum/preferences/proc/save_preferences(client/C) @@ -71,7 +74,8 @@ sound='[sound]', randomslot='[randomslot]', volume='[volume]', - nanoui_fancy='[nanoui_fancy]' + nanoui_fancy='[nanoui_fancy]', + show_ghostitem_attack='[show_ghostitem_attack]' WHERE ckey='[C.ckey]'"} ) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 9b53e95b586..04f0f3ed42d 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -119,7 +119,7 @@ /obj/item/clothing/ears/offear name = "Other ear" w_class = 5.0 - icon = 'icons/mob/screen1_Midnight.dmi' + icon = 'icons/mob/screen_gen.dmi' icon_state = "block" slot_flags = SLOT_EARS | SLOT_TWOEARS diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 0c8d127a596..1654198d9c9 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -446,3 +446,54 @@ icon_state = "cybereye-red" item_state = "eyepatch" flags = NODROP + +/obj/item/clothing/glasses/proc/chameleon(var/mob/user) + var/input_glasses = input(user, "Choose a piece of eyewear to disguise as.", "Choose glasses style.") as null|anything in list("Sunglasses", "Medical HUD", "Mesons", "Science Goggles", "Glasses", "Security Sunglasses","Eyepatch","Welding","Gar") + + if(user && src in user.contents) + switch(input_glasses) + if("Sunglasses") + desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes." + name = "sunglasses" + icon_state = "sun" + item_state = "sunglasses" + if("Medical HUD") + name = "Health Scanner HUD" + desc = "A heads-up display that scans the humans in view and provides accurate data about their health status." + icon_state = "healthhud" + item_state = "healthhud" + if("Mesons") + name = "Optical Meson Scanner" + desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting condition." + icon_state = "meson" + item_state = "meson" + if("Science Goggles") + name = "Science Goggles" + desc = "A pair of snazzy goggles used to protect against chemical spills." + icon_state = "purple" + item_state = "glasses" + if("Glasses") + name = "Prescription Glasses" + desc = "Made by Nerd. Co." + icon_state = "glasses" + item_state = "glasses" + if("Security Sunglasses") + name = "HUDSunglasses" + desc = "Sunglasses with a HUD." + icon_state = "sunhud" + item_state = "sunglasses" + if("Eyepatch") + name = "eyepatch" + desc = "Yarr." + icon_state = "eyepatch" + item_state = "eyepatch" + if("Welding") + name = "welding goggles" + desc = "Protects the eyes from welders; approved by the mad scientist association." + icon_state = "welding-g" + item_state = "welding-g" + if("Gar") + desc = "Just who the hell do you think I am?!" + name = "gar glasses" + icon_state = "gar" + item_state = "gar" \ No newline at end of file diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm index 7d57902d4fd..44138b8e907 100644 --- a/code/modules/clothing/glasses/hud.dm +++ b/code/modules/clothing/glasses/hud.dm @@ -68,6 +68,14 @@ flash_protect = 1 HUDType = DATA_HUD_SECURITY_ADVANCED +/obj/item/clothing/glasses/hud/security/chameleon + name = "Chamleon Security HUD" + desc = "A stolen security HUD integrated with Syndicate chameleon technology. Toggle to disguise the HUD. Provides flash protection." + flash_protect = 1 + +/obj/item/clothing/glasses/hud/security/chameleon/attack_self(mob/user) + chameleon(user) + /obj/item/clothing/glasses/hud/security/jensenshades name = "augmented shades" desc = "Polarized bioneural eyewear, designed to augment your vision." diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index 1e6ef08edf6..88af8bf4dd3 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -202,9 +202,14 @@ desc = "Woof!" icon_state = "corgihead" item_state = "chickensuit" + flags = BLOCKHAIR + +/obj/item/clothing/head/corgi/super_hero + name = "super-hero corgi suit head" + desc = "Woof! This one seems to pulse with a strange power" flags = BLOCKHAIR | NODROP -/obj/item/clothing/head/corgi/en +/obj/item/clothing/head/corgi/super_hero/en name = "E-N suit head" icon_state = "enhead" diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index 066c4893f73..6e3fcffa7cf 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -190,112 +190,217 @@ piece.flags &= ~(STOPSPRESSUREDMAGE|AIRTIGHT) update_icon(1) -/obj/item/weapon/rig/proc/toggle_seals(var/mob/living/carbon/human/M, var/mob/living/user, var/instant) - - if(sealing) return - - if(!check_power_cost(M, 1)) //costs tiny amount of power to unseal/seal +/obj/item/weapon/rig/proc/seal(mob/living/user) + if(sealing) return 0 - deploy(M, instant) + if(!wearer || !user) + return - var/seal_target = (flags & NODROP) - var/failed_to_seal + var/sealed = (flags & NODROP) + if(sealed) + to_chat(user, "\The [src] is already sealed!") + return 0 - flags |= NODROP // No removing the suit while unsealing. - sealing = 1 + if(!check_power_cost(user, 1)) //need power to seal the suit + return 0 - if(!seal_target && !suit_is_deployed()) - M.visible_message("[M]'s suit flashes an error light.","Your suit flashes an error light. It can't function properly without being fully deployed.") - failed_to_seal = 1 + var/failed_to_seal = FALSE + + if(!suit_is_deployed()) + to_chat(user, "\The [src] cannot seal, as it is not fully deployed!") + return 0 + + flags |= NODROP + sealing = TRUE + + to_chat(user, "\The [src] begins to tighten it's seals.") + wearer.visible_message("\The [wearer]'s suit emits a quiet hum as it begins to tighten it's seals.", + "With a quiet hum, your suit begins to seal.") + + if(seal_delay && !do_after(user, seal_delay, target = wearer)) + to_chat(user, "You must remain still to seal \the [src]!") + failed_to_seal = TRUE if(!failed_to_seal) + deploy(user) - if(!instant) - M.visible_message("[M]'s suit emits a quiet hum as it begins to adjust its seals.","With a quiet hum, the suit begins running checks and adjusting components.") - if(seal_delay && !do_after(user, seal_delay, target = M)) - if(user) - to_chat(user, "You must remain still while the suit is adjusting the components.") - failed_to_seal = 1 + var/list/pieces_data = list(list(wearer.shoes, boots, "boots", boot_type), + list(wearer.gloves, gloves, "gloves", glove_type), + list(wearer.head, helmet, "helmet", helm_type), + list(wearer.wear_suit, chest, "chest", chest_type)) - if(!M) - failed_to_seal = 1 - else - for(var/list/piece_data in list(list(M.shoes,boots,"boots",boot_type),list(M.gloves,gloves,"gloves",glove_type),list(M.head,helmet,"helmet",helm_type),list(M.wear_suit,chest,"chest",chest_type))) + for(var/list/piece_data in pieces_data) + var/obj/item/user_piece = piece_data[1] + var/obj/item/correct_piece = piece_data[2] + var/msg_type = piece_data[3] + var/piece_type = piece_data[4] - var/obj/item/piece = piece_data[1] - var/obj/item/compare_piece = piece_data[2] - var/msg_type = piece_data[3] - var/piece_type = piece_data[4] + if(!user_piece || !piece_type) + continue - if(!piece || !piece_type) - continue + if(user_piece != correct_piece) + to_chat(user, "\The [user_piece] is blocking \the [src] from deploying.") + failed_to_seal = TRUE - if(!istype(M) || !istype(piece) || !istype(compare_piece) || !msg_type) - if(M) - to_chat(M, "You must remain still while the suit is adjusting the components.") - failed_to_seal = 1 - break + if(seal_delay && !do_after(user, seal_delay, needhand = 0, target = wearer)) + to_chat(user, "You must remain still to seal \the [src]!") + failed_to_seal = TRUE - if(!failed_to_seal && M.back == src && piece == compare_piece) + if(failed_to_seal) + break - if(seal_delay && !instant && !do_after(user, seal_delay, needhand = 0, target = M)) - failed_to_seal = 1 + correct_piece.icon_state = "[initial(icon_state)]_sealed" + switch(msg_type) + if("boots") + to_chat(wearer, "\The [correct_piece] seal around your feet.") + if(user != wearer) + to_chat(user, "\The [correct_piece] has been sealed.") + wearer.update_inv_shoes() + if("gloves") + to_chat(wearer, "\The [correct_piece] tighten around your fingers and wrists.") + if(user != wearer) + to_chat(user, "\The [correct_piece] has been sealed.") + wearer.update_inv_gloves() + if("chest") + to_chat(wearer, "\The [correct_piece] cinches tight again your chest.") + if(user != wearer) + to_chat(user, "\The [correct_piece] has been sealed.") + wearer.update_inv_wear_suit() + if("helmet") + to_chat(wearer, "\The [correct_piece] hisses closed.") + if(user != wearer) + to_chat(user, "\The [correct_piece] has been sealed.") + wearer.update_inv_head() + if(helmet) + helmet.update_light(wearer) - piece.icon_state = "[initial(icon_state)][!seal_target ? "_sealed" : ""]" - switch(msg_type) - if("boots") - to_chat(M, "\The [piece] [!seal_target ? "seal around your feet" : "relax their grip on your legs"].") - M.update_inv_shoes() - if("gloves") - to_chat(M, "\The [piece] [!seal_target ? "tighten around your fingers and wrists" : "become loose around your fingers"].") - M.update_inv_gloves() - if("chest") - to_chat(M, "\The [piece] [!seal_target ? "cinches tight again your chest" : "releases your chest"].") - M.update_inv_wear_suit() - if("helmet") - to_chat(M, "\The [piece] hisses [!seal_target ? "closed" : "open"].") - M.update_inv_head() - if(helmet) - helmet.update_light(wearer) + correct_piece.armor["bio"] = 100 - //sealed pieces become airtight, protecting against diseases - if (!seal_target) - piece.armor["bio"] = 100 - else - piece.armor["bio"] = src.armor["bio"] - - else - failed_to_seal = 1 - - if((M && !(istype(M) && M.back == src) && !istype(M,/mob/living/silicon)) || (!seal_target && !suit_is_deployed())) - failed_to_seal = 1 - - sealing = null + sealing = FALSE if(failed_to_seal) - for(var/obj/item/piece in list(helmet,boots,gloves,chest)) - if(!piece) continue - piece.icon_state = "[initial(icon_state)][!seal_target ? "" : "_sealed"]" - if(seal_target) - flags |= NODROP - else - flags &= ~NODROP + for(var/obj/item/piece in list(helmet, boots, gloves, chest)) + if(!piece) + continue + piece.icon_state = "[initial(icon_state)]" + flags &= ~NODROP if(airtight) update_component_sealed() update_icon(1) return 0 - // Success! - if(seal_target) - flags &= ~NODROP - else - flags |= NODROP - to_chat(M, "Your entire suit [!(flags & NODROP) ? "loosens as the components relax" : "tightens around you as the components lock into place"].") + if(user != wearer) + to_chat(user, "\The [src] has been loosened.") + to_chat(wearer, "Your entire suit tightens around you as the components lock into place.") + if(airtight) + update_component_sealed() + update_icon(1) + +/obj/item/weapon/rig/proc/unseal(mob/living/user) + if(sealing) + return 0 + + if(!wearer || !user) + return + + var/sealed = (flags & NODROP) + if(!sealed) + to_chat(user, "\The [src] is already unsealed!") + return 0 + + sealing = TRUE + + var/failed_to_seal = FALSE + + if(!suit_is_deployed()) + to_chat(user, "\The [src] cannot unseal, as it is not fully deployed!") + failed_to_seal = TRUE + + if(!failed_to_seal) + if(user != wearer) + to_chat(user, "\The [src] begins to loosen it's seals.") + wearer.visible_message("\The [wearer]'s suit emits a quiet hum as it begins to loosen it's seals.", + "With a quiet hum, your suit begins to unseal.") + + if(seal_delay && !do_after(user, seal_delay, target = wearer)) + to_chat(user, "You must remain still to unseal \the [src]!") + failed_to_seal = TRUE + + if(!failed_to_seal) + var/list/pieces_data = list(list(wearer.shoes, boots, "boots", boot_type), + list(wearer.gloves, gloves, "gloves", glove_type), + list(wearer.head, helmet, "helmet", helm_type), + list(wearer.wear_suit, chest, "chest", chest_type)) + + for(var/list/piece_data in pieces_data) + var/obj/item/user_piece = piece_data[1] + var/obj/item/correct_piece = piece_data[2] + var/msg_type = piece_data[3] + var/piece_type = piece_data[4] + + if(!correct_piece || !piece_type) + continue + + if(user_piece != correct_piece) + to_chat(user, "\The [user_piece] is blocking \the [src] from deploying.") + failed_to_seal = TRUE + + if(seal_delay && !do_after(user, seal_delay, needhand = 0, target = wearer)) + to_chat(user, "You must remain still to unseal \the [src]!") + failed_to_seal = TRUE + + if(failed_to_seal) + break + + correct_piece.icon_state = "[initial(icon_state)]" + switch(msg_type) + if("boots") + to_chat(wearer, "\The [correct_piece] relax their grip on your legs.") + if(user != wearer) + to_chat(user, "\The [correct_piece] has been unsealed.") + wearer.update_inv_shoes() + if("gloves") + to_chat(wearer, "\The [correct_piece] become loose around your fingers.") + if(user != wearer) + to_chat(user, "\The [correct_piece] has been unsealed.") + wearer.update_inv_gloves() + if("chest") + to_chat(wearer, "\The [correct_piece] releases your chest.") + if(user != wearer) + to_chat(user, "\The [correct_piece] has been unsealed.") + wearer.update_inv_wear_suit() + if("helmet") + to_chat(wearer, "\The [correct_piece] hisses open.") + if(user != wearer) + to_chat(user, "\The [correct_piece] has been unsealed.") + wearer.update_inv_head() + if(helmet) + helmet.update_light(wearer) + + correct_piece.armor["bio"] = armor["bio"] + + sealing = FALSE + + if(failed_to_seal) + for(var/obj/item/piece in list(helmet, boots, gloves, chest)) + if(!piece) + continue + piece.icon_state = "[initial(icon_state)]_sealed" + if(airtight) + update_component_sealed() + update_icon(1) + return 0 + + if(user != wearer) + to_chat(user, "\The [src] has been unsealed.") + to_chat(wearer, "Your entire suit loosens as the components relax.") + + flags &= ~NODROP + + for(var/obj/item/rig_module/module in installed_modules) + module.deactivate() - if(!(flags & NODROP)) - for(var/obj/item/rig_module/module in installed_modules) - module.deactivate() if(airtight) update_component_sealed() update_icon(1) @@ -310,7 +415,6 @@ piece.flags |= AIRTIGHT /obj/item/weapon/rig/process() - // If we've lost any parts, grab them back. var/mob/living/M for(var/obj/item/piece in list(gloves,boots,helmet,chest)) @@ -367,7 +471,6 @@ cell.use(module.process()*10) /obj/item/weapon/rig/proc/check_power_cost(var/mob/living/user, var/cost, var/use_unconcious, var/obj/item/rig_module/mod, var/user_is_ai) - if(!istype(user)) return 0 @@ -524,7 +627,6 @@ return 1 -//TODO: Fix Topic vulnerabilities for malfunction and AI override. /obj/item/weapon/rig/Topic(href,href_list) if(!check_suit_access(usr)) return 0 @@ -532,11 +634,13 @@ if(href_list["toggle_piece"]) if(ishuman(usr) && (usr.stat || usr.stunned || usr.lying)) return 0 - toggle_piece(href_list["toggle_piece"], wearer, user = usr) + toggle_piece(href_list["toggle_piece"], usr) else if(href_list["toggle_seals"]) - toggle_seals(wearer, usr) + if(flags & NODROP) + unseal(usr) + else + seal(usr) else if(href_list["interact_module"]) - var/module_index = text2num(href_list["interact_module"]) if(module_index > 0 && module_index <= installed_modules.len) @@ -559,7 +663,7 @@ locked = !locked usr.set_machine(src) - src.add_fingerprint(usr) + add_fingerprint(usr) return 0 /obj/item/weapon/rig/proc/notify_ai(var/message) @@ -570,8 +674,11 @@ if(ai && ai.client && !ai.stat) to_chat(ai, "[message]") -/obj/item/weapon/rig/equipped(mob/living/carbon/human/M) +/obj/item/weapon/rig/equipped(mob/living/carbon/human/M, slot) ..() + if(!istype(M) || slot != slot_back) + return //we don't care about picking up/nonhumans + spawn(1) //equipped() is called BEFORE the item is actually set as the slot if(seal_delay > 0 && istype(M) && M.back == src) @@ -588,115 +695,108 @@ wearer.wearing_rig = src update_icon() -/obj/item/weapon/rig/proc/toggle_piece(var/piece, var/mob/living/carbon/human/H, var/deploy_mode, var/force, var/mob/living/user) +/obj/item/weapon/rig/proc/toggle_piece(var/piece, var/mob/living/user, var/deploy_mode, var/force) + if(!istype(wearer) || wearer.back != src) + if(force) //can only force retracting sorry + for(var/obj/item/uneq_piece in list(helmet, gloves, boots, chest)) + if(uneq_piece) + if(isliving(uneq_piece.loc)) + var/mob/living/L = uneq_piece.loc + L.unEquip(uneq_piece, 1) + uneq_piece.flags &= ~NODROP + uneq_piece.forceMove(src) + return 0 - if(!force) //forces the hardsuit to ignore most checks, as the suit being dropped should retract all pieces regardless of power status - if(sealing || !cell || !cell.charge) //or else you have issues with shit getting stuck - return + if(sealing || !cell || !cell.charge) + return 0 - if(!istype(wearer) || !wearer.back == src) - return - - if(usr == wearer && (usr.stat||usr.paralysis||usr.stunned)) // If the usr isn't wearing the suit it's probably an AI. - return + if(user == wearer && user.incapacitated()) // If the user isn't wearing the suit it's probably an AI. + return 0 var/obj/item/check_slot var/equip_to var/obj/item/use_obj - if(!H) - return - switch(piece) if("helmet") equip_to = slot_head use_obj = helmet - check_slot = H.head + check_slot = wearer.head if("gauntlets") equip_to = slot_gloves use_obj = gloves - check_slot = H.gloves + check_slot = wearer.gloves if("boots") equip_to = slot_shoes use_obj = boots - check_slot = H.shoes + check_slot = wearer.shoes if("chest") equip_to = slot_wear_suit use_obj = chest - check_slot = H.wear_suit + check_slot = wearer.wear_suit if(use_obj) - if(check_slot == use_obj && deploy_mode != ONLY_DEPLOY) - - var/mob/living/carbon/human/holder - - if(use_obj) - holder = use_obj.loc - if(istype(holder)) - if(use_obj && check_slot == use_obj) - to_chat(H, "Your [use_obj.name] [use_obj.gender == PLURAL ? "retract" : "retracts"] swiftly.") - use_obj.flags &= ~NODROP - holder.unEquip(use_obj, 1) - use_obj.forceMove(src) - - else if (deploy_mode != ONLY_RETRACT) - if(check_slot) - if(check_slot != use_obj) - to_chat(H, "You are unable to deploy \the [piece] as \the [check_slot] [check_slot.gender == PLURAL ? "are" : "is"] in the way.") + if(check_slot == use_obj && deploy_mode != ONLY_DEPLOY) //user is wearing it, retract it if not forced to deploy + if((flags & NODROP) && equip_to != slot_head && !force) //you can only retract the helmet if the suit isn't unsealed + to_chat(user, "You can't retract \the [use_obj] while the suit is sealed!") return + + var/mob/living/to_strip + if(wearer) + to_strip = wearer + else if(isliving(use_obj.loc)) + to_strip = use_obj.loc + + if(to_strip) + to_strip.unEquip(use_obj, 1) + + use_obj.flags &= ~NODROP + use_obj.forceMove(src) + if(wearer) + to_chat(wearer, "Your [use_obj] [use_obj.gender == PLURAL ? "retract" : "retracts"] swiftly.") + + else if(deploy_mode != ONLY_RETRACT) + if(check_slot && check_slot != use_obj) + to_chat(wearer, "You are unable to deploy \the [piece] as \the [check_slot] [check_slot.gender == PLURAL ? "are" : "is"] in the way.") + return + use_obj.forceMove(wearer) + use_obj.flags &= ~NODROP + if(!wearer.equip_to_slot_if_possible(use_obj, equip_to, 0, 1)) + use_obj.forceMove(src) else - use_obj.forceMove(H) - use_obj.flags &= ~NODROP - if(!H.equip_to_slot_if_possible(use_obj, equip_to, 0, 1)) - use_obj.forceMove(src) - else - to_chat(H, "Your [use_obj.name] [use_obj.gender == PLURAL ? "deploy" : "deploys"] swiftly.") - use_obj.flags |= NODROP + if(wearer) + to_chat(wearer, "Your [use_obj.name] [use_obj.gender == PLURAL ? "deploy" : "deploys"] swiftly.") + use_obj.flags |= NODROP if(piece == "helmet" && helmet) - helmet.update_light(H) + helmet.update_light(wearer) -/obj/item/weapon/rig/proc/deploy(mob/M,var/sealed, mob/user) +/obj/item/weapon/rig/proc/deploy(mob/user) + if(!wearer || !user) + return 0 - var/mob/living/carbon/human/H = M + if(flags & NODROP) + if(wearer.head && wearer.head != helmet) + to_chat(user, "\The [wearer.head] is blocking \the [src] from deploying!") + return 0 + if(wearer.gloves && wearer.gloves != gloves) + to_chat(user, "\The [wearer.gloves] is preventing \the [src] from deploying!") + return 0 + if(wearer.shoes && wearer.shoes != boots) + to_chat(user, "\The [wearer.shoes] is preventing \the [src] from deploying!") + return 0 + if(wearer.wear_suit && wearer.wear_suit != chest) + to_chat(user, "\The [wearer.wear_suit] is preventing \the [src] from deploying!") + return 0 - if(!H || !istype(H)) return - if(H.back != src) - return - - if(sealed) - if(H.head) - var/obj/item/garbage = H.head - H.unEquip(garbage) - H.head = null - qdel(garbage) - - if(H.gloves) - var/obj/item/garbage = H.gloves - H.unEquip(garbage) - H.gloves = null - qdel(garbage) - - if(H.shoes) - var/obj/item/garbage = H.shoes - H.unEquip(garbage) - H.shoes = null - qdel(garbage) - - if(H.wear_suit) - var/obj/item/garbage = H.wear_suit - H.unEquip(garbage) - H.wear_suit = null - qdel(garbage) - - for(var/piece in list("helmet","gauntlets","chest","boots")) - toggle_piece(piece, wearer, ONLY_DEPLOY, user = user) + for(var/piece in list("helmet", "gauntlets", "chest", "boots")) + toggle_piece(piece, user, ONLY_DEPLOY) /obj/item/weapon/rig/dropped(var/mob/user) ..() for(var/piece in list("helmet","gauntlets","chest","boots")) - toggle_piece(piece, wearer, ONLY_RETRACT, 1, user = user) + toggle_piece(piece, user, ONLY_RETRACT, 1) if(wearer) wearer.wearing_rig = null wearer = null @@ -871,7 +971,6 @@ return 0 // AIs are a bit slower than regular and ignore move intent. - wearer.last_move_intent = world.time + ai_controlled_move_delay wearer_move_delay = world.time + ai_controlled_move_delay var/tickcomp = 0 diff --git a/code/modules/clothing/spacesuits/rig/rig_verbs.dm b/code/modules/clothing/spacesuits/rig/rig_verbs.dm index f4769eddf0b..5214ea919f6 100644 --- a/code/modules/clothing/spacesuits/rig/rig_verbs.dm +++ b/code/modules/clothing/spacesuits/rig/rig_verbs.dm @@ -1,6 +1,5 @@ // Interface for humans. /obj/item/weapon/rig/verb/hardsuit_interface() - set name = "Open Hardsuit Interface" set desc = "Open the hardsuit system interface." set category = "Hardsuit" @@ -10,7 +9,6 @@ ui_interact(usr) /obj/item/weapon/rig/verb/toggle_vision() - set name = "Toggle Visor" set desc = "Turns your rig visor off or on." set category = "Hardsuit" @@ -44,7 +42,6 @@ visor.deactivate() /obj/item/weapon/rig/proc/toggle_helmet() - set name = "Toggle Helmet" set desc = "Deploys or retracts your helmet." set category = "Hardsuit" @@ -61,10 +58,9 @@ if(M.incapacitated()) return - toggle_piece("helmet",wearer, user = usr) + toggle_piece("helmet", usr) /obj/item/weapon/rig/proc/toggle_chest() - set name = "Toggle Chestpiece" set desc = "Deploys or retracts your chestpiece." set category = "Hardsuit" @@ -77,10 +73,9 @@ if(M.incapacitated()) return - toggle_piece("chest",wearer, user = usr) + toggle_piece("chest", usr) /obj/item/weapon/rig/proc/toggle_gauntlets() - set name = "Toggle Gauntlets" set desc = "Deploys or retracts your gauntlets." set category = "Hardsuit" @@ -97,10 +92,9 @@ if(M.incapacitated()) return - toggle_piece("gauntlets",wearer, user = usr) + toggle_piece("gauntlets", usr) /obj/item/weapon/rig/proc/toggle_boots() - set name = "Toggle Boots" set desc = "Deploys or retracts your boots." set category = "Hardsuit" @@ -117,10 +111,9 @@ if(M.incapacitated()) return - toggle_piece("boots",wearer, user = usr) + toggle_piece("boots", usr) /obj/item/weapon/rig/verb/deploy_suit() - set name = "Deploy Hardsuit" set desc = "Deploys helmet, gloves and boots." set category = "Hardsuit" @@ -143,7 +136,6 @@ deploy(wearer, usr) /obj/item/weapon/rig/verb/toggle_seals_verb() - set name = "Toggle Hardsuit" set desc = "Activates or deactivates your rig." set category = "Hardsuit" @@ -160,10 +152,12 @@ if(M.incapacitated()) return - toggle_seals(wearer) + if(flags & NODROP) + unseal(usr) + else + seal(usr) /obj/item/weapon/rig/verb/switch_vision_mode() - set name = "Switch Vision Mode" set desc = "Switches between available vision modes." set category = "Hardsuit" @@ -197,7 +191,6 @@ visor.engage() /obj/item/weapon/rig/verb/alter_voice() - set name = "Configure Voice Synthesiser" set desc = "Toggles or configures your voice synthesizer." set category = "Hardsuit" @@ -225,7 +218,6 @@ speech.engage() /obj/item/weapon/rig/verb/select_module() - set name = "Select Module" set desc = "Selects a module as your primary system." set category = "Hardsuit" @@ -265,7 +257,6 @@ to_chat(usr, "Primary system is now: [selected_module.interface_name].") /obj/item/weapon/rig/verb/toggle_module() - set name = "Toggle Module" set desc = "Toggle a system module." set category = "Hardsuit" @@ -307,7 +298,6 @@ module.activate() /obj/item/weapon/rig/verb/engage_module() - set name = "Engage Module" set desc = "Engages a system module." set category = "Hardsuit" diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index c8b62d446be..5abc5e86cbf 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -152,17 +152,25 @@ item_state = "chickensuit" body_parts_covered = UPPER_TORSO|ARMS|LOWER_TORSO|LEGS|FEET flags_inv = HIDESHOES|HIDEJUMPSUIT + +/obj/item/clothing/suit/corgisuit/super_hero + name = "super-hero corgi suit" + desc = "A suit made long ago by the ancient empire KFC. This one pulses with a strange power." flags = NODROP -/obj/item/clothing/suit/corgisuit/en - name = "\improper E-N suit" +/obj/item/clothing/suit/corgisuit/super_hero/en + name = "\improper super-hero E-N suit" icon_state = "ensuit" -/obj/item/clothing/suit/corgisuit/en/New() +/obj/item/clothing/suit/corgisuit/super_hero/en/New() ..() processing_objects.Add(src) -/obj/item/clothing/suit/corgisuit/en/process() +/obj/item/clothing/suit/corgisuit/super_hero/en/Destroy() + processing_objects.Remove(src) + return ..() + +/obj/item/clothing/suit/corgisuit/super_hero/en/process() if(prob(2)) for(var/obj/M in orange(2,src)) if(!M.anchored && (M.flags & CONDUCT)) diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm index 23c15a258d7..b6dc4eee727 100644 --- a/code/modules/hydroponics/grown.dm +++ b/code/modules/hydroponics/grown.dm @@ -293,7 +293,7 @@ /obj/item/weapon/reagent_containers/food/snacks/grown/attack(var/mob/living/carbon/M, var/mob/user, var/def_zone) if(awakening) - user << "The [src] is twitching and shaking, preventing you from eating it." + to_chat(user, "The [src] is twitching and shaking, preventing you from eating it.") return if(user == M) return ..() @@ -334,8 +334,7 @@ var/turf/simulated/location = get_turf(M) if(istype(location)) location.add_blood_floor(M) if("fire") - if (!(RESIST_COLD in M.mutations)) - M.take_organ_damage(0, force) + M.take_organ_damage(0, force) M.updatehealth() if(seed && seed.get_trait(TRAIT_CARNIVOROUS)) @@ -452,7 +451,7 @@ if("killertomato") if(awakening || istype(user.loc,/turf/space)) return - user << "You begin to awaken the Killer Tomato..." + to_chat(user, "You begin to awaken the Killer Tomato...") awakening = 1 spawn(30) diff --git a/code/modules/hydroponics/seed_packets.dm b/code/modules/hydroponics/seed_packets.dm index dee87d848d3..2649b04c3e4 100644 --- a/code/modules/hydroponics/seed_packets.dm +++ b/code/modules/hydroponics/seed_packets.dm @@ -307,3 +307,6 @@ var/global/list/plant_seed_sprites = list() /obj/item/seeds/coffeerseed seed_type = "coffeer" + +/obj/item/seeds/cash + seed_type = "cashtree" \ No newline at end of file diff --git a/code/modules/martial_arts/adminfu.dm b/code/modules/martial_arts/adminfu.dm new file mode 100644 index 00000000000..6f8df44f53f --- /dev/null +++ b/code/modules/martial_arts/adminfu.dm @@ -0,0 +1,117 @@ +///Adminfu +//Help act:Heal/revie GP //p is for help +//Disarm:Stun +//Grab:Neck +//Harm:Gib +#define HEAL_COMBO "GP" + +/datum/martial_art/adminfu + name = "Way of the Dancing Admin" + help_verb = /mob/living/carbon/human/proc/adminfu_help + +/datum/martial_art/adminfu/proc/check_streak(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + if(findtext(streak,HEAL_COMBO)) + streak = "" + healPalm(A,D) + return 1 + return 0 + +/datum/martial_art/adminfu/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + + if(!D.stat)//do not kill what is dead... + A.do_attack_animation(D) + D.visible_message("[A] manifests a large glowing toolbox and shoves it in [D]'s chest!", \ + "[A] shoves a mystical toolbox in your chest!") + D.death() + + return 1 + + +/datum/martial_art/adminfu/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + A.do_attack_animation(D) + D.Weaken(25) + D.Stun(25) + return 1 + +/datum/martial_art/adminfu/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + add_to_streak("G",D) + if(check_streak(A,D)) + return 1 + D.grabbedby(A,1) + var/obj/item/weapon/grab/G = A.get_active_hand() + if(G) + G.state = GRAB_NECK + +/datum/martial_art/adminfu/help_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + add_to_streak("P",D) + if(check_streak(A,D)) + return 1 + +/datum/martial_art/adminfu/proc/healPalm(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + A.do_attack_animation(D) + D.visible_message("[A] smacks [D] in the forehead!") + + //its the staff of healing code..hush + if(istype(D,/mob)) + var/old_stat = D.stat + if(isanimal(D) && D.stat == DEAD) + var/mob/living/simple_animal/O = D + var/mob/living/simple_animal/P = new O.type(O.loc) + P.real_name = O.real_name + P.name = O.name + if(iscorgi(O)) + var/mob/living/simple_animal/pet/corgi/C = O + if(C.inventory_head) + C.inventory_head.loc = C.loc + if(C.inventory_back) + C.inventory_back.loc = C.loc + if(O.mind) + O.mind.transfer_to(P) + else + P.key = O.key + qdel(O) + D = P + else + D.revive() + D.suiciding = 0 + if(!D.ckey) + for(var/mob/dead/observer/ghost in player_list) + if(D.real_name == ghost.real_name) + ghost.reenter_corpse() + break + if(old_stat != DEAD) + to_chat(D, "You feel great!") + else + to_chat(D, "You rise with a start, you're alive!!!") + return 1 + +/mob/living/carbon/human/proc/adminfu_help() + set name = "Recall Teachings" + set desc = "Remember the way of the dancing admin." + set category = "Adminfu" + + to_chat(usr, "Grab: Automatic Neck Grab.") + to_chat(usr, "Disarm: Stun/weaken") + to_chat(usr, "Harm: Death.") + to_chat(usr, "Healing Palm::Combo:Grab,Help intent. Heals or revives a crature.") + + +/obj/item/weapon/adminfu_scroll + name = "frayed scroll" + desc = "An aged and frayed scrap of paper written in shifting runes. There are hand-drawn illustrations of pugilism." + icon = 'icons/obj/wizard.dmi' + icon_state ="scroll2" + var/used = 0 + +/obj/item/weapon/adminfu_scroll/attack_self(mob/user as mob) + if(!ishuman(user)) + return + if(!used) + var/mob/living/carbon/human/H = user + var/datum/martial_art/adminfu/F = new/datum/martial_art/adminfu(null) + F.teach(H) + to_chat(H, "You have learned the ancient martial art of the Admins.") + used = 1 + desc = "It's completely blank." + name = "empty scroll" + icon_state = "blankscroll" diff --git a/code/modules/martial_arts/brawling.dm b/code/modules/martial_arts/brawling.dm new file mode 100644 index 00000000000..06bd174a0e2 --- /dev/null +++ b/code/modules/martial_arts/brawling.dm @@ -0,0 +1,106 @@ +/datum/martial_art/boxing + name = "Boxing" + +/datum/martial_art/boxing/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + to_chat(A, "Can't disarm while boxing!") + return 1 + +/datum/martial_art/boxing/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + to_chat(A, "Can't grab while boxing!") + return 1 + +/datum/martial_art/boxing/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + + A.do_attack_animation(D) + + var/atk_verb = pick("left hook","right hook","straight punch") + + var/damage = rand(5, 8) + A.species.punchdamagelow + if(!damage) + playsound(D.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + D.visible_message("[A] has attempted to hit [D] with a [atk_verb]!") + add_logs(D, A, "attempted to hit", atk_verb) + return 0 + + + var/obj/item/organ/external/affecting = D.get_organ(ran_zone(A.zone_sel.selecting)) + var/armor_block = D.run_armor_check(affecting, "melee") + + playsound(D.loc, 'sound/weapons/punch1.ogg', 25, 1, -1) + + D.visible_message("[A] has hit [D] with a [atk_verb]!", \ + "[A] has hit [D] with a [atk_verb]!") + + D.apply_damage(damage, STAMINA, affecting, armor_block) + add_logs(D, A, "punched") + if(D.getStaminaLoss() > 50) + var/knockout_prob = D.getStaminaLoss() + rand(-15,15) + if((D.stat != DEAD) && prob(knockout_prob)) + D.visible_message("[A] has knocked [D] out with a haymaker!", \ + "[A] has knocked [D] out with a haymaker!") + D.apply_effect(10,WEAKEN,armor_block) + D.SetSleeping(5) + D.forcesay(hit_appends) + else if(D.lying) + D.forcesay(hit_appends) + return 1 + +/datum/martial_art/drunk_brawling + name = "Drunken Brawling" + +/datum/martial_art/drunk_brawling/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + if(prob(70)) + A.visible_message("[A] tries to grab ahold of [D], but fails!", \ + "You fail to grab ahold of [D]!") + return 1 + D.grabbedby(A,1) + var/obj/item/weapon/grab/G = A.get_active_hand() + if(G) + D.visible_message("[A] grabs ahold of [D] drunkenly!", \ + "[A] grabs ahold of [D] drunkenly!") + return 1 + +/datum/martial_art/drunk_brawling/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + add_logs(D, A, "punched") + A.do_attack_animation(D) + + var/atk_verb = pick("jab","uppercut","overhand punch","drunken right hook","drunken left hook") + + var/damage = rand(0,6) + + if(atk_verb == "uppercut") + if(prob(90)) + damage = 0 + else //10% chance to do a massive amount of damage + damage = 14 + + if(prob(50)) //they are drunk, they aren't going to land half of their hits + damage = 0 + + if(!damage) + playsound(D.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + D.visible_message("[A] has attempted to hit [D] with a [atk_verb]!") + return 1 //returns 1 so that they actually miss and don't switch to attackhand damage + + var/obj/item/organ/external/affecting = D.get_organ(ran_zone(A.zone_sel.selecting)) + var/armor_block = D.run_armor_check(affecting, "melee") + + playsound(D.loc, 'sound/weapons/punch1.ogg', 25, 1, -1) + + + D.visible_message("[A] has hit [D] with a [atk_verb]!", \ + "[A] has hit [D] with a [atk_verb]!") + + D.apply_damage(damage, BRUTE, null, armor_block) + D.apply_effect(damage, STAMINA, armor_block) + if(D.getStaminaLoss() > 50) + var/knockout_prob = D.getStaminaLoss() + rand(-15,15) + if((D.stat != DEAD) && prob(knockout_prob)) + D.visible_message("[A] has knocked [D] out with a haymaker!", \ + "[A] has knocked [D] out with a haymaker!") + D.apply_effect(10,WEAKEN,armor_block) + D.Paralyse(5) + D.forcesay(hit_appends) + else if(D.lying) + D.forcesay(hit_appends) + return 1 \ No newline at end of file diff --git a/code/modules/martial_arts/krav_maga.dm b/code/modules/martial_arts/krav_maga.dm new file mode 100644 index 00000000000..9b589878475 --- /dev/null +++ b/code/modules/martial_arts/krav_maga.dm @@ -0,0 +1,173 @@ +/datum/martial_art/krav_maga + name = "Krav Maga" + var/datum/action/neck_chop/neckchop = new/datum/action/neck_chop() + var/datum/action/leg_sweep/legsweep = new/datum/action/leg_sweep() + var/datum/action/lung_punch/lungpunch = new/datum/action/lung_punch() + +/datum/action/neck_chop + name = "Neck Chop - Injures the neck, stopping the victim from speaking for a while." + button_icon_state = "neckchop" + +/datum/action/neck_chop/Trigger() + if(owner.incapacitated()) + to_chat(owner, "You can't use Krav Maga while you're incapacitated.") + return + to_chat(owner, "Your next attack will be a Neck Chop.") + owner.visible_message("[owner] assumes the Neck Chop stance!") + var/mob/living/carbon/human/H = owner + H.martial_art.streak = "neck_chop" + +/datum/action/leg_sweep + name = "Leg Sweep - Trips the victim, rendering them prone and unable to move for a short time." + button_icon_state = "legsweep" + +/datum/action/leg_sweep/Trigger() + if(owner.incapacitated()) + to_chat(owner, "You can't use Krav Maga while you're incapacitated.") + return + to_chat(owner, "Your next attack will be a Leg Sweep.") + owner.visible_message("[owner] assumes the Leg Sweep stance!") + var/mob/living/carbon/human/H = owner + H.martial_art.streak = "leg_sweep" + +/datum/action/lung_punch//referred to internally as 'quick choke' + name = "Lung Punch - Delivers a strong punch just above the victim's abdomen, constraining the lungs. The victim will be unable to breathe for a short time." + button_icon_state = "lungpunch" + +/datum/action/lung_punch/Trigger() + if(owner.incapacitated()) + to_chat(owner, "You can't use Krav Maga while you're incapacitated.") + return + to_chat(owner, "Your next attack will be a Lung Punch.") + owner.visible_message("[owner] assumes the Lung Punch stance!") + var/mob/living/carbon/human/H = owner + H.martial_art.streak = "quick_choke"//internal name for lung punch + +/datum/martial_art/krav_maga/teach(var/mob/living/carbon/human/H,var/make_temporary=0) + ..() + to_chat(H, "You know the arts of Krav Maga!") + to_chat(H, "Place your cursor over a move at the top of the screen to see what it does.") + neckchop.Grant(H) + legsweep.Grant(H) + lungpunch.Grant(H) + +/datum/martial_art/krav_maga/remove(var/mob/living/carbon/human/H) + ..() + to_chat(H, "You suddenly forget the arts of Krav Maga...") + neckchop.Remove(H) + legsweep.Remove(H) + lungpunch.Remove(H) + +/datum/martial_art/krav_maga/proc/check_streak(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + switch(streak) + if("neck_chop") + streak = "" + neck_chop(A,D) + return 1 + if("leg_sweep") + streak = "" + leg_sweep(A,D) + return 1 + if("quick_choke")//is actually lung punch + streak = "" + quick_choke(A,D) + return 1 + return 0 + +/datum/martial_art/krav_maga/proc/leg_sweep(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + if(D.stat || D.weakened) + return 0 + D.visible_message("[A] leg sweeps [D]!", \ + "[A] leg sweeps you!") + playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1) + D.apply_damage(5, BRUTE) + D.Weaken(2) + return 1 + +/datum/martial_art/krav_maga/proc/quick_choke(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)//is actually lung punch + D.visible_message("[A] pounds [D] on the chest!", \ + "[A] slams your chest! You can't breathe!") + playsound(get_turf(A), 'sound/effects/hit_punch.ogg', 50, 1, -1) + D.losebreath += 5 + D.adjustOxyLoss(10) + return 1 + +/datum/martial_art/krav_maga/proc/neck_chop(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + D.visible_message("[A] karate chops [D]'s neck!", \ + "[A] karate chops your neck, rendering you unable to speak for a short time!") + playsound(get_turf(A), 'sound/effects/hit_punch.ogg', 50, 1, -1) + D.apply_damage(5, BRUTE) + D.silent += 10 + return 1 + +datum/martial_art/krav_maga/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + if(check_streak(A,D)) + return 1 + ..() + +/datum/martial_art/krav_maga/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + if(check_streak(A,D)) + return 1 + add_logs(A, D, "punched") + A.do_attack_animation(D) + var/picked_hit_type = pick("punches", "kicks") + var/bonus_damage = 10 + if(D.weakened || D.resting || D.lying) + bonus_damage += 5 + picked_hit_type = "stomps on" + D.apply_damage(bonus_damage, BRUTE) + if(picked_hit_type == "kicks" || picked_hit_type == "stomps") + playsound(get_turf(D), 'sound/effects/hit_kick.ogg', 50, 1, -1) + else + playsound(get_turf(D), 'sound/effects/hit_punch.ogg', 50, 1, -1) + D.visible_message("[A] [picked_hit_type] [D]!", \ + "[A] [picked_hit_type] you!") + return 1 + +/datum/martial_art/krav_maga/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + if(check_streak(A,D)) + return 1 + if(prob(60)) + if(D.hand) + if(istype(D.l_hand, /obj/item)) + var/obj/item/I = D.l_hand + D.drop_item() + A.put_in_hands(I) + else + if(istype(D.r_hand, /obj/item)) + var/obj/item/I = D.r_hand + D.drop_item() + A.put_in_hands(I) + D.visible_message("[A] has disarmed [D]!", \ + "[A] has disarmed [D]!") + playsound(D, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + else + D.visible_message("[A] attempted to disarm [D]!", \ + "[A] attempted to disarm [D]!") + playsound(D, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + return 1 + +//Krav Maga Gloves + +/obj/item/clothing/gloves/color/black/krav_maga + var/datum/martial_art/krav_maga/style = new + +/obj/item/clothing/gloves/color/black/krav_maga/equipped(mob/user, slot) + if(!ishuman(user)) + return + if(slot == slot_gloves) + var/mob/living/carbon/human/H = user + style.teach(H,1) + +/obj/item/clothing/gloves/color/black/krav_maga/dropped(mob/user) + if(!ishuman(user)) + return + var/mob/living/carbon/human/H = user + if(H.get_item_by_slot(slot_gloves) == src) + style.remove(H) + +/obj/item/clothing/gloves/color/black/krav_maga/sec//more obviously named, given to sec + name = "krav maga gloves" + desc = "These gloves can teach you to perform Krav Maga using nanochips." + icon_state = "fightgloves" + item_state = "fightgloves" \ No newline at end of file diff --git a/code/modules/martial_arts/martial.dm b/code/modules/martial_arts/martial.dm new file mode 100644 index 00000000000..d128e22c0f6 --- /dev/null +++ b/code/modules/martial_arts/martial.dm @@ -0,0 +1,246 @@ +/datum/martial_art + var/name = "Martial Art" + var/streak = "" + var/max_streak_length = 6 + var/current_target = null + var/temporary = 0 + var/datum/martial_art/base = null // The permanent style + var/deflection_chance = 0 //Chance to deflect projectiles + var/help_verb = null + +/datum/martial_art/proc/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + return 0 + +/datum/martial_art/proc/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + return 0 + +/datum/martial_art/proc/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + return 0 + +/datum/martial_art/proc/help_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + return 0 + +/datum/martial_art/proc/add_to_streak(var/element,var/mob/living/carbon/human/D) + if(D != current_target) + current_target = D + streak = "" + streak = streak+element + if(length(streak) > max_streak_length) + streak = copytext(streak,2) + return + +/datum/martial_art/proc/basic_hit(var/mob/living/carbon/human/A,var/mob/living/carbon/human/D) + + A.do_attack_animation(D) + var/damage = rand(A.species.punchdamagelow, A.species.punchdamagehigh) + var/datum/unarmed_attack/attack = A.species.unarmed + + var/atk_verb = "[pick(attack.attack_verb)]" + if(D.lying) + atk_verb = "kick" + + if(!damage) + playsound(D.loc, attack.miss_sound, 25, 1, -1) + D.visible_message("[A] has attempted to [atk_verb] [D]!") + return 0 + + var/obj/item/organ/external/affecting = D.get_organ(ran_zone(A.zone_sel.selecting)) + var/armor_block = D.run_armor_check(affecting, "melee") + + playsound(D.loc, attack.attack_sound, 25, 1, -1) + D.visible_message("[A] has [atk_verb]ed [D]!", \ + "[A] has [atk_verb]ed [D]!") + + D.apply_damage(damage, BRUTE, affecting, armor_block) + + add_logs(D, A, "punched") + + if((D.stat != DEAD) && damage >= A.species.punchstunthreshold) + D.visible_message("[A] has weakened [D]!!", \ + "[A] has weakened [D]!") + D.apply_effect(4, WEAKEN, armor_block) + D.forcesay(hit_appends) + else if(D.lying) + D.forcesay(hit_appends) + return 1 + +/datum/martial_art/proc/teach(var/mob/living/carbon/human/H,var/make_temporary=0) + if(help_verb) + H.verbs += help_verb + if(make_temporary) + temporary = 1 + if(temporary) + if(H.martial_art) + base = H.martial_art.base + else + base = src + H.martial_art = src + +/datum/martial_art/proc/remove(var/mob/living/carbon/human/H) + if(H.martial_art != src) + return + H.martial_art = base + if(help_verb) + H.verbs -= help_verb + +//ITEMS + +/obj/item/clothing/gloves/boxing + var/datum/martial_art/boxing/style = new + +/obj/item/clothing/gloves/boxing/equipped(mob/user, slot) + if(!ishuman(user)) + return + if(slot == slot_gloves) + var/mob/living/carbon/human/H = user + style.teach(H,1) + return + +/obj/item/clothing/gloves/boxing/dropped(mob/user) + if(!ishuman(user)) + return + var/mob/living/carbon/human/H = user + if(H.get_item_by_slot(slot_gloves) == src) + style.remove(H) + return + +/obj/item/weapon/storage/belt/champion/wrestling + name = "Wrestling Belt" + var/datum/martial_art/wrestling/style = new + +/obj/item/weapon/storage/belt/champion/wrestling/equipped(mob/user, slot) + if(!ishuman(user)) + return + if(slot == slot_belt) + var/mob/living/carbon/human/H = user + style.teach(H,1) + to_chat(user, "You have an urge to flex your muscles and get into a fight. You have the knowledge of a thousand wrestlers before you. You can remember more by using the Recall teaching verb in the wrestling tab.") + return + +/obj/item/weapon/storage/belt/champion/wrestling/dropped(mob/user) + if(!ishuman(user)) + return + var/mob/living/carbon/human/H = user + if(H.get_item_by_slot(slot_belt) == src) + style.remove(H) + to_chat(user, "You no longer have an urge to flex your muscles.") + return + +/obj/item/weapon/plasma_fist_scroll + name = "frayed scroll" + desc = "An aged and frayed scrap of paper written in shifting runes. There are hand-drawn illustrations of pugilism." + icon = 'icons/obj/wizard.dmi' + icon_state ="scroll2" + var/used = 0 + +/obj/item/weapon/plasma_fist_scroll/attack_self(mob/user as mob) + if(!ishuman(user)) + return + if(!used) + var/mob/living/carbon/human/H = user + var/datum/martial_art/plasma_fist/F = new/datum/martial_art/plasma_fist(null) + F.teach(H) + to_chat(H, "You have learned the ancient martial art of Plasma Fist.") + used = 1 + desc = "It's completely blank." + name = "empty scroll" + icon_state = "blankscroll" + +/obj/item/weapon/sleeping_carp_scroll + name = "mysterious scroll" + desc = "A scroll filled with strange markings. It seems to be drawings of some sort of martial art." + icon = 'icons/obj/wizard.dmi' + icon_state = "scroll2" + +/obj/item/weapon/sleeping_carp_scroll/attack_self(mob/living/carbon/human/user as mob) + if(!istype(user) || !user) + return + to_chat(user, "You have learned the ancient martial art of the Sleeping Carp! \ + Your hand-to-hand combat has become much more effective, and you are now able to deflect any projectiles directed toward you. \ + However, you are also unable to use any ranged weaponry. \ + You can learn more about your newfound art by using the Recall Teachings verb in the Sleeping Carp tab.") + + + var/datum/martial_art/the_sleeping_carp/theSleepingCarp = new(null) + theSleepingCarp.teach(user) + user.drop_item() + visible_message("[src] lights up in fire and quickly burns to ash.") + new /obj/effect/decal/cleanable/ash(get_turf(src)) + qdel(src) + +/obj/item/weapon/twohanded/bostaff + name = "bo staff" + desc = "A long, tall staff made of polished wood. Traditionally used in ancient old-Earth martial arts. Can be wielded to both kill and incapacitate." + force = 10 + w_class = 4 + slot_flags = SLOT_BACK + force_unwielded = 10 + force_wielded = 24 + throwforce = 20 + throw_speed = 2 + attack_verb = list("smashed", "slammed", "whacked", "thwacked") + icon = 'icons/obj/weapons.dmi' + icon_state = "bostaff0" + + +/obj/item/weapon/twohanded/bostaff/update_icon() + icon_state = "bostaff[wielded]" + return + +/obj/item/weapon/twohanded/bostaff/attack(mob/target, mob/living/user) + add_fingerprint(user) + if((CLUMSY in user.disabilities) && prob(50)) + to_chat(user, "You club yourself over the head with [src].") + user.Weaken(3) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + H.apply_damage(2*force, BRUTE, "head") + else + user.take_organ_damage(2*force) + return + if(isrobot(target)) + return ..() + if(!isliving(target)) + return ..() + var/mob/living/carbon/C = target + if(C.stat) + to_chat(user, "It would be dishonorable to attack a foe while they cannot retaliate.") + return + switch(user.a_intent) + if("disarm") + if(!wielded) + return ..() + if(!ishuman(target)) + return ..() + var/mob/living/carbon/human/H = target + var/list/fluffmessages = list("[user] clubs [H] with [src]!", \ + "[user] smacks [H] with the butt of [src]!", \ + "[user] broadsides [H] with [src]!", \ + "[user] smashes [H]'s head with [src]!", \ + "[user] beats [H] with front of [src]!", \ + "[user] twirls and slams [H] with [src]!") + H.visible_message("[pick(fluffmessages)]", \ + "[pick(fluffmessages)]") + playsound(get_turf(user), 'sound/effects/woodhit.ogg', 75, 1, -1) + H.adjustStaminaLoss(rand(13,20)) + if(prob(10)) + H.visible_message("[H] collapses!", \ + "Your legs give out!") + H.Weaken(4) + if(H.staminaloss && !H.sleeping) + var/total_health = (H.health - H.staminaloss) + if(total_health <= config.health_threshold_crit && !H.stat) + H.visible_message("[user] delivers a heavy hit to [H]'s head, knocking them out cold!", \ + "[user] knocks you unconscious!") + H.SetSleeping(30) + H.adjustBrainLoss(25) + return + else + return ..() + return ..() + +/obj/item/weapon/twohanded/bostaff/IsShield() + if(wielded) + return 1 + else + return 0 \ No newline at end of file diff --git a/code/modules/martial_arts/mimejutsu.dm b/code/modules/martial_arts/mimejutsu.dm new file mode 100644 index 00000000000..79133de67f0 --- /dev/null +++ b/code/modules/martial_arts/mimejutsu.dm @@ -0,0 +1,119 @@ +#define MIMECHUCKS_COMBO "DH" +#define MIMESMOKE_COMBO "DD" +#define MIMEPALM_COMBO "GD" + +/datum/martial_art/mimejutsu + name = "Mimejutsu" + help_verb = /mob/living/carbon/human/proc/mimejutsu_help + +/datum/martial_art/mimejutsu/proc/check_streak(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + if(findtext(streak,MIMECHUCKS_COMBO)) + streak = "" + mimeChuck(A,D) + return 1 + if(findtext(streak,MIMESMOKE_COMBO)) + streak = "" + mimeSmoke(A,D) + return 1 + if(findtext(streak,MIMEPALM_COMBO)) + streak = "" + mimePalm(A,D) + return 1 + return 0 + +/datum/martial_art/mimejutsu/proc/mimeChuck(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + if(!D.stat && !D.stunned && !D.weakened) + var/damage = rand(5, 8) + A.species.punchdamagelow + if(!damage) + playsound(D.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + D.visible_message("[A] swings invisible nunchcuks at [D]..and misses?") + return 0 + + + var/obj/item/organ/external/affecting = D.get_organ(ran_zone(A.zone_sel.selecting)) + var/armor_block = D.run_armor_check(affecting, "melee") + + D.visible_message("[A] has hit [D] with invisible nuncucks!", \ + "[A] has hit [D] with a with invisible nuncuck!") + playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + + D.apply_damage(damage, STAMINA, affecting, armor_block) + add_logs(D, A, "mimechucked") + + return 1 + return basic_hit(A,D) + +/datum/martial_art/mimejutsu/proc/mimeSmoke(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + + D.visible_message("[A] throws an invisible smoke bomb!!") + + var/datum/effect/system/bad_smoke_spread/smoke = new /datum/effect/system/bad_smoke_spread() + smoke.set_up(5, 0, D.loc) + smoke.start() + + return basic_hit(A,D) + +/datum/martial_art/mimejutsu/proc/mimePalm(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + if(!D.stat && !D.stunned && !D.weakened) + D.visible_message("[A] has barely touched [D] with thier palm!", \ + "[A] hovers thier palm over your face!") + + var/atom/throw_target = get_edge_target_turf(D, get_dir(D, get_step_away(D, A))) + D.throw_at(throw_target, 200, 4,A) + return basic_hit(A,D) + + +/datum/martial_art/mimejutsu/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + add_to_streak("D",D) + if(check_streak(A,D)) + return 1 + + return ..() + +/datum/martial_art/mimejutsu/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + add_to_streak("G",D) + if(check_streak(A,D)) + return 1 + + return 1 + +/datum/martial_art/mimejutsu/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + add_to_streak("H",D) + if(check_streak(A,D)) + return 1 + + A.do_attack_animation(D) + + return 1 + +/obj/item/weapon/mimejutsu_scroll + name = "Mimejutsu 'scroll'" + desc = "Its a beret with a note stapled to it..." + icon = 'icons/obj/clothing/hats.dmi' + icon_state = "beret" + var/used = 0 + +/obj/item/weapon/mimejutsu_scroll/attack_self(mob/user as mob) + if(!ishuman(user)) + return + if(!used) + var/mob/living/carbon/human/H = user + var/datum/martial_art/mimejutsu/F = new/datum/martial_art/mimejutsu(null) + F.teach(H) + to_chat(H, "You have learned the ancient martial art of mimes.") + used = 1 + desc = "It used to have something stapled to it..the staple is still there." + name = "beret with staple" + icon_state = "beret" + +/mob/living/carbon/human/proc/mimejutsu_help() + set name = "Recall Ancient Mimeing" + set desc = "Remember the martial techniques of Mimejutsu." + set category = "Mimejutsu" + + to_chat(usr, "You make a invisible box around yourself and recall the teachings of Mimejutsu...") + + to_chat(usr, "Mimechucks: Disarm Harm. Hits the opponent with invisible nunchucks.") + to_chat(usr, "Smokebomb: Disarm Disarm. Drops a mime smokebomb.") + to_chat(usr, "Silent Palm: Grab Disarm. Using mime energy throw someone back.") + diff --git a/code/modules/martial_arts/plasma_fist.dm b/code/modules/martial_arts/plasma_fist.dm new file mode 100644 index 00000000000..d2e047dc08d --- /dev/null +++ b/code/modules/martial_arts/plasma_fist.dm @@ -0,0 +1,86 @@ +#define TORNADO_COMBO "HHD" +#define THROWBACK_COMBO "DHD" +#define PLASMA_COMBO "HDDDH" + +/datum/martial_art/plasma_fist + name = "Plasma Fist" + help_verb = /mob/living/carbon/human/proc/plasma_fist_help + + +/datum/martial_art/plasma_fist/proc/check_streak(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + if(findtext(streak,TORNADO_COMBO)) + streak = "" + Tornado(A,D) + return 1 + if(findtext(streak,THROWBACK_COMBO)) + streak = "" + Throwback(A,D) + return 1 + if(findtext(streak,PLASMA_COMBO)) + streak = "" + Plasma(A,D) + return 1 + return 0 + +/datum/martial_art/plasma_fist/proc/Tornado(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + A.say("TORNADO SWEEP!") + spawn(0) + for(var/i in list(NORTH,SOUTH,EAST,WEST,EAST,SOUTH,NORTH,SOUTH,EAST,WEST,EAST,SOUTH)) + A.dir = i + playsound(A.loc, 'sound/weapons/punch1.ogg', 15, 1, -1) + sleep(1) + var/obj/effect/proc_holder/spell/aoe_turf/repulse/R = new(null) + var/list/turfs = list() + for(var/turf/T in range(1,A)) + turfs.Add(T) + R.cast(turfs) + return + +/datum/martial_art/plasma_fist/proc/Throwback(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + D.visible_message("[A] has hit [D] with Plasma Punch!", \ + "[A] has hit [D] with Plasma Punch!") + playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1) + var/atom/throw_target = get_edge_target_turf(D, get_dir(D, get_step_away(D, A))) + D.throw_at(throw_target, 200, 4,A) + A.say("HYAH!") + return + +/datum/martial_art/plasma_fist/proc/Plasma(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + A.do_attack_animation(D) + playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1) + A.say("PLASMA FIST!") + D.visible_message("[A] has hit [D] with THE PLASMA FIST TECHNIQUE!", \ + "[A] has hit [D] with THE PLASMA FIST TECHNIQUE!") + D.gib() + return + +/datum/martial_art/plasma_fist/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + add_to_streak("H",D) + if(check_streak(A,D)) + return 1 + basic_hit(A,D) + return 1 + +/datum/martial_art/plasma_fist/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + add_to_streak("D",D) + if(check_streak(A,D)) + return 1 + basic_hit(A,D) + return 1 + +/datum/martial_art/plasma_fist/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + add_to_streak("G",D) + if(check_streak(A,D)) + return 1 + basic_hit(A,D) + return 1 + +/mob/living/carbon/human/proc/plasma_fist_help() + set name = "Recall Teachings" + set desc = "Remember the martial techniques of the Plasma Fist." + set category = "Plasma Fist" + + to_chat(usr, "You clench your fists and have a flashback of knowledge...") + to_chat(usr, "Tornado Sweep: Harm Harm Disarm. Repulses target and everyone back.") + to_chat(usr, "Throwback: Disarm Harm Disarm. Throws the target and an item at them.") + to_chat(usr, "The Plasma Fist: Harm Disarm Disarm Disarm Harm. Knocks the brain out of the opponent and gibs their body.") \ No newline at end of file diff --git a/code/modules/martial_arts/sleeping_carp.dm b/code/modules/martial_arts/sleeping_carp.dm new file mode 100644 index 00000000000..3202f8fbe27 --- /dev/null +++ b/code/modules/martial_arts/sleeping_carp.dm @@ -0,0 +1,137 @@ +//Used by the gang of the same name. Uses combos. Basic attacks bypass armor and never miss +#define WRIST_WRENCH_COMBO "DD" +#define BACK_KICK_COMBO "HG" +#define STOMACH_KNEE_COMBO "GH" +#define HEAD_KICK_COMBO "DHH" +#define ELBOW_DROP_COMBO "HDHDH" +/datum/martial_art/the_sleeping_carp + name = "The Sleeping Carp" + deflection_chance = 100 + help_verb = /mob/living/carbon/human/proc/sleeping_carp_help + +/datum/martial_art/the_sleeping_carp/proc/check_streak(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + if(findtext(streak,WRIST_WRENCH_COMBO)) + streak = "" + wristWrench(A,D) + return 1 + if(findtext(streak,BACK_KICK_COMBO)) + streak = "" + backKick(A,D) + return 1 + if(findtext(streak,STOMACH_KNEE_COMBO)) + streak = "" + kneeStomach(A,D) + return 1 + if(findtext(streak,HEAD_KICK_COMBO)) + streak = "" + headKick(A,D) + return 1 + if(findtext(streak,ELBOW_DROP_COMBO)) + streak = "" + elbowDrop(A,D) + return 1 + return 0 + +/datum/martial_art/the_sleeping_carp/proc/wristWrench(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + if(!D.stat && !D.stunned && !D.weakened) + A.do_attack_animation(D) + D.visible_message("[A] grabs [D]'s wrist and wrenches it sideways!", \ + "[A] grabs your wrist and violently wrenches it to the side!") + playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + D.emote("scream") + D.drop_item() + D.apply_damage(5, BRUTE, pick("l_arm", "r_arm")) + D.Stun(3) + return 1 + return basic_hit(A,D) + +/datum/martial_art/the_sleeping_carp/proc/backKick(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + if(A.dir == D.dir && !D.stat && !D.weakened) + A.do_attack_animation(D) + D.visible_message("[A] kicks [D] in the back!", \ + "[A] kicks you in the back, making you stumble and fall!") + step_to(D,get_step(D,D.dir),1) + D.Weaken(4) + playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1) + return 1 + return basic_hit(A,D) + +/datum/martial_art/the_sleeping_carp/proc/kneeStomach(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + if(!D.stat && !D.weakened) + A.do_attack_animation(D) + D.visible_message("[A] knees [D] in the stomach!", \ + "[A] winds you with a knee in the stomach!") + D.audible_message("[D] gags!") + D.losebreath += 3 + D.Stun(2) + playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1) + return 1 + return basic_hit(A,D) + +/datum/martial_art/the_sleeping_carp/proc/headKick(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + if(!D.stat && !D.weakened) + A.do_attack_animation(D) + D.visible_message("[A] kicks [D] in the head!", \ + "[A] kicks you in the jaw!") + D.apply_damage(20, BRUTE, "head") + D.drop_item() + playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1) + D.Stun(4) + return 1 + return basic_hit(A,D) + +/datum/martial_art/the_sleeping_carp/proc/elbowDrop(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + if(D.weakened || D.resting || D.stat) + A.do_attack_animation(D) + D.visible_message("[A] elbow drops [D]!", \ + "[A] piledrives you with their elbow!") + if(D.stat) + D.death() //FINISH HIM! + D.apply_damage(50, BRUTE, "chest") + playsound(get_turf(D), 'sound/weapons/punch1.ogg', 75, 1, -1) + return 1 + return basic_hit(A,D) + +/datum/martial_art/the_sleeping_carp/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + add_to_streak("G",D) + if(check_streak(A,D)) + return 1 + D.grabbedby(A,1) + var/obj/item/weapon/grab/G = A.get_active_hand() + if(G) + G.state = GRAB_AGGRESSIVE //Instant aggressive grab + +/datum/martial_art/the_sleeping_carp/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + add_to_streak("H",D) + if(check_streak(A,D)) + return 1 + A.do_attack_animation(D) + var/atk_verb = pick("punches", "kicks", "chops", "hits", "slams") + D.visible_message("[A] [atk_verb] [D]!", \ + "[A] [atk_verb] you!") + D.apply_damage(rand(10,15), BRUTE) + playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, 1, -1) + if(prob(D.getBruteLoss()) && !D.lying) + D.visible_message("[D] stumbles and falls!", "The blow sends you to the ground!") + D.Weaken(4) + return 1 + + +/datum/martial_art/the_sleeping_carp/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + add_to_streak("D",D) + if(check_streak(A,D)) + return 1 + return ..() + +/mob/living/carbon/human/proc/sleeping_carp_help() + set name = "Recall Teachings" + set desc = "Remember the martial techniques of the Sleeping Carp clan." + set category = "Sleeping Carp" + + to_chat(usr, "You retreat inward and recall the teachings of the Sleeping Carp...") + + to_chat(usr, "Wrist Wrench: Disarm Disarm. Forces opponent to drop item in hand.") + to_chat(usr, "Back Kick: Harm Grab. Opponent must be facing away. Knocks down.") + to_chat(usr, "Stomach Knee: Grab Harm. Knocks the wind out of opponent and stuns.") + to_chat(usr, "Head Kick: Disarm Harm Harm. Decent damage, forces opponent to drop item in hand.") + to_chat(usr, "Elbow Drop: Harm Disarm Harm Disarm Harm. Opponent must be on the ground. Deals huge damage, instantly kills anyone in critical condition.") diff --git a/code/modules/martial_arts/wrestleing.dm b/code/modules/martial_arts/wrestleing.dm new file mode 100644 index 00000000000..d0b3a4e697e --- /dev/null +++ b/code/modules/martial_arts/wrestleing.dm @@ -0,0 +1,67 @@ +/datum/martial_art/wrestling + name = "Wrestling" + help_verb = /mob/living/carbon/human/proc/wrestling_help + +// combo refence since wrestling uses a different format to sleeping carp and plasma fist. +// Clinch "G" +// Suplex "GD" +// Advanced grab "G" + +/datum/martial_art/wrestling/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + D.grabbedby(A,1) + var/obj/item/weapon/grab/G = A.get_active_hand() + if(G && prob(50)) + G.state = GRAB_AGGRESSIVE + D.visible_message("[A] has [D] in a clinch!", \ + "[A] has [D] in a clinch!") + else + D.visible_message("[A] fails to get [D] in a clinch!", \ + "[A] fails to get [D] in a clinch!") + return 1 + + +/datum/martial_art/wrestling/proc/Suplex(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + + D.visible_message("[A] suplexes [D]!", \ + "[A] suplexes [D]!") + D.forceMove(A.loc) + var/armor_block = D.run_armor_check(null, "melee") + D.apply_damage(30, BRUTE, null, armor_block) + D.apply_effect(6, WEAKEN, armor_block) + add_logs(D, A, "suplexed") + + A.SpinAnimation(10,1) + + D.SpinAnimation(10,1) + spawn(3) + armor_block = A.run_armor_check(null, "melee") + A.apply_effect(4, WEAKEN, armor_block) + return + +/datum/martial_art/wrestling/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + if(istype(A.get_inactive_hand(),/obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = A.get_inactive_hand() + if(G.affecting == D) + Suplex(A,D) + return 1 + harm_act(A,D) + return 1 + +/datum/martial_art/wrestling/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D) + D.grabbedby(A,1) + D.visible_message("[A] holds [D] down!", \ + "[A] holds [D] down!") + var/obj/item/organ/external/affecting = D.get_organ(ran_zone(A.zone_sel.selecting)) + var/armor_block = D.run_armor_check(affecting, "melee") + D.apply_damage(10, STAMINA, affecting, armor_block) + return 1 + +/mob/living/carbon/human/proc/wrestling_help() + set name = "Recall Teachings" + set desc = "Remember how to wrestle." + set category = "Wrestling" + + to_chat(usr, "You flex your muscles and have a revelation...") + to_chat(usr, "Clinch: Grab. Passively gives you a chance to immediately aggressively grab someone. Not always successful.") + to_chat(usr, "Suplex: Disarm someone you are grabbing. Suplexes your target to the floor. Greatly injures them and leaves both you and your target on the floor.") + to_chat(usr, "Advanced grab: Grab. Passively causes stamina damage when grabbing someone.") diff --git a/code/modules/mining/abandonedcrates.dm b/code/modules/mining/abandonedcrates.dm index 16c247b6b50..25358df5af2 100644 --- a/code/modules/mining/abandonedcrates.dm +++ b/code/modules/mining/abandonedcrates.dm @@ -1,114 +1,218 @@ +//Originally coded by ISaidNo, later modified by Kelenius. Ported from Baystation12. + /obj/structure/closet/crate/secure/loot name = "abandoned crate" desc = "What could be inside?" icon_state = "securecrate" - icon_opened = "securecrateopen" - icon_closed = "securecrate" var/code = null var/lastattempt = null - var/attempts = 3 - locked = 1 - var/min = 1 - var/max = 10 + var/attempts = 10 + var/codelen = 4 /obj/structure/closet/crate/secure/loot/New() ..() - code = rand(min,max) - var/loot = rand(1,30) - switch(loot) - if(1) - new/obj/item/weapon/reagent_containers/food/drinks/bottle/rum(src) - new/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiadeus(src) - new/obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey(src) - new/obj/item/weapon/lighter/zippo(src) - if(2) - new/obj/item/weapon/pickaxe/drill(src) - new/obj/item/device/taperecorder(src) - new/obj/item/clothing/suit/space(src) - new/obj/item/clothing/head/helmet/space(src) - if(3) - return - if(4) - new/obj/item/weapon/reagent_containers/glass/beaker/bluespace(src) - if(5 to 6) - for(var/i = 0, i < 10, i++) - new/obj/item/weapon/ore/diamond(src) - if(7) - return - if(8) - return - if(9) - for(var/i = 0, i < 3, i++) - new/obj/machinery/portable_atmospherics/hydroponics(src) - if(10) - for(var/i = 0, i < 3, i++) - new/obj/item/weapon/reagent_containers/glass/beaker/noreact(src) - if(11 to 13) - new/obj/item/weapon/melee/classic_baton(src) - if(14) - return - if(15) - new/obj/item/clothing/under/chameleon(src) - for(var/i = 0, i < 7, i++) - new/obj/item/clothing/accessory/horrible(src) - if(16) - new/obj/item/clothing/under/shorts(src) - new/obj/item/clothing/under/shorts/red(src) - new/obj/item/clothing/under/shorts/blue(src) - //Dummy crates start here. - if(17 to 29) - return - //Dummy crates end here. - if(30) - new/obj/item/weapon/melee/baton(src) + var/list/digits = list("1", "2", "3", "4", "5", "6", "7", "8", "9", "z") + code = "" + for(var/i = 0, i < codelen, i++) + var/dig = pick(digits) + code += dig + digits -= dig //Player can enter codes with matching digits, but there are never matching digits in the answer -/obj/structure/closet/crate/secure/loot/togglelock(mob/user as mob) + var/loot = rand(1,100) //100 different crates with varying chances of spawning + switch(loot) + if(1 to 5) //5% chance + new /obj/item/weapon/reagent_containers/food/drinks/bottle/rum(src) + new /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiadeus(src) + new /obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey(src) + new /obj/item/weapon/lighter(src) + if(6 to 10) + new /obj/item/weapon/bedsheet(src) + new /obj/item/weapon/kitchen/knife(src) + new /obj/item/weapon/wirecutters(src) + new /obj/item/weapon/screwdriver(src) + new /obj/item/weapon/weldingtool(src) + new /obj/item/weapon/hatchet(src) + new /obj/item/weapon/crowbar(src) + if(11 to 15) + new /obj/item/weapon/reagent_containers/glass/beaker/bluespace(src) + if(16 to 20) + for(var/i in 1 to 10) + new /obj/item/weapon/ore/diamond(src) + if(21 to 25) + for(var/i in 1 to 5) + new /obj/item/weapon/contraband/poster(src) + if(26 to 30) + for(var/i in 1 to 3) + new /obj/item/weapon/reagent_containers/glass/beaker/noreact(src) + if(31 to 35) + new /obj/item/seeds/cash(src) + if(36 to 40) + new /obj/item/weapon/melee/baton(src) + if(41 to 45) + new /obj/item/clothing/under/shorts/red(src) + new /obj/item/clothing/under/shorts/blue(src) + if(46 to 50) + new /obj/item/clothing/under/chameleon(src) + for(var/i in 1 to 7) + new /obj/item/clothing/accessory/horrible(src) + if(51 to 52) // 2% chance + new /obj/item/weapon/melee/classic_baton(src) + if(53 to 54) + new /obj/item/toy/balloon(src) + if(55 to 56) + var/newitem = pick(subtypesof(/obj/item/toy/prize)) + new newitem(src) + if(57 to 58) + new /obj/item/toy/syndicateballoon(src) + if(59 to 60) + new /obj/item/weapon/gun/energy/kinetic_accelerator/hyper(src) + new /obj/item/clothing/suit/space(src) + new /obj/item/clothing/head/helmet/space(src) + if(61 to 62) + for(var/i in 1 to 5) + new /obj/item/clothing/head/kitty(src) + new /obj/item/clothing/accessory/petcollar(src) + if(63 to 64) + for(var/i in 1 to rand(4, 7)) + var/newcoin = pick(/obj/item/weapon/coin/silver, /obj/item/weapon/coin/silver, /obj/item/weapon/coin/silver, /obj/item/weapon/coin/iron, /obj/item/weapon/coin/iron, /obj/item/weapon/coin/iron, /obj/item/weapon/coin/gold, /obj/item/weapon/coin/diamond, /obj/item/weapon/coin/plasma, /obj/item/weapon/coin/uranium) + new newcoin(src) + if(65 to 66) + new /obj/item/clothing/suit/ianshirt(src) + new /obj/item/clothing/suit/corgisuit(src) + new /obj/item/clothing/head/corgi(src) + if(67 to 68) + for(var/i in 1 to rand(4, 7)) + var /newitem = pick(subtypesof(/obj/item/weapon/stock_parts) - /obj/item/weapon/stock_parts/subspace) + new newitem(src) + if(69 to 70) + for(var/i in 1 to 5) + new /obj/item/weapon/ore/bluespace_crystal(src) + if(71 to 72) + new /obj/item/weapon/pickaxe/drill(src) + if(73 to 74) + new /obj/item/weapon/pickaxe/drill/jackhammer(src) + if(75 to 76) + new /obj/item/weapon/pickaxe/diamond(src) + if(77 to 78) + new /obj/item/weapon/pickaxe/drill/diamonddrill(src) + if(79 to 80) + new /obj/item/weapon/cane(src) + new /obj/item/clothing/head/collectable/tophat(src) + if(81 to 82) + new /obj/item/weapon/gun/energy/plasmacutter(src) + if(83 to 84) + new /obj/item/toy/katana(src) + if(85 to 86) + new /obj/item/weapon/defibrillator/compact(src) + if(87) //1% chance + new /obj/item/weed_extract(src) + if(88) + new /obj/item/organ/internal/brain(src) + if(89) + new /obj/item/organ/internal/brain/xeno(src) + if(90) + new /obj/item/organ/internal/heart(src) + if(91) + new /obj/item/device/soulstone(src) + if(92) + new /obj/item/weapon/katana(src) + if(93) + new /obj/item/weapon/dnainjector/xraymut(src) + if(94) + new /obj/item/weapon/storage/backpack/clown(src) + new /obj/item/clothing/under/rank/clown(src) + new /obj/item/clothing/shoes/clown_shoes(src) + new /obj/item/device/pda/clown(src) + new /obj/item/clothing/mask/gas/clown_hat(src) + new /obj/item/weapon/bikehorn(src) + new /obj/item/toy/crayon/rainbow(src) + new /obj/item/weapon/reagent_containers/spray/waterflower(src) + if(95) + new /obj/item/clothing/under/mime(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/device/pda/mime(src) + new /obj/item/clothing/gloves/color/white(src) + new /obj/item/clothing/mask/gas/mime(src) + new /obj/item/clothing/head/beret(src) + new /obj/item/clothing/suit/suspenders(src) + new /obj/item/toy/crayon/mime(src) + new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(src) + if(96) + new /obj/item/weapon/hand_tele(src) + if(97) + new /obj/item/clothing/mask/balaclava + new /obj/item/weapon/gun/projectile/automatic/pistol(src) + new /obj/item/ammo_box/magazine/m10mm(src) + if(98) + new /obj/item/weapon/katana/cursed(src) + if(99) + new /obj/item/weapon/storage/belt/champion(src) + new /obj/item/clothing/mask/luchador(src) + if(100) + new /obj/item/clothing/head/bearpelt(src) + +/obj/structure/closet/crate/secure/loot/attack_hand(mob/user) if(locked) to_chat(user, "The crate is locked with a Deca-code lock.") - var/input = input(usr, "Enter digit from [min] to [max].", "Deca-Code Lock", "") as num + var/input = input(usr, "Enter [codelen] digits.", "Deca-Code Lock", "") as text if(in_range(src, user)) - input = Clamp(input, 0, 10) if (input == code) to_chat(user, "The crate unlocks!") locked = 0 overlays.Cut() - overlays += greenlight - else if (input == null || input > max || input < min) + overlays += "securecrateg" + else if (input == null || length(input) != codelen) to_chat(user, "You leave the crate alone.") else to_chat(user, "A red light flashes.") - lastattempt = input + lastattempt = replacetext(input, 0, "z") attempts-- - if (attempts == 0) - to_chat(user, "The crate's anti-tamper system activates!") - var/turf/T = get_turf(src.loc) - explosion(T, -1, -1, 1, 1) - qdel(src) - return - else - to_chat(user, "You attempt to interact with the device using a hand gesture, but it appears this crate is from before the DECANECT came out.") - return + if(attempts == 0) + boom(user) else return ..() -/obj/structure/closet/crate/secure/loot/attackby(obj/item/weapon/W as obj, mob/user as mob, params) +/obj/structure/closet/crate/secure/loot/attack_animal(mob/user) + boom(user) + +/obj/structure/closet/crate/secure/loot/attackby(obj/item/weapon/W, mob/user) if(locked) - if (istype(W, /obj/item/weapon/card/emag)) - to_chat(user, "The crate unlocks!") - locked = 0 - if (istype(W, /obj/item/device/multitool)) + if(istype(W, /obj/item/weapon/card/emag)) + boom(user) + if(istype(W, /obj/item/device/multitool)) to_chat(user, "DECA-CODE LOCK REPORT:") - if (attempts == 1) + if(attempts == 1) to_chat(user, "* Anti-Tamper Bomb will activate on next failed access attempt.") else to_chat(user, "* Anti-Tamper Bomb will activate after [src.attempts] failed access attempts.") - if (lastattempt == null) - to_chat(user, " has been made to open the crate thus far.") - return - // hot and cold - if (code > lastattempt) - to_chat(user, "* Last access attempt lower than expected code.") - else - to_chat(user, "* Last access attempt higher than expected code.") + if(lastattempt != null) + var/list/guess = list() + var/bulls = 0 + var/cows = 0 + for(var/i = 1, i < codelen + 1, i++) + var/a = copytext(lastattempt, i, i+1) //Stuff the code into the list + guess += a + guess[a] = i + for(var/i in guess) //Go through list and count matches + var/a = findtext(code, i) + if(a == guess[i]) + ++bulls + else if(a) + ++cows + to_chat(user, "Last code attempt had [bulls] correct digits at correct positions and [cows] correct digits at incorrect positions.") else ..() else ..() + +/obj/structure/closet/crate/secure/loot/togglelock(mob/user) + if(locked) + boom(user) + else + ..() + +/obj/structure/closet/crate/secure/loot/proc/boom(mob/user) + to_chat(user, "The crate's anti-tamper system activates!") + for(var/atom/movable/AM in src) + qdel(AM) + var/turf/T = get_turf(src) + explosion(T, -1, -1, 1, 1) + qdel(src) \ No newline at end of file diff --git a/code/modules/mining/machine_input_output_plates.dm b/code/modules/mining/machine_input_output_plates.dm index e63918d77fa..7d28cedb3da 100644 --- a/code/modules/mining/machine_input_output_plates.dm +++ b/code/modules/mining/machine_input_output_plates.dm @@ -1,7 +1,7 @@ /**********************Input and output plates**************************/ /obj/machinery/mineral/input - icon = 'icons/mob/screen1.dmi' + icon = 'icons/mob/screen_gen.dmi' icon_state = "x2" name = "Input area" density = 0 @@ -10,7 +10,7 @@ icon_state = "blank" /obj/machinery/mineral/output - icon = 'icons/mob/screen1.dmi' + icon = 'icons/mob/screen_gen.dmi' icon_state = "x" name = "Output area" density = 0 diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 3d067d0c8fa..7a8e608c224 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -28,10 +28,9 @@ W.forceMove(src) //TODO: move to equipped? l_hand = W W.layer = 20 //TODO: move to equipped? -// l_hand.screen_loc = ui_lhand W.equipped(src,slot_l_hand) - if(client) client.screen |= W - if(pulling == W) stop_pulling() + if(pulling == W) + stop_pulling() update_inv_l_hand() return 1 return 0 @@ -44,10 +43,9 @@ W.forceMove(src) r_hand = W W.layer = 20 -// r_hand.screen_loc = ui_rhand W.equipped(src,slot_r_hand) - if(client) client.screen |= W - if(pulling == W) stop_pulling() + if(pulling == W) + stop_pulling() update_inv_r_hand() return 1 return 0 diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm index eb2ae210e71..831d01dbc87 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm @@ -23,7 +23,6 @@ large = 1 /mob/living/carbon/alien/humanoid/sentinel/large/update_icons() - update_hud() //TODO: remove the need for this to be here overlays.Cut() if(stat == DEAD) icon_state = "prat_dead" diff --git a/code/modules/mob/living/carbon/alien/humanoid/empress.dm b/code/modules/mob/living/carbon/alien/humanoid/empress.dm index d4716aafccb..ffc8e04429e 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/empress.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/empress.dm @@ -17,8 +17,6 @@ pixel_x = -32 /mob/living/carbon/alien/humanoid/empress/large/update_icons() - - update_hud() //TODO: remove the need for this to be here overlays.Cut() if(stat == DEAD) diff --git a/code/modules/mob/living/carbon/alien/humanoid/login.dm b/code/modules/mob/living/carbon/alien/humanoid/login.dm index 607a03fef0f..914371a969d 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/login.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/login.dm @@ -1,6 +1,5 @@ /mob/living/carbon/alien/humanoid/Login() ..() - update_hud() if(!isturf(loc)) client.eye = loc client.perspective = EYE_PERSPECTIVE diff --git a/code/modules/mob/living/carbon/alien/humanoid/queen.dm b/code/modules/mob/living/carbon/alien/humanoid/queen.dm index 5b2e19f011d..2b5060468a1 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/queen.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/queen.dm @@ -31,29 +31,26 @@ ..() -/mob/living/carbon/alien/humanoid/queen +/mob/living/carbon/alien/humanoid/queen/handle_regular_hud_updates() + ..() //-Yvarov - handle_regular_hud_updates() - - ..() //-Yvarov - - if (src.healths) - if (src.stat != 2) - switch(health) - if(250 to INFINITY) - src.healths.icon_state = "health0" - if(175 to 250) - src.healths.icon_state = "health1" - if(100 to 175) - src.healths.icon_state = "health2" - if(50 to 100) - src.healths.icon_state = "health3" - if(0 to 50) - src.healths.icon_state = "health4" - else - src.healths.icon_state = "health5" - else - src.healths.icon_state = "health6" + if (healths) + if (stat != DEAD) + switch(health) + if(250 to INFINITY) + healths.icon_state = "health0" + if(175 to 250) + healths.icon_state = "health1" + if(100 to 175) + healths.icon_state = "health2" + if(50 to 100) + healths.icon_state = "health3" + if(0 to 50) + healths.icon_state = "health4" + else + healths.icon_state = "health5" + else + healths.icon_state = "health6" //Queen verbs @@ -81,7 +78,6 @@ large = 1 /mob/living/carbon/alien/humanoid/queen/large/update_icons() - update_hud() //TODO: remove the need for this to be here overlays.Cut() if(stat == DEAD) diff --git a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm index 20622869e27..fb489552f78 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm @@ -12,12 +12,10 @@ var/list/overlays_standing[X_TOTAL_LAYERS] /mob/living/carbon/alien/humanoid/update_icons() - update_hud() //TODO: remove the need for this to be here overlays.Cut() for(var/image/I in overlays_standing) overlays += I - if(stat == DEAD) //If we mostly took damage from fire if(fireloss > 125) @@ -65,7 +63,6 @@ update_inv_r_hand(0) update_inv_l_hand(0) update_inv_pockets(0) - update_hud() update_icons() update_fire() update_transform() @@ -76,14 +73,6 @@ ..() update_icons() - -/mob/living/carbon/alien/humanoid/update_hud() - //TODO - if (client) -// if(other) client.screen |= hud_used.other //Not used -// else client.screen -= hud_used.other //Not used - client.screen |= contents - /mob/living/carbon/alien/humanoid/update_fire() overlays -= overlays_standing[X_FIRE_LAYER] if(on_fire) @@ -94,7 +83,16 @@ overlays_standing[X_FIRE_LAYER] = null /mob/living/carbon/alien/humanoid/update_inv_wear_suit(var/update_icons=1) + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_suit] + inv.update_icon() + if(wear_suit) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + wear_suit.screen_loc = ui_oclothing //TODO //...draw the item in the inventory screen + client.screen += wear_suit //Either way, add the item to the HUD + var/t_state = wear_suit.item_state if(!t_state) t_state = wear_suit.icon_state var/image/standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]") @@ -105,8 +103,6 @@ t_suit = "armor" standing.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "[t_suit]blood") - //TODO - wear_suit.screen_loc = ui_alien_oclothing if (istype(wear_suit, /obj/item/clothing/suit/straight_jacket)) unEquip(handcuffed) drop_r_hand() @@ -139,6 +135,7 @@ /mob/living/carbon/alien/humanoid/update_inv_r_hand(var/update_icons=1) + ..(1) if(r_hand) var/t_state = r_hand.item_state if(!t_state) t_state = r_hand.icon_state @@ -149,6 +146,7 @@ if(update_icons) update_icons() /mob/living/carbon/alien/humanoid/update_inv_l_hand(var/update_icons=1) + ..(1) if(l_hand) var/t_state = l_hand.item_state if(!t_state) t_state = l_hand.icon_state @@ -158,15 +156,6 @@ overlays_standing[X_L_HAND_LAYER] = null if(update_icons) update_icons() -//Call when target overlay should be added/removed -/mob/living/carbon/alien/humanoid/update_targeted(var/update_icons=1) - if (targeted_by && target_locked) - overlays_standing[TARGETED_LAYER] = target_locked - else if (!targeted_by && target_locked) - qdel(target_locked) - if (!targeted_by) - overlays_standing[TARGETED_LAYER] = null - if(update_icons) update_icons() //Xeno Overlays Indexes////////// #undef X_HEAD_LAYER diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index 5fbfd6c5012..e10b3d257d3 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -59,8 +59,8 @@ to_chat(user, "This one seems particularly lifeless. Perhaps it will regain some of its luster later..") /obj/item/organ/internal/brain/remove(var/mob/living/user,special = 0) - - name = "[dna.real_name]'s [initial(name)]" + if(dna) + name = "[dna.real_name]'s [initial(name)]" if(!owner) return ..() // Probably a redundant removal; just bail diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 26def9b6520..4bb2fbd4a5f 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -2,11 +2,6 @@ var/canEnterVentWith = "/obj/item/weapon/implant=0&/obj/item/clothing/mask/facehugger=0&/obj/item/device/radio/borg=0&/obj/machinery/camera=0" var/datum/middleClickOverride/middleClickOverride = null -/mob/living/carbon/Login() - ..() - update_hud() - return - /mob/living/carbon/prepare_huds() ..() prepare_data_huds() @@ -188,7 +183,7 @@ -/mob/living/carbon/proc/swap_hand() +/mob/living/carbon/swap_hand() var/obj/item/item_in_hand = src.get_active_hand() if(item_in_hand) //this segment checks if the item in your hand is twohanded. if(istype(item_in_hand,/obj/item/weapon/twohanded)) @@ -196,20 +191,15 @@ to_chat(usr, "Your other hand is too busy holding the [item_in_hand.name]") return src.hand = !( src.hand ) - if(hud_used.l_hand_hud_object && hud_used.r_hand_hud_object) - if(hand) //This being 1 means the left hand is in use - hud_used.l_hand_hud_object.icon_state = "hand_active" - hud_used.r_hand_hud_object.icon_state = "hand_inactive" - else - hud_used.l_hand_hud_object.icon_state = "hand_inactive" - hud_used.r_hand_hud_object.icon_state = "hand_active" - /*if (!( src.hand )) - src.hands.dir = NORTH - else - src.hands.dir = SOUTH*/ - return + if(hud_used && hud_used.inv_slots[slot_l_hand] && hud_used.inv_slots[slot_r_hand]) + var/obj/screen/inventory/hand/H + H = hud_used.inv_slots[slot_l_hand] + H.update_icon() + H = hud_used.inv_slots[slot_r_hand] + H.update_icon() -/mob/living/carbon/proc/activate_hand(var/selhand) //0 or "r" or "right" for right hand; 1 or "l" or "left" for left hand. + +/mob/living/carbon/activate_hand(var/selhand) //0 or "r" or "right" for right hand; 1 or "l" or "left" for left hand. if(istext(selhand)) selhand = lowertext(selhand) @@ -761,7 +751,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, buckled.user_unbuckle_mob(src,src) else if(src && buckled) - src << "You fail to unbuckle yourself!" + to_chat(src, "You fail to unbuckle yourself!") else buckled.user_unbuckle_mob(src,src) @@ -856,6 +846,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, clear_alert("handcuffed") update_action_buttons() //some of our action buttons might be unusable when we're handcuffed. update_inv_handcuffed() + update_hud_handcuffed() /mob/living/carbon/get_standard_pixel_y_offset(lying = 0) if(lying) diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index d74dcbd54c4..8264db804fd 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -179,16 +179,17 @@ continue if(species.flags & ALL_RPARTS) //If the user is a species who can have a robotic head... var/obj/item/organ/external/head/H = organs_by_name["head"] + var/datum/robolimb/robohead = all_robolimbs[H.model] if(!H) return if(species.name in S.species_allowed) //If this is a hairstyle native to the user's species... - if(H.model == "Morpheus Cyberkinetics") //Check to see if they have the default head. + if(robohead.is_monitor && (robohead.company in S.models_allowed)) //Check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. valid_hairstyles += hairstyle //Give them their hairstyles if they do. continue else //If they don't have the default head, they shouldn't be getting any hairstyles they wouldn't normally. continue else - if(H.model == "Morpheus Cyberkinetics") //If the hairstyle is not native to the user's species, and they're using the default head, don't let them access it. + if(robohead.is_monitor) //If the hair style is not native to the user's species and they're using a head with an ipc-style screen, don't let them access it. continue else if("Human" in S.species_allowed) //If the user has a robotic head and the hairstyle can fit humans, let them use it as a wig for their humanoid robot head. @@ -212,17 +213,18 @@ continue if(species.flags & ALL_RPARTS) //If the user is a species who can have a robotic head... var/obj/item/organ/external/head/H = organs_by_name["head"] + var/datum/robolimb/robohead = all_robolimbs[H.model] if(!H) continue // No head, no hair if(species.name in S.species_allowed) //If this is a facial hair style native to the user's species... - if(H.model == "Morpheus Cyberkinetics") //Check to see if they have the default head. + if(robohead.is_monitor && (robohead.company in S.models_allowed)) //Check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. valid_facial_hairstyles += facialhairstyle //Give them their facial hair styles if they do. continue else //If they don't have the default head, they shouldn't be getting any facial hair styles they wouldn't normally. continue else - if(H.model == "Morpheus Cyberkinetics") //If the facial hair style is not native to the user's species, and they're using the default head, don't let them access it. + if(robohead.is_monitor) //If the facial hair style is not native to the user's species and they're using a head with an ipc-style screen, don't let them access it. continue else if("Human" in S.species_allowed) //If the user has a robotic head and the facial hair style can fit humans, let them use it as a postiche for their humanoid robot head. diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 0b15e284eef..714e9c45146 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -33,7 +33,7 @@ var/msg = "*---------*\nThis is " - if( skipjumpsuit && skipface ) //big suits/masks/helmets make it hard to tell their gender + if(skipjumpsuit && skipface) //big suits/masks/helmets make it hard to tell their gender t_He = "They" t_his = "their" t_him = "them" @@ -52,7 +52,18 @@ t_his = "her" t_him = "her" - msg += "[src.name]!\n" + msg += "[name]" + + var/list/nospecies = list("Abductor", "Shadowling", "Neara", "Monkey", "Stok", "Farwa", "Wolpin") //species that won't show their race no matter what + + if (skipjumpsuit && skipface || (species.name in nospecies)) //either obscured or on the nospecies list + msg += "!\n" //omit the species when examining + else if (species.name == "Slime People") //snowflakey because Slime People are defined as a plural + msg += ", a slime person!\n" + else if (species.name == "Unathi") //DAMN YOU, VOWELS + msg += ", a unathi!\n" + else + msg += ", \a [lowertext(species.name)]!\n" //uniform if(w_uniform && !skipjumpsuit) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index d4bd888076c..3e5cb90f380 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -37,6 +37,8 @@ prev_gender = gender // Debug for plural genders make_blood() + martial_art = default_martial_art + var/mob/M = src faction |= "\ref[M]" //what @@ -1593,24 +1595,37 @@ to_chat(src, "You cannot change your monitor or optical display in your current state.") return + var/obj/item/organ/external/head/head_organ = get_organ("head") + if(!head_organ || head_organ.is_stump() || (head_organ.status & ORGAN_DESTROYED)) //If the rock'em-sock'em robot's head came off during a fight, they shouldn't be able to change their screen/optics. + to_chat(src, "Where's your head at? Can't change your monitor/display without one.") + return + if(species.flags & ALL_RPARTS) //If they can have a fully cybernetic body... - if(client.prefs.rlimb_data["head"]) //If head is present here, that means it's not the default Morpheus. Thus, no screen to adjust. Instead, let them change the colour of their optics! + var/obj/item/organ/external/head/H = organs_by_name["head"] + var/datum/robolimb/robohead = all_robolimbs[H.model] + if(!H) + return + if(!robohead.is_monitor) //If they've got a prosthetic head and it isn't a monitor, they've no screen to adjust. Instead, let them change the colour of their optics! var/optic_colour = input(src, "Select optic colour", rgb(r_markings, g_markings, b_markings)) as color|null + if(incapacitated()) + to_chat(src, "You were interrupted while changing the colour of your optics.") + return if(optic_colour) r_markings = hex2num(copytext(optic_colour, 2, 4)) g_markings = hex2num(copytext(optic_colour, 4, 6)) b_markings = hex2num(copytext(optic_colour, 6, 8)) update_markings() - else if(!client.prefs.rlimb_data["head"])//Means that the character has the default Morpheus head, which has a screen. Time to customize. + else if(robohead.is_monitor) //Means that the character's head is a monitor (has a screen). Time to customize. var/list/hair = list() for(var/i in hair_styles_list) var/datum/sprite_accessory/hair/tmp_hair = hair_styles_list[i] - if(species.name in tmp_hair.species_allowed) + if((species.name in tmp_hair.species_allowed) && (robohead.company in tmp_hair.models_allowed)) //Populate the list of available monitor styles only with styles that the monitor-head is allowed to use. hair += i var/new_style = input(src, "Select a monitor display", "Monitor Display", h_style) as null|anything in hair if(incapacitated()) + to_chat(src, "You were interrupted while changing your monitor display.") return if(new_style) h_style = new_style diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 25be2232432..33cb567ba4a 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -55,6 +55,8 @@ switch(M.a_intent) if(I_HELP) + if(attacker_style && attacker_style.help_act(H, src))//adminfu only... + return 1 if(can_operate(src)) if(health >= config.health_threshold_crit) if(src.surgeries.len) diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index c0e58942cfc..cf47ee3b5d0 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -20,7 +20,7 @@ if(species.can_revive_by_healing) var/obj/item/organ/internal/brain/B = get_int_organ(/obj/item/organ/internal/brain) if(B) - if((health >= (config.health_threshold_dead + config.health_threshold_crit) * 0.5) && stat == DEAD) + if((health >= (config.health_threshold_dead + config.health_threshold_crit) * 0.5) && stat == DEAD && getBrainLoss()<120) update_revive() if(stat == CONSCIOUS && (src in dead_mob_list)) //Defib fix update_revive() diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 96104fb6862..e2ebed386b3 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -1,3 +1,4 @@ +var/global/default_martial_art = new/datum/martial_art /mob/living/carbon/human hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD,SPECIALROLE_HUD,NATIONS_HUD) diff --git a/code/modules/mob/living/carbon/human/interactive/interactive.dm b/code/modules/mob/living/carbon/human/interactive/interactive.dm index 679fd55bb1f..14402788451 100644 --- a/code/modules/mob/living/carbon/human/interactive/interactive.dm +++ b/code/modules/mob/living/carbon/human/interactive/interactive.dm @@ -396,16 +396,15 @@ faction -= "neutral" faction += "hostile" +/mob/living/carbon/human/interactive/create_mob_hud() + if(!hud_used) + hud_used = new /datum/hud/human(src) + /mob/living/carbon/human/interactive/New() ..() snpc_list += src - // setup screen HUD because the game expects user mobs to have zone_sel etc - if(hud_used) - qdel(hud_used) //remove the hud objects - hud_used = null - hud_used = new /datum/hud(src) - hud_used.human_hud() + create_mob_hud() sync_mind() random() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 0f5f6a1a3d2..14585c8d972 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -448,9 +448,12 @@ if(status_flags & GODMODE) return 1 //godmode if(adjusted_pressure >= species.hazard_high_pressure) - var/pressure_damage = min( ( (adjusted_pressure / species.hazard_high_pressure) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) - take_overall_damage(brute=pressure_damage, used_weapon = "High Pressure") - throw_alert("pressure", /obj/screen/alert/highpressure, 2) + if(!(RESIST_HEAT in mutations)) + var/pressure_damage = min( ( (adjusted_pressure / species.hazard_high_pressure) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) + take_overall_damage(brute=pressure_damage, used_weapon = "High Pressure") + throw_alert("pressure", /obj/screen/alert/highpressure, 2) + else + clear_alert("pressure") else if(adjusted_pressure >= species.warning_high_pressure) throw_alert("pressure", /obj/screen/alert/highpressure, 1) else if(adjusted_pressure >= species.warning_low_pressure) @@ -469,6 +472,8 @@ /mob/living/carbon/human/handle_fire() if(..()) return + if(RESIST_HEAT in mutations) + return var/thermal_protection = 0 //Simple check to estimate how protected we are against multiple temperatures if(wear_suit) if(wear_suit.max_heat_protection_temperature >= FIRE_SUIT_MAX_TEMP_PROTECT) @@ -547,11 +552,13 @@ return thermal_protection_flags /mob/living/carbon/human/proc/get_heat_protection(temperature) //Temperature is the temperature you're being exposed to. + + if(RESIST_HEAT in mutations) + return 1 + var/thermal_protection_flags = get_heat_protection_flags(temperature) var/thermal_protection = 0.0 - if(RESIST_HEAT in mutations) - return 1 if(thermal_protection_flags) if(thermal_protection_flags & HEAD) thermal_protection += THERMAL_PROTECTION_HEAD diff --git a/code/modules/mob/living/carbon/human/login.dm b/code/modules/mob/living/carbon/human/login.dm index c9c23b31857..d4b160509ea 100644 --- a/code/modules/mob/living/carbon/human/login.dm +++ b/code/modules/mob/living/carbon/human/login.dm @@ -4,5 +4,4 @@ if(species && species.ventcrawler) to_chat(src, "You can ventcrawl! Use alt+click on vents to quickly travel about the station.") update_pipe_vision() - update_hud() return diff --git a/code/modules/mob/living/carbon/human/species/plasmaman.dm b/code/modules/mob/living/carbon/human/species/plasmaman.dm index 5bced02a651..76c06871250 100644 --- a/code/modules/mob/living/carbon/human/species/plasmaman.dm +++ b/code/modules/mob/living/carbon/human/species/plasmaman.dm @@ -186,7 +186,7 @@ H.emote(pick("giggle", "laugh")) SA.moles = 0 - if( (abs(310.15 - breath.temperature) > 50) && !(RESIST_HEAT in H.mutations)) // Hot air hurts :( + if(abs(310.15 - breath.temperature) > 50) // Hot air hurts :( if(H.status_flags & GODMODE) return 1 //godmode if(breath.temperature < cold_level_1) diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 28da2348c23..03091a7e50f 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -333,7 +333,7 @@ return 1 /datum/species/proc/handle_temperature(datum/gas_mixture/breath, var/mob/living/carbon/human/H) // called by human/life, handles temperatures - if( (abs(310.15 - breath.temperature) > 50) && !(RESIST_HEAT in H.mutations)) // Hot air hurts :( + if(abs(310.15 - breath.temperature) > 50) // Hot air hurts :( if(H.status_flags & GODMODE) return 1 //godmode if(breath.temperature < cold_level_1) if(prob(20)) @@ -646,11 +646,11 @@ H.healthdoll.overlays += image('icons/mob/screen_gen.dmi',"[O.limb_name][icon_num]") switch(H.nutrition) - if(450 to INFINITY) + if(NUTRITION_LEVEL_FULL to INFINITY) H.throw_alert("nutrition", /obj/screen/alert/fat) - if(350 to 450) + if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FULL) H.clear_alert("nutrition") - if(250 to 350) + if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY) H.throw_alert("nutrition", /obj/screen/alert/hungry) else H.throw_alert("nutrition", /obj/screen/alert/starving) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 7e4ba1d7cdd..004f54a45ba 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -72,7 +72,6 @@ There are several things that need to be remembered: update_body() //Handles updating your mob's icon to reflect their gender/race/complexion etc update_hair() //Handles updating your hair overlay (used to be update_face, but mouth and ...eyes were merged into update_body) - update_targeted() // Updates the target overlay when someone points a gun at you > All of these procs update our overlays_lying and overlays_standing, and then call update_icons() by default. If you wish to update several overlays at once, you can set the argument to 0 to disable the update and call @@ -124,9 +123,6 @@ Please contact me on #coderbus IRC. ~Carn x //this proc is messy as I was forced to include some old laggy cloaking code to it so that I don't break cloakers //I'll work on removing that stuff by rewriting some of the cloaking stuff at a later date. /mob/living/carbon/human/update_icons() - - update_hud() //TODO: remove the need for this - var/stealth = 0 var/obj/item/clothing/suit/armor/abductor/vest/V // Begin the most snowflakey bullshit code I've ever written. I'm so sorry, but there was no other way. for(V in list(wear_suit)) @@ -365,6 +361,9 @@ var/global/list/damage_icon_parts = list() if(m_style && m_style != "None") var/datum/sprite_accessory/marking_style = marking_styles_list[m_style] if(marking_style) + var/obj/item/organ/external/head/head_organ = get_organ("head") + if((!head_organ || head_organ.is_stump() || (head_organ.status & ORGAN_DESTROYED)) && marking_style.marking_location == "head") + return //If the head is destroyed and it is the organ the marking is located on, get us out of here. This prevents floating optical markings on decapitated IPCs, for example. var/icon/markings_s = new/icon("icon" = marking_style.icon, "icon_state" = "[marking_style.icon_state]_s") if(marking_style.do_colouration) markings_s.Blend(rgb(r_markings, g_markings, b_markings), ICON_ADD) @@ -401,7 +400,8 @@ var/global/list/damage_icon_parts = list() var/icon/head_accessory_s = new/icon("icon" = head_accessory_style.icon, "icon_state" = "[head_accessory_style.icon_state]_s") if(head_accessory_style.do_colouration) head_accessory_s.Blend(rgb(r_headacc, g_headacc, b_headacc), ICON_ADD) - head_accessory_standing.Blend(head_accessory_s, ICON_OVERLAY) + head_accessory_standing = head_accessory_s //head_accessory_standing.Blend(head_accessory_s, ICON_OVERLAY) + //Having it this way preserves animations. Useful for animated antennae. else //warning("Invalid ha_style for [species.name]: [ha_style]") @@ -441,7 +441,8 @@ var/global/list/damage_icon_parts = list() else if(hair_style.do_colouration) hair_s.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) - hair_standing.Blend(hair_s, ICON_OVERLAY) + hair_standing = hair_s //hair_standing.Blend(hair_s, ICON_OVERLAY) + //Having it this way preserves animations. Useful for IPC screens. else //warning("Invalid h_style for [species.name]: [h_style]") //hair_standing.Blend(debrained_s, ICON_OVERLAY)//how does i overlay for fish? @@ -506,23 +507,6 @@ var/global/list/damage_icon_parts = list() add_image = 1 for(var/mut in mutations) switch(mut) - /* - if(HULK) - if(fat) - standing.underlays += "hulk_[fat]_s" - else - standing.underlays += "hulk_[g]_s" - add_image = 1 - if(RESIST_COLD) - standing.underlays += "fire[fat]_s" - add_image = 1 - if(RESIST_HEAT) - standing.underlays += "cold[fat]_s" - add_image = 1 - if(TK) - standing.underlays += "telekinesishead[fat]_s" - add_image = 1 - */ if(LASER) standing.overlays += "lasereyes_s" add_image = 1 @@ -549,15 +533,6 @@ var/global/list/damage_icon_parts = list() update_fhair(0) if(update_icons) update_icons() -//Call when target overlay should be added/removed -/mob/living/carbon/human/update_targeted(var/update_icons=1) - if (targeted_by && target_locked) - overlays_standing[TARGETED_LAYER] = target_locked - else if (!targeted_by && target_locked) - qdel(target_locked) - if (!targeted_by) - overlays_standing[TARGETED_LAYER] = null - if(update_icons) update_icons() /mob/living/carbon/human/update_fire() remove_overlay(FIRE_LAYER) @@ -598,15 +573,23 @@ var/global/list/damage_icon_parts = list() update_inv_wear_pda(0) UpdateDamageIcon() update_icons() - //Hud Stuff - update_hud() update_fire() /* --------------------------------------- */ //vvvvvv UPDATE_INV PROCS vvvvvv /mob/living/carbon/human/update_inv_w_uniform(var/update_icons=1) - if(w_uniform && istype(w_uniform, /obj/item/clothing/under) ) - w_uniform.screen_loc = ui_iclothing + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[slot_w_uniform] + if(inv) + inv.update_icon() + + if(w_uniform && istype(w_uniform, /obj/item/clothing/under)) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + w_uniform.screen_loc = ui_iclothing //...draw the item in the inventory screen + client.screen += w_uniform //Either way, add the item to the HUD + var/t_color = w_uniform.item_color if(!t_color) t_color = icon_state var/image/standing = image("icon_state" = "[t_color]_s") @@ -654,8 +637,17 @@ var/global/list/damage_icon_parts = list() if(update_icons) update_icons() /mob/living/carbon/human/update_inv_wear_id(var/update_icons=1) + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_id] + if(inv) + inv.update_icon() + if(wear_id) - wear_id.screen_loc = ui_id //TODO + if(client && hud_used && hud_used.hud_shown) + wear_id.screen_loc = ui_id + client.screen += wear_id + if(w_uniform && w_uniform:displays_id) overlays_standing[ID_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "id") else @@ -666,7 +658,18 @@ var/global/list/damage_icon_parts = list() if(update_icons) update_icons() /mob/living/carbon/human/update_inv_gloves(var/update_icons=1) + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[slot_gloves] + if(inv) + inv.update_icon() + if(gloves) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + gloves.screen_loc = ui_gloves //...draw the item in the inventory screen + client.screen += gloves //Either way, add the item to the HUD + var/t_state = gloves.item_state if(!t_state) t_state = gloves.icon_state @@ -695,7 +698,17 @@ var/global/list/damage_icon_parts = list() /mob/living/carbon/human/update_inv_glasses(var/update_icons=1) + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[slot_glasses] + if(inv) + inv.update_icon() + if(glasses) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + glasses.screen_loc = ui_glasses //...draw the item in the inventory screen + client.screen += glasses //Either way, add the item to the HUD if(glasses.icon_override) overlays_standing[GLASSES_LAYER] = image("icon" = glasses.icon_override, "icon_state" = "[glasses.icon_state]") @@ -709,8 +722,23 @@ var/global/list/damage_icon_parts = list() if(update_icons) update_icons() /mob/living/carbon/human/update_inv_ears(var/update_icons=1) + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[slot_l_ear] + if(inv) + inv.update_icon() + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[slot_r_ear] + if(inv) + inv.update_icon() + if(l_ear || r_ear) if(l_ear) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + l_ear.screen_loc = ui_l_ear //...draw the item in the inventory screen + client.screen += l_ear //Either way, add the item to the HUD var/t_type = l_ear.icon_state if(l_ear.icon_override) @@ -723,6 +751,10 @@ var/global/list/damage_icon_parts = list() overlays_standing[EARS_LAYER] = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]") if(r_ear) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + r_ear.screen_loc = ui_r_ear //...draw the item in the inventory screen + client.screen += r_ear //Either way, add the item to the HUD var/t_type = r_ear.icon_state if(r_ear.icon_override) @@ -739,7 +771,17 @@ var/global/list/damage_icon_parts = list() if(update_icons) update_icons() /mob/living/carbon/human/update_inv_shoes(var/update_icons=1) + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[slot_shoes] + if(inv) + inv.update_icon() + if(shoes) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + shoes.screen_loc = ui_shoes //...draw the item in the inventory screen + client.screen += shoes //Either way, add the item to the HUD var/image/standing if(shoes.icon_override) @@ -765,7 +807,17 @@ var/global/list/damage_icon_parts = list() if(update_icons) update_icons() /mob/living/carbon/human/update_inv_s_store(var/update_icons=1) + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[slot_s_store] + if(inv) + inv.update_icon() + if(s_store) + if(client && hud_used && hud_used.hud_shown) + s_store.screen_loc = ui_sstore1 + client.screen += s_store + var/t_state = s_store.item_state if(!t_state) t_state = s_store.icon_state @@ -778,8 +830,13 @@ var/global/list/damage_icon_parts = list() /mob/living/carbon/human/update_inv_head(var/update_icons=1) + ..() + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[slot_head] + if(inv) + inv.update_icon() + if(head) - head.screen_loc = ui_head //TODO var/image/standing if(head.icon_override) standing = image("icon" = head.icon_override, "icon_state" = "[head.icon_state]") @@ -800,8 +857,17 @@ var/global/list/damage_icon_parts = list() if(update_icons) update_icons() /mob/living/carbon/human/update_inv_belt(var/update_icons=1) + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[slot_belt] + if(inv) + inv.update_icon() + + if(hud_used.hud_shown && belt) + client.screen += belt + belt.screen_loc = ui_belt + if(belt) - belt.screen_loc = ui_belt //TODO var/t_state = belt.item_state if(!t_state) t_state = belt.icon_state @@ -818,8 +884,17 @@ var/global/list/damage_icon_parts = list() /mob/living/carbon/human/update_inv_wear_suit(var/update_icons=1) - if( wear_suit && istype(wear_suit, /obj/item/clothing/suit) ) //TODO check this - wear_suit.screen_loc = ui_oclothing //TODO + + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_suit] + if(inv) + inv.update_icon() + + if(wear_suit && istype(wear_suit, /obj/item/clothing/suit)) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + wear_suit.screen_loc = ui_oclothing //TODO //...draw the item in the inventory screen + client.screen += wear_suit //Either way, add the item to the HUD var/image/standing if(wear_suit.icon_override) @@ -863,19 +938,44 @@ var/global/list/damage_icon_parts = list() if(update_icons) update_icons() -/mob/living/carbon/human/update_inv_pockets(var/update_icons=1) - if(l_store) l_store.screen_loc = ui_storage1 //TODO - if(r_store) r_store.screen_loc = ui_storage2 //TODO - if(update_icons) update_icons() +/mob/living/carbon/human/update_inv_pockets() + if(client && hud_used) + var/obj/screen/inventory/inv -/mob/living/carbon/human/update_inv_wear_pda(var/update_icons=1) - if(wear_pda) wear_pda.screen_loc = ui_pda - if(update_icons) update_icons() + inv = hud_used.inv_slots[slot_l_store] + if(inv) + inv.update_icon() -/mob/living/carbon/human/update_inv_wear_mask(var/update_icons=1) - if( wear_mask && ( istype(wear_mask, /obj/item/clothing/mask) || istype(wear_mask, /obj/item/clothing/accessory) ) ) - wear_mask.screen_loc = ui_mask //TODO + inv = hud_used.inv_slots[slot_r_store] + if(inv) + inv.update_icon() + if(hud_used.hud_shown) + if(l_store) + client.screen += l_store + l_store.screen_loc = ui_storage1 + + if(r_store) + client.screen += r_store + r_store.screen_loc = ui_storage2 + +/mob/living/carbon/human/update_inv_wear_pda() + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_pda] + if(inv) + inv.update_icon() + + if(wear_pda) + client.screen += wear_pda + wear_pda.screen_loc = ui_pda + +/mob/living/carbon/human/update_inv_wear_mask(var/update_icons = 1) + ..() + if(client && hud_used) + var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_mask] + if(inv) + inv.update_icon() + if(wear_mask && (istype(wear_mask, /obj/item/clothing/mask) || istype(wear_mask, /obj/item/clothing/accessory))) var/image/standing if(wear_mask.icon_override) standing = image("icon" = wear_mask.icon_override, "icon_state" = "[wear_mask.icon_state]") @@ -884,10 +984,10 @@ var/global/list/damage_icon_parts = list() else standing = image("icon" = 'icons/mob/mask.dmi', "icon_state" = "[wear_mask.icon_state]") - if( !istype(wear_mask, /obj/item/clothing/mask/cigarette) && wear_mask.blood_DNA ) + if(!istype(wear_mask, /obj/item/clothing/mask/cigarette) && wear_mask.blood_DNA) var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "maskblood") bloodsies.color = wear_mask.blood_color - standing.overlays += bloodsies + standing.overlays += bloodsies overlays_standing[FACEMASK_LAYER] = standing else overlays_standing[FACEMASK_LAYER] = null @@ -895,9 +995,8 @@ var/global/list/damage_icon_parts = list() /mob/living/carbon/human/update_inv_back(var/update_icons=1) + ..() if(back) - back.screen_loc = ui_back //TODO - //determine the icon to use var/icon/standing if(back.icon_override) @@ -911,15 +1010,6 @@ var/global/list/damage_icon_parts = list() else standing = image("icon" = 'icons/mob/back.dmi', "icon_state" = "[back.icon_state]") - /* - //determine state to use - var/overlay_state - if(back.item_state) - overlay_state = back.item_state - else - overlay_state = back.icon_state - */ - //create the image overlays_standing[BACK_LAYER] = standing else @@ -927,37 +1017,14 @@ var/global/list/damage_icon_parts = list() if(update_icons) update_icons() - -/mob/living/carbon/human/update_hud() //TODO: do away with this if possible - if(client) - for(var/obj/item/I in get_all_slots()) - client.screen |= I // Items only please, no arms allowed - if(hud_used) - hud_used.hidden_inventory_update() //Updates the screenloc of the items on the 'other' inventory bar - update_inv_handcuffed(0) // update handcuff overlay - - /mob/living/carbon/human/update_inv_handcuffed(var/update_icons=1) + overlays_standing[HANDCUFF_LAYER] = null if(handcuffed) - drop_r_hand() - drop_l_hand() - stop_pulling() //TODO: should be handled elsewhere - if(hud_used) //hud handcuff icons - var/obj/screen/inventory/R = hud_used.r_hand_hud_object - var/obj/screen/inventory/L = hud_used.l_hand_hud_object - R.overlays += image("icon"='icons/mob/screen_gen.dmi', "icon_state"="markus") - L.overlays += image("icon"='icons/mob/screen_gen.dmi', "icon_state"="gabrielle") if(istype(handcuffed, /obj/item/weapon/restraints/handcuffs/pinkcuffs)) overlays_standing[HANDCUFF_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "pinkcuff1") else overlays_standing[HANDCUFF_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "handcuff1") - else - overlays_standing[HANDCUFF_LAYER] = null - if(hud_used) - var/obj/screen/inventory/R = hud_used.r_hand_hud_object - var/obj/screen/inventory/L = hud_used.l_hand_hud_object - R.overlays.Cut() - L.overlays.Cut() + if(update_icons) update_icons() @@ -978,36 +1045,57 @@ var/global/list/damage_icon_parts = list() /mob/living/carbon/human/update_inv_r_hand(var/update_icons=1) + ..() if(r_hand) - r_hand.screen_loc = ui_rhand //TODO var/t_state = r_hand.item_state - if(!t_state) t_state = r_hand.icon_state + if(!t_state) + t_state = r_hand.icon_state - var/image/I = image("icon" = r_hand.righthand_file, "icon_state"="[t_state]") + var/image/I = image("icon" = r_hand.righthand_file, "icon_state" = "[t_state]") I = center_image(I, r_hand.inhand_x_dimension, r_hand.inhand_y_dimension) overlays_standing[R_HAND_LAYER] = I - - if (handcuffed) drop_r_hand() else overlays_standing[R_HAND_LAYER] = null - if(update_icons) update_icons() + if(update_icons) + update_icons() /mob/living/carbon/human/update_inv_l_hand(var/update_icons=1) + ..() if(l_hand) - l_hand.screen_loc = ui_lhand //TODO var/t_state = l_hand.item_state - if(!t_state) t_state = l_hand.icon_state + if(!t_state) + t_state = l_hand.icon_state - var/image/I = image("icon" = l_hand.lefthand_file, "icon_state"="[t_state]") + var/image/I = image("icon" = l_hand.lefthand_file, "icon_state" = "[t_state]") I = center_image(I, l_hand.inhand_x_dimension, l_hand.inhand_y_dimension) overlays_standing[L_HAND_LAYER] = I - - if (handcuffed) drop_l_hand() else overlays_standing[L_HAND_LAYER] = null - if(update_icons) update_icons() + if(update_icons) + update_icons() +//human HUD updates for items in our inventory + +//update whether our head item appears on our hud. +/mob/living/carbon/human/update_hud_head(obj/item/I) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) + I.screen_loc = ui_head + client.screen += I + +//update whether our mask item appears on our hud. +/mob/living/carbon/human/update_hud_wear_mask(obj/item/I) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) + I.screen_loc = ui_mask + client.screen += I + +//update whether our back item appears on our hud. +/mob/living/carbon/human/update_hud_back(obj/item/I) + if(client && hud_used && hud_used.hud_shown) + I.screen_loc = ui_back + client.screen += I /mob/living/carbon/human/proc/update_tail_layer(var/update_icons=1) diff --git a/code/modules/mob/living/carbon/slime/login.dm b/code/modules/mob/living/carbon/slime/login.dm deleted file mode 100644 index d3ac320f2f4..00000000000 --- a/code/modules/mob/living/carbon/slime/login.dm +++ /dev/null @@ -1,4 +0,0 @@ -/mob/living/carbon/slime/Login() - ..() - update_hud() - return diff --git a/code/modules/mob/living/carbon/superheroes.dm b/code/modules/mob/living/carbon/superheroes.dm index d8f741928fd..08f5089a200 100644 --- a/code/modules/mob/living/carbon/superheroes.dm +++ b/code/modules/mob/living/carbon/superheroes.dm @@ -107,8 +107,8 @@ H.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(H), slot_shoes) H.equip_to_slot_or_del(new /obj/item/clothing/under/color/brown(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/corgisuit(H), slot_wear_suit) - H.equip_to_slot_or_del(new /obj/item/clothing/head/corgi(H), slot_head) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/corgisuit/super_hero(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/clothing/head/corgi/super_hero(H), slot_head) H.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/yellow(H), slot_gloves) H.equip_to_slot_or_del(new /obj/item/weapon/bedsheet/orange(H), slot_back) @@ -126,8 +126,8 @@ H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black/greytide(H), slot_shoes) H.equip_to_slot_or_del(new /obj/item/clothing/under/color/grey(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/corgisuit/en(H), slot_wear_suit) - H.equip_to_slot_or_del(new /obj/item/clothing/head/corgi/en(H), slot_head) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/corgisuit/super_hero/en(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/clothing/head/corgi/super_hero/en(H), slot_head) H.equip_to_slot_or_del(new /obj/item/weapon/bedsheet/cult(H), slot_back) diff --git a/code/modules/mob/living/carbon/update_icons.dm b/code/modules/mob/living/carbon/update_icons.dm index e22ad5e66dc..05224c28dde 100644 --- a/code/modules/mob/living/carbon/update_icons.dm +++ b/code/modules/mob/living/carbon/update_icons.dm @@ -32,4 +32,59 @@ floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart it in next life(). /mob/living/carbon/proc/handle_transform_change() + return + +//update whether handcuffs appears on our hud. +/mob/living/carbon/proc/update_hud_handcuffed() + if(hud_used) + var/obj/screen/inventory/R = hud_used.inv_slots[slot_r_hand] + var/obj/screen/inventory/L = hud_used.inv_slots[slot_l_hand] + if(R && L) + R.update_icon() + L.update_icon() + +/mob/living/carbon/update_inv_r_hand(ignore_cuffs) + if(handcuffed && !ignore_cuffs) + drop_r_hand() + return + if(r_hand) + if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD) + r_hand.screen_loc = ui_rhand + client.screen += r_hand + +/mob/living/carbon/update_inv_l_hand(ignore_cuffs) + if(handcuffed && !ignore_cuffs) + drop_l_hand() + return + if(l_hand) + if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD) + l_hand.screen_loc = ui_lhand + client.screen += l_hand + +/mob/living/carbon/update_inv_wear_mask() + if(istype(wear_mask, /obj/item/clothing/mask)) + update_hud_wear_mask(wear_mask) + +/mob/living/carbon/update_inv_back() + if(client && hud_used && hud_used.inv_slots[slot_back]) + var/obj/screen/inventory/inv = hud_used.inv_slots[slot_back] + inv.update_icon() + + if(back) + update_hud_back(back) + +/mob/living/carbon/update_inv_head() + if(head) + update_hud_head(head) + +//update whether our head item appears on our hud. +/mob/living/carbon/proc/update_hud_head(obj/item/I) + return + +//update whether our mask item appears on our hud. +/mob/living/carbon/proc/update_hud_wear_mask(obj/item/I) + return + +//update whether our back item appears on our hud. +/mob/living/carbon/proc/update_hud_back(obj/item/I) return \ No newline at end of file diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 6e47fd45626..866c01c9702 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -15,7 +15,6 @@ if(BRUTE) adjustBruteLoss(damage * blocked) if(BURN) - if(RESIST_HEAT in mutations) damage = 0 adjustFireLoss(damage * blocked) if(TOX) adjustToxLoss(damage * blocked) diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 59a208d7c2e..7e70e3a613f 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -265,7 +265,7 @@ if(!hud_used) return if(!client) return - if(hud_used.hud_shown != 1) //Hud toggled to minimal + if(!hud_used.hud_shown) return client.screen -= hud_used.hide_actions_toggle diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index e29444641c4..37b326dc4c5 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -92,9 +92,6 @@ //sort of a legacy burn method for /electrocute, /shock, and the e_chair /mob/living/proc/burn_skin(burn_amount) if(istype(src, /mob/living/carbon/human)) -// to_chat(world, "DEBUG: burn_skin(), mutations=[mutations]") - if (RESIST_HEAT in src.mutations) //fireproof - return 0 var/mob/living/carbon/human/H = src //make this damage method divide the damage to be done among all the body parts, then burn each body part for that much damage. will have better effect then just randomly picking a body part var/divided_damage = (burn_amount)/(H.organs.len) var/extradam = 0 //added to when organ is at max dam @@ -688,38 +685,71 @@ gib() return -/atom/movable/proc/do_attack_animation(atom/A) +/atom/movable/proc/do_attack_animation(atom/A, end_pixel_y) var/pixel_x_diff = 0 var/pixel_y_diff = 0 + var/final_pixel_y = initial(pixel_y) + if(end_pixel_y) + final_pixel_y = end_pixel_y + var/direction = get_dir(src, A) - switch(direction) - if(NORTH) - pixel_y_diff = 8 - if(SOUTH) - pixel_y_diff = -8 - if(EAST) - pixel_x_diff = 8 - if(WEST) - pixel_x_diff = -8 - if(NORTHEAST) - pixel_x_diff = 8 - pixel_y_diff = 8 - if(NORTHWEST) - pixel_x_diff = -8 - pixel_y_diff = 8 - if(SOUTHEAST) - pixel_x_diff = 8 - pixel_y_diff = -8 - if(SOUTHWEST) - pixel_x_diff = -8 - pixel_y_diff = -8 + if(direction & NORTH) + pixel_y_diff = 8 + else if(direction & SOUTH) + pixel_y_diff = -8 + + if(direction & EAST) + pixel_x_diff = 8 + else if(direction & WEST) + pixel_x_diff = -8 + animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, time = 2) - animate(pixel_x = initial(pixel_x), pixel_y = initial(pixel_y), time = 2) + animate(pixel_x = initial(pixel_x), pixel_y = final_pixel_y, time = 2) + /mob/living/do_attack_animation(atom/A) - ..() + var/final_pixel_y = get_standard_pixel_y_offset(lying) + ..(A, final_pixel_y) floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement. + // What icon do we use for the attack? + var/image/I + if(hand && l_hand) // Attacked with item in left hand. + I = image(l_hand.icon, A, l_hand.icon_state, A.layer + 1) + else if(!hand && r_hand) // Attacked with item in right hand. + I = image(r_hand.icon, A, r_hand.icon_state, A.layer + 1) + else // Attacked with a fist? + return + + // Who can see the attack? + var/list/viewing = list() + for(var/mob/M in viewers(A)) + if(M.client && M.client.prefs.show_ghostitem_attack) + viewing |= M.client + flick_overlay(I, viewing, 5) // 5 ticks/half a second + + // Scale the icon. + I.transform *= 0.75 + // The icon should not rotate. + I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA + + // Set the direction of the icon animation. + var/direction = get_dir(src, A) + if(direction & NORTH) + I.pixel_y = -16 + else if(direction & SOUTH) + I.pixel_y = 16 + + if(direction & EAST) + I.pixel_x = -16 + else if(direction & WEST) + I.pixel_x = 16 + + if(!direction) // Attacked self?! + I.pixel_z = 16 + + // And animate the attack! + animate(I, alpha = 175, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3) /atom/movable/proc/receive_damage(atom/A) var/pixel_x_diff = rand(-3,3) diff --git a/code/modules/mob/living/silicon/emote.dm b/code/modules/mob/living/silicon/emote.dm index cd6bd83af64..c5c3603466e 100644 --- a/code/modules/mob/living/silicon/emote.dm +++ b/code/modules/mob/living/silicon/emote.dm @@ -5,9 +5,6 @@ param = copytext(act, t1 + 1, length(act) + 1) act = copytext(act, 1, t1) - if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' - act = copytext(act,1,length(act)) - //Emote Cooldown System (it's so simple!) // proc/handle_emote_CD() located in [code\modules\mob\emote.dm] var/on_CD = 0 @@ -15,7 +12,8 @@ //Cooldown-inducing emotes if("scream", "screams") on_CD = handle_emote_CD(50) //longer cooldown - if("ping","buzz","beep","yes","no") //halt is exempt because it's used to stop criminal scum //WHOEVER THOUGHT THAT WAS A GOOD IDEA IS GOING TO GET SHOT. + if("ping","pings","buzz","buzzs","buzzes","beep","beeps","yes","no") + //halt is exempt because it's used to stop criminal scum //WHOEVER THOUGHT THAT WAS A GOOD IDEA IS GOING TO GET SHOT. on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm //Everything else, including typos of the above emotes else @@ -26,7 +24,7 @@ //--FalseIncarnate switch(act) - if("ping") + if("ping","pings") var/M = null if(param) for (var/mob/A in view(null, null)) @@ -43,7 +41,7 @@ playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) m_type = 2 - if("buzz") + if("buzz","buzzs","buzzes") var/M = null if(param) for (var/mob/A in view(null, null)) @@ -60,7 +58,7 @@ playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0) m_type = 2 - if("beep") + if("beep","beeps") var/M = null if(param) for (var/mob/A in view(null, null)) @@ -116,4 +114,7 @@ playsound(src.loc, 'sound/goonstation/voice/robot_scream.ogg', 80, 0) m_type = 2 + if("help") + to_chat(src, "yes, no, beep, ping, buzz") + ..(act, m_type, message) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/pai/emote.dm b/code/modules/mob/living/silicon/pai/emote.dm index 8328290ba80..a418c0972d5 100644 --- a/code/modules/mob/living/silicon/pai/emote.dm +++ b/code/modules/mob/living/silicon/pai/emote.dm @@ -1,6 +1,2 @@ /mob/living/silicon/pai/emote(var/act, var/m_type=1, var/message = null) - switch(act) - if ("help") - to_chat(src, "ping, beep, buzz.") - - ..(act, m_type, message) \ No newline at end of file + ..(act, m_type, message) diff --git a/code/modules/mob/living/silicon/pai/recruit.dm b/code/modules/mob/living/silicon/pai/recruit.dm index 980e1bb09ee..949c946a6c8 100644 --- a/code/modules/mob/living/silicon/pai/recruit.dm +++ b/code/modules/mob/living/silicon/pai/recruit.dm @@ -354,7 +354,7 @@ var/datum/paiController/paiController // Global handler for pAI candidates to_chat(O, "\blue A pAI card is looking for personalities. (Teleport | Sign Up)") //question(O.client) proc/check_recruit(var/mob/dead/observer/O) - if(jobban_isbanned(O, "pAI") || jobban_isbanned(O,"nonhumandept")) + if(jobban_isbanned(O, ROLE_PAI) || jobban_isbanned(O,"nonhumandept")) return 0 if(!player_old_enough_antag(O.client,ROLE_PAI)) return 0 diff --git a/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm b/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm index 305c89e87cb..151fc6de51d 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm @@ -38,10 +38,9 @@ set desc = "Activate a low power omnidirectional LED. Toggled on or off." set category = "Drone" - if(luminosity) - set_light(0) - return - set_light(2) + if(lamp_intensity) + lamp_intensity = lamp_max // setting this to lamp_max will make control_headlamp shutoff the lamp + control_headlamp() //Actual picking-up event. /mob/living/silicon/robot/drone/attack_hand(mob/living/carbon/human/M as mob) diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm index 0c841f41207..30273aec02c 100644 --- a/code/modules/mob/living/silicon/robot/emote.dm +++ b/code/modules/mob/living/silicon/robot/emote.dm @@ -5,15 +5,12 @@ param = copytext(act, t1 + 1, length(act) + 1) act = copytext(act, 1, t1) - if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' - act = copytext(act,1,length(act)) - //Emote Cooldown System (it's so simple!) // proc/handle_emote_CD() located in [code\modules\mob\emote.dm] var/on_CD = 0 switch(act) //Cooldown-inducing emotes - if("law","flip","halt") //halt is exempt because it's used to stop criminal scum //WHOEVER THOUGHT THAT WAS A GOOD IDEA IS GOING TO GET SHOT. + if("law","flip","flips","halt") //halt is exempt because it's used to stop criminal scum //WHOEVER THOUGHT THAT WAS A GOOD IDEA IS GOING TO GET SHOT. on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm //Everything else, including typos of the above emotes else @@ -25,7 +22,7 @@ switch(act) - if ("salute") + if ("salute","salutes") if (!src.buckled) var/M = null if (param) @@ -41,7 +38,7 @@ else message = "[src] salutes." m_type = 1 - if ("bow") + if ("bow","bows") if (!src.buckled) var/M = null if (param) @@ -58,16 +55,16 @@ message = "[src] bows." m_type = 1 - if ("clap") + if ("clap","claps") if (!src.restrained()) message = "[src] claps." m_type = 2 - if ("flap") + if ("flap","flaps") if (!src.restrained()) message = "[src] flaps its wings." m_type = 2 - if ("aflap") + if ("aflap","aflaps") if (!src.restrained()) message = "[src] flaps its wings ANGRILY!" m_type = 2 @@ -76,11 +73,11 @@ message = "[src] twitches violently." m_type = 1 - if ("twitch_s") + if ("twitch_s","twitches") message = "[src] twitches." m_type = 1 - if ("nod") + if ("nod","nods") message = "[src] nods." m_type = 1 @@ -88,7 +85,7 @@ message = "[src] shudders violently for a moment, then becomes motionless, its eyes slowly darkening." m_type = 1 - if ("glare") + if ("glare","glares") var/M = null if (param) for (var/mob/A in view(null, null)) @@ -103,7 +100,7 @@ else message = "[src] glares." - if ("stare") + if ("stare","stares") var/M = null if (param) for (var/mob/A in view(null, null)) @@ -118,7 +115,7 @@ else message = "[src] stares." - if ("look") + if ("look","looks") var/M = null if (param) for (var/mob/A in view(null, null)) @@ -154,12 +151,12 @@ else to_chat(src, "You are not security.") - if ("flip") + if ("flip","flips") m_type = 1 message = "[src] does a flip!" src.SpinAnimation(5,1) if ("help") - to_chat(src, "salute, bow-(none)/mob, clap, flap, aflap, twitch, twitch_s, nod, deathgasp, glare-(none)/mob, stare-(none)/mob, look, beep, ping, \nbuzz, law, halt") + to_chat(src, "salute, bow-(none)/mob, clap, flap, aflap, twitch, twitches, nod, deathgasp, glare-(none)/mob, stare-(none)/mob, look,\n law, halt") ..(act, m_type, message) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 58f965dad7e..cba9fb4c1e1 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -1023,14 +1023,6 @@ var/list/robot_verbs_default = list( overlays += "minerjetpack-[icon_state]" update_fire() -//Call when target overlay should be added/removed -/mob/living/silicon/robot/update_targeted() - if(!targeted_by && target_locked) - qdel(target_locked) - update_icons() - if (targeted_by && target_locked) - overlays += target_locked - /mob/living/silicon/robot/proc/installed_modules() if(weapon_lock) to_chat(src, "\red Weapon lock active, unable to use modules! Count:[weaponlock_time]") diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index c80fcd9a92c..3c5206ba3a5 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -306,6 +306,9 @@ if(!locked && !open) var/obj/item/device/paicard/card = W if(card.pai && card.pai.mind) + if(!card.pai.ckey || jobban_isbanned(card.pai, ROLE_SENTIENT)) + to_chat(user, "[W] is unable to establish a connection to [src].") + return if(!user.drop_item()) return W.forceMove(src) @@ -322,7 +325,7 @@ else to_chat(user, "The personality slot is locked.") else - to_chat(user, "[src] is not compatible with [W]") + to_chat(user, "[src] is not compatible with [W].") else if(istype(W, /obj/item/weapon/hemostat) && paicard) if(open) to_chat(user, "Close the access panel before manipulating the personality slot!") diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm index 86be6f3013c..5a2ef732eb5 100644 --- a/code/modules/mob/living/simple_animal/hostile/bees.dm +++ b/code/modules/mob/living/simple_animal/hostile/bees.dm @@ -144,7 +144,7 @@ if(beegent && isliving(target)) var/mob/living/L = target if(!isnull(target.reagents)) - beegent.reaction_mob(L, TOUCH) + beegent.reaction_mob(L, INGEST) L.reagents.add_reagent(beegent.id, rand(1,5)) target.attack_animal(src) diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index cc1de35947d..fd38b3e81c7 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -33,6 +33,8 @@ /mob/living/simple_animal/hostile/Life() . = ..() + if(ranged) + ranged_cooldown-- if(!.) walk(src, 0) return 0 @@ -46,8 +48,6 @@ /mob/living/simple_animal/hostile/handle_automated_action() if(AIStatus == AI_OFF) return 0 - if(ranged) - ranged_cooldown-- var/list/possible_targets = ListTargets() //we look around for potential targets and make it a list for later use. if(environment_smash) EscapeConfinement() diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index 84235f90979..5cf956e610a 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -31,12 +31,13 @@ client.images = null //remove the images such as AIs being unable to see runes client.screen = list() //remove hud items just in case - if(hud_used) - qdel(hud_used) //remove the hud objects - hud_used = null if(client.click_intercept) client.click_intercept.quit() // Let's not keep any old click_intercepts - hud_used = new /datum/hud(src) + + if(!hud_used) + create_mob_hud() + if(hud_used) + hud_used.show_hud(hud_used.hud_version) next_move = 1 sight |= SEE_SELF @@ -70,6 +71,8 @@ //readd this mob's HUDs (antag, med, etc) reload_huds() + add_click_catcher() + if(viewing_alternate_appearances && viewing_alternate_appearances.len) for(var/aakey in viewing_alternate_appearances) var/datum/alternate_appearance/AA = viewing_alternate_appearances[aakey] diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 4e5e6c9b21c..658959001a1 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1097,6 +1097,11 @@ var/list/slot_equipment_priority = list( \ /mob/proc/IsAdvancedToolUser()//This might need a rename but it should replace the can this mob use things check return 0 +/mob/proc/swap_hand() + return + +/mob/proc/activate_hand(selhand) + return /mob/proc/Jitter(amount) jitteriness = max(jitteriness, amount, 0) @@ -1269,8 +1274,8 @@ mob/proc/yank_out_object() set name = "Respawn as NPC" set category = "Ghost" - if(jobban_isbanned(usr, "NPC")) - to_chat(usr, "You are banned from playing as NPC's.") + if(jobban_isbanned(usr, ROLE_SENTIENT)) + to_chat(usr, "You are banned from playing as sentient animals.") return if(!ticker || ticker.current_state < 3) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index ac459679f10..8b4b39e006a 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -18,10 +18,6 @@ var/obj/screen/m_select = null var/obj/screen/healths = null var/obj/screen/throw_icon = null - var/obj/screen/gun/item/item_use_icon = null - var/obj/screen/gun/move/gun_move_icon = null - var/obj/screen/gun/run/gun_run_icon = null - var/obj/screen/gun/mode/gun_setting_icon = null /*A bunch of this stuff really needs to go under their own defines instead of being globally attached to mob. A variable should only be globally attached to turfs/objects/whatever, when it is in fact needed as such. diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index fcbcd410a89..98437a53ffd 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -24,6 +24,7 @@ layer = 21 item_state = "nothing" + icon = 'icons/mob/screen_gen.dmi' w_class = 5.0 diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index a967c2df779..468a6cfe9df 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -451,7 +451,7 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HARM) if("left") a_intent = intent_numeric((intent_numeric(a_intent)+3) % 4) if(hud_used && hud_used.action_intent) - hud_used.action_intent.icon_state = "intent_[a_intent]" + hud_used.action_intent.icon_state = "[a_intent]" else if(isrobot(src) || islarva(src)) switch(input) diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 68913c6ad25..117cf33ff52 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -149,11 +149,8 @@ winset(src, "mapwindow.map", "icon-size=[src.reset_stretch]") viewingCanvas = 0 mob.reset_view() - mob.button_pressed_F12() - if(!mob.hud_used.hud_shown) - mob.button_pressed_F12() - mob.update_hud() - mob.update_action_buttons() + if(mob.hud_used) + mob.hud_used.show_hud(HUD_STYLE_STANDARD) if(mob.control_object) Move_object(direct) @@ -240,7 +237,6 @@ move_delay = world.time//set move delay move_delay += T.slowdown mob.last_movement = world.time - mob.last_move_intent = world.time + 10 switch(mob.m_intent) if("run") if(mob.drowsyness > 0) diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index 23e3fb1d906..e5c0c6ab38c 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -43,6 +43,8 @@ // Restrict some styles to specific species var/list/species_allowed = list("Human", "Slime People") + var/models_allowed = list() //Specifies which, if any, hairstyles can be accessed by which prosthetics. Should equal the manufacturing company name in robolimbs.dm. + var/marking_location //Specifies which bodypart a body marking is located on. // Whether or not the accessory can be affected by colouration var/do_colouration = 1 @@ -57,7 +59,6 @@ */ /datum/sprite_accessory/hair - icon = 'icons/mob/human_face.dmi' // default icon for all hairs bald @@ -379,105 +380,169 @@ //////END VG HAIRSTYLES/////// ////////////////////////////// + ipc_screen_pink - name = "pink IPC screen" + name = "Pink IPC Screen" icon_state = "ipc_pink" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_red - name = "red IPC screen" + name = "Red IPC Screen" icon_state = "ipc_red" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_green - name = "green IPC screen" + name = "Green IPC Screen" icon_state = "ipc_green" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_blue - name = "blue IPC screen" + name = "Blue IPC Screen" icon_state = "ipc_blue" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_breakout - name = "breakout IPC screen" + name = "Breakout IPC Screen" icon_state = "ipc_breakout" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_eight - name = "eight IPC screen" + name = "Eight IPC Screen" icon_state = "ipc_eight" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_rainbow - name = "rainbow IPC screen" + name = "Rainbow IPC Screen" icon_state = "ipc_rainbow" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_goggles - name = "goggles IPC screen" + name = "Goggles IPC Screen" icon_state = "ipc_goggles" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_heart - name = "heart IPC screen" + name = "Heart IPC Screen" icon_state = "ipc_heart" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_monoeye - name = "monoeye IPC screen" + name = "Monoeye IPC Screen" icon_state = "ipc_monoeye" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_nature - name = "nature IPC screen" + name = "Nature IPC Screen" icon_state = "ipc_nature" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_orange - name = "orange IPC screen" + name = "Orange IPC Screen" icon_state = "ipc_orange" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_purple - name = "purple IPC screen" + name = "Purple IPC Screen" icon_state = "ipc_purple" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_shower - name = "shower IPC screen" + name = "Shower IPC Screen" icon_state = "ipc_shower" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_static - name = "static IPC screen" + name = "Static IPC Screen" icon_state = "ipc_static" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_yellow - name = "yellow IPC screen" + name = "Yellow IPC Screen" icon_state = "ipc_yellow" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_scrolling - name = "scanline IPC screen" + name = "Scanline IPC Screen" icon_state = "ipc_scroll" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_console - name = "console IPC screen" + name = "Console IPC Screen" icon_state = "ipc_console" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_rgb - name = "rgb IPC screen" + name = "RGB IPC Screen" icon_state = "ipc_rgb" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") ipc_screen_glider - name = "glider IPC screen" + name = "Glider IPC Screen" icon_state = "ipc_gol_glider" species_allowed = list("Machine") + models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.") + + hesphiastos_alt_off + name = "Dark Hesphiastos Screen" + icon_state = "hesphiastos_alt_off" + species_allowed = list("Machine") + models_allowed = list("Hesphiastos Industries alt.") + + hesphiastos_alt_pink + name = "Pink Hesphiastos Screen" + icon_state = "hesphiastos_alt_pink" + species_allowed = list("Machine") + models_allowed = list("Hesphiastos Industries alt.") + + hesphiastos_alt_orange + name = "Orange Hesphiastos Screen" + icon_state = "hesphiastos_alt_orange" + species_allowed = list("Machine") + models_allowed = list("Hesphiastos Industries alt.") + + hesphiastos_alt_goggle + name = "Goggles Hesphiastos Screen" + icon_state = "hesphiastos_alt_goggles" + species_allowed = list("Machine") + models_allowed = list("Hesphiastos Industries alt.") + + hesphiastos_alt_scroll + name = "Scrolling Hesphiastos Screen" + icon_state = "hesphiastos_alt_scroll" + species_allowed = list("Machine") + models_allowed = list("Hesphiastos Industries alt.") + + hesphiastos_alt_rgb + name = "RGB Hesphiastos Screen" + icon_state = "hesphiastos_alt_rgb" + species_allowed = list("Machine") + models_allowed = list("Hesphiastos Industries alt.") + + hesphiastos_alt_rainbow + name = "Rainbow Hesphiastos Screen" + icon_state = "hesphiastos_alt_rainbow" + species_allowed = list("Machine") + models_allowed = list("Hesphiastos Industries alt.") + /* /////////////////////////////////// @@ -496,8 +561,7 @@ name = "Shaved" icon_state = "bald" gender = NEUTER - species_allowed = list("Human", "Unathi", "Tajaran", "Skrell", "Vox", "Diona", "Kidan", "Greys", "Machine", "Vulpkanin", "Slime People") - + species_allowed = list("Human", "Unathi", "Tajaran", "Skrell", "Vox", "Diona", "Kidan", "Greys", "Vulpkanin", "Slime People") watson name = "Watson Mustache" @@ -1785,6 +1849,21 @@ icon_state = "antennae" species_allowed = list("Machine") +/datum/sprite_accessory/head_accessory/ipc_tv_antennae + name = "T.V. Antennae" + icon_state = "tvantennae" + species_allowed = list("Machine") + +/datum/sprite_accessory/head_accessory/ipc_tesla_antennae + name = "Tesla Antennae" + icon_state = "tesla" + species_allowed = list("Machine") + +/datum/sprite_accessory/head_accessory/ipc_light + name = "Head Light" + icon_state = "light" + species_allowed = list("Machine") + /* BODY MARKINGS */ @@ -1832,6 +1911,32 @@ name = "Humanoid Optics" species_allowed = list("Machine") icon_state = "optics" + models_allowed = list("Bishop Cybernetics", "Hesphiastos Industries", "Ward-Takahashi", "Xion Manufacturing Group", "Zeng-Hu Pharmaceuticals") //Should be the same as the manufacturing company of the limb in robolimbs.dm + marking_location = "head" + +/datum/sprite_accessory/body_markings/optics/bishop_alt + name = "Bishop Alt. Optics" + species_allowed = list("Machine") + icon_state = "bishop_alt_optics" + models_allowed = list("Bishop Cybernetics alt.") + +/datum/sprite_accessory/body_markings/optics/morpheus_alt + name = "Morpheus Alt. Optics" + species_allowed = list("Machine") + icon_state = "morpheus_alt_optics" + models_allowed = list("Morpheus Cyberkinetics alt.") + +/datum/sprite_accessory/body_markings/optics/wardtakahashi_alt + name = "Ward-Takahashi Alt. Optics" + species_allowed = list("Machine") + icon_state = "wardtakahashi_alt_optics" + models_allowed = list("Ward-Takahashi alt.") + +/datum/sprite_accessory/body_markings/optics/xion_alt + name = "Xion Alt. Optics" + species_allowed = list("Machine") + icon_state = "xion_alt_optics" + models_allowed = list("Xion Manufacturing Group alt.") /datum/sprite_accessory/body_markings/tattoo // Tattoos applied post-round startup with tattoo guns in item_defines.dm name = "base tattoo" diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 5e3641803ff..ac3dd8af716 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -346,10 +346,10 @@ if(ispath(MP, /mob/living/simple_animal/butterfly)) return 1 - if(ispath(MP, /mob/living/simple_animal/borer) && !jobban_isbanned(src, "alien") && !jobban_isbanned(src, "Syndicate")) + if(ispath(MP, /mob/living/simple_animal/borer) && !jobban_isbanned(src, ROLE_BORER) && !jobban_isbanned(src, "Syndicate")) return 1 - if(ispath(MP, /mob/living/simple_animal/diona) && !jobban_isbanned(src, "Dionaea")) + if(ispath(MP, /mob/living/simple_animal/diona) && !jobban_isbanned(src, ROLE_NYMPH)) return 1 return 0 diff --git a/code/modules/mob/update_icons.dm b/code/modules/mob/update_icons.dm index 0362ffa6097..8a1f1b04cb1 100644 --- a/code/modules/mob/update_icons.dm +++ b/code/modules/mob/update_icons.dm @@ -7,9 +7,6 @@ /mob/proc/update_icons() return -/mob/proc/update_hud() - return - /mob/proc/update_inv_handcuffed() return @@ -61,14 +58,11 @@ /mob/proc/update_inv_pockets() return -mob/proc/update_inv_wear_pda() +/mob/proc/update_inv_wear_pda() return /mob/proc/update_inv_ears() return -/mob/proc/update_targeted() - return - /mob/proc/update_transform() return \ No newline at end of file diff --git a/code/modules/ninja/suit/suit_initialisation.dm b/code/modules/ninja/suit/suit_initialisation.dm index f1abfbe725a..9954281b06f 100644 --- a/code/modules/ninja/suit/suit_initialisation.dm +++ b/code/modules/ninja/suit/suit_initialisation.dm @@ -28,7 +28,10 @@ sleep(10) to_chat(usr, "Disconnecting neural-net interface... Success.") - usr.hud_used.instantiate() + if(usr.hud_used) + qdel(usr.hud_used) + usr.hud_used = null + usr.create_mob_hud() usr.regenerate_icons() sleep(5) @@ -61,7 +64,12 @@ sleep(5) to_chat(usr, "Suit secured, extending neural-net interface...") - usr.hud_used.human_hud('icons/mob/screen1_NinjaHUD.dmi',"#ffffff",255) + if(usr.hud_used) + qdel(usr.hud_used) + usr.hud_used = null + usr.hud_used = new /datum/hud/human(usr, 'icons/mob/screen_ninja.dmi', "#ffffff", 255) + if(usr.hud_used) + usr.hud_used.show_hud(usr.hud_used.hud_version) usr.regenerate_icons() sleep(10) diff --git a/code/modules/pda/ai.dm b/code/modules/pda/ai.dm index 49cadaf7d1e..bb6bd8e7e63 100644 --- a/code/modules/pda/ai.dm +++ b/code/modules/pda/ai.dm @@ -99,6 +99,6 @@ if(!istype(pAI)) return 0 if(!pAI.software["messenger"]) - usr << "You have not purchased the digital messenger!" + to_chat(usr, "You have not purchased the digital messenger!") return 0 return ..() && !pAI.silence_time \ No newline at end of file diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 7dda66629d7..6e61be2a257 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -5,11 +5,16 @@ /obj/item/weapon/stock_parts/cell/New() ..() + processing_objects.Add(src) charge = maxcharge spawn(5) updateicon() +/obj/item/weapon/stock_parts/cell/Destroy() + processing_objects.Remove(src) + return ..() + /obj/item/weapon/stock_parts/cell/proc/updateicon() if(isnull(src.overlay_image)) src.overlay_image = image('icons/obj/power.dmi') diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 3890b433eaf..4cc08d08471 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -337,7 +337,6 @@ continue M.show_message("[user.name] smashed the light!", 3, "You hear a tinkle of breaking glass", 2) if(on && (W.flags & CONDUCT)) - //if(!user.mutations & RESIST_COLD) if (prob(12)) electrocute_mob(user, get_area(src), src, 0.3) broken() @@ -374,7 +373,6 @@ var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread s.set_up(3, 1, src) s.start() - //if(!user.mutations & RESIST_COLD) if (prob(75)) electrocute_mob(user, get_area(src), src, rand(0.7,1.0)) diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 2aea246d314..2b53068bcf6 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -84,10 +84,7 @@ /obj/item/weapon/gun/afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params) if(flag) return //we're placing gun on a table or in backpack if(istype(target, /obj/machinery/recharger) && istype(src, /obj/item/weapon/gun/energy)) return//Shouldnt flag take care of this? - if(user && user.client && user.client.gun_mode && !(A in target)) - PreFire(A,user,params) //They're using the new gun system, locate what they're aiming at. - else - Fire(A,user,params) //Otherwise, fire normally. + Fire(A,user,params) //Otherwise, fire normally. /obj/item/weapon/gun/proc/isHandgun() return 1 diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index bb556a4f178..6f92bc79fca 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -181,15 +181,14 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out. return if(usr.client.view == world.view) - if(!usr.hud_used.hud_shown) - usr.button_pressed_F12(1) // If the user has already limited their HUD this avoids them having a HUD when they zoom in - usr.button_pressed_F12(1) + if(usr.hud_used) + usr.hud_used.show_hud(HUD_STYLE_NOHUD) usr.client.view = 12 zoom = 1 else usr.client.view = world.view - if(!usr.hud_used.hud_shown) - usr.button_pressed_F12(1) + if(usr.hud_used) + usr.hud_used.show_hud(HUD_STYLE_STANDARD) zoom = 0 to_chat(usr, "Zoom mode [zoom?"en":"dis"]abled.") diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 74c76842e55..879bbf7fad0 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -194,6 +194,7 @@ if(istype(target, /mob/living/carbon)) var/mob/living/carbon/M = target if(M.can_inject(null,0,hit_zone)) // Pass the hit zone to see if it can inject by whether it hit the head or the body. + reagents.reaction(M, INGEST) reagents.trans_to(M, reagents.total_volume) return 1 else diff --git a/code/modules/projectiles/targeting.dm b/code/modules/projectiles/targeting.dm deleted file mode 100644 index 2093b47a69c..00000000000 --- a/code/modules/projectiles/targeting.dm +++ /dev/null @@ -1,367 +0,0 @@ -/obj/item/weapon/gun/verb/toggle_firerate() - set name = "Toggle Firerate" - set category = "Object" - firerate = !firerate - if (firerate == 0) - to_chat(loc, "You will now continue firing when your target moves.") - else - to_chat(loc, "You will now only fire once, then lower your aim, when your target moves.") - -/obj/item/weapon/gun/verb/lower_aim() - set name = "Lower Aim" - set category = "Object" - if(target) - stop_aim() - usr.visible_message("\blue \The [usr] lowers \the [src]...") - -//Clicking gun will still lower aim for guns that don't overwrite this -/obj/item/weapon/gun/attack_self() - lower_aim() - -//Removing the lock and the buttons. -/obj/item/weapon/gun/dropped(mob/user as mob) - stop_aim() - if (user.client) - user.client.remove_gun_icons() - return ..() - -/obj/item/weapon/gun/equipped(var/mob/user, var/slot) - if (slot != slot_l_hand && slot != slot_r_hand) - stop_aim() - if (user.client) - user.client.remove_gun_icons() - return ..() - -//Removes lock fro mall targets -/obj/item/weapon/gun/proc/stop_aim() - if(target) - for(var/mob/living/M in target) - if(M) - M.NotTargeted(src) //Untargeting people. - qdel(target) - -//Compute how to fire..... -/obj/item/weapon/gun/proc/PreFire(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, params) - //Lets not spam it. - if(lock_time > world.time - 2) return - . - if(ismob(A) && isliving(A) && !(A in target)) - Aim(A) //Clicked a mob, aim at them - else //Didn't click someone, check if there is anyone along that guntrace - var/mob/living/M = GunTrace(user.x,user.y,A.x,A.y,user.z,user) //Find dat mob. - if(M && isliving(M) && M in view(user) && !(M in target)) - Aim(M) //Aha! Aim at them! - else if(!ismob(M) || (ismob(M) && !(M in view(user)))) //Nope! They weren't there! - Fire(A,user,params) //Fire like normal, then. - user.dir = get_cardinal_dir(src, A) - -//Aiming at the target mob. -/obj/item/weapon/gun/proc/Aim(var/mob/living/M) - if(!target || !(M in target)) - lock_time = world.time - if(target && !automatic) //If they're targeting someone and they have a non automatic weapon. - for(var/mob/living/L in target) - if(L) - L.NotTargeted(src) - qdel(target) - usr.visible_message("\red [usr] turns \the [src] on [M]!") - else - usr.visible_message("\red [usr] aims \a [src] at [M]!") - M.Targeted(src) - -//HE MOVED, SHOOT HIM! -/obj/item/weapon/gun/proc/TargetActed(var/mob/living/T) - var/mob/living/M = loc - if(M == T) return - if(!istype(M)) return - if(src != M.get_active_hand()) - stop_aim() - return - M.last_move_intent = world.time - if(can_fire()) - var/firing_check = can_hit(T,usr) //0 if it cannot hit them, 1 if it is capable of hitting, and 2 if a special check is preventing it from firing. - if(firing_check > 0) - if(firing_check == 1) - Fire(T,usr, reflex = 1) - else if(!told_cant_shoot) - to_chat(M, "\red They can't be hit from here!") - told_cant_shoot = 1 - spawn(30) - told_cant_shoot = 0 - else - click_empty(M) - - usr.dir = get_cardinal_dir(src, T) - - if (!firerate) // If firerate is set to lower aim after one shot, untarget the target - T.NotTargeted(src) - -//Yay, math! - -#define SIGN(X) ((X<0)?-1:1) - -proc/GunTrace(X1,Y1,X2,Y2,Z=1,exc_obj,PX1=16,PY1=16,PX2=16,PY2=16) -// to_chat(bluh, "Tracin' [X1],[Y1] to [X2],[Y2] on floor [Z].") - var/turf/T - var/mob/living/M - if(X1==X2) - if(Y1==Y2) return 0 //Light cannot be blocked on same tile - else - var/s = SIGN(Y2-Y1) - Y1+=s - while(1) - T = locate(X1,Y1,Z) - if(!T) return 0 - M = locate() in T - if(M) return M - M = locate() in orange(1,T)-exc_obj - if(M) return M - Y1+=s - else - var - m=(32*(Y2-Y1)+(PY2-PY1))/(32*(X2-X1)+(PX2-PX1)) - b=(Y1+PY1/32-0.015625)-m*(X1+PX1/32-0.015625) //In tiles - signX = SIGN(X2-X1) - signY = SIGN(Y2-Y1) - if(X1= 5) - if(ismob(I.loc)) - to_chat(I.loc, "You can only target 5 people at once!") - return - else - return - for(var/mob/living/K in viewers(usr)) - K << 'sound/weapons/TargetOn.ogg' - - if(!targeted_by) targeted_by = list() - targeted_by += I - I.lock_time = world.time + 20 //Target has 2 second to realize they're targeted and stop (or target the opponent). - to_chat(src, "((Your character is being targeted. They have 2 seconds to stop any click or move actions. \ - While targeted, they may drag and drop items in or into the map, speak, and click on interface buttons. \ - Clicking on the map objects (floors and walls are fine), their items (other than a weapon to de-target), or moving will result in being fired upon. \ - The aggressor may also fire manually, so try not to get on their bad side.))") - - if(targeted_by.len == 1) - spawn(0) - target_locked = image("icon" = 'icons/effects/Targeted.dmi', "icon_state" = "locking") - overlays += target_locked - spawn(0) - sleep(20) - if(target_locked) - target_locked = image("icon" = 'icons/effects/Targeted.dmi', "icon_state" = "locked") - update_targeted() - - //Adding the buttons to the controler person - var/mob/living/T = I.loc - if(T) - if(T.client) - T.client.add_gun_icons() - else - I.lower_aim() - return - /*if(m_intent == "run" && T.client.target_can_move == 1 && T.client.target_can_run == 0 && (ishuman(T))) - to_chat(src, "\red Your move intent is now set to walk, as your targeter permits it.")//Self explanitory. - - set_m_intent("walk")*/ - - //Processing the aiming. Should be probably in separate object with process() but lasy. - while(targeted_by && T.client) - if(last_move_intent > I.lock_time + 10 && !T.client.target_can_move) //If target moved when not allowed to - I.TargetActed(src) - if(I.last_moved_mob == src) //If they were the last ones to move, give them more of a grace period, so that an automatic weapon can hold down a room better. - I.lock_time = world.time + 5 - I.lock_time = world.time + 5 - I.last_moved_mob = src - else if(last_move_intent > I.lock_time + 10 && !T.client.target_can_run && m_intent == "run") //If the target ran while targeted - I.TargetActed(src) - if(I.last_moved_mob == src) //If they were the last ones to move, give them more of a grace period, so that an automatic weapon can hold down a room better. - I.lock_time = world.time + 5 - I.lock_time = world.time + 5 - I.last_moved_mob = src - if(last_target_click > I.lock_time + 10 && !T.client.target_can_click) //If the target clicked the map to pick something up/shoot/etc - I.TargetActed(src) - if(I.last_moved_mob == src) //If they were the last ones to move, give them more of a grace period, so that an automatic weapon can hold down a room better. - I.lock_time = world.time + 5 - I.lock_time = world.time + 5 - I.last_moved_mob = src - sleep(1) - -mob/living/proc/NotTargeted(var/obj/item/weapon/gun/I) - if(!I.silenced) - for(var/mob/living/M in viewers(src)) - M << 'sound/weapons/TargetOff.ogg' - targeted_by -= I - I.target.Remove(src) //De-target them - if(!I.target.len) - qdel(I.target) - var/mob/living/T = I.loc //Remove the targeting icons - if(T && ismob(T) && !I.target) - T.client.remove_gun_icons() - if(!targeted_by.len) - qdel(target_locked) //Remove the overlay - qdel(targeted_by) - spawn(1) update_targeted() - -mob/living/Move() - . = ..() - for(var/obj/item/weapon/gun/G in targeted_by) //Handle moving out of the gunner's view. - var/mob/living/M = G.loc - if(!(M in view(src))) - NotTargeted(G) - for(var/obj/item/weapon/gun/G in src) //Handle the gunner loosing sight of their target/s - if(G.target) - for(var/mob/living/M in G.target) - if(M && !(M in view(src))) - M.NotTargeted(G) - -//If you move out of range, it isn't going to still stay locked on you any more. -client/var - target_can_move = 0 - target_can_run = 0 - target_can_click = 0 - gun_mode = 0 - -//These are called by the on-screen buttons, adjusting what the victim can and cannot do. -client/proc/add_gun_icons() - screen += usr.item_use_icon - /*screen += usr.gun_move_icon - if (target_can_move) - screen += usr.gun_run_icon*/ - - - -client/proc/remove_gun_icons() - if(!usr) return - screen -= usr.item_use_icon - /*screen -= usr.gun_move_icon - if (target_can_move) - screen -= usr.gun_run_icon*/ - -client/verb/ToggleGunMode() - set hidden = 1 - gun_mode = !gun_mode - if(gun_mode) - to_chat(usr, "You will now take people captive.") - else - to_chat(usr, "You will now shoot where you target.") - for(var/obj/item/weapon/gun/G in usr) - G.stop_aim() - remove_gun_icons() - if(usr.gun_setting_icon) - usr.gun_setting_icon.icon_state = "gun[gun_mode]" - - -/*client/verb/AllowTargetMove() - set hidden=1 - - //Changing client's permissions - target_can_move = !target_can_move - if(target_can_move) - to_chat(usr, "Target may now walk.") - //usr.gun_run_icon = new /obj/screen/gun/run(null) //adding icon for running permission - screen += usr.gun_run_icon - else - to_chat(usr, "Target may no longer move.") - target_can_run = 0 - qdel(usr.gun_run_icon) //no need for icon for running permission - - //Updating walking permission button - if(usr.gun_move_icon) - usr.gun_move_icon.icon_state = "no_walk[target_can_move]" - usr.gun_move_icon.name = "[target_can_move ? "Disallow" : "Allow"] Walking" - - //Handling change for all the guns on client - for(var/obj/item/weapon/gun/G in usr) - G.lock_time = world.time + 5 - if(G.target) - for(var/mob/living/M in G.target) - if(target_can_move) - to_chat(M, "Your character may now walk at the discretion of their targeter.") - if(!target_can_run && (ishuman(M))) - to_chat(M, "\red Your move intent is now set to walk, as your targeter permits it.") - M.set_m_intent("walk") - else - to_chat(M, "\red Your character will now be shot if they move.") - -mob/living/proc/set_m_intent(var/intent) - if (intent != "walk" && intent != "run") - return 0 - m_intent = intent - if(hud_used) - if (hud_used.move_intent) - hud_used.move_intent.icon_state = intent == "walk" ? "walking" : "running" - -client/verb/AllowTargetRun() - set hidden=1 - - //Changing client's permissions - target_can_run = !target_can_run - if(target_can_run) - to_chat(usr, "Target may now run.") - else - to_chat(usr, "Target may no longer run.") - - //Updating running permission button - if(usr.gun_run_icon) - usr.gun_run_icon.icon_state = "no_run[target_can_run]" - usr.gun_run_icon.name = "[target_can_run ? "Disallow" : "Allow"] Running" - - //Handling change for all the guns on client - for(var/obj/item/weapon/gun/G in src) - G.lock_time = world.time + 5 - if(G.target) - for(var/mob/living/M in G.target) - if(target_can_run) - to_chat(M, "Your character may now run at the discretion of their targeter.") - else - to_chat(M, "\red Your character will now be shot if they run.")*/ - -client/verb/AllowTargetClick() - set hidden=1 - - //Changing client's permissions - target_can_click = !target_can_click - if(target_can_click) - to_chat(usr, "Target may now use items.") - else - to_chat(usr, "Target may no longer use items.") - - if(usr.item_use_icon) - usr.item_use_icon.icon_state = "no_item[target_can_click]" - usr.item_use_icon.name = "[target_can_click ? "Disallow" : "Allow"] Item Use" - - //Handling change for all the guns on client - for(var/obj/item/weapon/gun/G in src) - G.lock_time = world.time + 5 - if(G.target) - for(var/mob/living/M in G.target) - if(target_can_click) - to_chat(M, "Your character may now use items at the discretion of their targeter.") - else - to_chat(M, "\red Your character will now be shot if they use items.") diff --git a/code/modules/reagents/oldchem/chemical_reaction/chemical_reaction_slime.dm b/code/modules/reagents/oldchem/chemical_reaction/chemical_reaction_slime.dm index 3a08a28a741..e9dd50dcf67 100644 --- a/code/modules/reagents/oldchem/chemical_reaction/chemical_reaction_slime.dm +++ b/code/modules/reagents/oldchem/chemical_reaction/chemical_reaction_slime.dm @@ -661,4 +661,4 @@ var/mob/living/carbon/slime/S = new /mob/living/carbon/slime S.colour = pick("grey","orange", "metal", "blue", "purple", "dark purple", "dark blue", "green", "silver", "yellow", "gold", "yellow", "red", "silver", "pink", "cerulean", "sepia", "bluespace", "pyrite", "light pink", "oil", "adamantine", "black") S.forceMove(get_turf(holder.my_atom)) - S.visible_message("Infused with plasma, the core begins to quiver and grow, and soon a new baby slime emerges from it!") + S.visible_message("Infused with plasma, the core begins to quiver and grow, and soon a new baby slime emerges from it!") \ No newline at end of file diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm index 5099f11ed19..e2c8b5f0670 100644 --- a/code/modules/reagents/reagent_containers/food/snacks.dm +++ b/code/modules/reagents/reagent_containers/food/snacks.dm @@ -2206,6 +2206,9 @@ ..() reagents.add_reagent("nutriment", 8) reagents.add_reagent("gold", 5) + spawn(1) + reagents.del_reagent("egg") + reagents.update_total() bitesize = 3 /obj/item/weapon/reagent_containers/food/snacks/dough_ball @@ -2581,6 +2584,9 @@ New() ..() reagents.add_reagent("nutriment", 6) + spawn(1) + reagents.del_reagent("egg") + reagents.update_total() bitesize = 2 /obj/item/weapon/reagent_containers/food/snacks/breadslice @@ -3013,6 +3019,9 @@ ..() reagents.add_reagent("nutriment", 2) reagents.add_reagent("sugar", 5) + spawn(1) + reagents.del_reagent("egg") + reagents.update_total() bitesize = 2 /obj/item/weapon/reagent_containers/food/snacks/friedbanana diff --git a/code/modules/reagents/reagent_containers/food/snacks/candy.dm b/code/modules/reagents/reagent_containers/food/snacks/candy.dm index 9ddd19c7e2c..39abcac4a6a 100644 --- a/code/modules/reagents/reagent_containers/food/snacks/candy.dm +++ b/code/modules/reagents/reagent_containers/food/snacks/candy.dm @@ -66,6 +66,9 @@ ..() reagents.add_reagent("nutriment", 3) reagents.add_reagent("sugar", 3) + spawn(1) + reagents.del_reagent("egg") + reagents.update_total() bitesize = 2 /obj/item/weapon/reagent_containers/food/snacks/candy/taffy @@ -287,8 +290,9 @@ /obj/item/weapon/reagent_containers/food/snacks/candy/gummybear/poison/New() ..() reagents.add_reagent("poisonberryjuice", 12) - reagents.del_reagent("sugar") - reagents.update_total() + spawn(1) + reagents.del_reagent("sugar") + reagents.update_total() bitesize = 3 /obj/item/weapon/reagent_containers/food/snacks/candy/gummybear/green @@ -381,8 +385,9 @@ /obj/item/weapon/reagent_containers/food/snacks/candy/gummyworm/poison/New() ..() reagents.add_reagent("poisonberryjuice", 12) - reagents.del_reagent("sugar") - reagents.update_total() + spawn(1) + reagents.del_reagent("sugar") + reagents.update_total() bitesize = 3 /obj/item/weapon/reagent_containers/food/snacks/candy/gummyworm/green @@ -475,8 +480,9 @@ /obj/item/weapon/reagent_containers/food/snacks/candy/jellybean/poison/New() ..() reagents.add_reagent("poisonberryjuice", 12) - reagents.del_reagent("sugar") - reagents.update_total() + spawn(1) + reagents.del_reagent("sugar") + reagents.update_total() bitesize = 3 /obj/item/weapon/reagent_containers/food/snacks/candy/jellybean/green @@ -627,8 +633,9 @@ /obj/item/weapon/reagent_containers/food/snacks/candy/cotton/poison/New() ..() reagents.add_reagent("poisonberryjuice", 20) - reagents.del_reagent("sugar") - reagents.update_total() + spawn(1) + reagents.del_reagent("sugar") + reagents.update_total() bitesize = 4 /obj/item/weapon/reagent_containers/food/snacks/candy/cotton/green @@ -701,8 +708,9 @@ /obj/item/weapon/reagent_containers/food/snacks/candy/cotton/rainbow/New() ..() reagents.add_reagent("omnizine", 20) - reagents.del_reagent("sugar") - reagents.update_total() + spawn(1) + reagents.del_reagent("sugar") + reagents.update_total() bitesize = 4 /obj/item/weapon/reagent_containers/food/snacks/candy/cotton/bad_rainbow @@ -715,8 +723,9 @@ /obj/item/weapon/reagent_containers/food/snacks/candy/cotton/bad_rainbow/New() ..() reagents.add_reagent("sulfonal", 20) - reagents.del_reagent("sugar") - reagents.update_total() + spawn(1) + reagents.del_reagent("sugar") + reagents.update_total() bitesize = 4 // *********************************************************** diff --git a/code/modules/reagents/reagent_containers/food/snacks/seafood.dm b/code/modules/reagents/reagent_containers/food/snacks/seafood.dm index 96780490507..410c225247c 100644 --- a/code/modules/reagents/reagent_containers/food/snacks/seafood.dm +++ b/code/modules/reagents/reagent_containers/food/snacks/seafood.dm @@ -63,6 +63,9 @@ ..() reagents.add_reagent("nutriment", 4) reagents.add_reagent("carpotoxin", 3) + spawn(1) + reagents.del_reagent("egg") + reagents.update_total() bitesize = 3 /obj/item/weapon/reagent_containers/food/snacks/fishburger diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 45ed8f0a08b..f34b727c354 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -223,7 +223,6 @@ being_used = 0 ..() - /obj/item/slimepotion/steroid name = "slime steroid" desc = "A potent chemical mix that will cause a baby slime to generate more extract." diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 2f7c0c06496..2a794de2ff8 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -302,10 +302,6 @@ //rotate our direction dir = angle2dir(rotation+dir2angle(dir)) - //resmooth if need be. - if(smooth) - smooth_icon(src) - //rotate the pixel offsets too. if (pixel_x || pixel_y) if (rotation < 0) @@ -316,6 +312,9 @@ pixel_x = oldPY pixel_y = (oldPX*(-1)) +/atom/proc/postDock() + if(smooth) + smooth_icon(src) //this is the main proc. It instantly moves our mobile port to stationary port S1 @@ -368,7 +367,7 @@ var/list/door_unlock_list = list() - for(var/i=1, i<=L0.len, ++i) + for(var/i in 1 to L0.len) var/turf/T0 = L0[i] if(!T0) continue @@ -443,6 +442,12 @@ T0.CalculateAdjacentTurfs() air_master.add_to_active(T0,1) + for(var/A1 in L1) + var/turf/T1 = A1 + T1.postDock() + for(var/atom/movable/M in T1) + M.postDock() + loc = S1.loc dir = S1.dir diff --git a/code/modules/surgery/limb_reattach.dm b/code/modules/surgery/limb_reattach.dm index e9464fab9a1..3386f4b9366 100644 --- a/code/modules/surgery/limb_reattach.dm +++ b/code/modules/surgery/limb_reattach.dm @@ -97,7 +97,10 @@ E.forceMove(target) if(target.get_species() == "Machine")//as this is the only step needed for ipc put togethers if(target_zone == "head") - target.h_style = "" + var/obj/item/organ/external/head/H = target.organs_by_name["head"] + var/datum/robolimb/robohead = all_robolimbs[H.model] + if(robohead.is_monitor) //Ensures that if an IPC gets a head that's got a human hair wig attached to their body, the hair won't wipe. + target.h_style = "" E.status &= ~ORGAN_DESTROYED if(E.children) for(var/obj/item/organ/external/C in E.children) diff --git a/code/modules/surgery/organs/organ_icon.dm b/code/modules/surgery/organs/organ_icon.dm index ee0e450ae15..db6ffd81a2a 100644 --- a/code/modules/surgery/organs/organ_icon.dm +++ b/code/modules/surgery/organs/organ_icon.dm @@ -71,6 +71,14 @@ var/global/list/limb_icon_cache = list() overlays |= lip_icon mob_icon.Blend(lip_icon, ICON_OVERLAY) + if(owner.m_style) + var/datum/sprite_accessory/marking_style = marking_styles_list[owner.m_style] + if(marking_style && marking_style.species_allowed && (species.name in marking_style.species_allowed) && marking_style.marking_location == "head") + var/icon/markings_s = new/icon("icon" = marking_style.icon, "icon_state" = "[marking_style.icon_state]_s") + if(marking_style.do_colouration) + markings_s.Blend(rgb(owner.r_markings, owner.g_markings, owner.b_markings), ICON_ADD) + overlays |= markings_s + if(owner.ha_style) var/datum/sprite_accessory/head_accessory_style = head_accessory_styles_list[owner.ha_style] if(head_accessory_style && head_accessory_style.species_allowed && (species.name in head_accessory_style.species_allowed)) @@ -81,7 +89,7 @@ var/global/list/limb_icon_cache = list() if(owner.f_style) var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[owner.f_style] - if(facial_hair_style && facial_hair_style.species_allowed && (species.name in facial_hair_style.species_allowed)) + if(facial_hair_style && ((facial_hair_style.species_allowed && (species.name in facial_hair_style.species_allowed)) || (src.species.flags & ALL_RPARTS))) var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") if(species.name == "Slime People") // I am el worstos facial_s.Blend(rgb(owner.r_skin, owner.g_skin, owner.b_skin, 160), ICON_AND) @@ -91,7 +99,7 @@ var/global/list/limb_icon_cache = list() if(owner.h_style && !(owner.head && (owner.head.flags & BLOCKHEADHAIR))) var/datum/sprite_accessory/hair_style = hair_styles_list[owner.h_style] - if(hair_style && (species.name in hair_style.species_allowed)) + if(hair_style && ((species.name in hair_style.species_allowed) || (src.species.flags & ALL_RPARTS))) var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") if(species.name == "Slime People") // I am el worstos hair_s.Blend(rgb(owner.r_skin, owner.g_skin, owner.b_skin, 160), ICON_AND) diff --git a/code/modules/surgery/organs/robolimbs.dm b/code/modules/surgery/organs/robolimbs.dm index bcebd7e1e64..0229ee80cae 100644 --- a/code/modules/surgery/organs/robolimbs.dm +++ b/code/modules/surgery/organs/robolimbs.dm @@ -1,4 +1,5 @@ var/global/list/all_robolimbs = list() +var/global/list/robolimb_data = list() var/global/list/chargen_robolimbs = list() var/global/datum/robolimb/basic_robolimb @@ -9,41 +10,114 @@ var/global/datum/robolimb/basic_robolimb all_robolimbs[R.company] = R if(!R.unavailable_at_chargen) if(R != "head" && R != "chest" && R != "groin" ) //Part of the method that ensures only IPCs can access head, chest and groin prosthetics. - chargen_robolimbs[R.company] = R + if(R.has_subtypes) //Ensures solos get added to the list as well be incorporating has_subtypes == 1 and has_subtypes == 2. + chargen_robolimbs[R.company] = R //List only main brands and solo parts. /datum/robolimb var/company = "Unbranded" // Shown when selecting the limb. var/desc = "A generic unbranded robotic prosthesis." // Seen when examining a limb. var/icon = 'icons/mob/human_races/robotic.dmi' // Icon base to draw from. var/unavailable_at_chargen // If set, not available at chargen. + var/is_monitor // If set, limb is a monitor and should be getting monitor styles. + var/has_subtypes = 2 // If null, object is a model. If 1, object is a brand (that serves as the default model) with child models. If 2, object is a brand that has no child models and thus also serves as the model.. + var/parts = list("chest", "groin", "head", "r_arm", "r_hand", "r_leg", "r_foot", "l_leg", "l_foot", "l_arm", "l_hand") //Defines what parts said brand can replace on a body. /datum/robolimb/bishop company = "Bishop Cybernetics" desc = "This limb has a white polymer casing with blue holo-displays." - icon = 'icons/mob/human_races/cyberlimbs/bishop.dmi' + icon = 'icons/mob/human_races/cyberlimbs/bishop/bishop_main.dmi' + has_subtypes = 1 -/datum/robolimb/hesphaistos +/datum/robolimb/bishop/alt1 + company = "Bishop Cybernetics alt." + icon = 'icons/mob/human_races/cyberlimbs/bishop/bishop_alt1.dmi' + parts = list("head") + has_subtypes = null + +/datum/robolimb/bishop/monitor + company = "Bishop Cybernetics mtr." + icon = 'icons/mob/human_races/cyberlimbs/bishop/bishop_monitor.dmi' + parts = list("head") + is_monitor = 1 + has_subtypes = null + +/datum/robolimb/hesphiastos company = "Hesphiastos Industries" desc = "This limb has a militaristic black and green casing with gold stripes." - icon = 'icons/mob/human_races/cyberlimbs/hesphaistos.dmi' + icon = 'icons/mob/human_races/cyberlimbs/hesphiastos/hesphiastos_main.dmi' + has_subtypes = 1 -/datum/robolimb/ipc +/datum/robolimb/hesphiastos/alt1 + company = "Hesphiastos Industries alt." + icon = 'icons/mob/human_races/cyberlimbs/hesphiastos/hesphiastos_alt1.dmi' + parts = list("head") + is_monitor = 1 + has_subtypes = null + +/datum/robolimb/hesphiastos/monitor + company = "Hesphiastos Industries mtr." + icon = 'icons/mob/human_races/cyberlimbs/hesphiastos/hesphiastos_monitor.dmi' + parts = list("head") + is_monitor = 1 + has_subtypes = null + +/datum/robolimb/morpheus company = "Morpheus Cyberkinetics" desc = "This limb is simple and functional; no effort has been made to make it look human." - icon = 'icons/mob/human_races/cyberlimbs/ipc.dmi' + icon = 'icons/mob/human_races/cyberlimbs/morpheus/morpheus_main.dmi' unavailable_at_chargen = 1 + is_monitor = 1 + has_subtypes = 1 + +/datum/robolimb/morpheus/alt1 + company = "Morpheus Cyberkinetics alt." + icon = 'icons/mob/human_races/cyberlimbs/morpheus/morpheus_alt1.dmi' + parts = list("head") + unavailable_at_chargen = null + is_monitor = null + has_subtypes = 2 //Edge case. We want to be able to pick this one, and if we had it left as null for has_subtypes we'd be assuming it'll be chosen as a child model, + //and since the parent is unavailable at chargen, we wouldn't be able to see it in the list anyway. Now, we'll be able to select the Morpheus Ckt. Alt. head as a solo-model. /datum/robolimb/wardtakahashi company = "Ward-Takahashi" desc = "This limb features sleek black and white polymers." - icon = 'icons/mob/human_races/cyberlimbs/wardtakahashi.dmi' + icon = 'icons/mob/human_races/cyberlimbs/wardtakahashi/wardtakahashi_main.dmi' + has_subtypes = 1 + +/datum/robolimb/wardtakahashi/alt1 + company = "Ward-Takahashi alt." + icon = 'icons/mob/human_races/cyberlimbs/wardtakahashi/wardtakahashi_alt1.dmi' + parts = list("head") + has_subtypes = null + +/datum/robolimb/wardtakahashi/monitor + company = "Ward-Takahashi mtr." + icon = 'icons/mob/human_races/cyberlimbs/wardtakahashi/wardtakahashi_monitor.dmi' + parts = list("head") + is_monitor = 1 + has_subtypes = null /datum/robolimb/xion company = "Xion Manufacturing Group" desc = "This limb has a minimalist black and red casing." - icon = 'icons/mob/human_races/cyberlimbs/xion.dmi' + icon = 'icons/mob/human_races/cyberlimbs/xion/xion_main.dmi' + has_subtypes = 1 + +/datum/robolimb/xion/alt1 + company = "Xion Manufacturing Group alt." + icon = 'icons/mob/human_races/cyberlimbs/xion/xion_alt1.dmi' + parts = list("head") + has_subtypes = null + +/datum/robolimb/xion/monitor + company = "Xion Manufacturing Group mtr." + icon = 'icons/mob/human_races/cyberlimbs/xion/xion_monitor.dmi' + parts = list("head") + is_monitor = 1 + has_subtypes = null /datum/robolimb/zenghu company = "Zeng-Hu Pharmaceuticals" desc = "This limb has a rubbery fleshtone covering with visible seams." - icon = 'icons/mob/human_races/cyberlimbs/zenghu.dmi' \ No newline at end of file + icon = 'icons/mob/human_races/cyberlimbs/zenghu/zenghu_main.dmi' + has_subtypes = 2 \ No newline at end of file diff --git a/html/browser/boardui.js b/html/browser/boardui.js new file mode 100644 index 00000000000..68ee667a355 --- /dev/null +++ b/html/browser/boardui.js @@ -0,0 +1,395 @@ +var g_startOffset = null; +var g_selectedPiece = null; +var moveNumber = 1; + +var g_allMoves = []; +var g_playerWhite = true; +var g_changingFen = false; +var g_analyzing = false; + +var g_uiBoard; +var g_cellSize = 45; + +function UINewGame() { + moveNumber = 1; + + var pgnTextBox = document.getElementById("PgnTextBox"); + pgnTextBox.value = ""; + + EnsureAnalysisStopped(); + ResetGame(); + if (InitializeBackgroundEngine()) { + g_backgroundEngine.postMessage("go"); + } + g_allMoves = []; + RedrawBoard(); + + if (!g_playerWhite) { + SearchAndRedraw(); + } +} + +function UIClose() { + window.location = "byond://?src=" + hSrc + ";close=1"; +} + +function EnsureAnalysisStopped() { + if (g_analyzing && g_backgroundEngine != null) { + g_backgroundEngine.terminate(); + g_backgroundEngine = null; + } +} + +function UIAnalyzeToggle() { + if (InitializeBackgroundEngine()) { + if (!g_analyzing) { + g_backgroundEngine.postMessage("analyze"); + } else { + EnsureAnalysisStopped(); + } + g_analyzing = !g_analyzing; + document.getElementById("AnalysisToggleLink").innerText = g_analyzing ? "Analysis: On" : "Analysis: Off"; + } else { + alert("Your browser must support web workers for analysis - (chrome4, ff4, safari)"); + } +} + +function UIChangeFEN() { + if (!g_changingFen) { + var fenTextBox = document.getElementById("FenTextBox"); + var result = InitializeFromFen(fenTextBox.value); + if (result.length != 0) { + UpdatePVDisplay(result); + return; + } else { + UpdatePVDisplay(''); + } + g_allMoves = []; + + EnsureAnalysisStopped(); + InitializeBackgroundEngine(); + + g_playerWhite = !!g_toMove; + g_backgroundEngine.postMessage("position " + GetFen()); + + RedrawBoard(); + } +} + +function UIChangeStartPlayer() { + g_playerWhite = !g_playerWhite; + RedrawBoard(); +} + +function UpdatePgnTextBox(move) { + var pgnTextBox = document.getElementById("PgnTextBox"); + if (g_toMove != 0) { + pgnTextBox.value += moveNumber + ". "; + moveNumber++; + } + pgnTextBox.value += GetMoveSAN(move) + " "; +} + +function UIChangeTimePerMove() { + var timePerMove = document.getElementById("TimePerMove"); + g_timeout = parseInt(timePerMove.value, 10); +} + +function FinishMove(bestMove, value, timeTaken, ply) { + if (bestMove != null) { + UIPlayMove(bestMove, BuildPVMessage(bestMove, value, timeTaken, ply)); + } else { + window.location = "byond://?src=" + hSrc + ";checkmate=1"; + } +} + +function UIPlayMove(move, pv) { + UpdatePgnTextBox(move); + + g_allMoves[g_allMoves.length] = move; + MakeMove(move); + + UpdatePVDisplay(pv); + + UpdateFromMove(move); +} + +function UIUndoMove() { + if (g_allMoves.length == 0) { + return; + } + + if (g_backgroundEngine != null) { + g_backgroundEngine.terminate(); + g_backgroundEngine = null; + } + + UnmakeMove(g_allMoves[g_allMoves.length - 1]); + g_allMoves.pop(); + + if (g_playerWhite != !!g_toMove && g_allMoves.length != 0) { + UnmakeMove(g_allMoves[g_allMoves.length - 1]); + g_allMoves.pop(); + } + + RedrawBoard(); +} + +function UpdatePVDisplay(pv) { + if (pv != null) { + var outputDiv = document.getElementById("output"); + if (outputDiv.firstChild != null) { + outputDiv.removeChild(outputDiv.firstChild); + } + outputDiv.appendChild(document.createTextNode(pv)); + } +} + +function SearchAndRedraw() { + if (g_analyzing) { + EnsureAnalysisStopped(); + InitializeBackgroundEngine(); + g_backgroundEngine.postMessage("position " + GetFen()); + g_backgroundEngine.postMessage("analyze"); + return; + } + + if (InitializeBackgroundEngine()) { + g_backgroundEngine.postMessage("search " + g_timeout); + } else { + Search(FinishMove, 99, null); + } +} + +var g_backgroundEngineValid = true; +var g_backgroundEngine; + +function InitializeBackgroundEngine() { + if (!g_backgroundEngineValid) { + return false; + } + + if (g_backgroundEngine == null) { + g_backgroundEngineValid = true; + try { + g_backgroundEngine = new Worker("garbochess.js"); + g_backgroundEngine.onmessage = function (e) { + if (e.data.match("^pv") == "pv") { + UpdatePVDisplay(e.data.substr(3, e.data.length - 3)); + } else if (e.data.match("^message") == "message") { + EnsureAnalysisStopped(); + UpdatePVDisplay(e.data.substr(8, e.data.length - 8)); + } else { + UIPlayMove(GetMoveFromString(e.data), null); + } + } + g_backgroundEngine.error = function (e) { + alert("Error from background worker:" + e.message); + } + g_backgroundEngine.postMessage("position " + GetFen()); + } catch (error) { + g_backgroundEngineValid = false; + } + } + + return g_backgroundEngineValid; +} + +function UpdateFromMove(move) { + var fromX = (move & 0xF) - 4; + var fromY = ((move >> 4) & 0xF) - 2; + var toX = ((move >> 8) & 0xF) - 4; + var toY = ((move >> 12) & 0xF) - 2; + + if (!g_playerWhite) { + fromY = 7 - fromY; + toY = 7 - toY; + fromX = 7 - fromX; + toX = 7 - toX; + } + + if ((move & moveflagCastleKing) || + (move & moveflagCastleQueen) || + (move & moveflagEPC) || + (move & moveflagPromotion)) { + RedrawPieces(); + } else { + var fromSquare = g_uiBoard[fromY * 8 + fromX]; + $(g_uiBoard[toY * 8 + toX]) + .empty() + .append($(fromSquare).children()); + } +} + +function RedrawPieces() { + for (y = 0; y < 8; ++y) { + for (x = 0; x < 8; ++x) { + var td = g_uiBoard[y * 8 + x]; + var pieceY = g_playerWhite ? y : 7 - y; + var piece = g_board[((pieceY + 2) * 0x10) + (g_playerWhite ? x : 7 - x) + 4]; + var pieceName = null; + switch (piece & 0x7) { + case piecePawn: pieceName = "pawn"; break; + case pieceKnight: pieceName = "knight"; break; + case pieceBishop: pieceName = "bishop"; break; + case pieceRook: pieceName = "rook"; break; + case pieceQueen: pieceName = "queen"; break; + case pieceKing: pieceName = "king"; break; + } + if (pieceName != null) { + pieceName += "_"; + pieceName += (piece & 0x8) ? "white" : "black"; + } + + if (pieceName != null) { + var img = document.createElement("div"); + $(img).addClass('sprite-' + pieceName); + img.style.backgroundImage = "url('sprites.png')"; + img.width = g_cellSize; + img.height = g_cellSize; + var divimg = document.createElement("div"); + divimg.appendChild(img); + + $(divimg).draggable({ start: function (e, ui) { + if (g_selectedPiece === null) { + g_selectedPiece = this; + var offset = $(this).closest('table').offset(); + g_startOffset = { + left: e.pageX - offset.left, + top: e.pageY - offset.top + }; + } else { + return g_selectedPiece == this; + } + }}); + + $(divimg).mousedown(function(e) { + if (g_selectedPiece === null) { + var offset = $(this).closest('table').offset(); + g_startOffset = { + left: e.pageX - offset.left, + top: e.pageY - offset.top + }; + e.stopPropagation(); + g_selectedPiece = this; + g_selectedPiece.style.backgroundImage = "url('img/transpBlue50.png')"; + } else if (g_selectedPiece === this) { + g_selectedPiece.style.backgroundImage = null; + g_selectedPiece = null; + } + }); + + $(td).empty().append(divimg); + } else { + $(td).empty(); + } + } + } +} + +function RedrawBoard() { + var div = $("#board")[0]; + + var table = document.createElement("table"); + table.cellPadding = "0px"; + table.cellSpacing = "0px"; + $(table).addClass('no-highlight'); + + var tbody = document.createElement("tbody"); + + g_uiBoard = []; + + var dropPiece = function (e, ui) { + var endX = e.pageX - $(table).offset().left; + var endY = e.pageY - $(table).offset().top; + + endX = Math.floor(endX / g_cellSize); + endY = Math.floor(endY / g_cellSize); + + var startX = Math.floor(g_startOffset.left / g_cellSize); + var startY = Math.floor(g_startOffset.top / g_cellSize); + + if (!g_playerWhite) { + startY = 7 - startY; + endY = 7 - endY; + startX = 7 - startX; + endX = 7 - endX; + } + + var moves = GenerateValidMoves(); + var move = null; + for (var i = 0; i < moves.length; i++) { + if ((moves[i] & 0xFF) == MakeSquare(startY, startX) && + ((moves[i] >> 8) & 0xFF) == MakeSquare(endY, endX)) { + move = moves[i]; + } + } + + if (!g_playerWhite) { + startY = 7 - startY; + endY = 7 - endY; + startX = 7 - startX; + endX = 7 - endX; + } + + g_selectedPiece.style.left = 0; + g_selectedPiece.style.top = 0; + + if (!(startX == endX && startY == endY) && move != null) { + UpdatePgnTextBox(move); + + if (InitializeBackgroundEngine()) { + g_backgroundEngine.postMessage(FormatMove(move)); + } + + g_allMoves[g_allMoves.length] = move; + MakeMove(move); + + UpdateFromMove(move); + + g_selectedPiece.style.backgroundImage = null; + g_selectedPiece = null; + + var fen = GetFen(); + document.getElementById("FenTextBox").value = fen; + + setTimeout("SearchAndRedraw()", 0); + } else { + g_selectedPiece.style.backgroundImage = null; + g_selectedPiece = null; + } + }; + + for (y = 0; y < 8; ++y) { + var tr = document.createElement("tr"); + + for (x = 0; x < 8; ++x) { + var td = document.createElement("td"); + td.style.width = g_cellSize + "px"; + td.style.height = g_cellSize + "px"; + td.style.backgroundColor = ((y ^ x) & 1) ? "#D18947" : "#FFCE9E"; + tr.appendChild(td); + g_uiBoard[y * 8 + x] = td; + } + + tbody.appendChild(tr); + } + + table.appendChild(tbody); + + $('body').droppable({ drop: dropPiece }); + $(table).mousedown(function(e) { + if (g_selectedPiece !== null) { + dropPiece(e); + } + }); + + RedrawPieces(); + + $(div).empty(); + div.appendChild(table); + + g_changingFen = true; + document.getElementById("FenTextBox").value = GetFen(); + g_changingFen = false; +} diff --git a/html/browser/chess.css b/html/browser/chess.css new file mode 100644 index 00000000000..43c61a04cf4 --- /dev/null +++ b/html/browser/chess.css @@ -0,0 +1,23 @@ + #FenTextBox { + width: 400px; + } + #TimePerMove { + width: 50px; + } + .no-highlight { + -webkit-tap-highlight-color: rgba(0,0,0,0); + } + .sprite-bishop_black{ background-position: 0 0; width: 45px; height: 45px; } + .sprite-bishop_white{ background-position: 0 -95px; width: 45px; height: 45px; } + .sprite-king_black{ background-position: 0 -190px; width: 45px; height: 45px; } + .sprite-king_white{ background-position: 0 -285px; width: 45px; height: 45px; } + .sprite-knight_black{ background-position: 0 -380px; width: 45px; height: 45px; } + .sprite-knight_white{ background-position: 0 -475px; width: 45px; height: 45px; } + .sprite-pawn_black{ background-position: 0 -570px; width: 45px; height: 45px; } + .sprite-pawn_white{ background-position: 0 -665px; width: 45px; height: 45px; } + .sprite-queen_black{ background-position: 0 -760px; width: 45px; height: 45px; } + .sprite-queen_white{ background-position: 0 -855px; width: 45px; height: 45px; } + .sprite-rook_black{ background-position: 0 -950px; width: 45px; height: 45px; } + .sprite-rook_white{ background-position: 0 -1045px; width: 45px; height: 45px; } + background-image:url(background.png) no-repeat center center fixed; + background-size:cover; \ No newline at end of file diff --git a/html/browser/garbochess.js b/html/browser/garbochess.js new file mode 100644 index 00000000000..7e94bea53d9 --- /dev/null +++ b/html/browser/garbochess.js @@ -0,0 +1,2515 @@ +"use strict"; + +// Perf TODO: +// Merge material updating with psq values +// Put move scoring inline in generator +// Remove need for fliptable in psq tables. Access them by color +// Optimize pawn move generation + +// Non-perf todo: +// Checks in first q? +// Pawn eval. +// Better king evaluation +// Better move sorting in PV nodes (especially root) + +var g_debug = true; +var g_timeout = 40; + +function GetFen(){ + var result = ""; + for (var row = 0; row < 8; row++) { + if (row != 0) + result += '/'; + var empty = 0; + for (var col = 0; col < 8; col++) { + var piece = g_board[((row + 2) << 4) + col + 4]; + if (piece == 0) { + empty++; + } + else { + if (empty != 0) + result += empty; + empty = 0; + + var pieceChar = [" ", "p", "n", "b", "r", "q", "k", " "][(piece & 0x7)]; + result += ((piece & colorWhite) != 0) ? pieceChar.toUpperCase() : pieceChar; + } + } + if (empty != 0) { + result += empty; + } + } + + result += g_toMove == colorWhite ? " w" : " b"; + result += " "; + if (g_castleRights == 0) { + result += "-"; + } + else { + if ((g_castleRights & 1) != 0) + result += "K"; + if ((g_castleRights & 2) != 0) + result += "Q"; + if ((g_castleRights & 4) != 0) + result += "k"; + if ((g_castleRights & 8) != 0) + result += "q"; + } + + result += " "; + + if (g_enPassentSquare == -1) { + result += '-'; + } + else { + result += FormatSquare(g_enPassentSquare); + } + + return result; +} + +function GetMoveSAN(move, validMoves) { + var from = move & 0xFF; + var to = (move >> 8) & 0xFF; + + if (move & moveflagCastleKing) return "O-O"; + if (move & moveflagCastleQueen) return "O-O-O"; + + var pieceType = g_board[from] & 0x7; + var result = ["", "", "N", "B", "R", "Q", "K", ""][pieceType]; + + var dupe = false, rowDiff = true, colDiff = true; + if (validMoves == null) { + validMoves = GenerateValidMoves(); + } + for (var i = 0; i < validMoves.length; i++) { + var moveFrom = validMoves[i] & 0xFF; + var moveTo = (validMoves[i] >> 8) & 0xFF; + if (moveFrom != from && + moveTo == to && + (g_board[moveFrom] & 0x7) == pieceType) { + dupe = true; + if ((moveFrom & 0xF0) == (from & 0xF0)) { + rowDiff = false; + } + if ((moveFrom & 0x0F) == (from & 0x0F)) { + colDiff = false; + } + } + } + + if (dupe) { + if (colDiff) { + result += FormatSquare(from).charAt(0); + } else if (rowDiff) { + result += FormatSquare(from).charAt(1); + } else { + result += FormatSquare(from); + } + } else if (pieceType == piecePawn && (g_board[to] != 0 || (move & moveflagEPC))) { + result += FormatSquare(from).charAt(0); + } + + if (g_board[to] != 0 || (move & moveflagEPC)) { + result += "x"; + } + + result += FormatSquare(to); + + if (move & moveflagPromotion) { + if (move & moveflagPromoteBishop) result += "=B"; + else if (move & moveflagPromoteKnight) result += "=N"; + else if (move & moveflagPromoteQueen) result += "=Q"; + else result += "=R"; + } + + MakeMove(move); + if (g_inCheck) { + result += GenerateValidMoves().length == 0 ? "#" : "+"; + } + UnmakeMove(move); + + return result; +} + +function FormatSquare(square) { + var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; + return letters[(square & 0xF) - 4] + ((9 - (square >> 4)) + 1); +} + +function FormatMove(move) { + var result = FormatSquare(move & 0xFF) + FormatSquare((move >> 8) & 0xFF); + if (move & moveflagPromotion) { + if (move & moveflagPromoteBishop) result += "b"; + else if (move & moveflagPromoteKnight) result += "n"; + else if (move & moveflagPromoteQueen) result += "q"; + else result += "r"; + } + return result; +} + +function GetMoveFromString(moveString) { + var moves = GenerateValidMoves(); + for (var i = 0; i < moves.length; i++) { + if (FormatMove(moves[i]) == moveString) { + return moves[i]; + } + } + alert("busted! ->" + moveString + " fen:" + GetFen()); +} + +function PVFromHash(move, ply) { + if (ply == 0) + return ""; + + if (move == 0) { + if (g_inCheck) return "checkmate"; + return "stalemate"; + } + + var pvString = " " + GetMoveSAN(move); + MakeMove(move); + + var hashNode = g_hashTable[g_hashKeyLow & g_hashMask]; + if (hashNode != null && hashNode.lock == g_hashKeyHigh && hashNode.bestMove != null) { + pvString += PVFromHash(hashNode.bestMove, ply - 1); + } + + UnmakeMove(move); + + return pvString; +} + +// +// Searching code +// + +var g_startTime; + +var g_nodeCount; +var g_qNodeCount; +var g_searchValid; +var g_globalPly = 0; + +function Search(finishMoveCallback, maxPly, finishPlyCallback) { + var lastEval; + var alpha = minEval; + var beta = maxEval; + + g_globalPly++; + g_nodeCount = 0; + g_qNodeCount = 0; + g_searchValid = true; + + var bestMove = 0; + var value; + + g_startTime = (new Date()).getTime(); + + var i; + for (i = 1; i <= maxPly && g_searchValid; i++) { + var tmp = AlphaBeta(i, 0, alpha, beta); + if (!g_searchValid) break; + + value = tmp; + + if (value > alpha && value < beta) { + alpha = value - 500; + beta = value + 500; + + if (alpha < minEval) alpha = minEval; + if (beta > maxEval) beta = maxEval; + } else if (alpha != minEval) { + alpha = minEval; + beta = maxEval; + i--; + } + + if (g_hashTable[g_hashKeyLow & g_hashMask] != null) { + bestMove = g_hashTable[g_hashKeyLow & g_hashMask].bestMove; + } + + if (finishPlyCallback != null) { + finishPlyCallback(bestMove, value, (new Date()).getTime() - g_startTime, i); + } + } + + if (finishMoveCallback != null) { + finishMoveCallback(bestMove, value, (new Date()).getTime() - g_startTime, i - 1); + } +} + +var minEval = -2000000; +var maxEval = +2000000; + +var minMateBuffer = minEval + 2000; +var maxMateBuffer = maxEval - 2000; + +var materialTable = [0, 800, 3350, 3450, 5000, 9750, 600000]; + +var pawnAdj = +[ + 0, 0, 0, 0, 0, 0, 0, 0, + -25, 105, 135, 270, 270, 135, 105, -25, + -80, 0, 30, 176, 176, 30, 0, -80, + -85, -5, 25, 175, 175, 25, -5, -85, + -90, -10, 20, 125, 125, 20, -10, -90, + -95, -15, 15, 75, 75, 15, -15, -95, + -100, -20, 10, 70, 70, 10, -20, -100, + 0, 0, 0, 0, 0, 0, 0, 0 +]; + +var knightAdj = + [-200, -100, -50, -50, -50, -50, -100, -200, + -100, 0, 0, 0, 0, 0, 0, -100, + -50, 0, 60, 60, 60, 60, 0, -50, + -50, 0, 30, 60, 60, 30, 0, -50, + -50, 0, 30, 60, 60, 30, 0, -50, + -50, 0, 30, 30, 30, 30, 0, -50, + -100, 0, 0, 0, 0, 0, 0, -100, + -200, -50, -25, -25, -25, -25, -50, -200 + ]; + +var bishopAdj = + [ -50,-50,-25,-10,-10,-25,-50,-50, + -50,-25,-10, 0, 0,-10,-25,-50, + -25,-10, 0, 25, 25, 0,-10,-25, + -10, 0, 25, 40, 40, 25, 0,-10, + -10, 0, 25, 40, 40, 25, 0,-10, + -25,-10, 0, 25, 25, 0,-10,-25, + -50,-25,-10, 0, 0,-10,-25,-50, + -50,-50,-25,-10,-10,-25,-50,-50 + ]; + +var rookAdj = + [ -60, -30, -10, 20, 20, -10, -30, -60, + 40, 70, 90,120,120, 90, 70, 40, + -60, -30, -10, 20, 20, -10, -30, -60, + -60, -30, -10, 20, 20, -10, -30, -60, + -60, -30, -10, 20, 20, -10, -30, -60, + -60, -30, -10, 20, 20, -10, -30, -60, + -60, -30, -10, 20, 20, -10, -30, -60, + -60, -30, -10, 20, 20, -10, -30, -60 + ]; + +var kingAdj = + [ 50, 150, -25, -125, -125, -25, 150, 50, + 50, 150, -25, -125, -125, -25, 150, 50, + 50, 150, -25, -125, -125, -25, 150, 50, + 50, 150, -25, -125, -125, -25, 150, 50, + 50, 150, -25, -125, -125, -25, 150, 50, + 50, 150, -25, -125, -125, -25, 150, 50, + 50, 150, -25, -125, -125, -25, 150, 50, + 150, 250, 75, -25, -25, 75, 250, 150 + ]; + +var emptyAdj = + [0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + ]; + +var pieceSquareAdj = new Array(8); + +// Returns the square flipped +var flipTable = new Array(256); + +function PawnEval(color) { + var pieceIdx = (color | 1) << 4; + var from = g_pieceList[pieceIdx++]; + while (from != 0) { + from = g_pieceList[pieceIdx++]; + } +} + +function Mobility(color) { + var result = 0; + var from, to, mob, pieceIdx; + var enemy = color == 8 ? 0x10 : 0x8 + var mobUnit = color == 8 ? g_mobUnit[0] : g_mobUnit[1]; + + // Knight mobility + mob = -3; + pieceIdx = (color | 2) << 4; + from = g_pieceList[pieceIdx++]; + while (from != 0) { + mob += mobUnit[g_board[from + 31]]; + mob += mobUnit[g_board[from + 33]]; + mob += mobUnit[g_board[from + 14]]; + mob += mobUnit[g_board[from - 14]]; + mob += mobUnit[g_board[from - 31]]; + mob += mobUnit[g_board[from - 33]]; + mob += mobUnit[g_board[from + 18]]; + mob += mobUnit[g_board[from - 18]]; + from = g_pieceList[pieceIdx++]; + } + result += 65 * mob; + + // Bishop mobility + mob = -4; + pieceIdx = (color | 3) << 4; + from = g_pieceList[pieceIdx++]; + while (from != 0) { + to = from - 15; while (g_board[to] == 0) { to -= 15; mob++; } + if (g_board[to] & enemy) { + mob++; + if (!(g_board[to] & piecePawn)) { + to -= 15; while (g_board[to] == 0) to -= 15; + mob += mobUnit[g_board[to]] << 2; + } + } + + to = from - 17; while (g_board[to] == 0) { to -= 17; mob++; } + if (g_board[to] & enemy) { + mob++; + if (!(g_board[to] & piecePawn)) { + to -= 17; while (g_board[to] == 0) to -= 17; + mob += mobUnit[g_board[to]] << 2; + } + } + + to = from + 15; while (g_board[to] == 0) { to += 15; mob++; } + if (g_board[to] & enemy) { + mob++; + if (!(g_board[to] & piecePawn)) { + to += 15; while (g_board[to] == 0) to += 15; + mob += mobUnit[g_board[to]] << 2; + } + } + + to = from + 17; while (g_board[to] == 0) { to += 17; mob++; } + if (g_board[to] & enemy) { + mob++; + if (!(g_board[to] & piecePawn)) { + to += 17; while (g_board[to] == 0) to += 17; + mob += mobUnit[g_board[to]] << 2; + } + } + + from = g_pieceList[pieceIdx++]; + } + result += 44 * mob; + + // Rook mobility + mob = -4; + pieceIdx = (color | 4) << 4; + from = g_pieceList[pieceIdx++]; + while (from != 0) { + to = from - 1; while (g_board[to] == 0) { to--; mob++;} if (g_board[to] & enemy) mob++; + to = from + 1; while (g_board[to] == 0) { to++; mob++; } if (g_board[to] & enemy) mob++; + to = from + 16; while (g_board[to] == 0) { to += 16; mob++; } if (g_board[to] & enemy) mob++; + to = from - 16; while (g_board[to] == 0) { to -= 16; mob++; } if (g_board[to] & enemy) mob++; + from = g_pieceList[pieceIdx++]; + } + result += 25 * mob; + + // Queen mobility + mob = -2; + pieceIdx = (color | 5) << 4; + from = g_pieceList[pieceIdx++]; + while (from != 0) { + to = from - 15; while (g_board[to] == 0) { to -= 15; mob++; } if (g_board[to] & enemy) mob++; + to = from - 17; while (g_board[to] == 0) { to -= 17; mob++; } if (g_board[to] & enemy) mob++; + to = from + 15; while (g_board[to] == 0) { to += 15; mob++; } if (g_board[to] & enemy) mob++; + to = from + 17; while (g_board[to] == 0) { to += 17; mob++; } if (g_board[to] & enemy) mob++; + to = from - 1; while (g_board[to] == 0) { to--; mob++; } if (g_board[to] & enemy) mob++; + to = from + 1; while (g_board[to] == 0) { to++; mob++; } if (g_board[to] & enemy) mob++; + to = from + 16; while (g_board[to] == 0) { to += 16; mob++; } if (g_board[to] & enemy) mob++; + to = from - 16; while (g_board[to] == 0) { to -= 16; mob++; } if (g_board[to] & enemy) mob++; + from = g_pieceList[pieceIdx++]; + } + result += 22 * mob; + + return result; +} + +function Evaluate() { + var curEval = g_baseEval; + + var evalAdjust = 0; + // Black queen gone, then cancel white's penalty for king movement + if (g_pieceList[pieceQueen << 4] == 0) + evalAdjust -= pieceSquareAdj[pieceKing][g_pieceList[(colorWhite | pieceKing) << 4]]; + // White queen gone, then cancel black's penalty for king movement + if (g_pieceList[(colorWhite | pieceQueen) << 4] == 0) + evalAdjust += pieceSquareAdj[pieceKing][flipTable[g_pieceList[pieceKing << 4]]]; + + // Black bishop pair + if (g_pieceCount[pieceBishop] >= 2) + evalAdjust -= 500; + // White bishop pair + if (g_pieceCount[pieceBishop | colorWhite] >= 2) + evalAdjust += 500; + + var mobility = Mobility(8) - Mobility(0); + + if (g_toMove == 0) { + // Black + curEval -= mobility; + curEval -= evalAdjust; + } + else { + curEval += mobility; + curEval += evalAdjust; + } + + return curEval; +} + +function ScoreMove(move){ + var moveTo = (move >> 8) & 0xFF; + var captured = g_board[moveTo] & 0x7; + var piece = g_board[move & 0xFF]; + var score; + if (captured != 0) { + var pieceType = piece & 0x7; + score = (captured << 5) - pieceType; + } else { + score = historyTable[piece & 0xF][moveTo]; + } + return score; +} + +function QSearch(alpha, beta, ply) { + g_qNodeCount++; + + var realEval = g_inCheck ? (minEval + 1) : Evaluate(); + + if (realEval >= beta) + return realEval; + + if (realEval > alpha) + alpha = realEval; + + var moves = new Array(); + var moveScores = new Array(); + var wasInCheck = g_inCheck; + + if (wasInCheck) { + // TODO: Fast check escape generator and fast checking moves generator + GenerateCaptureMoves(moves, null); + GenerateAllMoves(moves); + + for (var i = 0; i < moves.length; i++) { + moveScores[i] = ScoreMove(moves[i]); + } + } else { + GenerateCaptureMoves(moves, null); + + for (var i = 0; i < moves.length; i++) { + var captured = g_board[(moves[i] >> 8) & 0xFF] & 0x7; + var pieceType = g_board[moves[i] & 0xFF] & 0x7; + + moveScores[i] = (captured << 5) - pieceType; + } + } + + for (var i = 0; i < moves.length; i++) { + var bestMove = i; + for (var j = moves.length - 1; j > i; j--) { + if (moveScores[j] > moveScores[bestMove]) { + bestMove = j; + } + } + { + var tmpMove = moves[i]; + moves[i] = moves[bestMove]; + moves[bestMove] = tmpMove; + + var tmpScore = moveScores[i]; + moveScores[i] = moveScores[bestMove]; + moveScores[bestMove] = tmpScore; + } + + if (!wasInCheck && !See(moves[i])) { + continue; + } + + if (!MakeMove(moves[i])) { + continue; + } + + var value = -QSearch(-beta, -alpha, ply - 1); + + UnmakeMove(moves[i]); + + if (value > realEval) { + if (value >= beta) + return value; + + if (value > alpha) + alpha = value; + + realEval = value; + } + } + + /* Disable checks... Too slow currently + + if (ply == 0 && !wasInCheck) { + moves = new Array(); + GenerateAllMoves(moves); + + for (var i = 0; i < moves.length; i++) { + moveScores[i] = ScoreMove(moves[i]); + } + + for (var i = 0; i < moves.length; i++) { + var bestMove = i; + for (var j = moves.length - 1; j > i; j--) { + if (moveScores[j] > moveScores[bestMove]) { + bestMove = j; + } + } + { + var tmpMove = moves[i]; + moves[i] = moves[bestMove]; + moves[bestMove] = tmpMove; + + var tmpScore = moveScores[i]; + moveScores[i] = moveScores[bestMove]; + moveScores[bestMove] = tmpScore; + } + + if (!MakeMove(moves[i])) { + continue; + } + var checking = g_inCheck; + UnmakeMove(moves[i]); + + if (!checking) { + continue; + } + + if (!See(moves[i])) { + continue; + } + + MakeMove(moves[i]); + + var value = -QSearch(-beta, -alpha, ply - 1); + + UnmakeMove(moves[i]); + + if (value > realEval) { + if (value >= beta) + return value; + + if (value > alpha) + alpha = value; + + realEval = value; + } + } + } + */ + + return realEval; +} + +function StoreHash(value, flags, ply, move, depth) { + if (value >= maxMateBuffer) + value += depth; + else if (value <= minMateBuffer) + value -= depth; + g_hashTable[g_hashKeyLow & g_hashMask] = new HashEntry(g_hashKeyHigh, value, flags, ply, move); +} + +function IsHashMoveValid(hashMove) { + var from = hashMove & 0xFF; + var to = (hashMove >> 8) & 0xFF; + var ourPiece = g_board[from]; + var pieceType = ourPiece & 0x7; + if (pieceType < piecePawn || pieceType > pieceKing) return false; + // Can't move a piece we don't control + if (g_toMove != (ourPiece & 0x8)) + return false; + // Can't move to a square that has something of the same color + if (g_board[to] != 0 && (g_toMove == (g_board[to] & 0x8))) + return false; + if (pieceType == piecePawn) { + if (hashMove & moveflagEPC) { + return false; + } + + // Valid moves are push, capture, double push, promotions + var dir = to - from; + if ((g_toMove == colorWhite) != (dir < 0)) { + // Pawns have to move in the right direction + return false; + } + + var row = to & 0xF0; + if (((row == 0x90 && !g_toMove) || + (row == 0x20 && g_toMove)) != (hashMove & moveflagPromotion)) { + // Handle promotions + return false; + } + + if (dir == -16 || dir == 16) { + // White/Black push + return g_board[to] == 0; + } else if (dir == -15 || dir == -17 || dir == 15 || dir == 17) { + // White/Black capture + return g_board[to] != 0; + } else if (dir == -32) { + // Double white push + if (row != 0x60) return false; + if (g_board[to] != 0) return false; + if (g_board[from - 16] != 0) return false; + } else if (dir == 32) { + // Double black push + if (row != 0x50) return false; + if (g_board[to] != 0) return false; + if (g_board[from + 16] != 0) return false; + } else { + return false; + } + + return true; + } else { + // This validates that this piece type can actually make the attack + if (hashMove >> 16) return false; + return IsSquareAttackableFrom(to, from); + } +} + +function IsRepDraw() { + var stop = g_moveCount - 1 - g_move50; + stop = stop < 0 ? 0 : stop; + for (var i = g_moveCount - 5; i >= stop; i -= 2) { + if (g_repMoveStack[i] == g_hashKeyLow) + return true; + } + return false; +} + +function MovePicker(hashMove, depth, killer1, killer2) { + this.hashMove = hashMove; + this.depth = depth; + this.killer1 = killer1; + this.killer2 = killer2; + + this.moves = new Array(); + this.losingCaptures = null; + this.moveCount = 0; + this.atMove = -1; + this.moveScores = null; + this.stage = 0; + + this.nextMove = function () { + if (++this.atMove == this.moveCount) { + this.stage++; + if (this.stage == 1) { + if (this.hashMove != null && IsHashMoveValid(hashMove)) { + this.moves[0] = hashMove; + this.moveCount = 1; + } + if (this.moveCount != 1) { + this.hashMove = null; + this.stage++; + } + } + + if (this.stage == 2) { + GenerateCaptureMoves(this.moves, null); + this.moveCount = this.moves.length; + this.moveScores = new Array(this.moveCount); + // Move ordering + for (var i = this.atMove; i < this.moveCount; i++) { + var captured = g_board[(this.moves[i] >> 8) & 0xFF] & 0x7; + var pieceType = g_board[this.moves[i] & 0xFF] & 0x7; + this.moveScores[i] = (captured << 5) - pieceType; + } + // No moves, onto next stage + if (this.atMove == this.moveCount) this.stage++; + } + + if (this.stage == 3) { + if (IsHashMoveValid(this.killer1) && + this.killer1 != this.hashMove) { + this.moves[this.moves.length] = this.killer1; + this.moveCount = this.moves.length; + } else { + this.killer1 = 0; + this.stage++; + } + } + + if (this.stage == 4) { + if (IsHashMoveValid(this.killer2) && + this.killer2 != this.hashMove) { + this.moves[this.moves.length] = this.killer2; + this.moveCount = this.moves.length; + } else { + this.killer2 = 0; + this.stage++; + } + } + + if (this.stage == 5) { + GenerateAllMoves(this.moves); + this.moveCount = this.moves.length; + // Move ordering + for (var i = this.atMove; i < this.moveCount; i++) this.moveScores[i] = ScoreMove(this.moves[i]); + // No moves, onto next stage + if (this.atMove == this.moveCount) this.stage++; + } + + if (this.stage == 6) { + // Losing captures + if (this.losingCaptures != null) { + for (var i = 0; i < this.losingCaptures.length; i++) { + this.moves[this.moves.length] = this.losingCaptures[i]; + } + for (var i = this.atMove; i < this.moveCount; i++) this.moveScores[i] = ScoreMove(this.moves[i]); + this.moveCount = this.moves.length; + } + // No moves, onto next stage + if (this.atMove == this.moveCount) this.stage++; + } + + if (this.stage == 7) + return 0; + } + + var bestMove = this.atMove; + for (var j = this.atMove + 1; j < this.moveCount; j++) { + if (this.moveScores[j] > this.moveScores[bestMove]) { + bestMove = j; + } + } + + if (bestMove != this.atMove) { + var tmpMove = this.moves[this.atMove]; + this.moves[this.atMove] = this.moves[bestMove]; + this.moves[bestMove] = tmpMove; + + var tmpScore = this.moveScores[this.atMove]; + this.moveScores[this.atMove] = this.moveScores[bestMove]; + this.moveScores[bestMove] = tmpScore; + } + + var candidateMove = this.moves[this.atMove]; + if ((this.stage > 1 && candidateMove == this.hashMove) || + (this.stage > 3 && candidateMove == this.killer1) || + (this.stage > 4 && candidateMove == this.killer2)) { + return this.nextMove(); + } + + if (this.stage == 2 && !See(candidateMove)) { + if (this.losingCaptures == null) { + this.losingCaptures = new Array(); + } + this.losingCaptures[this.losingCaptures.length] = candidateMove; + return this.nextMove(); + } + + return this.moves[this.atMove]; + } +} + +function AllCutNode(ply, depth, beta, allowNull) { + if (ply <= 0) { + return QSearch(beta - 1, beta, 0); + } + + if ((g_nodeCount & 127) == 127) { + if ((new Date()).getTime() - g_startTime > g_timeout) { + // Time cutoff + g_searchValid = false; + return beta - 1; + } + } + + g_nodeCount++; + + if (IsRepDraw()) + return 0; + + // Mate distance pruning + if (minEval + depth >= beta) + return beta; + + if (maxEval - (depth + 1) < beta) + return beta - 1; + + var hashMove = null; + var hashNode = g_hashTable[g_hashKeyLow & g_hashMask]; + if (hashNode != null && hashNode.lock == g_hashKeyHigh) { + hashMove = hashNode.bestMove; + if (hashNode.hashDepth >= ply) { + var hashValue = hashNode.value; + + // Fixup mate scores + if (hashValue >= maxMateBuffer) + hashValue -= depth; + else if (hashValue <= minMateBuffer) + hashValue += depth; + + if (hashNode.flags == hashflagExact) + return hashValue; + if (hashNode.flags == hashflagAlpha && hashValue < beta) + return hashValue; + if (hashNode.flags == hashflagBeta && hashValue >= beta) + return hashValue; + } + } + + // TODO - positional gain? + + if (!g_inCheck && + allowNull && + beta > minMateBuffer && + beta < maxMateBuffer) { + // Try some razoring + if (hashMove == null && + ply < 4) { + var razorMargin = 2500 + 200 * ply; + if (g_baseEval < beta - razorMargin) { + var razorBeta = beta - razorMargin; + var v = QSearch(razorBeta - 1, razorBeta, 0); + if (v < razorBeta) + return v; + } + } + + // TODO - static null move + + // Null move + if (ply > 1 && + g_baseEval >= beta - (ply >= 4 ? 2500 : 0) && + // Disable null move if potential zugzwang (no big pieces) + (g_pieceCount[pieceBishop | g_toMove] != 0 || + g_pieceCount[pieceKnight | g_toMove] != 0 || + g_pieceCount[pieceRook | g_toMove] != 0 || + g_pieceCount[pieceQueen | g_toMove] != 0)) { + var r = 3 + (ply >= 5 ? 1 : ply / 4); + if (g_baseEval - beta > 1500) r++; + + g_toMove = 8 - g_toMove; + g_baseEval = -g_baseEval; + g_hashKeyLow ^= g_zobristBlackLow; + g_hashKeyHigh ^= g_zobristBlackHigh; + + var value = -AllCutNode(ply - r, depth + 1, -(beta - 1), false); + + g_hashKeyLow ^= g_zobristBlackLow; + g_hashKeyHigh ^= g_zobristBlackHigh; + g_toMove = 8 - g_toMove; + g_baseEval = -g_baseEval; + + if (value >= beta) + return beta; + } + } + + var moveMade = false; + var realEval = minEval - 1; + var inCheck = g_inCheck; + + var movePicker = new MovePicker(hashMove, depth, g_killers[depth][0], g_killers[depth][1]); + + for (;;) { + var currentMove = movePicker.nextMove(); + if (currentMove == 0) { + break; + } + + var plyToSearch = ply - 1; + + if (!MakeMove(currentMove)) { + continue; + } + + var value; + var doFullSearch = true; + + if (g_inCheck) { + // Check extensions + plyToSearch++; + } else { + var reduced = plyToSearch - (movePicker.atMove > 14 ? 2 : 1); + + // Futility pruning +/* if (movePicker.stage == 5 && !inCheck) { + if (movePicker.atMove >= (15 + (1 << (5 * ply) >> 2)) && + realEval > minMateBuffer) { + UnmakeMove(currentMove); + continue; + } + + if (ply < 7) { + var reducedPly = reduced <= 0 ? 0 : reduced; + var futilityValue = -g_baseEval + (900 * (reducedPly + 2)) - (movePicker.atMove * 10); + if (futilityValue < beta) { + if (futilityValue > realEval) { + realEval = futilityValue; + } + UnmakeMove(currentMove); + continue; + } + } + }*/ + + // Late move reductions + if (movePicker.stage == 5 && movePicker.atMove > 5 && ply >= 3) { + value = -AllCutNode(reduced, depth + 1, -(beta - 1), true); + doFullSearch = (value >= beta); + } + } + + if (doFullSearch) { + value = -AllCutNode(plyToSearch, depth + 1, -(beta - 1), true); + } + + moveMade = true; + + UnmakeMove(currentMove); + + if (!g_searchValid) { + return beta - 1; + } + + if (value > realEval) { + if (value >= beta) { + var histTo = (currentMove >> 8) & 0xFF; + if (g_board[histTo] == 0) { + var histPiece = g_board[currentMove & 0xFF] & 0xF; + historyTable[histPiece][histTo] += ply * ply; + if (historyTable[histPiece][histTo] > 32767) { + historyTable[histPiece][histTo] >>= 1; + } + + if (g_killers[depth][0] != currentMove) { + g_killers[depth][1] = g_killers[depth][0]; + g_killers[depth][0] = currentMove; + } + } + + StoreHash(value, hashflagBeta, ply, currentMove, depth); + return value; + } + + realEval = value; + hashMove = currentMove; + } + } + + if (!moveMade) { + // If we have no valid moves it's either stalemate or checkmate + if (g_inCheck) + // Checkmate. + return minEval + depth; + else + // Stalemate + return 0; + } + + StoreHash(realEval, hashflagAlpha, ply, hashMove, depth); + + return realEval; +} + +function AlphaBeta(ply, depth, alpha, beta) { + if (ply <= 0) { + return QSearch(alpha, beta, 0); + } + + g_nodeCount++; + + if (depth > 0 && IsRepDraw()) + return 0; + + // Mate distance pruning + var oldAlpha = alpha; + alpha = alpha < minEval + depth ? alpha : minEval + depth; + beta = beta > maxEval - (depth + 1) ? beta : maxEval - (depth + 1); + if (alpha >= beta) + return alpha; + + var hashMove = null; + var hashFlag = hashflagAlpha; + var hashNode = g_hashTable[g_hashKeyLow & g_hashMask]; + if (hashNode != null && hashNode.lock == g_hashKeyHigh) { + hashMove = hashNode.bestMove; + } + + var inCheck = g_inCheck; + + var moveMade = false; + var realEval = minEval; + + var movePicker = new MovePicker(hashMove, depth, g_killers[depth][0], g_killers[depth][1]); + + for (;;) { + var currentMove = movePicker.nextMove(); + if (currentMove == 0) { + break; + } + + var plyToSearch = ply - 1; + + if (!MakeMove(currentMove)) { + continue; + } + + if (g_inCheck) { + // Check extensions + plyToSearch++; + } + + var value; + if (moveMade) { + value = -AllCutNode(plyToSearch, depth + 1, -alpha, true); + if (value > alpha) { + value = -AlphaBeta(plyToSearch, depth + 1, -beta, -alpha); + } + } else { + value = -AlphaBeta(plyToSearch, depth + 1, -beta, -alpha); + } + + moveMade = true; + + UnmakeMove(currentMove); + + if (!g_searchValid) { + return alpha; + } + + if (value > realEval) { + if (value >= beta) { + var histTo = (currentMove >> 8) & 0xFF; + if (g_board[histTo] == 0) { + var histPiece = g_board[currentMove & 0xFF] & 0xF; + historyTable[histPiece][histTo] += ply * ply; + if (historyTable[histPiece][histTo] > 32767) { + historyTable[histPiece][histTo] >>= 1; + } + + if (g_killers[depth][0] != currentMove) { + g_killers[depth][1] = g_killers[depth][0]; + g_killers[depth][0] = currentMove; + } + } + + StoreHash(value, hashflagBeta, ply, currentMove, depth); + return value; + } + + if (value > oldAlpha) { + hashFlag = hashflagExact; + alpha = value; + } + + realEval = value; + hashMove = currentMove; + } + } + + if (!moveMade) { + // If we have no valid moves it's either stalemate or checkmate + if (inCheck) + // Checkmate. + return minEval + depth; + else + // Stalemate + return 0; + } + + StoreHash(realEval, hashFlag, ply, hashMove, depth); + + return realEval; +} + +// +// Board code +// + +// This somewhat funky scheme means that a piece is indexed by it's lower 4 bits when accessing in arrays. The fifth bit (black bit) +// is used to allow quick edge testing on the board. +var colorBlack = 0x10; +var colorWhite = 0x08; + +var pieceEmpty = 0x00; +var piecePawn = 0x01; +var pieceKnight = 0x02; +var pieceBishop = 0x03; +var pieceRook = 0x04; +var pieceQueen = 0x05; +var pieceKing = 0x06; + +var g_vectorDelta = new Array(256); + +var g_bishopDeltas = [-15, -17, 15, 17]; +var g_knightDeltas = [31, 33, 14, -14, -31, -33, 18, -18]; +var g_rookDeltas = [-1, +1, -16, +16]; +var g_queenDeltas = [-1, +1, -15, +15, -17, +17, -16, +16]; + +var g_castleRightsMask = [ +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 7,15,15,15, 3,15,15,11, 0, 0, 0, 0, +0, 0, 0, 0,15,15,15,15,15,15,15,15, 0, 0, 0, 0, +0, 0, 0, 0,15,15,15,15,15,15,15,15, 0, 0, 0, 0, +0, 0, 0, 0,15,15,15,15,15,15,15,15, 0, 0, 0, 0, +0, 0, 0, 0,15,15,15,15,15,15,15,15, 0, 0, 0, 0, +0, 0, 0, 0,15,15,15,15,15,15,15,15, 0, 0, 0, 0, +0, 0, 0, 0,15,15,15,15,15,15,15,15, 0, 0, 0, 0, +0, 0, 0, 0,13,15,15,15,12,15,15,14, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + +var moveflagEPC = 0x2 << 16; +var moveflagCastleKing = 0x4 << 16; +var moveflagCastleQueen = 0x8 << 16; +var moveflagPromotion = 0x10 << 16; +var moveflagPromoteKnight = 0x20 << 16; +var moveflagPromoteQueen = 0x40 << 16; +var moveflagPromoteBishop = 0x80 << 16; + +function MT() { + var N = 624; + var M = 397; + var MAG01 = [0x0, 0x9908b0df]; + + this.mt = new Array(N); + this.mti = N + 1; + + this.setSeed = function() + { + var a = arguments; + switch (a.length) { + case 1: + if (a[0].constructor === Number) { + this.mt[0]= a[0]; + for (var i = 1; i < N; ++i) { + var s = this.mt[i - 1] ^ (this.mt[i - 1] >>> 30); + this.mt[i] = ((1812433253 * ((s & 0xffff0000) >>> 16)) + << 16) + + 1812433253 * (s & 0x0000ffff) + + i; + } + this.mti = N; + return; + } + + this.setSeed(19650218); + + var l = a[0].length; + var i = 1; + var j = 0; + + for (var k = N > l ? N : l; k != 0; --k) { + var s = this.mt[i - 1] ^ (this.mt[i - 1] >>> 30) + this.mt[i] = (this.mt[i] + ^ (((1664525 * ((s & 0xffff0000) >>> 16)) << 16) + + 1664525 * (s & 0x0000ffff))) + + a[0][j] + + j; + if (++i >= N) { + this.mt[0] = this.mt[N - 1]; + i = 1; + } + if (++j >= l) { + j = 0; + } + } + + for (var k = N - 1; k != 0; --k) { + var s = this.mt[i - 1] ^ (this.mt[i - 1] >>> 30); + this.mt[i] = (this.mt[i] + ^ (((1566083941 * ((s & 0xffff0000) >>> 16)) << 16) + + 1566083941 * (s & 0x0000ffff))) + - i; + if (++i >= N) { + this.mt[0] = this.mt[N-1]; + i = 1; + } + } + + this.mt[0] = 0x80000000; + return; + default: + var seeds = new Array(); + for (var i = 0; i < a.length; ++i) { + seeds.push(a[i]); + } + this.setSeed(seeds); + return; + } + } + + this.setSeed(0x1BADF00D); + + this.next = function (bits) + { + if (this.mti >= N) { + var x = 0; + + for (var k = 0; k < N - M; ++k) { + x = (this.mt[k] & 0x80000000) | (this.mt[k + 1] & 0x7fffffff); + this.mt[k] = this.mt[k + M] ^ (x >>> 1) ^ MAG01[x & 0x1]; + } + for (var k = N - M; k < N - 1; ++k) { + x = (this.mt[k] & 0x80000000) | (this.mt[k + 1] & 0x7fffffff); + this.mt[k] = this.mt[k + (M - N)] ^ (x >>> 1) ^ MAG01[x & 0x1]; + } + x = (this.mt[N - 1] & 0x80000000) | (this.mt[0] & 0x7fffffff); + this.mt[N - 1] = this.mt[M - 1] ^ (x >>> 1) ^ MAG01[x & 0x1]; + + this.mti = 0; + } + + var y = this.mt[this.mti++]; + y ^= y >>> 11; + y ^= (y << 7) & 0x9d2c5680; + y ^= (y << 15) & 0xefc60000; + y ^= y >>> 18; + return (y >>> (32 - bits)) & 0xFFFFFFFF; + } +} + +// Position variables +var g_board = new Array(256); // Sentinel 0x80, pieces are in low 4 bits, 0x8 for color, 0x7 bits for piece type +var g_toMove; // side to move, 0 or 8, 0 = black, 8 = white +var g_castleRights; // bitmask representing castling rights, 1 = wk, 2 = wq, 4 = bk, 8 = bq +var g_enPassentSquare; +var g_baseEval; +var g_hashKeyLow, g_hashKeyHigh; +var g_inCheck; + +// Utility variables +var g_moveCount = 0; +var g_moveUndoStack = new Array(); + +var g_move50 = 0; +var g_repMoveStack = new Array(); + +var g_hashSize = 1 << 22; +var g_hashMask = g_hashSize - 1; +var g_hashTable; + +var g_killers; +var historyTable = new Array(32); + +var g_zobristLow; +var g_zobristHigh; +var g_zobristBlackLow; +var g_zobristBlackHigh; + +// Evaulation variables +var g_mobUnit; + +var hashflagAlpha = 1; +var hashflagBeta = 2; +var hashflagExact = 3; + +function HashEntry(lock, value, flags, hashDepth, bestMove, globalPly) { + this.lock = lock; + this.value = value; + this.flags = flags; + this.hashDepth = hashDepth; + this.bestMove = bestMove; +} + +function MakeSquare(row, column) { + return ((row + 2) << 4) | (column + 4); +} + +function MakeTable(table) { + var result = new Array(256); + for (var i = 0; i < 256; i++) { + result[i] = 0; + } + for (var row = 0; row < 8; row++) { + for (var col = 0; col < 8; col++) { + result[MakeSquare(row, col)] = table[row * 8 + col]; + } + } + return result; +} + +function ResetGame() { + g_killers = new Array(128); + for (var i = 0; i < 128; i++) { + g_killers[i] = [0, 0]; + } + + g_hashTable = new Array(g_hashSize); + + for (var i = 0; i < 32; i++) { + historyTable[i] = new Array(256); + for (var j = 0; j < 256; j++) + historyTable[i][j] = 0; + } + + var mt = new MT(0x1badf00d); + + g_zobristLow = new Array(256); + g_zobristHigh = new Array(256); + for (var i = 0; i < 256; i++) { + g_zobristLow[i] = new Array(16); + g_zobristHigh[i] = new Array(16); + for (var j = 0; j < 16; j++) { + g_zobristLow[i][j] = mt.next(32); + g_zobristHigh[i][j] = mt.next(32); + } + } + g_zobristBlackLow = mt.next(32); + g_zobristBlackHigh = mt.next(32); + + for (var row = 0; row < 8; row++) { + for (var col = 0; col < 8; col++) { + var square = MakeSquare(row, col); + flipTable[square] = MakeSquare(7 - row, col); + } + } + + pieceSquareAdj[piecePawn] = MakeTable(pawnAdj); + pieceSquareAdj[pieceKnight] = MakeTable(knightAdj); + pieceSquareAdj[pieceBishop] = MakeTable(bishopAdj); + pieceSquareAdj[pieceRook] = MakeTable(rookAdj); + pieceSquareAdj[pieceQueen] = MakeTable(emptyAdj); + pieceSquareAdj[pieceKing] = MakeTable(kingAdj); + + var pieceDeltas = [[], [], g_knightDeltas, g_bishopDeltas, g_rookDeltas, g_queenDeltas, g_queenDeltas]; + + for (var i = 0; i < 256; i++) { + g_vectorDelta[i] = new Object(); + g_vectorDelta[i].delta = 0; + g_vectorDelta[i].pieceMask = new Array(2); + g_vectorDelta[i].pieceMask[0] = 0; + g_vectorDelta[i].pieceMask[1] = 0; + } + + // Initialize the vector delta table + for (var row = 0; row < 0x80; row += 0x10) + for (var col = 0; col < 0x8; col++) { + var square = row | col; + + // Pawn moves + var index = square - (square - 17) + 128; + g_vectorDelta[index].pieceMask[colorWhite >> 3] |= (1 << piecePawn); + index = square - (square - 15) + 128; + g_vectorDelta[index].pieceMask[colorWhite >> 3] |= (1 << piecePawn); + + index = square - (square + 17) + 128; + g_vectorDelta[index].pieceMask[0] |= (1 << piecePawn); + index = square - (square + 15) + 128; + g_vectorDelta[index].pieceMask[0] |= (1 << piecePawn); + + for (var i = pieceKnight; i <= pieceKing; i++) { + for (var dir = 0; dir < pieceDeltas[i].length; dir++) { + var target = square + pieceDeltas[i][dir]; + while (!(target & 0x88)) { + index = square - target + 128; + + g_vectorDelta[index].pieceMask[colorWhite >> 3] |= (1 << i); + g_vectorDelta[index].pieceMask[0] |= (1 << i); + + var flip = -1; + if (square < target) + flip = 1; + + if ((square & 0xF0) == (target & 0xF0)) { + // On the same row + g_vectorDelta[index].delta = flip * 1; + } else if ((square & 0x0F) == (target & 0x0F)) { + // On the same column + g_vectorDelta[index].delta = flip * 16; + } else if ((square % 15) == (target % 15)) { + g_vectorDelta[index].delta = flip * 15; + } else if ((square % 17) == (target % 17)) { + g_vectorDelta[index].delta = flip * 17; + } + + if (i == pieceKnight) { + g_vectorDelta[index].delta = pieceDeltas[i][dir]; + break; + } + + if (i == pieceKing) + break; + + target += pieceDeltas[i][dir]; + } + } + } + } + + InitializeEval(); + InitializeFromFen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); +} + +function InitializeEval() { + g_mobUnit = new Array(2); + for (var i = 0; i < 2; i++) { + g_mobUnit[i] = new Array(); + var enemy = i == 0 ? 0x10 : 8; + var friend = i == 0 ? 8 : 0x10; + g_mobUnit[i][0] = 1; + g_mobUnit[i][0x80] = 0; + g_mobUnit[i][enemy | piecePawn] = 1; + g_mobUnit[i][enemy | pieceBishop] = 2; + g_mobUnit[i][enemy | pieceKnight] = 2; + g_mobUnit[i][enemy | pieceRook] = 4; + g_mobUnit[i][enemy | pieceQueen] = 6; + g_mobUnit[i][enemy | pieceKing] = 6; + g_mobUnit[i][friend | piecePawn] = 0; + g_mobUnit[i][friend | pieceBishop] = 0; + g_mobUnit[i][friend | pieceKnight] = 0; + g_mobUnit[i][friend | pieceRook] = 0; + g_mobUnit[i][friend | pieceQueen] = 0; + g_mobUnit[i][friend | pieceKing] = 0; + } +} + +function SetHash() { + var result = new Object(); + result.hashKeyLow = 0; + result.hashKeyHigh = 0; + + for (var i = 0; i < 256; i++) { + var piece = g_board[i]; + if (piece & 0x18) { + result.hashKeyLow ^= g_zobristLow[i][piece & 0xF] + result.hashKeyHigh ^= g_zobristHigh[i][piece & 0xF] + } + } + + if (!g_toMove) { + result.hashKeyLow ^= g_zobristBlackLow; + result.hashKeyHigh ^= g_zobristBlackHigh; + } + + return result; +} + +function InitializeFromFen(fen) { + var chunks = fen.split(' '); + + for (var i = 0; i < 256; i++) + g_board[i] = 0x80; + + var row = 0; + var col = 0; + + var pieces = chunks[0]; + for (var i = 0; i < pieces.length; i++) { + var c = pieces.charAt(i); + + if (c == '/') { + row++; + col = 0; + } + else { + if (c >= '0' && c <= '9') { + for (var j = 0; j < parseInt(c); j++) { + g_board[MakeSquare(row, col)] = 0; + col++; + } + } + else { + var isBlack = c >= 'a' && c <= 'z'; + var piece = isBlack ? colorBlack : colorWhite; + if (!isBlack) + c = pieces.toLowerCase().charAt(i); + switch (c) { + case 'p': + piece |= piecePawn; + break; + case 'b': + piece |= pieceBishop; + break; + case 'n': + piece |= pieceKnight; + break; + case 'r': + piece |= pieceRook; + break; + case 'q': + piece |= pieceQueen; + break; + case 'k': + piece |= pieceKing; + break; + } + + g_board[MakeSquare(row, col)] = piece; + col++; + } + } + } + + InitializePieceList(); + + g_toMove = chunks[1].charAt(0) == 'w' ? colorWhite : 0; + var them = 8 - g_toMove; + + g_castleRights = 0; + if (chunks[2].indexOf('K') != -1) { + if (g_board[MakeSquare(7, 4)] != (pieceKing | colorWhite) || + g_board[MakeSquare(7, 7)] != (pieceRook | colorWhite)) { + return 'Invalid FEN: White kingside castling not allowed'; + } + g_castleRights |= 1; + } + if (chunks[2].indexOf('Q') != -1) { + if (g_board[MakeSquare(7, 4)] != (pieceKing | colorWhite) || + g_board[MakeSquare(7, 0)] != (pieceRook | colorWhite)) { + return 'Invalid FEN: White queenside castling not allowed'; + } + g_castleRights |= 2; + } + if (chunks[2].indexOf('k') != -1) { + if (g_board[MakeSquare(0, 4)] != (pieceKing | colorBlack) || + g_board[MakeSquare(0, 7)] != (pieceRook | colorBlack)) { + return 'Invalid FEN: Black kingside castling not allowed'; + } + g_castleRights |= 4; + } + if (chunks[2].indexOf('q') != -1) { + if (g_board[MakeSquare(0, 4)] != (pieceKing | colorBlack) || + g_board[MakeSquare(0, 0)] != (pieceRook | colorBlack)) { + return 'Invalid FEN: Black queenside castling not allowed'; + } + g_castleRights |= 8; + } + + g_enPassentSquare = -1; + if (chunks[3].indexOf('-') == -1) { + var col = chunks[3].charAt(0).charCodeAt() - 'a'.charCodeAt(); + var row = 8 - (chunks[3].charAt(1).charCodeAt() - '0'.charCodeAt()); + g_enPassentSquare = MakeSquare(row, col); + } + + var hashResult = SetHash(); + g_hashKeyLow = hashResult.hashKeyLow; + g_hashKeyHigh = hashResult.hashKeyHigh; + + g_baseEval = 0; + for (var i = 0; i < 256; i++) { + if (g_board[i] & colorWhite) { + g_baseEval += pieceSquareAdj[g_board[i] & 0x7][i]; + g_baseEval += materialTable[g_board[i] & 0x7]; + } else if (g_board[i] & colorBlack) { + g_baseEval -= pieceSquareAdj[g_board[i] & 0x7][flipTable[i]]; + g_baseEval -= materialTable[g_board[i] & 0x7]; + } + } + if (!g_toMove) g_baseEval = -g_baseEval; + + g_move50 = 0; + g_inCheck = IsSquareAttackable(g_pieceList[(g_toMove | pieceKing) << 4], them); + + // Check for king capture (invalid FEN) + if (IsSquareAttackable(g_pieceList[(them | pieceKing) << 4], g_toMove)) { + return 'Invalid FEN: Can capture king'; + } + + // Checkmate/stalemate + if (GenerateValidMoves().length == 0) { + return g_inCheck ? 'Checkmate' : 'Stalemate'; + } + + return ''; +} + +var g_pieceIndex = new Array(256); +var g_pieceList = new Array(2 * 8 * 16); +var g_pieceCount = new Array(2 * 8); + +function InitializePieceList() { + for (var i = 0; i < 16; i++) { + g_pieceCount[i] = 0; + for (var j = 0; j < 16; j++) { + // 0 is used as the terminator for piece lists + g_pieceList[(i << 4) | j] = 0; + } + } + + for (var i = 0; i < 256; i++) { + g_pieceIndex[i] = 0; + if (g_board[i] & (colorWhite | colorBlack)) { + var piece = g_board[i] & 0xF; + + g_pieceList[(piece << 4) | g_pieceCount[piece]] = i; + g_pieceIndex[i] = g_pieceCount[piece]; + g_pieceCount[piece]++; + } + } +} + +function MakeMove(move){ + var me = g_toMove >> 3; + var otherColor = 8 - g_toMove; + + var flags = move & 0xFF0000; + var to = (move >> 8) & 0xFF; + var from = move & 0xFF; + var captured = g_board[to]; + var piece = g_board[from]; + var epcEnd = to; + + if (flags & moveflagEPC) { + epcEnd = me ? (to + 0x10) : (to - 0x10); + captured = g_board[epcEnd]; + g_board[epcEnd] = pieceEmpty; + } + + g_moveUndoStack[g_moveCount] = new UndoHistory(g_enPassentSquare, g_castleRights, g_inCheck, g_baseEval, g_hashKeyLow, g_hashKeyHigh, g_move50, captured); + g_moveCount++; + + g_enPassentSquare = -1; + + if (flags) { + if (flags & moveflagCastleKing) { + if (IsSquareAttackable(from + 1, otherColor) || + IsSquareAttackable(from + 2, otherColor)) { + g_moveCount--; + return false; + } + + var rook = g_board[to + 1]; + + g_hashKeyLow ^= g_zobristLow[to + 1][rook & 0xF]; + g_hashKeyHigh ^= g_zobristHigh[to + 1][rook & 0xF]; + g_hashKeyLow ^= g_zobristLow[to - 1][rook & 0xF]; + g_hashKeyHigh ^= g_zobristHigh[to - 1][rook & 0xF]; + + g_board[to - 1] = rook; + g_board[to + 1] = pieceEmpty; + + g_baseEval -= pieceSquareAdj[rook & 0x7][me == 0 ? flipTable[to + 1] : (to + 1)]; + g_baseEval += pieceSquareAdj[rook & 0x7][me == 0 ? flipTable[to - 1] : (to - 1)]; + + var rookIndex = g_pieceIndex[to + 1]; + g_pieceIndex[to - 1] = rookIndex; + g_pieceList[((rook & 0xF) << 4) | rookIndex] = to - 1; + } else if (flags & moveflagCastleQueen) { + if (IsSquareAttackable(from - 1, otherColor) || + IsSquareAttackable(from - 2, otherColor)) { + g_moveCount--; + return false; + } + + var rook = g_board[to - 2]; + + g_hashKeyLow ^= g_zobristLow[to -2][rook & 0xF]; + g_hashKeyHigh ^= g_zobristHigh[to - 2][rook & 0xF]; + g_hashKeyLow ^= g_zobristLow[to + 1][rook & 0xF]; + g_hashKeyHigh ^= g_zobristHigh[to + 1][rook & 0xF]; + + g_board[to + 1] = rook; + g_board[to - 2] = pieceEmpty; + + g_baseEval -= pieceSquareAdj[rook & 0x7][me == 0 ? flipTable[to - 2] : (to - 2)]; + g_baseEval += pieceSquareAdj[rook & 0x7][me == 0 ? flipTable[to + 1] : (to + 1)]; + + var rookIndex = g_pieceIndex[to - 2]; + g_pieceIndex[to + 1] = rookIndex; + g_pieceList[((rook & 0xF) << 4) | rookIndex] = to + 1; + } + } + + if (captured) { + // Remove our piece from the piece list + var capturedType = captured & 0xF; + g_pieceCount[capturedType]--; + var lastPieceSquare = g_pieceList[(capturedType << 4) | g_pieceCount[capturedType]]; + g_pieceIndex[lastPieceSquare] = g_pieceIndex[epcEnd]; + g_pieceList[(capturedType << 4) | g_pieceIndex[lastPieceSquare]] = lastPieceSquare; + g_pieceList[(capturedType << 4) | g_pieceCount[capturedType]] = 0; + + g_baseEval += materialTable[captured & 0x7]; + g_baseEval += pieceSquareAdj[captured & 0x7][me ? flipTable[epcEnd] : epcEnd]; + + g_hashKeyLow ^= g_zobristLow[epcEnd][capturedType]; + g_hashKeyHigh ^= g_zobristHigh[epcEnd][capturedType]; + g_move50 = 0; + } else if ((piece & 0x7) == piecePawn) { + var diff = to - from; + if (diff < 0) diff = -diff; + if (diff > 16) { + g_enPassentSquare = me ? (to + 0x10) : (to - 0x10); + } + g_move50 = 0; + } + + g_hashKeyLow ^= g_zobristLow[from][piece & 0xF]; + g_hashKeyHigh ^= g_zobristHigh[from][piece & 0xF]; + g_hashKeyLow ^= g_zobristLow[to][piece & 0xF]; + g_hashKeyHigh ^= g_zobristHigh[to][piece & 0xF]; + g_hashKeyLow ^= g_zobristBlackLow; + g_hashKeyHigh ^= g_zobristBlackHigh; + + g_castleRights &= g_castleRightsMask[from] & g_castleRightsMask[to]; + + g_baseEval -= pieceSquareAdj[piece & 0x7][me == 0 ? flipTable[from] : from]; + + // Move our piece in the piece list + g_pieceIndex[to] = g_pieceIndex[from]; + g_pieceList[((piece & 0xF) << 4) | g_pieceIndex[to]] = to; + + if (flags & moveflagPromotion) { + var newPiece = piece & (~0x7); + if (flags & moveflagPromoteKnight) + newPiece |= pieceKnight; + else if (flags & moveflagPromoteQueen) + newPiece |= pieceQueen; + else if (flags & moveflagPromoteBishop) + newPiece |= pieceBishop; + else + newPiece |= pieceRook; + + g_hashKeyLow ^= g_zobristLow[to][piece & 0xF]; + g_hashKeyHigh ^= g_zobristHigh[to][piece & 0xF]; + g_board[to] = newPiece; + g_hashKeyLow ^= g_zobristLow[to][newPiece & 0xF]; + g_hashKeyHigh ^= g_zobristHigh[to][newPiece & 0xF]; + + g_baseEval += pieceSquareAdj[newPiece & 0x7][me == 0 ? flipTable[to] : to]; + g_baseEval -= materialTable[piecePawn]; + g_baseEval += materialTable[newPiece & 0x7]; + + var pawnType = piece & 0xF; + var promoteType = newPiece & 0xF; + + g_pieceCount[pawnType]--; + + var lastPawnSquare = g_pieceList[(pawnType << 4) | g_pieceCount[pawnType]]; + g_pieceIndex[lastPawnSquare] = g_pieceIndex[to]; + g_pieceList[(pawnType << 4) | g_pieceIndex[lastPawnSquare]] = lastPawnSquare; + g_pieceList[(pawnType << 4) | g_pieceCount[pawnType]] = 0; + g_pieceIndex[to] = g_pieceCount[promoteType]; + g_pieceList[(promoteType << 4) | g_pieceIndex[to]] = to; + g_pieceCount[promoteType]++; + } else { + g_board[to] = g_board[from]; + + g_baseEval += pieceSquareAdj[piece & 0x7][me == 0 ? flipTable[to] : to]; + } + g_board[from] = pieceEmpty; + + g_toMove = otherColor; + g_baseEval = -g_baseEval; + + if ((piece & 0x7) == pieceKing || g_inCheck) { + if (IsSquareAttackable(g_pieceList[(pieceKing | (8 - g_toMove)) << 4], otherColor)) { + UnmakeMove(move); + return false; + } + } else { + var kingPos = g_pieceList[(pieceKing | (8 - g_toMove)) << 4]; + + if (ExposesCheck(from, kingPos)) { + UnmakeMove(move); + return false; + } + + if (epcEnd != to) { + if (ExposesCheck(epcEnd, kingPos)) { + UnmakeMove(move); + return false; + } + } + } + + g_inCheck = false; + + if (flags <= moveflagEPC) { + var theirKingPos = g_pieceList[(pieceKing | g_toMove) << 4]; + + // First check if the piece we moved can attack the enemy king + g_inCheck = IsSquareAttackableFrom(theirKingPos, to); + + if (!g_inCheck) { + // Now check if the square we moved from exposes check on the enemy king + g_inCheck = ExposesCheck(from, theirKingPos); + + if (!g_inCheck) { + // Finally, ep. capture can cause another square to be exposed + if (epcEnd != to) { + g_inCheck = ExposesCheck(epcEnd, theirKingPos); + } + } + } + } + else { + // Castle or promotion, slow check + g_inCheck = IsSquareAttackable(g_pieceList[(pieceKing | g_toMove) << 4], 8 - g_toMove); + } + + g_repMoveStack[g_moveCount - 1] = g_hashKeyLow; + g_move50++; + + return true; +} + +function UnmakeMove(move){ + g_toMove = 8 - g_toMove; + g_baseEval = -g_baseEval; + + g_moveCount--; + g_enPassentSquare = g_moveUndoStack[g_moveCount].ep; + g_castleRights = g_moveUndoStack[g_moveCount].castleRights; + g_inCheck = g_moveUndoStack[g_moveCount].inCheck; + g_baseEval = g_moveUndoStack[g_moveCount].baseEval; + g_hashKeyLow = g_moveUndoStack[g_moveCount].hashKeyLow; + g_hashKeyHigh = g_moveUndoStack[g_moveCount].hashKeyHigh; + g_move50 = g_moveUndoStack[g_moveCount].move50; + + var otherColor = 8 - g_toMove; + var me = g_toMove >> 3; + var them = otherColor >> 3; + + var flags = move & 0xFF0000; + var captured = g_moveUndoStack[g_moveCount].captured; + var to = (move >> 8) & 0xFF; + var from = move & 0xFF; + + var piece = g_board[to]; + + if (flags) { + if (flags & moveflagCastleKing) { + var rook = g_board[to - 1]; + g_board[to + 1] = rook; + g_board[to - 1] = pieceEmpty; + + var rookIndex = g_pieceIndex[to - 1]; + g_pieceIndex[to + 1] = rookIndex; + g_pieceList[((rook & 0xF) << 4) | rookIndex] = to + 1; + } + else if (flags & moveflagCastleQueen) { + var rook = g_board[to + 1]; + g_board[to - 2] = rook; + g_board[to + 1] = pieceEmpty; + + var rookIndex = g_pieceIndex[to + 1]; + g_pieceIndex[to - 2] = rookIndex; + g_pieceList[((rook & 0xF) << 4) | rookIndex] = to - 2; + } + } + + if (flags & moveflagPromotion) { + piece = (g_board[to] & (~0x7)) | piecePawn; + g_board[from] = piece; + + var pawnType = g_board[from] & 0xF; + var promoteType = g_board[to] & 0xF; + + g_pieceCount[promoteType]--; + + var lastPromoteSquare = g_pieceList[(promoteType << 4) | g_pieceCount[promoteType]]; + g_pieceIndex[lastPromoteSquare] = g_pieceIndex[to]; + g_pieceList[(promoteType << 4) | g_pieceIndex[lastPromoteSquare]] = lastPromoteSquare; + g_pieceList[(promoteType << 4) | g_pieceCount[promoteType]] = 0; + g_pieceIndex[to] = g_pieceCount[pawnType]; + g_pieceList[(pawnType << 4) | g_pieceIndex[to]] = to; + g_pieceCount[pawnType]++; + } + else { + g_board[from] = g_board[to]; + } + + var epcEnd = to; + if (flags & moveflagEPC) { + if (g_toMove == colorWhite) + epcEnd = to + 0x10; + else + epcEnd = to - 0x10; + g_board[to] = pieceEmpty; + } + + g_board[epcEnd] = captured; + + // Move our piece in the piece list + g_pieceIndex[from] = g_pieceIndex[to]; + g_pieceList[((piece & 0xF) << 4) | g_pieceIndex[from]] = from; + + if (captured) { + // Restore our piece to the piece list + var captureType = captured & 0xF; + g_pieceIndex[epcEnd] = g_pieceCount[captureType]; + g_pieceList[(captureType << 4) | g_pieceCount[captureType]] = epcEnd; + g_pieceCount[captureType]++; + } +} + +function ExposesCheck(from, kingPos){ + var index = kingPos - from + 128; + // If a queen can't reach it, nobody can! + if ((g_vectorDelta[index].pieceMask[0] & (1 << (pieceQueen))) != 0) { + var delta = g_vectorDelta[index].delta; + var pos = kingPos + delta; + while (g_board[pos] == 0) pos += delta; + + var piece = g_board[pos]; + if (((piece & (g_board[kingPos] ^ 0x18)) & 0x18) == 0) + return false; + + // Now see if the piece can actually attack the king + var backwardIndex = pos - kingPos + 128; + return (g_vectorDelta[backwardIndex].pieceMask[(piece >> 3) & 1] & (1 << (piece & 0x7))) != 0; + } + return false; +} + +function IsSquareOnPieceLine(target, from) { + var index = from - target + 128; + var piece = g_board[from]; + return (g_vectorDelta[index].pieceMask[(piece >> 3) & 1] & (1 << (piece & 0x7))) ? true : false; +} + +function IsSquareAttackableFrom(target, from){ + var index = from - target + 128; + var piece = g_board[from]; + if (g_vectorDelta[index].pieceMask[(piece >> 3) & 1] & (1 << (piece & 0x7))) { + // Yes, this square is pseudo-attackable. Now, check for real attack + var inc = g_vectorDelta[index].delta; + do { + from += inc; + if (from == target) + return true; + } while (g_board[from] == 0); + } + + return false; +} + +function IsSquareAttackable(target, color) { + // Attackable by pawns? + var inc = color ? -16 : 16; + var pawn = (color ? colorWhite : colorBlack) | 1; + if (g_board[target - (inc - 1)] == pawn) + return true; + if (g_board[target - (inc + 1)] == pawn) + return true; + + // Attackable by pieces? + for (var i = 2; i <= 6; i++) { + var index = (color | i) << 4; + var square = g_pieceList[index]; + while (square != 0) { + if (IsSquareAttackableFrom(target, square)) + return true; + square = g_pieceList[++index]; + } + } + return false; +} + +function GenerateMove(from, to) { + return from | (to << 8); +} + +function GenerateMove(from, to, flags){ + return from | (to << 8) | flags; +} + +function GenerateValidMoves() { + var moveList = new Array(); + var allMoves = new Array(); + GenerateCaptureMoves(allMoves, null); + GenerateAllMoves(allMoves); + + for (var i = allMoves.length - 1; i >= 0; i--) { + if (MakeMove(allMoves[i])) { + moveList[moveList.length] = allMoves[i]; + UnmakeMove(allMoves[i]); + } + } + + return moveList; +} + +function GenerateAllMoves(moveStack) { + var from, to, piece, pieceIdx; + + // Pawn quiet moves + pieceIdx = (g_toMove | 1) << 4; + from = g_pieceList[pieceIdx++]; + while (from != 0) { + GeneratePawnMoves(moveStack, from); + from = g_pieceList[pieceIdx++]; + } + + // Knight quiet moves + pieceIdx = (g_toMove | 2) << 4; + from = g_pieceList[pieceIdx++]; + while (from != 0) { + to = from + 31; if (g_board[to] == 0) moveStack[moveStack.length] = GenerateMove(from, to); + to = from + 33; if (g_board[to] == 0) moveStack[moveStack.length] = GenerateMove(from, to); + to = from + 14; if (g_board[to] == 0) moveStack[moveStack.length] = GenerateMove(from, to); + to = from - 14; if (g_board[to] == 0) moveStack[moveStack.length] = GenerateMove(from, to); + to = from - 31; if (g_board[to] == 0) moveStack[moveStack.length] = GenerateMove(from, to); + to = from - 33; if (g_board[to] == 0) moveStack[moveStack.length] = GenerateMove(from, to); + to = from + 18; if (g_board[to] == 0) moveStack[moveStack.length] = GenerateMove(from, to); + to = from - 18; if (g_board[to] == 0) moveStack[moveStack.length] = GenerateMove(from, to); + from = g_pieceList[pieceIdx++]; + } + + // Bishop quiet moves + pieceIdx = (g_toMove | 3) << 4; + from = g_pieceList[pieceIdx++]; + while (from != 0) { + to = from - 15; while (g_board[to] == 0) { moveStack[moveStack.length] = GenerateMove(from, to); to -= 15; } + to = from - 17; while (g_board[to] == 0) { moveStack[moveStack.length] = GenerateMove(from, to); to -= 17; } + to = from + 15; while (g_board[to] == 0) { moveStack[moveStack.length] = GenerateMove(from, to); to += 15; } + to = from + 17; while (g_board[to] == 0) { moveStack[moveStack.length] = GenerateMove(from, to); to += 17; } + from = g_pieceList[pieceIdx++]; + } + + // Rook quiet moves + pieceIdx = (g_toMove | 4) << 4; + from = g_pieceList[pieceIdx++]; + while (from != 0) { + to = from - 1; while (g_board[to] == 0) { moveStack[moveStack.length] = GenerateMove(from, to); to--; } + to = from + 1; while (g_board[to] == 0) { moveStack[moveStack.length] = GenerateMove(from, to); to++; } + to = from + 16; while (g_board[to] == 0) { moveStack[moveStack.length] = GenerateMove(from, to); to += 16; } + to = from - 16; while (g_board[to] == 0) { moveStack[moveStack.length] = GenerateMove(from, to); to -= 16; } + from = g_pieceList[pieceIdx++]; + } + + // Queen quiet moves + pieceIdx = (g_toMove | 5) << 4; + from = g_pieceList[pieceIdx++]; + while (from != 0) { + to = from - 15; while (g_board[to] == 0) { moveStack[moveStack.length] = GenerateMove(from, to); to -= 15; } + to = from - 17; while (g_board[to] == 0) { moveStack[moveStack.length] = GenerateMove(from, to); to -= 17; } + to = from + 15; while (g_board[to] == 0) { moveStack[moveStack.length] = GenerateMove(from, to); to += 15; } + to = from + 17; while (g_board[to] == 0) { moveStack[moveStack.length] = GenerateMove(from, to); to += 17; } + to = from - 1; while (g_board[to] == 0) { moveStack[moveStack.length] = GenerateMove(from, to); to--; } + to = from + 1; while (g_board[to] == 0) { moveStack[moveStack.length] = GenerateMove(from, to); to++; } + to = from + 16; while (g_board[to] == 0) { moveStack[moveStack.length] = GenerateMove(from, to); to += 16; } + to = from - 16; while (g_board[to] == 0) { moveStack[moveStack.length] = GenerateMove(from, to); to -= 16; } + from = g_pieceList[pieceIdx++]; + } + + // King quiet moves + { + pieceIdx = (g_toMove | 6) << 4; + from = g_pieceList[pieceIdx]; + to = from - 15; if (g_board[to] == 0) moveStack[moveStack.length] = GenerateMove(from, to); + to = from - 17; if (g_board[to] == 0) moveStack[moveStack.length] = GenerateMove(from, to); + to = from + 15; if (g_board[to] == 0) moveStack[moveStack.length] = GenerateMove(from, to); + to = from + 17; if (g_board[to] == 0) moveStack[moveStack.length] = GenerateMove(from, to); + to = from - 1; if (g_board[to] == 0) moveStack[moveStack.length] = GenerateMove(from, to); + to = from + 1; if (g_board[to] == 0) moveStack[moveStack.length] = GenerateMove(from, to); + to = from - 16; if (g_board[to] == 0) moveStack[moveStack.length] = GenerateMove(from, to); + to = from + 16; if (g_board[to] == 0) moveStack[moveStack.length] = GenerateMove(from, to); + + if (!g_inCheck) { + var castleRights = g_castleRights; + if (!g_toMove) + castleRights >>= 2; + if (castleRights & 1) { + // Kingside castle + if (g_board[from + 1] == pieceEmpty && g_board[from + 2] == pieceEmpty) { + moveStack[moveStack.length] = GenerateMove(from, from + 0x02, moveflagCastleKing); + } + } + if (castleRights & 2) { + // Queenside castle + if (g_board[from - 1] == pieceEmpty && g_board[from - 2] == pieceEmpty && g_board[from - 3] == pieceEmpty) { + moveStack[moveStack.length] = GenerateMove(from, from - 0x02, moveflagCastleQueen); + } + } + } + } +} + +function GenerateCaptureMoves(moveStack, moveScores) { + var from, to, piece, pieceIdx; + var inc = (g_toMove == 8) ? -16 : 16; + var enemy = g_toMove == 8 ? 0x10 : 0x8; + + // Pawn captures + pieceIdx = (g_toMove | 1) << 4; + from = g_pieceList[pieceIdx++]; + while (from != 0) { + to = from + inc - 1; + if (g_board[to] & enemy) { + MovePawnTo(moveStack, from, to); + } + + to = from + inc + 1; + if (g_board[to] & enemy) { + MovePawnTo(moveStack, from, to); + } + + from = g_pieceList[pieceIdx++]; + } + + if (g_enPassentSquare != -1) { + var inc = (g_toMove == colorWhite) ? -16 : 16; + var pawn = g_toMove | piecePawn; + + var from = g_enPassentSquare - (inc + 1); + if ((g_board[from] & 0xF) == pawn) { + moveStack[moveStack.length] = GenerateMove(from, g_enPassentSquare, moveflagEPC); + } + + from = g_enPassentSquare - (inc - 1); + if ((g_board[from] & 0xF) == pawn) { + moveStack[moveStack.length] = GenerateMove(from, g_enPassentSquare, moveflagEPC); + } + } + + // Knight captures + pieceIdx = (g_toMove | 2) << 4; + from = g_pieceList[pieceIdx++]; + while (from != 0) { + to = from + 31; if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from + 33; if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from + 14; if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from - 14; if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from - 31; if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from - 33; if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from + 18; if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from - 18; if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + from = g_pieceList[pieceIdx++]; + } + + // Bishop captures + pieceIdx = (g_toMove | 3) << 4; + from = g_pieceList[pieceIdx++]; + while (from != 0) { + to = from; do { to -= 15; } while (g_board[to] == 0); if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from; do { to -= 17; } while (g_board[to] == 0); if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from; do { to += 15; } while (g_board[to] == 0); if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from; do { to += 17; } while (g_board[to] == 0); if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + from = g_pieceList[pieceIdx++]; + } + + // Rook captures + pieceIdx = (g_toMove | 4) << 4; + from = g_pieceList[pieceIdx++]; + while (from != 0) { + to = from; do { to--; } while (g_board[to] == 0); if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from; do { to++; } while (g_board[to] == 0); if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from; do { to -= 16; } while (g_board[to] == 0); if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from; do { to += 16; } while (g_board[to] == 0); if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + from = g_pieceList[pieceIdx++]; + } + + // Queen captures + pieceIdx = (g_toMove | 5) << 4; + from = g_pieceList[pieceIdx++]; + while (from != 0) { + to = from; do { to -= 15; } while (g_board[to] == 0); if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from; do { to -= 17; } while (g_board[to] == 0); if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from; do { to += 15; } while (g_board[to] == 0); if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from; do { to += 17; } while (g_board[to] == 0); if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from; do { to--; } while (g_board[to] == 0); if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from; do { to++; } while (g_board[to] == 0); if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from; do { to -= 16; } while (g_board[to] == 0); if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from; do { to += 16; } while (g_board[to] == 0); if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + from = g_pieceList[pieceIdx++]; + } + + // King captures + { + pieceIdx = (g_toMove | 6) << 4; + from = g_pieceList[pieceIdx]; + to = from - 15; if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from - 17; if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from + 15; if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from + 17; if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from - 1; if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from + 1; if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from - 16; if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + to = from + 16; if (g_board[to] & enemy) moveStack[moveStack.length] = GenerateMove(from, to); + } +} + +function MovePawnTo(moveStack, start, square) { + var row = square & 0xF0; + if ((row == 0x90) || (row == 0x20)) { + moveStack[moveStack.length] = GenerateMove(start, square, moveflagPromotion | moveflagPromoteQueen); + moveStack[moveStack.length] = GenerateMove(start, square, moveflagPromotion | moveflagPromoteKnight); + moveStack[moveStack.length] = GenerateMove(start, square, moveflagPromotion | moveflagPromoteBishop); + moveStack[moveStack.length] = GenerateMove(start, square, moveflagPromotion); + } + else { + moveStack[moveStack.length] = GenerateMove(start, square, 0); + } +} + +function GeneratePawnMoves(moveStack, from) { + var piece = g_board[from]; + var color = piece & colorWhite; + var inc = (color == colorWhite) ? -16 : 16; + + // Quiet pawn moves + var to = from + inc; + if (g_board[to] == 0) { + MovePawnTo(moveStack, from, to, pieceEmpty); + + // Check if we can do a 2 square jump + if ((((from & 0xF0) == 0x30) && color != colorWhite) || + (((from & 0xF0) == 0x80) && color == colorWhite)) { + to += inc; + if (g_board[to] == 0) { + moveStack[moveStack.length] = GenerateMove(from, to); + } + } + } +} + +function UndoHistory(ep, castleRights, inCheck, baseEval, hashKeyLow, hashKeyHigh, move50, captured) { + this.ep = ep; + this.castleRights = castleRights; + this.inCheck = inCheck; + this.baseEval = baseEval; + this.hashKeyLow = hashKeyLow; + this.hashKeyHigh = hashKeyHigh; + this.move50 = move50; + this.captured = captured; +} + +var g_seeValues = [0, 1, 3, 3, 5, 9, 900, 0, + 0, 1, 3, 3, 5, 9, 900, 0]; + +function See(move) { + var from = move & 0xFF; + var to = (move >> 8) & 0xFF; + + var fromPiece = g_board[from]; + + var fromValue = g_seeValues[fromPiece & 0xF]; + var toValue = g_seeValues[g_board[to] & 0xF]; + + if (fromValue <= toValue) { + return true; + } + + if (move >> 16) { + // Castles, promotion, ep are always good + return true; + } + + var us = (fromPiece & colorWhite) ? colorWhite : 0; + var them = 8 - us; + + // Pawn attacks + // If any opponent pawns can capture back, this capture is probably not worthwhile (as we must be using knight or above). + var inc = (fromPiece & colorWhite) ? -16 : 16; // Note: this is capture direction from to, so reversed from normal move direction + if (((g_board[to + inc + 1] & 0xF) == (piecePawn | them)) || + ((g_board[to + inc - 1] & 0xF) == (piecePawn | them))) { + return false; + } + + var themAttacks = new Array(); + + // Knight attacks + // If any opponent knights can capture back, and the deficit we have to make up is greater than the knights value, + // it's not worth it. We can capture on this square again, and the opponent doesn't have to capture back. + var captureDeficit = fromValue - toValue; + SeeAddKnightAttacks(to, them, themAttacks); + if (themAttacks.length != 0 && captureDeficit > g_seeValues[pieceKnight]) { + return false; + } + + // Slider attacks + g_board[from] = 0; + for (var pieceType = pieceBishop; pieceType <= pieceQueen; pieceType++) { + if (SeeAddSliderAttacks(to, them, themAttacks, pieceType)) { + if (captureDeficit > g_seeValues[pieceType]) { + g_board[from] = fromPiece; + return false; + } + } + } + + // Pawn defenses + // At this point, we are sure we are making a "losing" capture. The opponent can not capture back with a + // pawn. They cannot capture back with a minor/major and stand pat either. So, if we can capture with + // a pawn, it's got to be a winning or equal capture. + if (((g_board[to - inc + 1] & 0xF) == (piecePawn | us)) || + ((g_board[to - inc - 1] & 0xF) == (piecePawn | us))) { + g_board[from] = fromPiece; + return true; + } + + // King attacks + SeeAddSliderAttacks(to, them, themAttacks, pieceKing); + + // Our attacks + var usAttacks = new Array(); + SeeAddKnightAttacks(to, us, usAttacks); + for (var pieceType = pieceBishop; pieceType <= pieceKing; pieceType++) { + SeeAddSliderAttacks(to, us, usAttacks, pieceType); + } + + g_board[from] = fromPiece; + + // We are currently winning the amount of material of the captured piece, time to see if the opponent + // can get it back somehow. We assume the opponent can capture our current piece in this score, which + // simplifies the later code considerably. + var seeValue = toValue - fromValue; + + for (; ; ) { + var capturingPieceValue = 1000; + var capturingPieceIndex = -1; + + // Find the least valuable piece of the opponent that can attack the square + for (var i = 0; i < themAttacks.length; i++) { + if (themAttacks[i] != 0) { + var pieceValue = g_seeValues[g_board[themAttacks[i]] & 0x7]; + if (pieceValue < capturingPieceValue) { + capturingPieceValue = pieceValue; + capturingPieceIndex = i; + } + } + } + + if (capturingPieceIndex == -1) { + // Opponent can't capture back, we win + return true; + } + + // Now, if seeValue < 0, the opponent is winning. If even after we take their piece, + // we can't bring it back to 0, then we have lost this battle. + seeValue += capturingPieceValue; + if (seeValue < 0) { + return false; + } + + var capturingPieceSquare = themAttacks[capturingPieceIndex]; + themAttacks[capturingPieceIndex] = 0; + + // Add any x-ray attackers + SeeAddXrayAttack(to, capturingPieceSquare, us, usAttacks, themAttacks); + + // Our turn to capture + capturingPieceValue = 1000; + capturingPieceIndex = -1; + + // Find our least valuable piece that can attack the square + for (var i = 0; i < usAttacks.length; i++) { + if (usAttacks[i] != 0) { + var pieceValue = g_seeValues[g_board[usAttacks[i]] & 0x7]; + if (pieceValue < capturingPieceValue) { + capturingPieceValue = pieceValue; + capturingPieceIndex = i; + } + } + } + + if (capturingPieceIndex == -1) { + // We can't capture back, we lose :( + return false; + } + + // Assume our opponent can capture us back, and if we are still winning, we can stand-pat + // here, and assume we've won. + seeValue -= capturingPieceValue; + if (seeValue >= 0) { + return true; + } + + capturingPieceSquare = usAttacks[capturingPieceIndex]; + usAttacks[capturingPieceIndex] = 0; + + // Add any x-ray attackers + SeeAddXrayAttack(to, capturingPieceSquare, us, usAttacks, themAttacks); + } +} + +function SeeAddXrayAttack(target, square, us, usAttacks, themAttacks) { + var index = square - target + 128; + var delta = -g_vectorDelta[index].delta; + if (delta == 0) + return; + square += delta; + while (g_board[square] == 0) { + square += delta; + } + + if ((g_board[square] & 0x18) && IsSquareOnPieceLine(target, square)) { + if ((g_board[square] & 8) == us) { + usAttacks[usAttacks.length] = square; + } else { + themAttacks[themAttacks.length] = square; + } + } +} + +// target = attacking square, us = color of knights to look for, attacks = array to add squares to +function SeeAddKnightAttacks(target, us, attacks) { + var pieceIdx = (us | pieceKnight) << 4; + var attackerSq = g_pieceList[pieceIdx++]; + + while (attackerSq != 0) { + if (IsSquareOnPieceLine(target, attackerSq)) { + attacks[attacks.length] = attackerSq; + } + attackerSq = g_pieceList[pieceIdx++]; + } +} + +function SeeAddSliderAttacks(target, us, attacks, pieceType) { + var pieceIdx = (us | pieceType) << 4; + var attackerSq = g_pieceList[pieceIdx++]; + var hit = false; + + while (attackerSq != 0) { + if (IsSquareAttackableFrom(target, attackerSq)) { + attacks[attacks.length] = attackerSq; + hit = true; + } + attackerSq = g_pieceList[pieceIdx++]; + } + + return hit; +} + +function BuildPVMessage(bestMove, value, timeTaken, ply) { + var totalNodes = g_nodeCount + g_qNodeCount; + return "Ply:" + ply + " Score:" + value + " Nodes:" + totalNodes + " NPS:" + ((totalNodes / (timeTaken / 1000)) | 0) + " " + PVFromHash(bestMove, 15); +} + +////////////////////////////////////////////////// +// Test Harness +////////////////////////////////////////////////// +function FinishPlyCallback(bestMove, value, timeTaken, ply) { + postMessage("pv " + BuildPVMessage(bestMove, value, timeTaken, ply)); +} + +function FinishMoveLocalTesting(bestMove, value, timeTaken, ply) { + if (bestMove != null) { + MakeMove(bestMove); + postMessage(FormatMove(bestMove)); + } +} + +var needsReset = true; +self.onmessage = function (e) { + if (e.data == "go" || needsReset) { + ResetGame(); + needsReset = false; + if (e.data == "go") return; + } + if (e.data.match("^position") == "position") { + ResetGame(); + var result = InitializeFromFen(e.data.substr(9, e.data.length - 9)); + if (result.length != 0) { + postMessage("message " + result); + } + } else if (e.data.match("^search") == "search") { + g_timeout = parseInt(e.data.substr(7, e.data.length - 7), 10); + Search(FinishMoveLocalTesting, 99, FinishPlyCallback); + } else if (e.data == "analyze") { + g_timeout = 99999999999; + Search(null, 99, FinishPlyCallback); + } else { + MakeMove(GetMoveFromString(e.data)); + } +} diff --git a/html/browser/jquery-1.8.2.min.js b/html/browser/jquery-1.8.2.min.js new file mode 100644 index 00000000000..bc3fbc81b26 --- /dev/null +++ b/html/browser/jquery-1.8.2.min.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
t
",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;be.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="
",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="

",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b0)for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
","
"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window); \ No newline at end of file diff --git a/html/browser/jquery-ui-1.8.24.custom.min.js b/html/browser/jquery-ui-1.8.24.custom.min.js new file mode 100644 index 00000000000..83d17fafc5e --- /dev/null +++ b/html/browser/jquery-ui-1.8.24.custom.min.js @@ -0,0 +1,37 @@ +/*! jQuery UI - v1.8.24 - 2012-09-28 +* https://github.com/jquery/jquery-ui +* Includes: jquery.ui.core.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){function c(b,c){var e=b.nodeName.toLowerCase();if("area"===e){var f=b.parentNode,g=f.name,h;return!b.href||!g||f.nodeName.toLowerCase()!=="map"?!1:(h=a("img[usemap=#"+g+"]")[0],!!h&&d(h))}return(/input|select|textarea|button|object/.test(e)?!b.disabled:"a"==e?b.href||c:c)&&d(b)}function d(b){return!a(b).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}a.ui=a.ui||{};if(a.ui.version)return;a.extend(a.ui,{version:"1.8.24",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}}),a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(b,c){return typeof b=="number"?this.each(function(){var d=this;setTimeout(function(){a(d).focus(),c&&c.call(d)},b)}):this._focus.apply(this,arguments)},scrollParent:function(){var b;return a.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?b=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(a.curCSS(this,"position",1))&&/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0):b=this.parents().filter(function(){return/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0),/fixed/.test(this.css("position"))||!b.length?a(document):b},zIndex:function(c){if(c!==b)return this.css("zIndex",c);if(this.length){var d=a(this[0]),e,f;while(d.length&&d[0]!==document){e=d.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){f=parseInt(d.css("zIndex"),10);if(!isNaN(f)&&f!==0)return f}d=d.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),a("").outerWidth(1).jquery||a.each(["Width","Height"],function(c,d){function h(b,c,d,f){return a.each(e,function(){c-=parseFloat(a.curCSS(b,"padding"+this,!0))||0,d&&(c-=parseFloat(a.curCSS(b,"border"+this+"Width",!0))||0),f&&(c-=parseFloat(a.curCSS(b,"margin"+this,!0))||0)}),c}var e=d==="Width"?["Left","Right"]:["Top","Bottom"],f=d.toLowerCase(),g={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};a.fn["inner"+d]=function(c){return c===b?g["inner"+d].call(this):this.each(function(){a(this).css(f,h(this,c)+"px")})},a.fn["outer"+d]=function(b,c){return typeof b!="number"?g["outer"+d].call(this,b):this.each(function(){a(this).css(f,h(this,b,!0,c)+"px")})}}),a.extend(a.expr[":"],{data:a.expr.createPseudo?a.expr.createPseudo(function(b){return function(c){return!!a.data(c,b)}}):function(b,c,d){return!!a.data(b,d[3])},focusable:function(b){return c(b,!isNaN(a.attr(b,"tabindex")))},tabbable:function(b){var d=a.attr(b,"tabindex"),e=isNaN(d);return(e||d>=0)&&c(b,!e)}}),a(function(){var b=document.body,c=b.appendChild(c=document.createElement("div"));c.offsetHeight,a.extend(c.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),a.support.minHeight=c.offsetHeight===100,a.support.selectstart="onselectstart"in c,b.removeChild(c).style.display="none"}),a.curCSS||(a.curCSS=a.css),a.extend(a.ui,{plugin:{add:function(b,c,d){var e=a.ui[b].prototype;for(var f in d)e.plugins[f]=e.plugins[f]||[],e.plugins[f].push([c,d[f]])},call:function(a,b,c){var d=a.plugins[b];if(!d||!a.element[0].parentNode)return;for(var e=0;e0?!0:(b[d]=1,e=b[d]>0,b[d]=0,e)},isOverAxis:function(a,b,c){return a>b&&a=9||!!b.button?this._mouseStarted?(this._mouseDrag(b),b.preventDefault()):(this._mouseDistanceMet(b)&&this._mouseDelayMet(b)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,b)!==!1,this._mouseStarted?this._mouseDrag(b):this._mouseUp(b)),!this._mouseStarted):this._mouseUp(b)},_mouseUp:function(b){return a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,b.target==this._mouseDownEvent.target&&a.data(b.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(b)),!1},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(a){return this.mouseDelayMet},_mouseStart:function(a){},_mouseDrag:function(a){},_mouseStop:function(a){},_mouseCapture:function(a){return!0}})})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28 +* https://github.com/jquery/jquery-ui +* Includes: jquery.ui.position.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.ui=a.ui||{};var c=/left|center|right/,d=/top|center|bottom/,e="center",f={},g=a.fn.position,h=a.fn.offset;a.fn.position=function(b){if(!b||!b.of)return g.apply(this,arguments);b=a.extend({},b);var h=a(b.of),i=h[0],j=(b.collision||"flip").split(" "),k=b.offset?b.offset.split(" "):[0,0],l,m,n;return i.nodeType===9?(l=h.width(),m=h.height(),n={top:0,left:0}):i.setTimeout?(l=h.width(),m=h.height(),n={top:h.scrollTop(),left:h.scrollLeft()}):i.preventDefault?(b.at="left top",l=m=0,n={top:b.of.pageY,left:b.of.pageX}):(l=h.outerWidth(),m=h.outerHeight(),n=h.offset()),a.each(["my","at"],function(){var a=(b[this]||"").split(" ");a.length===1&&(a=c.test(a[0])?a.concat([e]):d.test(a[0])?[e].concat(a):[e,e]),a[0]=c.test(a[0])?a[0]:e,a[1]=d.test(a[1])?a[1]:e,b[this]=a}),j.length===1&&(j[1]=j[0]),k[0]=parseInt(k[0],10)||0,k.length===1&&(k[1]=k[0]),k[1]=parseInt(k[1],10)||0,b.at[0]==="right"?n.left+=l:b.at[0]===e&&(n.left+=l/2),b.at[1]==="bottom"?n.top+=m:b.at[1]===e&&(n.top+=m/2),n.left+=k[0],n.top+=k[1],this.each(function(){var c=a(this),d=c.outerWidth(),g=c.outerHeight(),h=parseInt(a.curCSS(this,"marginLeft",!0))||0,i=parseInt(a.curCSS(this,"marginTop",!0))||0,o=d+h+(parseInt(a.curCSS(this,"marginRight",!0))||0),p=g+i+(parseInt(a.curCSS(this,"marginBottom",!0))||0),q=a.extend({},n),r;b.my[0]==="right"?q.left-=d:b.my[0]===e&&(q.left-=d/2),b.my[1]==="bottom"?q.top-=g:b.my[1]===e&&(q.top-=g/2),f.fractions||(q.left=Math.round(q.left),q.top=Math.round(q.top)),r={left:q.left-h,top:q.top-i},a.each(["left","top"],function(c,e){a.ui.position[j[c]]&&a.ui.position[j[c]][e](q,{targetWidth:l,targetHeight:m,elemWidth:d,elemHeight:g,collisionPosition:r,collisionWidth:o,collisionHeight:p,offset:k,my:b.my,at:b.at})}),a.fn.bgiframe&&c.bgiframe(),c.offset(a.extend(q,{using:b.using}))})},a.ui.position={fit:{left:function(b,c){var d=a(window),e=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft();b.left=e>0?b.left-e:Math.max(b.left-c.collisionPosition.left,b.left)},top:function(b,c){var d=a(window),e=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop();b.top=e>0?b.top-e:Math.max(b.top-c.collisionPosition.top,b.top)}},flip:{left:function(b,c){if(c.at[0]===e)return;var d=a(window),f=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft(),g=c.my[0]==="left"?-c.elemWidth:c.my[0]==="right"?c.elemWidth:0,h=c.at[0]==="left"?c.targetWidth:-c.targetWidth,i=-2*c.offset[0];b.left+=c.collisionPosition.left<0?g+h+i:f>0?g+h+i:0},top:function(b,c){if(c.at[1]===e)return;var d=a(window),f=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop(),g=c.my[1]==="top"?-c.elemHeight:c.my[1]==="bottom"?c.elemHeight:0,h=c.at[1]==="top"?c.targetHeight:-c.targetHeight,i=-2*c.offset[1];b.top+=c.collisionPosition.top<0?g+h+i:f>0?g+h+i:0}}},a.offset.setOffset||(a.offset.setOffset=function(b,c){/static/.test(a.curCSS(b,"position"))&&(b.style.position="relative");var d=a(b),e=d.offset(),f=parseInt(a.curCSS(b,"top",!0),10)||0,g=parseInt(a.curCSS(b,"left",!0),10)||0,h={top:c.top-e.top+f,left:c.left-e.left+g};"using"in c?c.using.call(b,h):d.css(h)},a.fn.offset=function(b){var c=this[0];return!c||!c.ownerDocument?null:b?a.isFunction(b)?this.each(function(c){a(this).offset(b.call(this,c,a(this).offset()))}):this.each(function(){a.offset.setOffset(this,b)}):h.call(this)}),a.curCSS||(a.curCSS=a.css),function(){var b=document.getElementsByTagName("body")[0],c=document.createElement("div"),d,e,g,h,i;d=document.createElement(b?"div":"body"),g={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},b&&a.extend(g,{position:"absolute",left:"-1000px",top:"-1000px"});for(var j in g)d.style[j]=g[j];d.appendChild(c),e=b||document.documentElement,e.insertBefore(d,e.firstChild),c.style.cssText="position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;",h=a(c).offset(function(a,b){return b}).offset(),d.innerHTML="",e.removeChild(d),i=h.top+h.left+(b?2e3:0),f.fractions=i>21&&i<22}()})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28 +* https://github.com/jquery/jquery-ui +* Includes: jquery.ui.draggable.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.widget("ui.draggable",a.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1},_create:function(){this.options.helper=="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))&&(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},destroy:function(){if(!this.element.data("draggable"))return;return this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy(),this},_mouseCapture:function(b){var c=this.options;return this.helper||c.disabled||a(b.target).is(".ui-resizable-handle")?!1:(this.handle=this._getHandle(b),this.handle?(c.iframeFix&&a(c.iframeFix===!0?"iframe":c.iframeFix).each(function(){a('
').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(a(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(b){var c=this.options;return this.helper=this._createHelper(b),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),a.ui.ddmanager&&(a.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(b),this.originalPageX=b.pageX,this.originalPageY=b.pageY,c.cursorAt&&this._adjustOffsetFromHelper(c.cursorAt),c.containment&&this._setContainment(),this._trigger("start",b)===!1?(this._clear(),!1):(this._cacheHelperProportions(),a.ui.ddmanager&&!c.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b),this._mouseDrag(b,!0),a.ui.ddmanager&&a.ui.ddmanager.dragStart(this,b),!0)},_mouseDrag:function(b,c){this.position=this._generatePosition(b),this.positionAbs=this._convertPositionTo("absolute");if(!c){var d=this._uiHash();if(this._trigger("drag",b,d)===!1)return this._mouseUp({}),!1;this.position=d.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";return a.ui.ddmanager&&a.ui.ddmanager.drag(this,b),!1},_mouseStop:function(b){var c=!1;a.ui.ddmanager&&!this.options.dropBehaviour&&(c=a.ui.ddmanager.drop(this,b)),this.dropped&&(c=this.dropped,this.dropped=!1);var d=this.element[0],e=!1;while(d&&(d=d.parentNode))d==document&&(e=!0);if(!e&&this.options.helper==="original")return!1;if(this.options.revert=="invalid"&&!c||this.options.revert=="valid"&&c||this.options.revert===!0||a.isFunction(this.options.revert)&&this.options.revert.call(this.element,c)){var f=this;a(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){f._trigger("stop",b)!==!1&&f._clear()})}else this._trigger("stop",b)!==!1&&this._clear();return!1},_mouseUp:function(b){return a("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),a.ui.ddmanager&&a.ui.ddmanager.dragStop(this,b),a.ui.mouse.prototype._mouseUp.call(this,b)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(b){var c=!this.options.handle||!a(this.options.handle,this.element).length?!0:!1;return a(this.options.handle,this.element).find("*").andSelf().each(function(){this==b.target&&(c=!0)}),c},_createHelper:function(b){var c=this.options,d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[b])):c.helper=="clone"?this.element.clone().removeAttr("id"):this.element;return d.parents("body").length||d.appendTo(c.appendTo=="parent"?this.element[0].parentNode:c.appendTo),d[0]!=this.element[0]&&!/(fixed|absolute)/.test(d.css("position"))&&d.css("position","absolute"),d},_adjustOffsetFromHelper:function(b){typeof b=="string"&&(b=b.split(" ")),a.isArray(b)&&(b={left:+b[0],top:+b[1]||0}),"left"in b&&(this.offset.click.left=b.left+this.margins.left),"right"in b&&(this.offset.click.left=this.helperProportions.width-b.right+this.margins.left),"top"in b&&(this.offset.click.top=b.top+this.margins.top),"bottom"in b&&(this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])&&(b.left+=this.scrollParent.scrollLeft(),b.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)b={top:0,left:0};return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var b=this.options;b.containment=="parent"&&(b.containment=this.helper[0].parentNode);if(b.containment=="document"||b.containment=="window")this.containment=[b.containment=="document"?0:a(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,b.containment=="document"?0:a(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(b.containment=="document"?0:a(window).scrollLeft())+a(b.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(b.containment=="document"?0:a(window).scrollTop())+(a(b.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(b.containment)&&b.containment.constructor!=Array){var c=a(b.containment),d=c[0];if(!d)return;var e=c.offset(),f=a(d).css("overflow")!="hidden";this.containment=[(parseInt(a(d).css("borderLeftWidth"),10)||0)+(parseInt(a(d).css("paddingLeft"),10)||0),(parseInt(a(d).css("borderTopWidth"),10)||0)+(parseInt(a(d).css("paddingTop"),10)||0),(f?Math.max(d.scrollWidth,d.offsetWidth):d.offsetWidth)-(parseInt(a(d).css("borderLeftWidth"),10)||0)-(parseInt(a(d).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(f?Math.max(d.scrollHeight,d.offsetHeight):d.offsetHeight)-(parseInt(a(d).css("borderTopWidth"),10)||0)-(parseInt(a(d).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=c}else b.containment.constructor==Array&&(this.containment=b.containment)},_convertPositionTo:function(b,c){c||(c=this.position);var d=b=="absolute"?1:-1,e=this.options,f=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=/(html|body)/i.test(f[0].tagName);return{top:c.top+this.offset.relative.top*d+this.offset.parent.top*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():g?0:f.scrollTop())*d),left:c.left+this.offset.relative.left*d+this.offset.parent.left*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:f.scrollLeft())*d)}},_generatePosition:function(b){var c=this.options,d=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(d[0].tagName),f=b.pageX,g=b.pageY;if(this.originalPosition){var h;if(this.containment){if(this.relative_container){var i=this.relative_container.offset();h=[this.containment[0]+i.left,this.containment[1]+i.top,this.containment[2]+i.left,this.containment[3]+i.top]}else h=this.containment;b.pageX-this.offset.click.lefth[2]&&(f=h[2]+this.offset.click.left),b.pageY-this.offset.click.top>h[3]&&(g=h[3]+this.offset.click.top)}if(c.grid){var j=c.grid[1]?this.originalPageY+Math.round((g-this.originalPageY)/c.grid[1])*c.grid[1]:this.originalPageY;g=h?j-this.offset.click.toph[3]?j-this.offset.click.toph[2]?k-this.offset.click.left=0;k--){var l=d.snapElements[k].left,m=l+d.snapElements[k].width,n=d.snapElements[k].top,o=n+d.snapElements[k].height;if(!(l-f=k&&g<=l||h>=k&&h<=l||gl)&&(e>=i&&e<=j||f>=i&&f<=j||ej);default:return!1}},a.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(b,c){var d=a.ui.ddmanager.droppables[b.options.scope]||[],e=c?c.type:null,f=(b.currentItem||b.element).find(":data(droppable)").andSelf();g:for(var h=0;h
').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("resizable",this.element.data("resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=c.handles||(a(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor==String){this.handles=="all"&&(this.handles="n,e,s,w,se,sw,ne,nw");var d=this.handles.split(",");this.handles={};for(var e=0;e');h.css({zIndex:c.zIndex}),"se"==f&&h.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[f]=".ui-resizable-"+f,this.element.append(h)}}this._renderAxis=function(b){b=b||this.element;for(var c in this.handles){this.handles[c].constructor==String&&(this.handles[c]=a(this.handles[c],this.element).show());if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var d=a(this.handles[c],this.element),e=0;e=/sw|ne|nw|se|n|s/.test(c)?d.outerHeight():d.outerWidth();var f=["padding",/ne|nw|n/.test(c)?"Top":/se|sw|s/.test(c)?"Bottom":/^e$/.test(c)?"Right":"Left"].join("");b.css(f,e),this._proportionallyResize()}if(!a(this.handles[c]).length)continue}},this._renderAxis(this.element),this._handles=a(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){if(!b.resizing){if(this.className)var a=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=a&&a[1]?a[1]:"se"}}),c.autoHide&&(this._handles.hide(),a(this.element).addClass("ui-resizable-autohide").hover(function(){if(c.disabled)return;a(this).removeClass("ui-resizable-autohide"),b._handles.show()},function(){if(c.disabled)return;b.resizing||(a(this).addClass("ui-resizable-autohide"),b._handles.hide())})),this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(b){a(b).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){b(this.element);var c=this.element;c.after(this.originalElement.css({position:c.css("position"),width:c.outerWidth(),height:c.outerHeight(),top:c.css("top"),left:c.css("left")})).remove()}return this.originalElement.css("resize",this.originalResizeStyle),b(this.originalElement),this},_mouseCapture:function(b){var c=!1;for(var d in this.handles)a(this.handles[d])[0]==b.target&&(c=!0);return!this.options.disabled&&c},_mouseStart:function(b){var d=this.options,e=this.element.position(),f=this.element;this.resizing=!0,this.documentScroll={top:a(document).scrollTop(),left:a(document).scrollLeft()},(f.is(".ui-draggable")||/absolute/.test(f.css("position")))&&f.css({position:"absolute",top:e.top,left:e.left}),this._renderProxy();var g=c(this.helper.css("left")),h=c(this.helper.css("top"));d.containment&&(g+=a(d.containment).scrollLeft()||0,h+=a(d.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:g,top:h},this.size=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalSize=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalPosition={left:g,top:h},this.sizeDiff={width:f.outerWidth()-f.width(),height:f.outerHeight()-f.height()},this.originalMousePosition={left:b.pageX,top:b.pageY},this.aspectRatio=typeof d.aspectRatio=="number"?d.aspectRatio:this.originalSize.width/this.originalSize.height||1;var i=a(".ui-resizable-"+this.axis).css("cursor");return a("body").css("cursor",i=="auto"?this.axis+"-resize":i),f.addClass("ui-resizable-resizing"),this._propagate("start",b),!0},_mouseDrag:function(b){var c=this.helper,d=this.options,e={},f=this,g=this.originalMousePosition,h=this.axis,i=b.pageX-g.left||0,j=b.pageY-g.top||0,k=this._change[h];if(!k)return!1;var l=k.apply(this,[b,i,j]),m=a.browser.msie&&a.browser.version<7,n=this.sizeDiff;this._updateVirtualBoundaries(b.shiftKey);if(this._aspectRatio||b.shiftKey)l=this._updateRatio(l,b);return l=this._respectSize(l,b),this._propagate("resize",b),c.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"}),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),this._updateCache(l),this._trigger("resize",b,this.ui()),!1},_mouseStop:function(b){this.resizing=!1;var c=this.options,d=this;if(this._helper){var e=this._proportionallyResizeElements,f=e.length&&/textarea/i.test(e[0].nodeName),g=f&&a.ui.hasScroll(e[0],"left")?0:d.sizeDiff.height,h=f?0:d.sizeDiff.width,i={width:d.helper.width()-h,height:d.helper.height()-g},j=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,k=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;c.animate||this.element.css(a.extend(i,{top:k,left:j})),d.helper.height(d.size.height),d.helper.width(d.size.width),this._helper&&!c.animate&&this._proportionallyResize()}return a("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",b),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(a){var b=this.options,c,e,f,g,h;h={minWidth:d(b.minWidth)?b.minWidth:0,maxWidth:d(b.maxWidth)?b.maxWidth:Infinity,minHeight:d(b.minHeight)?b.minHeight:0,maxHeight:d(b.maxHeight)?b.maxHeight:Infinity};if(this._aspectRatio||a)c=h.minHeight*this.aspectRatio,f=h.minWidth/this.aspectRatio,e=h.maxHeight*this.aspectRatio,g=h.maxWidth/this.aspectRatio,c>h.minWidth&&(h.minWidth=c),f>h.minHeight&&(h.minHeight=f),ea.width,k=d(a.height)&&e.minHeight&&e.minHeight>a.height;j&&(a.width=e.minWidth),k&&(a.height=e.minHeight),h&&(a.width=e.maxWidth),i&&(a.height=e.maxHeight);var l=this.originalPosition.left+this.originalSize.width,m=this.position.top+this.size.height,n=/sw|nw|w/.test(g),o=/nw|ne|n/.test(g);j&&n&&(a.left=l-e.minWidth),h&&n&&(a.left=l-e.maxWidth),k&&o&&(a.top=m-e.minHeight),i&&o&&(a.top=m-e.maxHeight);var p=!a.width&&!a.height;return p&&!a.left&&a.top?a.top=null:p&&!a.top&&a.left&&(a.left=null),a},_proportionallyResize:function(){var b=this.options;if(!this._proportionallyResizeElements.length)return;var c=this.helper||this.element;for(var d=0;d');var d=a.browser.msie&&a.browser.version<7,e=d?1:0,f=d?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+f,height:this.element.outerHeight()+f,position:"absolute",left:this.elementOffset.left-e+"px",top:this.elementOffset.top-e+"px",zIndex:++c.zIndex}),this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(a,b,c){return{width:this.originalSize.width+b}},w:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{left:f.left+b,width:e.width-b}},n:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{top:f.top+c,height:e.height-c}},s:function(a,b,c){return{height:this.originalSize.height+c}},se:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},sw:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,c,d]))},ne:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},nw:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,c,d]))}},_propagate:function(b,c){a.ui.plugin.call(this,b,[c,this.ui()]),b!="resize"&&this._trigger(b,c,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),a.extend(a.ui.resizable,{version:"1.8.24"}),a.ui.plugin.add("resizable","alsoResize",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=function(b){a(b).each(function(){var b=a(this);b.data("resizable-alsoresize",{width:parseInt(b.width(),10),height:parseInt(b.height(),10),left:parseInt(b.css("left"),10),top:parseInt(b.css("top"),10)})})};typeof e.alsoResize=="object"&&!e.alsoResize.parentNode?e.alsoResize.length?(e.alsoResize=e.alsoResize[0],f(e.alsoResize)):a.each(e.alsoResize,function(a){f(a)}):f(e.alsoResize)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.originalSize,g=d.originalPosition,h={height:d.size.height-f.height||0,width:d.size.width-f.width||0,top:d.position.top-g.top||0,left:d.position.left-g.left||0},i=function(b,d){a(b).each(function(){var b=a(this),e=a(this).data("resizable-alsoresize"),f={},g=d&&d.length?d:b.parents(c.originalElement[0]).length?["width","height"]:["width","height","top","left"];a.each(g,function(a,b){var c=(e[b]||0)+(h[b]||0);c&&c>=0&&(f[b]=c||null)}),b.css(f)})};typeof e.alsoResize=="object"&&!e.alsoResize.nodeType?a.each(e.alsoResize,function(a,b){i(a,b)}):i(e.alsoResize)},stop:function(b,c){a(this).removeData("resizable-alsoresize")}}),a.ui.plugin.add("resizable","animate",{stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d._proportionallyResizeElements,g=f.length&&/textarea/i.test(f[0].nodeName),h=g&&a.ui.hasScroll(f[0],"left")?0:d.sizeDiff.height,i=g?0:d.sizeDiff.width,j={width:d.size.width-i,height:d.size.height-h},k=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,l=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;d.element.animate(a.extend(j,l&&k?{top:l,left:k}:{}),{duration:e.animateDuration,easing:e.animateEasing,step:function(){var c={width:parseInt(d.element.css("width"),10),height:parseInt(d.element.css("height"),10),top:parseInt(d.element.css("top"),10),left:parseInt(d.element.css("left"),10)};f&&f.length&&a(f[0]).css({width:c.width,height:c.height}),d._updateCache(c),d._propagate("resize",b)}})}}),a.ui.plugin.add("resizable","containment",{start:function(b,d){var e=a(this).data("resizable"),f=e.options,g=e.element,h=f.containment,i=h instanceof a?h.get(0):/parent/.test(h)?g.parent().get(0):h;if(!i)return;e.containerElement=a(i);if(/document/.test(h)||h==document)e.containerOffset={left:0,top:0},e.containerPosition={left:0,top:0},e.parentData={element:a(document),left:0,top:0,width:a(document).width(),height:a(document).height()||document.body.parentNode.scrollHeight};else{var j=a(i),k=[];a(["Top","Right","Left","Bottom"]).each(function(a,b){k[a]=c(j.css("padding"+b))}),e.containerOffset=j.offset(),e.containerPosition=j.position(),e.containerSize={height:j.innerHeight()-k[3],width:j.innerWidth()-k[1]};var l=e.containerOffset,m=e.containerSize.height,n=e.containerSize.width,o=a.ui.hasScroll(i,"left")?i.scrollWidth:n,p=a.ui.hasScroll(i)?i.scrollHeight:m;e.parentData={element:i,left:l.left,top:l.top,width:o,height:p}}},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.containerSize,g=d.containerOffset,h=d.size,i=d.position,j=d._aspectRatio||b.shiftKey,k={top:0,left:0},l=d.containerElement;l[0]!=document&&/static/.test(l.css("position"))&&(k=g),i.left<(d._helper?g.left:0)&&(d.size.width=d.size.width+(d._helper?d.position.left-g.left:d.position.left-k.left),j&&(d.size.height=d.size.width/d.aspectRatio),d.position.left=e.helper?g.left:0),i.top<(d._helper?g.top:0)&&(d.size.height=d.size.height+(d._helper?d.position.top-g.top:d.position.top),j&&(d.size.width=d.size.height*d.aspectRatio),d.position.top=d._helper?g.top:0),d.offset.left=d.parentData.left+d.position.left,d.offset.top=d.parentData.top+d.position.top;var m=Math.abs((d._helper?d.offset.left-k.left:d.offset.left-k.left)+d.sizeDiff.width),n=Math.abs((d._helper?d.offset.top-k.top:d.offset.top-g.top)+d.sizeDiff.height),o=d.containerElement.get(0)==d.element.parent().get(0),p=/relative|absolute/.test(d.containerElement.css("position"));o&&p&&(m-=d.parentData.left),m+d.size.width>=d.parentData.width&&(d.size.width=d.parentData.width-m,j&&(d.size.height=d.size.width/d.aspectRatio)),n+d.size.height>=d.parentData.height&&(d.size.height=d.parentData.height-n,j&&(d.size.width=d.size.height*d.aspectRatio))},stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.position,g=d.containerOffset,h=d.containerPosition,i=d.containerElement,j=a(d.helper),k=j.offset(),l=j.outerWidth()-d.sizeDiff.width,m=j.outerHeight()-d.sizeDiff.height;d._helper&&!e.animate&&/relative/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m}),d._helper&&!e.animate&&/static/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m})}}),a.ui.plugin.add("resizable","ghost",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size;d.ghost=d.originalElement.clone(),d.ghost.css({opacity:.25,display:"block",position:"relative",height:f.height,width:f.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof e.ghost=="string"?e.ghost:""),d.ghost.appendTo(d.helper)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.ghost.css({position:"relative",height:d.size.height,width:d.size.width})},stop:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.helper&&d.helper.get(0).removeChild(d.ghost.get(0))}}),a.ui.plugin.add("resizable","grid",{resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size,g=d.originalSize,h=d.originalPosition,i=d.axis,j=e._aspectRatio||b.shiftKey;e.grid=typeof e.grid=="number"?[e.grid,e.grid]:e.grid;var k=Math.round((f.width-g.width)/(e.grid[0]||1))*(e.grid[0]||1),l=Math.round((f.height-g.height)/(e.grid[1]||1))*(e.grid[1]||1);/^(se|s|e)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l):/^(ne)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l,d.position.top=h.top-l):/^(sw)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l,d.position.left=h.left-k):(d.size.width=g.width+k,d.size.height=g.height+l,d.position.top=h.top-l,d.position.left=h.left-k)}});var c=function(a){return parseInt(a,10)||0},d=function(a){return!isNaN(parseInt(a,10))}})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28 +* https://github.com/jquery/jquery-ui +* Includes: jquery.ui.selectable.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.widget("ui.selectable",a.ui.mouse,{options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch"},_create:function(){var b=this;this.element.addClass("ui-selectable"),this.dragged=!1;var c;this.refresh=function(){c=a(b.options.filter,b.element[0]),c.addClass("ui-selectee"),c.each(function(){var b=a(this),c=b.offset();a.data(this,"selectable-item",{element:this,$element:b,left:c.left,top:c.top,right:c.left+b.outerWidth(),bottom:c.top+b.outerHeight(),startselected:!1,selected:b.hasClass("ui-selected"),selecting:b.hasClass("ui-selecting"),unselecting:b.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=c.addClass("ui-selectee"),this._mouseInit(),this.helper=a("
")},destroy:function(){return this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable"),this._mouseDestroy(),this},_mouseStart:function(b){var c=this;this.opos=[b.pageX,b.pageY];if(this.options.disabled)return;var d=this.options;this.selectees=a(d.filter,this.element[0]),this._trigger("start",b),a(d.appendTo).append(this.helper),this.helper.css({left:b.clientX,top:b.clientY,width:0,height:0}),d.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var d=a.data(this,"selectable-item");d.startselected=!0,!b.metaKey&&!b.ctrlKey&&(d.$element.removeClass("ui-selected"),d.selected=!1,d.$element.addClass("ui-unselecting"),d.unselecting=!0,c._trigger("unselecting",b,{unselecting:d.element}))}),a(b.target).parents().andSelf().each(function(){var d=a.data(this,"selectable-item");if(d){var e=!b.metaKey&&!b.ctrlKey||!d.$element.hasClass("ui-selected");return d.$element.removeClass(e?"ui-unselecting":"ui-selected").addClass(e?"ui-selecting":"ui-unselecting"),d.unselecting=!e,d.selecting=e,d.selected=e,e?c._trigger("selecting",b,{selecting:d.element}):c._trigger("unselecting",b,{unselecting:d.element}),!1}})},_mouseDrag:function(b){var c=this;this.dragged=!0;if(this.options.disabled)return;var d=this.options,e=this.opos[0],f=this.opos[1],g=b.pageX,h=b.pageY;if(e>g){var i=g;g=e,e=i}if(f>h){var i=h;h=f,f=i}return this.helper.css({left:e,top:f,width:g-e,height:h-f}),this.selectees.each(function(){var i=a.data(this,"selectable-item");if(!i||i.element==c.element[0])return;var j=!1;d.tolerance=="touch"?j=!(i.left>g||i.righth||i.bottome&&i.rightf&&i.bottom *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3},_create:function(){var a=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?a.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},destroy:function(){a.Widget.prototype.destroy.call(this),this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var b=this.items.length-1;b>=0;b--)this.items[b].item.removeData(this.widgetName+"-item");return this},_setOption:function(b,c){b==="disabled"?(this.options[b]=c,this.widget()[c?"addClass":"removeClass"]("ui-sortable-disabled")):a.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(b,c){var d=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type=="static")return!1;this._refreshItems(b);var e=null,f=this,g=a(b.target).parents().each(function(){if(a.data(this,d.widgetName+"-item")==f)return e=a(this),!1});a.data(b.target,d.widgetName+"-item")==f&&(e=a(b.target));if(!e)return!1;if(this.options.handle&&!c){var h=!1;a(this.options.handle,e).find("*").andSelf().each(function(){this==b.target&&(h=!0)});if(!h)return!1}return this.currentItem=e,this._removeCurrentsFromItems(),!0},_mouseStart:function(b,c,d){var e=this.options,f=this;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(b),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(b),this.originalPageX=b.pageX,this.originalPageY=b.pageY,e.cursorAt&&this._adjustOffsetFromHelper(e.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!=this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),e.containment&&this._setContainment(),e.cursor&&(a("body").css("cursor")&&(this._storedCursor=a("body").css("cursor")),a("body").css("cursor",e.cursor)),e.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",e.opacity)),e.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",e.zIndex)),this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",b,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!d)for(var g=this.containers.length-1;g>=0;g--)this.containers[g]._trigger("activate",b,f._uiHash(this));return a.ui.ddmanager&&(a.ui.ddmanager.current=this),a.ui.ddmanager&&!e.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(b),!0},_mouseDrag:function(b){this.position=this._generatePosition(b),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs);if(this.options.scroll){var c=this.options,d=!1;this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-b.pageY=0;e--){var f=this.items[e],g=f.item[0],h=this._intersectsWithPointer(f);if(!h)continue;if(f.instance!==this.currentContainer)continue;if(g!=this.currentItem[0]&&this.placeholder[h==1?"next":"prev"]()[0]!=g&&!a.ui.contains(this.placeholder[0],g)&&(this.options.type=="semi-dynamic"?!a.ui.contains(this.element[0],g):!0)){this.direction=h==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(f))this._rearrange(b,f);else break;this._trigger("change",b,this._uiHash());break}}return this._contactContainers(b),a.ui.ddmanager&&a.ui.ddmanager.drag(this,b),this._trigger("sort",b,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(b,c){if(!b)return;a.ui.ddmanager&&!this.options.dropBehaviour&&a.ui.ddmanager.drop(this,b);if(this.options.revert){var d=this,e=d.placeholder.offset();d.reverting=!0,a(this.helper).animate({left:e.left-this.offset.parent.left-d.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:e.top-this.offset.parent.top-d.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){d._clear(b)})}else this._clear(b,c);return!1},cancel:function(){var b=this;if(this.dragging){this._mouseUp({target:null}),this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("deactivate",null,b._uiHash(this)),this.containers[c].containerCache.over&&(this.containers[c]._trigger("out",null,b._uiHash(this)),this.containers[c].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),a.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?a(this.domPosition.prev).after(this.currentItem):a(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(b){var c=this._getItemsAsjQuery(b&&b.connected),d=[];return b=b||{},a(c).each(function(){var c=(a(b.item||this).attr(b.attribute||"id")||"").match(b.expression||/(.+)[-=_](.+)/);c&&d.push((b.key||c[1]+"[]")+"="+(b.key&&b.expression?c[1]:c[2]))}),!d.length&&b.key&&d.push(b.key+"="),d.join("&")},toArray:function(b){var c=this._getItemsAsjQuery(b&&b.connected),d=[];return b=b||{},c.each(function(){d.push(a(b.item||this).attr(b.attribute||"id")||"")}),d},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,d=this.positionAbs.top,e=d+this.helperProportions.height,f=a.left,g=f+a.width,h=a.top,i=h+a.height,j=this.offset.click.top,k=this.offset.click.left,l=d+j>h&&d+jf&&b+ka[this.floating?"width":"height"]?l:f0?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){return this._refreshItems(a),this.refreshPositions(),this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(b){var c=this,d=[],e=[],f=this._connectWith();if(f&&b)for(var g=f.length-1;g>=0;g--){var h=a(f[g]);for(var i=h.length-1;i>=0;i--){var j=a.data(h[i],this.widgetName);j&&j!=this&&!j.options.disabled&&e.push([a.isFunction(j.options.items)?j.options.items.call(j.element):a(j.options.items,j.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),j])}}e.push([a.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):a(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(var g=e.length-1;g>=0;g--)e[g][0].each(function(){d.push(this)});return a(d)},_removeCurrentsFromItems:function(){var a=this.currentItem.find(":data("+this.widgetName+"-item)");for(var b=0;b=0;g--){var h=a(f[g]);for(var i=h.length-1;i>=0;i--){var j=a.data(h[i],this.widgetName);j&&j!=this&&!j.options.disabled&&(e.push([a.isFunction(j.options.items)?j.options.items.call(j.element[0],b,{item:this.currentItem}):a(j.options.items,j.element),j]),this.containers.push(j))}}for(var g=e.length-1;g>=0;g--){var k=e[g][1],l=e[g][0];for(var i=0,m=l.length;i=0;c--){var d=this.items[c];if(d.instance!=this.currentContainer&&this.currentContainer&&d.item[0]!=this.currentItem[0])continue;var e=this.options.toleranceElement?a(this.options.toleranceElement,d.item):d.item;b||(d.width=e.outerWidth(),d.height=e.outerHeight());var f=e.offset();d.left=f.left,d.top=f.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(var c=this.containers.length-1;c>=0;c--){var f=this.containers[c].element.offset();this.containers[c].containerCache.left=f.left,this.containers[c].containerCache.top=f.top,this.containers[c].containerCache.width=this.containers[c].element.outerWidth(),this.containers[c].containerCache.height=this.containers[c].element.outerHeight()}return this},_createPlaceholder:function(b){var c=b||this,d=c.options;if(!d.placeholder||d.placeholder.constructor==String){var e=d.placeholder;d.placeholder={element:function(){var b=a(document.createElement(c.currentItem[0].nodeName)).addClass(e||c.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];return e||(b.style.visibility="hidden"),b},update:function(a,b){if(e&&!d.forcePlaceholderSize)return;b.height()||b.height(c.currentItem.innerHeight()-parseInt(c.currentItem.css("paddingTop")||0,10)-parseInt(c.currentItem.css("paddingBottom")||0,10)),b.width()||b.width(c.currentItem.innerWidth()-parseInt(c.currentItem.css("paddingLeft")||0,10)-parseInt(c.currentItem.css("paddingRight")||0,10))}}}c.placeholder=a(d.placeholder.element.call(c.element,c.currentItem)),c.currentItem.after(c.placeholder),d.placeholder.update(c,c.placeholder)},_contactContainers:function(b){var c=null,d=null;for(var e=this.containers.length-1;e>=0;e--){if(a.ui.contains(this.currentItem[0],this.containers[e].element[0]))continue;if(this._intersectsWith(this.containers[e].containerCache)){if(c&&a.ui.contains(this.containers[e].element[0],c.element[0]))continue;c=this.containers[e],d=e}else this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",b,this._uiHash(this)),this.containers[e].containerCache.over=0)}if(!c)return;if(this.containers.length===1)this.containers[d]._trigger("over",b,this._uiHash(this)),this.containers[d].containerCache.over=1;else if(this.currentContainer!=this.containers[d]){var f=1e4,g=null,h=this.positionAbs[this.containers[d].floating?"left":"top"];for(var i=this.items.length-1;i>=0;i--){if(!a.ui.contains(this.containers[d].element[0],this.items[i].item[0]))continue;var j=this.containers[d].floating?this.items[i].item.offset().left:this.items[i].item.offset().top;Math.abs(j-h)0?"down":"up")}if(!g&&!this.options.dropOnEmpty)return;this.currentContainer=this.containers[d],g?this._rearrange(b,g,null,!0):this._rearrange(b,null,this.containers[d].element,!0),this._trigger("change",b,this._uiHash()),this.containers[d]._trigger("change",b,this._uiHash(this)),this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[d]._trigger("over",b,this._uiHash(this)),this.containers[d].containerCache.over=1}},_createHelper:function(b){var c=this.options,d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[b,this.currentItem])):c.helper=="clone"?this.currentItem.clone():this.currentItem;return d.parents("body").length||a(c.appendTo!="parent"?c.appendTo:this.currentItem[0].parentNode)[0].appendChild(d[0]),d[0]==this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(d[0].style.width==""||c.forceHelperSize)&&d.width(this.currentItem.width()),(d[0].style.height==""||c.forceHelperSize)&&d.height(this.currentItem.height()),d},_adjustOffsetFromHelper:function(b){typeof b=="string"&&(b=b.split(" ")),a.isArray(b)&&(b={left:+b[0],top:+b[1]||0}),"left"in b&&(this.offset.click.left=b.left+this.margins.left),"right"in b&&(this.offset.click.left=this.helperProportions.width-b.right+this.margins.left),"top"in b&&(this.offset.click.top=b.top+this.margins.top),"bottom"in b&&(this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])&&(b.left+=this.scrollParent.scrollLeft(),b.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)b={top:0,left:0};return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.currentItem.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var b=this.options;b.containment=="parent"&&(b.containment=this.helper[0].parentNode);if(b.containment=="document"||b.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(b.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(b.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(b.containment)){var c=a(b.containment)[0],d=a(b.containment).offset(),e=a(c).css("overflow")!="hidden";this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(e?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("borderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(e?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(b,c){c||(c=this.position);var d=b=="absolute"?1:-1,e=this.options,f=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=/(html|body)/i.test(f[0].tagName);return{top:c.top+this.offset.relative.top*d+this.offset.parent.top*d-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():g?0:f.scrollTop())*d),left:c.left+this.offset.relative.left*d+this.offset.parent.left*d-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:f.scrollLeft())*d)}},_generatePosition:function(b){var c=this.options,d=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(d[0].tagName);this.cssPosition=="relative"&&(this.scrollParent[0]==document||this.scrollParent[0]==this.offsetParent[0])&&(this.offset.relative=this._getRelativeOffset());var f=b.pageX,g=b.pageY;if(this.originalPosition){this.containment&&(b.pageX-this.offset.click.leftthis.containment[2]&&(f=this.containment[2]+this.offset.click.left),b.pageY-this.offset.click.top>this.containment[3]&&(g=this.containment[3]+this.offset.click.top));if(c.grid){var h=this.originalPageY+Math.round((g-this.originalPageY)/c.grid[1])*c.grid[1];g=this.containment?h-this.offset.click.topthis.containment[3]?h-this.offset.click.topthis.containment[2]?i-this.offset.click.left=0;f--)c||d.push(function(a){return function(b){a._trigger("deactivate",b,this._uiHash(this))}}.call(this,this.containers[f])),this.containers[f].containerCache.over&&(d.push(function(a){return function(b){a._trigger("out",b,this._uiHash(this))}}.call(this,this.containers[f])),this.containers[f].containerCache.over=0);this._storedCursor&&a("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!c){this._trigger("beforeStop",b,this._uiHash());for(var f=0;f - - - Paradise Station Changelog - - - - - - - -
- - - - -
-
Paradise Station
- -

- Visit our IRC channel: #crew on neko.sneeza.me -
- - - - - -
- Current Project Maintainers: -Click Here-
- Currently Active GitHub contributor list: -Click Here-
- Coders: ZomgPonies, DaveTheHeadcrab, tigercat2000, FalseIncarnate, AuroraBlade, Tastyfish, Crazylemon64, KasparoVy
- Spriters: FullOfSkittles
- Sounds:
- Main Testers: Anyone who has submitted a bug to the issue tracker
- Thanks to: Baystation 12, /tg/station, /vg/station, NTstation, CDK Station devs, FacepunchStation, GoonStation devs, the original SpaceStation developers and Radithor for the title image.
Also a thanks to anybody who has contributed who is not listed here :( Ask to be added here on irc.
-
Have a bug to report?
Visit our Issue Tracker.
- Please ensure that the bug has not already been reported and be as descriptive as possible about the circumstances under which the bug occurred. -
- - -
-

14 April 2016

-

Aurorablade updated:

-
    -
  • Removes the !!FUN!! of having headslugs gold core spawnable.
  • -
-

Fox McCloud updated:

-
    -
  • Added in sounds (instead of a chat-based message) for when airlocks are bolted/unbolted
  • -
  • Added in sound for when airlocks deny access
  • -
  • cutting/pulsing wires will play a sound
  • -
  • ups nuke ops game mode population requirement from 20 to 30
  • -
  • Adds in mining drone upgrade modules to increase their health, combat capability, or reduce their ranged cooldowns
  • -
  • Adds in mining drone "AI upgrade" a sentience potion that only works on mining bots
  • -
  • Mining bots should be less likely to shoot you when attacking hostile mobs
  • -
  • Killer tomatoes actually live up to their name now and are hostile mobs
  • -
  • Killer tomatoes are an actual fruit now; activate it in your hands to make them into a mob
  • -
  • Killer tomatoes are directly mutated from regular tomatoes instead of blood tomatoes
  • -
  • Increased the yield of regular tomatoes by 1
  • -
  • Tweak some stats on the killer tomato seeds
  • -
  • Fixes the blind player preference not doing anything
  • -
  • Adds portaseeder to R&D
  • -
  • Scythes will conduct electricity now
  • -
  • Mini hoes play a slice sound instead of bludgeon sound
  • -
  • Plant analyzer properly has a description and origin tech
  • -
  • Can have hulk+dwarf mutations together
  • -
  • Can have heat+cold resist together
  • -
  • Can only remotely view people who also have remote view
  • -
  • Fixes cold mutation not having an overlay
  • -
  • Hallucinations will no longer tick down twice as fast as they should nor will they spawn twice as many hallucinations as they should
  • -
  • Incendiary mitochondria no longer asks who you want to cast it on (it always is meant to be cast on yourself)
  • -
  • Fixes permanent nearsightedness even when wearing prescription glasses
  • -
-

KasparoVy updated:

-
    -
  • Head accessories now behave like facial hair: They will no longer be hidden by clothing items that BLOCKHEADHAIR (have the BLOCKHEADHAIR flag).
  • -
  • Wearing a piece of clothing that blocks head hair will no longer make head accessories (facial markings/horns/antennae) invisible until an icon update is triggered while the headwear is off.
  • -
-

Meisaka updated:

-
    -
  • law manager no longer freaks out with Malf law
  • -
-

Tastyfish updated:

-
    -
  • The /vg/ library computer interface has been ported, giving a much better use experience.
  • -
  • Books can now be flagged for inappropriate content.
  • -
-

TheDZD updated:

-
    -
  • Removes shitty Caelcode bees.
  • -
  • Hydroponics can now manage bee colonies, bees produce honeycombs that can be ground to obtain honey, a decent nutriment+healing chemical
  • -
  • Hydroponics can inject a queen bee with a syringe of a reagent to alter her DNA to match that reagent, meaning all honeycombs produced will contain that reagent in small amounts
  • -
  • Bees with reagents will attack with that reagent. It takes 5u of a reagent to give a bee that reagent.
  • -
  • Added the ability to make Apiaries and Honey frames with wood
  • -
  • Added the ability to make Royal Bee Jelly from 10 Mutagen and 40 Honey
  • -
  • Added the ability to make more Queen Bees from Royal Bee Jelly by using it on an existing Queen, to split her into two Queens
  • -
  • Removes some snowflakey mob behavior from bears, snakes and panthers.
  • -
  • Hudson is feeling punny.
  • -
  • Hostile mob AI should now be a bit more cost-efficient.
  • -
-

monster860 updated:

-
    -
  • Adds area editing, link mode, and fill mode to the buildmode tool
  • -
- -

12 April 2016

-

FalseIncarnate updated:

-
    -
  • Adjusting the setting of a vendor circuit board is no longer random, but instead provides a select-able list.
  • -
  • Vendor Circuit Board design moved from the Circuit Imprinter to the Autolathe, acid requirement replaced by metal.
  • -
  • Burnt matches can no longer light cigarettes, pipes, or joints.
  • -
-

Fethas updated:

-
    -
  • Nukes the cargo train code rscadd:Adds simple vehicle framework and converts secway/janicart/snowmobiles/bikes/cars/ambulance to it rscadd:Adds space speedbike, red and blue versions, yes you WILL need a spacesuit rscadd:Maps janicart and secway onto metastation (but not ambulance no pareamedic garage, no i am not mapping that)
  • -
  • You should now be able to operate on IPC eyes, SHOULD bugfix:hopefully surgery on diona works right
  • -
-

Fox McCloud updated:

-
    -
  • Adds in TraitorVamp; game mode that's essentially like TraitorChan, but with a Vampire instead of a Changeling
  • -
  • Vampires cannot use holoparasites
  • -
  • Malf AI will automatically lose if it exits the station z-level
  • -
-

Tastyfish updated:

-
    -
  • All cats can kill mice now.
  • -
  • E-N can't suffocate.
  • -
  • Startup time is now shorter.
  • -
  • Removed the Station Collision away mission from rotation, due to multiple conceptual and technical issues.
  • -
- -

07 April 2016

-

Crazylemon64 updated:

-
    -
  • Removes an offset from the advanced virus stealth calculation, causing viruses to be more stealthy than the sum of their symptoms.
  • -
  • Mulebots will now send announcements to relevant requests consoles on delivery again.
  • -
-

FalseIncarnate updated:

-
    -
  • Adds logic gates, for doing illogical things in a logical manner.
  • -
  • Adds buildable light switches, for all your light toggling needs.
  • -
  • Fixes a resource duplication bug with mass driver buttons.
  • -
-

Fethas updated:

-
    -
  • maybe makes them last longer...maybe..and fixes the event end message
  • -
-

Fox McCloud updated:

-
    -
  • Maps in the slime management console to Xenobio
  • -
  • Reduces Xenobio monkey box count from 4 to 2
  • -
  • Fixes weakeyes having a negligible impact
  • -
  • Can spawn friendly animals with a new gold core reaction by injection with water
  • -
  • Hostile animal spawn increased from 3 to 5 for hostile gold cores
  • -
  • Swarmers, revenants, and morphs no longer gold core spawnable
  • -
  • Fixes invisible animal spawns from gold core/life reactions
  • -
  • Adds tape to the ArtVend
  • -
  • Can no longer use sentience potions on bots
  • -
  • Added in Plasma Dust reagent, acquired by grinding plasma sheets; it's more toxic than regular plasma and generates plasma gas when spilled onto turfs.
  • -
  • Slimecore reactions now require plasma dust as opposed to dispenser plasma
  • -
  • Added in new Rainbow slime; inject with plasma dust to get a random colored slime. Acquire by having 100 mutation chance on a slime when it splits.
  • -
  • Monkey Recycler can produce different types of monkey cubes; change the cube type by using a multitool on the recycler
  • -
  • Epinephrine/plasma reagents changing mutation rate has been removed
  • -
  • Mutation chance is inherited from slime generation to slime generation as opposed to being purely random.
  • -
  • New reactions added for red and blue extracts: red generates mutator, which increases mutation chance, and blue generates stabilizer, which decreases mutation chance.
  • -
  • Slime glycerol reaction removed
  • -
  • Slime cells are now high capacity cells (more power than before)
  • -
  • extract enhancer increases the slime core usage by 1 as oppose to setting it to three
  • -
  • slime enhancer increases slime cores by 1 as opposed to setting the core amount to 3
  • -
  • Chill reaction lowers body temperature slightly more so it doesn't just wear off instantly
  • -
  • Reduces Xenobio plasma sheets from 8 to 3 and removes that pesky boombox
  • -
  • Processors no longer produce 1 more slime core than intended
  • -
  • Less blank/spriteless/empty foods from the silver core reaction
  • -
  • Virology mix reactions now use plasma dust as opposed to plasma
  • -
  • Statues can no longer move/attack people unless they're in total darkness or all mobs viewing them are blinded
  • -
  • statues are invincible to anything other than full out gibbing.
  • -
  • Statues flicker lights spell range increased
  • -
  • Blind spell no longer impacts silicons
  • -
  • Fixes statues being able to attack/move whenever they feel like it, regardless of client statues
  • -
  • Fixes blind spell impacting the statue
  • -
-

Tastyfish updated:

-
    -
  • Beepsky is no longer a pokemon.
  • -
  • pAI-controlled Bots now reliably speak human-understandable languages over the radio.
  • -
  • More floor blood for the blood gods. (Or rather, as much as there was supposed to be.)
  • -
-

tigercat2000 updated:

-
    -
  • Items in your off hand will now count towards access.
  • -
- -

02 April 2016

-

Crazylemon64 updated:

-
    -
  • Metal foam walls will now produce flooring on space tiles
  • -
  • Syringes will now draw water from slime people.
  • -
-

FalseIncarnate updated:

-
    -
  • Let's you know when your container is full when filling from sinks.
  • -
  • Prevents splashing containers onto beakers and buckets that have a lid on them.
  • -
  • Pill bottles can now be labeled with a simple pen.
  • -
  • Beakers/buckets (and pill bottles) now accept 26 character labels from pens.
  • -
-

Fethas updated:

-
    -
  • Various spells have had a tweak to stun/reveal/cast, some other number stuff...
  • -
  • Nightvision
  • -
  • harvest code is now in the abilites file.
  • -
  • New fluff objectives
  • -
  • Hell has recently remapped its blood transit system and you can now once again crawl through blood. We are sorry for the-GIVE US YOUR SOUL!
  • -
-

FlattestGuitar updated:

-
    -
  • Alcoholic beverages now have proper levels of ethanol in them. Good luck passing out after a beer.
  • -
-

Fox McCloud updated:

-
    -
  • Adds in the Lusty Xenomorph Maid Mob; currently admin only.
  • -
  • Fixes xenomorph brains having the wrong sprite, no origin tech, and incorrect name
  • -
  • removes xenomorph egg from hotel
  • -
  • upgrades are no longer needed to for the available toys in the prize vendor
  • -
  • Implements Advanced Camera Consoles. A type of camera console that function like AI's vision style. Non-buildable/accessible.
  • -
  • Adds in Xenobiology Advance Cameras. A type of camera console that functions like advanced cameras, but only works in Xenobiology areas; can move around slimes and feed them with the console as well. Also non-buildable/accessible (for now).
  • -
  • Adds in cerulean slime reaction that generates a single use blueprint. On use it colors turfs a lavender color
  • -
  • Adds disease1 outbreak event
  • -
  • Adds appendecitis event
  • -
  • Roburgers now properly have nanomachines in them
  • -
  • Re-adds nanomachines
  • -
  • Experimentor properly generates nanomachines instead of itching powder
  • -
  • Fixes big roburgers having a healing reagent in them
  • -
  • Adds nanomachines to poison traitor bottles
  • -
  • Tajarans can now eat mice, chicks, parrots, and tribbles
  • -
  • Vulpkanin and Unathi can now eat mice, chicks, lizards, chickens, crabs, parrtos, and tribbles
  • -
  • fixes spawned changeling headcrab behavior
  • -
-

KasparoVy updated:

-
    -
  • Incisions made at the beginning of embedded object removal surgery can now be closed in the same procedure.
  • -
-

ProperPants updated:

-
    -
  • Maint drones have magboots.
  • -
  • Removed plastic from maint drones. Literally useless for station maintenance.
  • -
  • Increased starting amounts of some materials for maint drones and engi borgs.
  • -
  • Reduced the number of lines taken by Engineering cyborgs calling on materials stacks.
  • -
  • Operating tables can be deconstructed with a wrench.
  • -
  • Fixed and shortened description of metal sheets.
  • -
-

Tastyfish updated:

-
    -
  • Bots can now be controlled by players, by opening them up and inserting a pAI. *beep
  • -
  • MULEbots can now access the engineering destination.
  • -
  • All MULEbot destinations should now have the correct load/unload direction, meaning the crates won't be dumped inside the flaps.
  • -
  • Diagnostic HUD's now give health and status information about bots.
  • -
  • MULEbot rampage blood tracks are now rendered correctly and handle UE traces as appropriate.
  • -
  • Bots should (hopefully) lag the game less now.
  • -
  • Beepsky contains 30% more potato.
  • -
  • Action progress bars are now smooth.
  • -
  • Clicking a filled inventory slot's square with an open hand now clicks the item in the slot.
  • -
  • Status displays now display the time when in Shuttle ETA mode and no shuttle activity is happening.
  • -
  • Shuttle ETA countdowns on status displays are now amber.
  • -
  • pAI's can now use the PDA chatrooms.
  • -
  • Adds treadmills to brig cells, to give the prisoners something productive to do.
  • -
-

TheDZD updated:

-
    -
  • A lot of the guns and armor in the station collision, space hotel, academy, and wild west away missions have been removed/replaced.
  • -
  • Removes that fucking facehugger from station collision.
  • -
-

tigercat2000 updated:

-
    -
  • Virus2 has been removed.
  • -
  • Virus1 is back. Viva la revolution.
  • -
  • You can now have up to 20 characters.
  • -
- -

26 March 2016

-

Fox McCloud updated:

-
    -
  • Adds in dental implant surgery. Implant pills into people's teeth.
  • -
  • Major rebalance and Shadowling update (https://github.com/ParadiseSS13/Paradise/pull/3986 for details). In general, Shadowlings can no longer enthrall or engage in Shadowling like behavior, pre-hatch. Post-hatch, shadowlings are much more powerful, with a ride array of New abilities such as extending the shuttle or making thralls into lesser shadowlings. Shadowling gameplay should not revolve almost entirely around darkness, as opposed to pre-hatch shenanigans.
  • -
  • Robotics now has a "sterile" surgical area for performing augmentations
  • -
  • Adds the FixOVein and Bone Gel to the autolathe
  • -
  • ensures all surgical tools have origin tech on them; lowers origin tech on FixoVein
  • -
-

KasparoVy updated:

-
    -
  • Slime People can now wear underwear.
  • -
  • Slime People can now wear undershirts.
  • -
-

TheDZD updated:

-
    -
  • NT has removed trace amounts of a highly-addictive substance from the "100% real" cheese used in cheese-flavored snacks. As a result, incidence rates of crewmembers becoming addicted to Cheesie Honkers should reduce to zero.
  • -
  • After receiving complaints about crewmembers often being unable to physically function without a back-mounted barrel of coffee, NT has replaced station all sources of coffee on the station, including coffee beans themselves with a largely decaffeinated version. It was funny the first time almost every crewmember aboard the NSS Cyberiad was lugging around their own oil barrel filled with coffee, it wasn't so funny, nor good for productivity the eighteenth.
  • -
- -

25 March 2016

-

Crazylemon64 updated:

-
    -
  • You now will actually have the correct `real_name` on your DNA.
  • -
  • No more roundstart runtimes regarding IPC hair.
  • -
  • Mitocholide rejuv will work more usefully now.
  • -
  • Limbs and cyborg modules will no longer appear in your screen.
  • -
  • Cyborg module icons are now persistent throughout logging in and out.
  • -
  • Various cyborg modules, like engineering, now use the proper icon.
  • -
-

FlattestGuitar updated:

-
    -
  • Adds confetti grenades.
  • -
-

Fox McCloud updated:

-
    -
  • Fixes Sleeping Carp combos not having an attack animation
  • -
  • Fixes several chems not properly healing brute/burn damage, consistently, as intended
  • -
-

KasparoVy updated:

-
    -
  • Unbranded heads and groins no longer invisible.
  • -
  • Zeng-hu left leg will now be in line with the body when facing south.
  • -
- -

22 March 2016

-

Crazylemon64 updated:

-
    -
  • Repairs all sorts of eldritch occurences that happen when you put an organic head on an IPC body, as well as some decapitation bugs
  • -
  • Makes heads keep hair on removal
  • -
  • Amputated limbs from a DNA-injected individual now will keep their appearance of the DNA-injected person
  • -
  • Wounds will vanish on their own now
  • -
  • Admins now have an "incarnate" option on the player panel when viewing ghosts for quick player instantiation
  • -
  • Fixes a runtime regarding failing a limb reconnection surgery
  • -
  • Copying a client's preferences now overrides the previous mob's DNA
  • -
  • A DNA injector is now more thorough, and affects the DNA of mobs' limbs and organs
  • -
  • DNA-lacking species can no longer be DNA-injected
  • -
  • Brains are now labeled again
  • -
  • Splashing mitocholide on dead organs will make them live again.
  • -
  • The body scanner now detects necrotic limbs and organs.
  • -
  • pAIs and Drones are now affected by EMPs and explosions while held.
  • -
-

Fethas updated:

-
    -
  • Adds a surgery for infection treatmne/autopsys that is simply cut open, retract, cauterize
  • -
  • fixes a dumb error in internal bleeeding surgerys
  • -
  • Chaos types no longer random teleport, but will make the target hallucinate everyone looks like the guardian.
  • -
-

FlattestGuitar updated:

-
    -
  • Adds a snow, navy and desert military jacket.
  • -
-

Fox McCloud updated:

-
    -
  • Removes random 1% chance to heal fire damage
  • -
  • Removes passive healing from resist heat mutation
  • -
  • Regen mutation heals every cycle (albeit less, on average), but doesn't cost hunger
  • -
  • Fixes not being able to speak over xeno common or hivemind when you receive the Xeno hive node
  • -
  • Adds in the ability to transfer non-locked metal+glass only designs from the protolathe to autolathe
  • -
  • Changes Outpost Mass Driver to prevent accidental spacings
  • -
  • Shadow people no longer dust on death, are rad immune+virus immune, and can be cloned. Slip immunity removed
  • -
  • Shadowlings no longer get hungry or fat and no longer dust on death
  • -
-

KasparoVy updated:

-
    -
  • The ability to change your head, torso and groin as an IPC in the character creator. Non-IPCs cannot access the parts.
  • -
  • Head, torso and groin sprites for all mechanical limb/bodypart brands but Morpheus and the unbranded ones (since those already exist) from Polaris.
  • -
  • Faux-eye optics for non-Morpheus heads.
  • -
  • The ability to change optic (eye) colour if you've got a non-Morpheus head.
  • -
  • The ability to choose human hair styles (wigs) and facial hair styles (postiche) with non-Morpheus heads. Non-Morpheus heads cannot choose screens. Conversely, Morpheus heads cannot choose wigs or facial hair.
  • -
  • Two hair styles from Polaris.
  • -
  • The ability for IPCs to wear undergarments (shirts and trousers).
  • -
  • Antennae (colourable) for IPCs.
  • -
  • IPC monitor adjustment verb will now adjust optic colour if the head is non-Morpheus.
  • -
  • Combat/SWAT boots can now be toecut and jacksandals can't.
  • -
  • ASAP fix to what would've broken the ability to configure prostheses in character creation.
  • -
  • Adjusted masks no longer block CPR (including bandanas).
  • -
  • You can no longer run internals from adjusted breath masks (or airtight adjustable masks in general).
  • -
-

Regens updated:

-
    -
  • Robotic hearts will now properly give the mob a heart attack instead of just damaging it when EMP'd
  • -
  • Assisted organs will now also take damage from EMP's
  • -
  • Internal robotic and assisted organs will now actually take damage from EMP's
  • -
-

Tastyfish updated:

-
    -
  • Adds PDA chatrooms. Post memes! Talk to your fellow collaborators! Get caught!
  • -
  • You can now set the PDA messenger to automatically scroll down to new messages.
  • -
  • Pet collars now act as death alarms and can have ID's attached to them.
  • -
  • All domestic animals can now wear collars.
  • -
  • You can now make video cameras at the autolathe.
  • -
-

TheDZD updated:

-
    -
  • Fixes an instance of old code being so incredibly, unbelievably, makes-me-want-to-stab-myself-in-the-eye-edly idiotic.
  • -
-

TravellingMerchant updated:

-
    -
  • Kidan have new sprites!
  • -
-

tigercat2000 updated:

-
    -
  • Nukeops now have an assault pod, they can use it for 30 TC. Loud and mean.
  • -
  • Lighting overlays can no longer go below 0 lum_r/g/b
  • -
  • Shuttles will work with lighting better.
  • -
  • Wizards can no longer teleport to prohibited areas such as Central Command.
  • -
- -

16 March 2016

-

Crazylemon64 updated:

-
    -
  • Being in godmode now makes you immune to bombs
  • -
  • Science members now get compensated when they ship tech disks to centcomm.
  • -
  • Science crew are no longer paid when they "max" research.
  • -
  • Roboticists now get credit for making RIPLEYs and Firefighters
  • -
  • Slime people can now regrow limbs on a more lax nutrition requirement
  • -
  • Enhances the nutripump+ to let slime people regrow limbs with it active
  • -
  • Skeletons, slime people, IPCs, and Diona no longer leave blood when hit
  • -
  • Rejuvenating a slime person will no longer clog up their "blood"
  • -
  • Slime people will now regenerate "blood" from having water in their system
  • -
  • The decloner can now be created again
  • -
  • Environment smashing mobs can now destroy girders.
  • -
-

DaveTheHeadcrab updated:

-
    -
  • Removes the check for species on the update_markings proc.
  • -
-

FalseIncarnate updated:

-
    -
  • Xeno-botany is now more user-friendly, and less random letters/numbers.
  • -
  • Hydroponics now has a connector hooked up to the isolation tray and a new connector in their back room for those strange plants that like spewing plasma or eating nitrogen.
  • -
  • You can now (finally) build the xeno-botany machines, and science can print off their respective boards.
  • -
-

Fethas updated:

-
    -
  • Syringes are no longer sharp
  • -
  • byond likes direct pathing so item/organ/internal not item/organ even if it shouldn't be in the internal_organs list. This was preventing the list from doing stuff correctly.
  • -
  • fixed ipc organ manipulation surgery, you can now insert a replacment ipc organ directly instead of needing a screwdriver in your main hand
  • -
  • nanopaste now will repair organs with robotic >= 2 instead of > 2 cuase i am an idiot
  • -
  • Fix, hopefully, for a runtime for clientless mobs whos head are cut off...
  • -
  • Hopefully fixes issues with diona eyes
  • -
  • Though shalt not eat robotic organs..including cybernetic implants..
  • -
  • ITS SURGERY_STEP/DETHRALL NOT SURGERY_STEP/INTERNAL/DETHRALL
  • -
-

FlattestGuitar updated:

-
    -
  • Adds three new synthanol drinks
  • -
  • Drinking synthanol is now a bad idea if you're organic
  • -
  • A glass of holy water now looks like normal water
  • -
-

Fox McCloud updated:

-
    -
  • Adds in drink fizzing sound
  • -
  • Drink/bartender recipes use this new fizzing sound in addition to a few other recipes
  • -
  • Adds in a fuse burning sound
  • -
  • Bath salts, black powder, saltpetre, and charcoal use this sound now
  • -
  • Adds in a matchstrike+burning sound
  • -
  • Lighting a match triggers this new sound
  • -
  • Adds in scissors cutting sound
  • -
  • Cutting someone's hair uses this new sound
  • -
  • Adds in printer sounds
  • -
  • printing off papers from various devices typically uses these sounds
  • -
  • Adds computer ambience sounds
  • -
  • black box recorder and R&D core servers both play this sound at random rare intervals
  • -
  • Reduces the tech level (and requirement) for nanopaste
  • -
  • Reduces the tech level (and requirement) for the plasma pistol
  • -
  • Removes Nymph and drone tech levels
  • -
  • Reduces tech levels on the flora board
  • -
  • Adds tech level requirements to mech sleepers, mech syringe guns, mech tasers, and mech machine guns
  • -
  • Increases tech cost of the decloner
  • -
  • Removes the pacman generators
  • -
  • Removes emitter
  • -
  • Removes flora machine (functionless anyway)
  • -
  • Removes the pre-spawned nanopaste
  • -
  • Removes space suits
  • -
  • Removes excavation gear
  • -
  • Replaces the soil with actual hydroponic trays (more aesthetic than anything)
  • -
  • Removes most external asteroid access from the station
  • -
  • Excavation storage is now generic science storage
  • -
  • removed the plasma sheet
  • -
  • Fixes augments not showing up in R&D unless specifically searched for
  • -
  • Fixes some augments being unavailable in mech fabs
  • -
  • Fixes augments having no construction time
  • -
  • Fixes xenos not gaining plasma when breathing in plasma
  • -
  • Fixes plasma reagent not generating plasma for a person
  • -
  • Screaming has different sounds based on being male or female
  • -
  • Implements Goon's screaming sounds.
  • -
  • Screaming tone is now based on age of character instead of being random
  • -
  • Ups the cooldown on screaming from 2 seconds to 5 seconds
  • -
  • Removes chance for Whilhelm scream
  • -
  • Borgs can now scream
  • -
  • Monkey's now have a unique screaming sound
  • -
  • IPCs now scream like cyborgs
  • -
  • Updates slot machines to have higher jackpots and more payouts with more interesting sounds
  • -
  • Adds X-Ray, Thermal, Anti-tun, and Reviver implants to the nuke ops uplink (augments come with one auto-implanter) rcsadd: Adds in augment auto-implanter, which inserts and implant without surgery
  • -
  • tweaks a large number of chems; behaviors are largely retained, but new flavor messages, probabilities, etc may be present; overall, you can expect chems to do the same thing
  • -
  • Tabun re-replaced with Sarin rcsadd: New reagent: cholesterol: if overdosed on, it can cause a heart attack--fatty foods, cheese, eggs, and some meats all produce cholesterol in your body.
  • -
  • Mixing Sarin, Meth, or Cyanide will poison in a very small area of the reaction if you're not on internal OR not wearing a gas mask
  • -
  • Chemist warddrobe now has two gas masks
  • -
  • Teslium will now impact synthetics AND organics
  • -
  • Fixes facehuggers hugging already infected people
  • -
  • Fixes facehuggers hugging people while dead
  • -
  • Fixes Embryo's developing twice as fast as they should
  • -
  • Fixes up some behaviors with xeno eggs
  • -
  • Xeno acid can now melt through floors and the asteroid
  • -
  • Xeno's now play the gib sound when actually gibbed
  • -
  • Implements Changeling headcrabs/headspiders
  • -
  • Fixes xenos not throwing their organs when gibbed
  • -
  • Fixes swallowed mobs not being ejected when a human is gibbed
  • -
  • Adds in spider eggs reagent, an infectious reagent that requires surgery to correct
  • -
  • Fixes EMPs causing eye implant users to be permanently blind
  • -
  • Increases bag of holding's storage capacity
  • -
  • Removing a heart no longer kills the patient instantly, but induces a heart attack
  • -
  • Demon hearts will not work
  • -
  • Should now actually be able to re-insert hearts
  • -
  • Reworks addictions to bettter differentiate them betweeen overdosing and make them more realistic.
  • -
  • changes which chems are addictive, currently, the follow reagents are now addidctive: meth, crank, krokodil, bath salts, space drugs, perfluoradecalin, omnizine, coffee, nicotine, fliptonium, ultra lube, surge, fake cheese, weird cheese, ephedrine, diphenhydramine, teporone, and morphine
  • -
  • sleepers help you recover from addiction faster
  • -
  • Can now make cable coils in autolathes
  • -
  • Fixes the slot machine announcements not displaying properly
  • -
-

Tastyfish updated:

-
    -
  • The super fart mutation now gives you a spell-like ability instead of augmenting the emote.
  • -
  • Vampire abilities are now in their own Vampire tab, as well being action buttons at the top, like spells.
  • -
  • Cloning a vampire no longer makes them lose their abilities.
  • -
  • Vampires can no longer hypnotize chaplains.
  • -
  • Being a full vampire (500+ total blood) actually makes you immune to holy water reliably now.
  • -
  • Some old away missions are back: Academy, Black Market Packers, Space Hotel, Station Collision, and Wild West. Go out and round up some hostiles!
  • -
  • Shuttle consoles now pair up to the engineering, mining, research, or labor shuttle when built or used before pairing, as long as the shuttle is near the console, or the shuttle is moved to be nearby.
  • -
-

monster860 updated:

-
    -
  • Mining station now has a podbay.
  • -
  • Ore scooping module for the spacepod.
  • -
  • Three mining lasers for spacepod: Basic, normal, and burst.
  • -
  • Shooting weapons south or west of spacepod will actually hit adjacent targets now, and won't shoot through walls anymore.
  • -
-

taukausanake updated:

-
    -
  • Mice can now be picked up like diona
  • -
- -

08 March 2016

-

Crazylemon64 updated:

-
    -
  • Slime people are now more vulnerable to low temperatures.
  • -
  • Slime people are able to slowly regrow limbs at a high nutrition cost.
  • -
  • Slime people now slowly shift color based on reagents inside of them - disabled by default, toggle it with an IC verb
  • -
  • Slime people's cores are more vulnerable to damage
  • -
  • Species-related abilities now properly are removed - no more vox hair stylists, unfortunately.
  • -
-

Fethas updated:

-
    -
  • the nest buckle now looks for the right organ path
  • -
  • Fixed some sprites.
  • -
  • No more putting no drops in rechargers,
  • -
-

Fox McCloud updated:

-
    -
  • Implement's goon's gibbing sound
  • -
  • Implement's goon's gibbing sound for robots/silicons
  • -
  • Removes old gibbing sound
  • -
-

Spacemanspark updated:

-
    -
  • Lazarus Injector's can now be emagged to activate their special features, alongside using EMPs on them.
  • -
-

Tastyfish updated:

-
    -
  • Mimes now have a new ore, Tranquillite, used to bring peace and quiet to the station.
  • -
  • There are also permanent invisible walls and silent floors that can be made from tranquillite.
  • -
  • The Recitence mech is now buildable!
  • -
  • The Recitence mech is now playable!
  • -
  • Mid-round selection for various creatures and antagonists now consistently asks permission.
  • -
-

TheDZD updated:

-
    -
  • Adds justice helmets with flashing lights and annoying sirens.
  • -
  • Adds crates containing said helmets.
  • -
  • Also includes a version of the helmet that can only be spawned by admins, and just has a single red light in the center instead of the stereotypical police blinkers.
  • -
-

monster860 updated:

-
    -
  • Space pod transitions are now fixed.
  • -
- -

07 March 2016

-

Crazylemon64 updated:

-
    -
  • People with VAREDIT can now write matrix variables
  • -
  • People with VAREDIT can now modify path variables
  • -
  • Refactors the variable editor code somewhat.
  • -
  • The buildmode area tool now shows reticules of what you've selected.
  • -
  • Switching mobs while using the buildmode tool no longer screws up your UI.
  • -
  • Refactors buildmode so it's no longer a special-case system.
  • -
  • Adds a copy mode to build mode, which lets you duplicate objects.
  • -
  • Any mob in buildmode can work at the fastest possible rate.
  • -
  • Fixed a problem where the icons of a person would not correctly update when changing gender.
  • -
  • One's hairstyle only adjusts on gender change if it's incompatible with your new gender.
  • -
  • Fixed a bug where a person's icon would only be updated if their sprite had a new layer added or removed.
  • -
  • You no longer lose your name when monkeyized and reverted - you'll still look like a monkey while you're a monkey, though.
  • -
  • Your organs will now match your gender when you are cloned.
  • -
  • Skeletons (when a body rots) no longer retain a fleshy torso.
  • -
  • Putting people in an active cryotube now produces the message on insertion, rather than release.
  • -
  • An EMP'd cloning pod will now display its sprites correctly.
  • -
-

FalseIncarnate updated:

-
    -
  • Water Balloons can be filled from more sources than just beakers and watertanks.
  • -
-

Fox McCloud updated:

-
    -
  • Fixes the "yeah" glasses so the sound doesn't vary and a message is displayed, on use
  • -
  • Noir mode only activates when the glasses are equipped to your actual eyes
  • -
  • Noir Glasses mode can be toggled on or off (defaults to off)
  • -
  • Mimes can no longer use spells and continue speaking
  • -
  • Mime abilities are now spells with proper icons
  • -
  • Mime wall now last 30 seconds, up from 5
  • -
  • forecfields/invisible walls now block air currents
  • -
  • Adds the Sleeping Carp scroll to the uplink for 17 TC
  • -
  • Fixes Shadowlings being able to use guns
  • -
  • Fixes sleeping carp scroll users being able to use guns
  • -
  • Fixes the Experimentor throwing one item at a time
  • -
  • Experimentor menu now automatically refreshes after use
  • -
  • Lowers surgery times across the board
  • -
  • Removes scalpels causing 1 damage on successful surgery
  • -
  • Removes random chance to fracture ribs on a successful surgery
  • -
  • Mining drills now have an edge
  • -
-

KasparoVy updated:

-
    -
  • Jackets who have the verb available but are not intended to be adjusted will not have the action button available.
  • -
  • You can now adjust breath masks while buckled into beds and chairs.
  • -
  • Known issues with adjusted jackets using the wrong sprites.
  • -
  • Blueshield coat in hand and item icons.
  • -
  • Hulks now rip apart adjustable and droppable jackets. The items stored in the jackets get dropped on the ground.
  • -
-

Tastyfish updated:

-
    -
  • Infrared emitters can now be rotated while already in an assembly via the UI popup.
  • -
  • The infrared emitter can no longer be hidden inside of boxes and still work.
  • -
  • The beach now has a border and is splashier.
  • -
  • Gives Psychiatrist a paper bin, clipboard, and multicolored pen.
  • -
  • Gives the Librarian / Jouralist a multicolored pen.
  • -
  • Gives the NT Representative a clipboard.
  • -
  • The ethanol-based neurotoxin drink is now called Neuro-toxin to avoid being confused with the deadly toxin.
  • -
-

VampyrBytes updated:

-
    -
  • Fixes emotes ending with s needing 2. Emotes now work with grammatical options eg ping or pings, squish or squishes
  • -
  • Updated emote help with missing emotes. Help will also show any species specific emotes for your current species
  • -
- -

26 February 2016

-

FalseIncarnate updated:

-
    -
  • Chocolate can now make you fat, as expected.
  • -
-

Fox McCloud updated:

-
    -
  • stamina damage now regenerates slightly faster
  • -
  • Adds in whetstones for sharpening objects
  • -
  • Kitchen vendor starts off with 5 salt+pepper shakers
  • -
  • Can now point while lying or buckled
  • -
  • Fixes Capulettium Plus not silencing
  • -
  • Fixes slurring, stuttering, drugginess, and silences last half of what they should
  • -
-

KasparoVy updated:

-
    -
  • Jackets that start open are recognized as actually being open already now. This fixes a bug with certain items that don't have an open state, or cases where it ended up giving an item the wrong icon (one that didn't exist)
  • -
-

Spacemanspark updated:

-
    -
  • Fixes synthetics from giving off the proper message in the chat box when using the *yes and *no emotes.
  • -
-

Tastyfish updated:

-
    -
  • Wheelchairs, janicarts, and ambulances can now go through doors according to the user's driver's access.
  • -
- -

24 February 2016

-

Crazylemon64 updated:

-
    -
  • The defib should be more reliable on people who have ghosted
  • -
  • The defib will now give a message if the ghost is still haunting about
  • -
  • Attacking someone with an accessory will now let you put things on them without having to strip them.
  • -
  • Borers will now properly detach upon death of a mob they are controlling
  • -
  • Borers can now see their chemical count while in control of a mob
  • -
  • Borers can now silently communicate with their host - this is not available to the host until the borer has either begun to communicate, or has taken control at least once - this is to avoid spoiling that the borer exists
  • -
  • Borers won't be able to talk out loud inside of a host, by default - they can remove this safeguard with a verb under their borer tab. Borer hivespeak is unaffected.
  • -
  • Borers infesting and hiding are now silent.
  • -
  • Made borer's chem lists more nicely formatted
  • -
  • No more superspeed attacking simplemobs
  • -
  • New players now show up properly under the "who" verb when used as an admin
  • -
  • Mining drones will now automatically collect sand lying around
  • -
  • RIPLEYs can now drill asteroid turfs for sand
  • -
  • You can now load exosuit fuel generators with items containing their material - this means you can fuel yourself off of ores, but this will be highly inefficient and cost you mining points later on, as you can't take fuel back out.
  • -
  • You can now load the fuel generators from an ore box.
  • -
  • The plasma generator now produces 3x as much power from the same amount of fuel - this lets it even remotely compete with the uranium generator.
  • -
  • You can now light cigarettes off of burning mobs.
  • -
  • Exosuit tracking beacons now fit in boxes - prior, they were far too large for even a backpack, as they shared the same size as all other mecha equipment
  • -
  • Miners can now collect ore by walking over it with an ore satchel on.
  • -
-

FalseIncarnate updated:

-
    -
  • Adds prize tickets as a replacement for physical arcade prizes.
  • -
  • Adds a buildable prize counter to exchange tickets for prizes.
  • -
  • Adds a bike. Despite what Prof. Oak might claim, you can ride it indoors.
  • -
  • Adds colorful wallets, for that old school arcade pride.
  • -
  • Fixes accidental removal of plump helmet biscuit recipe.
  • -
  • Temporarily adds a prize counter to the bar (Cyberiad) or dorms (MetaStation), and adds a max upgrade one to the Ninja Holding Area (Cyberiad z2)
  • -
  • Fixes Metastation. Seriously fixed a lot, just read the PR description for the full list.
  • -
-

FlattestGuitar updated:

-
    -
  • Adds IPC alcohol and a few derivative drinks
  • -
  • IPCs can now drink and be fed from glasses
  • -
-

Fox McCloud updated:

-
    -
  • Laser eyes mutation no longer drains nutrition
  • -
  • splits the EMP kit into two things: the standard EMP kit (2 grenades and an implant), and the EMP flashlight by itself
  • -
  • nerfs heart attacks so they do less damage
  • -
  • Pickpocket gloves now put the item you strip into your hands as opposed to the floor
  • -
  • Picketpocket gloves can now silently strip accessories
  • -
  • Pickpocket gloves will no longer give a message for messing up a pickpocket
  • -
-

KasparoVy updated:

-
    -
  • Adjusting masks while they are not on the face will no longer turn off internals.
  • -
  • Adjusting masks while they are not on the face will now cause the mask to hide/reveal the wearer's identity the next time it's worn as intended.
  • -
  • Adds the ability to open/close bomber jackets.
  • -
  • Adds a security bomber jacket. This jacket inherits the protection and storage capabilities as a standard Security vest with additional bomber jacket benefits.
  • -
  • Adds UI button in top left of screen for jacket adjustment.
  • -
  • Replaces the standard bomber jacket in the Pod Pilot bay with the Security version.
  • -
  • Centralizes jacket/coat adjustment handling.
  • -
  • All jackets start closed by default.
  • -
  • Geneticist duffelbag on-mob sprite (for all species).
  • -
  • Vox-fitted backpacks, satchels, ERT backpacks, duffelbags and defib unit.
  • -
  • Refactors back-item icon generation.
  • -
  • Typo in the description of Santa's sack.
  • -
  • Missing punctuation and gender macros in the description of the bag of holding.
  • -
  • The tweak to back-icon generation fixes a bug where the wrong sprite name was being used to generate back-item icons.
  • -
-

PPI updated:

-
    -
  • Adds the ability to hide papers in vents. You can now leave a romantic love letter, exchange information in secret, or hide papers infused with the power of nar'sie from sight.
  • -
-

Regen1 updated:

-
    -
  • Adds the Immolator laser gun, a modified laser gun with 8 shots that will ignite mobs, can be made in R&D
  • -
-

Spacemanspark updated:

-
    -
  • Adds *yes and *no emotes to Synthetics. Glory to Synthetica.
  • -
-

Tastyfish updated:

-
    -
  • The PDA system has been completely redone behind the scenes! It should be functionally similar, although there is now a Home and Back button at the bottom as appropriate.
  • -
  • All of the heads now have multicolored pens.
  • -
  • EngiVend now has 10 camera assemblies.
  • -
  • Borgs can now use vending machines.
  • -
  • There are now picture frames that can be made from the autolathe or wood planks for papers, photos, posters, and canvases!
  • -
-

pinatacolada updated:

-
    -
  • Makes the Protect Station AI law board no longer consider people that damage the station crew, instead of human
  • -
-

ppi updated:

-
    -
  • When revealed Revenants will not be able to move at the maximum move speed, nor be able to pass through any solid object, like walls, windows, grills, computers and mechs.
  • -
- -

13 February 2016

-

Crazylemon64 updated:

-
    -
  • Relaxes the check on what atoms you can follow to any movable atom
  • -
  • Mages are now more ragin
  • -
  • Admins can now adjust the total number of wizards at runtime by tweaking either max_mages, or players_per mage
  • -
-

DaveTheHeadcrab updated:

-
    -
  • Adds new worn icons for duffelbags to better reflect their size, compliments of WJohn at /tg/
  • -
-

FalseIncarnate updated:

-
    -
  • Adds burritos, made from cutlets, beans, rice, capsacin oil (hotsauce), cheese, and flat dough (because we lack proper tortillas) in the microwave.
  • -
  • Adds chimichangas. You know you want a deep-fried burrito.
  • -
-

Fox McCloud updated:

-
    -
  • Updates some spell icons with better/higher quality icons
  • -
  • Updates unarmed attacks to allow for more customization
  • -
  • Updates martial arts so they factor in specie's attack messages and sounds
  • -
  • Re-balances Sleeping Carp fighting style
  • -
  • Re-balances Bo Staff
  • -
  • Rebalances Golem: they should now be spaceproof, fire+cold proof, rad proof, virus immune, clonable, parapen+syringe gun immune, deal increased melee damage. Their armor has been reduced to 55 melee across the board, their slip immunity removed, pain immunity removed, and they're slightly slower
  • -
  • Fixes Ei Nath generating two brains
  • -
  • Ensures the Necromatic Stone generates actual skeletons
  • -
  • Can now strip PDA/IDs from Golems
  • -
  • Fixes sleeping carp grab not being an instant aggressive grab
  • -
  • Fixes an exploit with declaring war on the station
  • -
-

KasparoVy updated:

-
    -
  • Orange and purple bandanas for all station species.
  • -
  • The ability to colour bandanas with a crayon in a washing machine.
  • -
  • Refactors the bandana adjustment system.
  • -
  • Minor adjustments to Tajaran and Unathi bandana east/west sprites.
  • -
  • Adjusting a bandana will now take if off of your head/face and put it in an available hand. If both hands are available, it goes in the selected hand.
  • -
  • Adjusting a coloured bandana will no longer revert it to the original coloured icons anymore.
  • -
  • Adjusting a bandana from mask-style to hat-style means the bandana won't obscure your identity anymore.
  • -
  • Greys now use re-positioned smokeables. They no longer smoke out the eyes.
  • -
-

TheDZD updated:

-
    -
  • Fixes spacepods being able to shoot through walls.
  • -
  • Lowers spacepod weapons fire delay.
  • -
  • Increases spacepod weapons energy costs.
  • -
  • Makes spacepods move at speeds not rivaling those of photon beams. They are now a hair bit faster than a person with a jetpack.
  • -
  • Reduces battery costs for spacepod movement.
  • -
- -

10 February 2016

-

Crazylemon64 updated:

-
    -
  • The cloner now checks for NO_SCAN on the brain when scanning - unclonable species are now truly unclonable. You are still able to revive them with a brain transplant and a defib, however.
  • -
  • A tier-4 DNA scanner linked to a cloning system will now be able to reproduce a body from a brain's DNA, in event of the original corpse being gibbed or similar.
  • -
  • Species with organic limbs and NO_BLOOD will no longer bleed (though still on hit - write that off as "bone powder")
  • -
  • Skeletons now lack internal organs, except for the runic mind which exists in their head - an analogue for the brain
  • -
  • Skeletons that drink milk will be regenerated at a moderate pace, have a small chance of mending bones, and will praise the great name of mr skeltal
  • -
  • Adds a reagent system for species reacting to specific reagents
  • -
  • Slime People can now select from all human hairstyles, and their "hair" will be tinted a shade of their body.
  • -
  • Increases the frequency of the cortical borer event.
  • -
  • People with borers cannot commit suicide - this applies to a controlling borer, too.
  • -
  • Borers can no longer overdose their hosts.
  • -
  • Borers can now inject Saline-Glucose, Spaceacillin, Hydrocodone, Mitocholide, Salbutamol, Capulettium+, and Charcoal. Styptic was removed, as it's pathetic at healing when directly injected. Salicyclic acid was removed too, as its functionality is duplicated by both hydrocodone and saline-glucose.
  • -
  • A mind trapped by a cortical borer can now understand things it could understand when normally in its body.
  • -
  • Changes chemistry's welding tank to a wall-mounted version, to increase the room available.
  • -
  • You can now gib butterflies and lizards with a knife
  • -
  • Ghosts can now follow mecha
  • -
  • You can now access an R&D console by emagging it - it did nothing before.
  • -
  • Walls will now properly smooth and show damage.
  • -
  • Fixes the dialog that occurs when the AI shuts off to actually do what it says it does
  • -
-

Fox McCloud updated:

-
    -
  • Fixes not being able to attach IEDs to beartraps
  • -
  • Can no longer spamclick someone to death using headslamming on a toilet/urimal
  • -
  • Toilet/urinal headslamming now plays a sound
  • -
  • Toilet headslamming damage reduced slightly
  • -
  • Can now fill open reagent containers in a toilet to receive "toilet water".
  • -
  • No more message spam when someone fills a container using a sink
  • -
  • Can now wash your face using a sink, which washes away lipstick and wakes you up slightly
  • -
  • Washing things will now use progress bars
  • -
  • Ensures consuming a single syndicate donk pocket won't get you addicted to meth
  • -
  • Kinetic Accelerators and E-bows automatically reload
  • -
-

Glorken updated:

-
    -
  • Added a Knight Arena for Holodeck.
  • -
  • Added red and blue claymore sprites.
  • -
  • Changed overrided to overrode when emagging Holodeck computer.
  • -
-

KasparoVy updated:

-
    -
  • Vox versions of the Officer SWAT sechailer + HOS SWAT sechailer + Warden SWAT sechailer.
  • -
  • Resprited versions of most Human masks to fit Unathi, Tajara and Vulpkanin.
  • -
  • Warden now gets their own version of the SWAT sechailer in their locker.
  • -
  • HOS now gets the appropriate version of the SWAT sechailer in their locker.
  • -
  • Repositioned smokeables now available for Vox, Unathi, Tajara and Vulpkanin.
  • -
  • Properly shades Vox bandana down-state sprites.
  • -
  • Readds Tajaran bald hairstyle.
  • -
  • Alternate style of non-Human breath mask (incl. surgical/sterile mask) down-state positioning.
  • -
  • Corrects all non-Human species' breath mask (incl. surgical/sterile mask) down-state icons to use the right position style.
  • -
  • Minor adjustments to Tajaran breath mask up-state sprites.
  • -
-

PPI updated:

-
    -
  • Adds a reconnect button to the File menu in the client.
  • -
  • Adds head patting
  • -
-

Regen updated:

-
    -
  • Powersink can now drain a lot more power before going boom
  • -
  • Buffed the powersinks drain rate
  • -
  • Buffed explosion from an overloaded powersink, try to find it instead of overloading the grid.
  • -
  • Admin log warning before the powersink explodes
  • -
-

Spacemanspark updated:

-
    -
  • Miners can now utilize the power of mob capsules to take along their lazarus injected mining creatures!
  • -
  • Store your Pokemo- er, sorry, I mean mining mobs that you've captured in the lazarus capsule belt.
  • -
-

Tastyfish updated:

-
    -
  • Species that don't breathe can kill themselves now!
  • -
  • Suicide messages are now catered to your species.
  • -
  • Shortened the default pill & patch name when using the ChemMaster.
  • -
  • The chaplain now has a service radio headset, as Space Jesus intended.
  • -
-

TheDZD updated:

-
    -
  • When Ahelping, "Question" is now "Mentorhelp" and "Player Complaint" is now "Adminhelp."
  • -
  • Mentorhelps and PM replies from mentors appear in a bold aqua blue color.
  • -
  • Adminhelps and PM replies from admins appear in a bold bright red color.
  • -
  • PM replies from players appear in a dull/dark purple color.
  • -
  • Adds admin attack log to players being converted to cult.
  • -
  • Adds shadowling thrall jobbans.
  • -
  • Jobbanned players who are converted to shadowling thrall, revolutionary, or cultist will have the control of their body offered up to eligible ghosts.
  • -
- -

31 January 2016

-

Crazylemon64 updated:

-
    -
  • Syndicate borgs can now interact with station machinery
  • -
  • People with slime people limbs can now *squish
  • -
  • Skrell's vulnerability to alcohol is checked on their liver, now - a liver transplant will let them take alcohol like a champ - lacking a liver will have the same effect as being a skrell, when drinking
  • -
-

FalseIncarnate updated:

-
    -
  • Adds in the Magic Eight Ball toy, found in Claw Game prize orbs.
  • -
  • Adds in the Magic Conch Shell, an admin-only shell of power.
  • -
-

Fox McCloud updated:

-
    -
  • Updates Summon Guns and Magic to include many of the new guns
  • -
  • Summon Guns/Magic can no longer be used during Ragin' Mages
  • -
-

Tastyfish updated:

-
    -
  • The emergency shuttle status in the Status tab now has ETA/ETD/etc like before.
  • -
  • Code Gamma+ now has a 5 minute emergency shuttle call, like Red.
  • -
-

pinatacolada updated:

-
    -
  • Adds NanoUI to the operating computer
  • -
  • Adds health announcing, critical and oxygen damage aural alerts to the computer, with a menu to selectively turn them on and off
  • -
- -

29 January 2016

-

Crazylemon updated:

-
    -
  • The DNA scanner has now undergone a seminar to recognize fake identities; It will now scan the actual person's identity, rather than their disguise (read: wearing a mask with or without someone else's ID).
  • -
  • Matter eater now allows you to eat humans as if you were fat.
  • -
  • Eating mobs with an aggressive grab now generates attack logs.
  • -
-

Crazylemon64 updated:

-
    -
  • For a short while, there was a clerical error where all AI communications equipment was replaced with bananas. This has now been fixed.
  • -
  • Ghosts can now see the contents of smartfridges and look at the drone console
  • -
  • Humans now only produce one message when shaken while SSD
  • -
  • The supermatter no longer will irradiate everyone, everywhere, when it explodes.
  • -
  • Writing on paper will now add hidden admin fingerprints, so that you can't forge mean notes in someone else's name.
  • -
  • Brains are no longer able to escape their brain by being a sorcerer.
  • -
  • Astral projecting with other runes on the same tile will now no longer prevent you from re-entering
  • -
  • Voxxy that is become ex-voxxy no longer carry voxxy appearance! yaya!
  • -
-

FalseIncarnate updated:

-
    -
  • Allows plants to be identified as enhanced*. Enhancing plants results from using reagents (like saltpetre) that affect the stats of a seed instead of using mutagens/machines. *May not meet standards for being classified as "organic produce". (This was already possible, just renames enhanced plants for easier differentiation)
  • -
-

Fox McCloud updated:

-
    -
  • Fixes mutadone not working with some genetic mutations
  • -
  • Fixes banana honk and silencer being alcoholic
  • -
  • Fixes Kahlua being non-alcoholic
  • -
  • Fixes polonium not metabolizing
  • -
  • Fixes being able to receive free unlimited boxes from the Merchandise store
  • -
  • Adds in wooden bucklers
  • -
  • Re-adds roman shield to the costume vendor
  • -
  • Buffs Riot shield damage from 8 to 10
  • -
  • Adds in a Skeleton race
  • -
  • Tweaks the skeletons colors to be more realistic and to blend in less with the floor
  • -
  • Adds in lichdom spell for the wizard
  • -
  • Adds in lesser summon guns spell for wizard
  • -
  • adds in Mjolnir and the singularity hammer as weapons the wizard can purchase
  • -
  • Wizard can purchase the charge spell from the spell book
  • -
  • Wizard can purchase a healing staff from the spell book
  • -
  • Tweaks and lowers spell costs of utility spells for wizard
  • -
  • Re-organizes the spellbook to be better divided into categories and have a better window size
  • -
  • Knock now opens+unlocks lockers
  • -
  • Magic Missile has a slightly longer cooldown and no longer deals damage, but has a lower cooldown is upgraded
  • -
-

KasparoVy updated:

-
    -
  • Navy blue Centcom Officer's beret for use by the Blueshield.
  • -
  • Adds the new navy blue beret to the Blueshield's locker.
  • -
  • Gives the Blueshield's berets (black and navy blue) the exact same strip delay and armour as the Security Officer's beret.
  • -
  • Adds TG energy katana back and belt sprite.
  • -
  • Bo staff back sprite.
  • -
  • Adjusts energy katana sprites to make the weapon stand out a bit more from the regular katana.
  • -
  • Cutting open the toes of footwear so species with feet-claws can wear them.
  • -
  • Toeless jackboots.
  • -
  • Cleans up glovesnipping and lighting a match with a shoe.
  • -
  • Lighting a match with a shoe produces a more appropriate message, handled at the same standard as glove-snippingboot-cutting.
  • -
-

Tastyfish updated:

-
    -
  • Cargonia now has its own section in the manifest.
  • -
-

TheDZD updated:

-
    -
  • Due to budget cuts and reports of operatives accidentally firing enough bullets to reach a state of what our scientists refer to as "enough dakka," Syndicate High Command has decided to restore the Syndicate Strike Team arsenal to using standard-issue L6 SAW ammunition.
  • -
- -

24 January 2016

-

KasparoVy updated:

-
    -
  • Fixes markings overlaying underwear.
  • -
  • Nude icon in underwear.dmi
  • -
  • Fixes Vox robes not using the correct on-mob sprites.
  • -
  • Fixes unreported bug where there was a slim chance during character preview icon generation that a character with Security Officer set to high would get rendered with either the wrong beret sprite or no beret sprite at all.
  • -
  • Fixes an issue where Sigholt's fluff beret wasn't using the correct sprites.
  • -
-

Tastyfish updated:

-
    -
  • Passively power-consuming borg modules, such as the peacekeeper movement and shield module, won't spam the user infinitely if they're low on power anymore.
  • -
- -

23 January 2016

-

Fox McCloud updated:

-
    -
  • Removes Vampire HUD
  • -
  • moves the Vampire blood counter to a more easy to see location
  • -
  • Adds in a Changeling chemical counter display
  • -
  • Adds in a Changeling sting counter display
  • -
  • Vampire total blood and usable blood will now appear under status
  • -
  • Changes vampire blood display to be similar to ling chemical counter
  • -
  • Fixes unnecessary toxin damage being dealt on severe bloodloss
  • -
  • Fixes human mobs not receiving proper random names
  • -
  • Adds in knight armor
  • -
  • Grants the chaplain a set of crusader knight armor
  • -
  • Adds in cult-resistant ERT paranormal space suit
  • -
  • Allows the Chaplain to convert his null rod into a holy sword with crusader knight armor
  • -
  • Chaplain's closet is now a secure closet
  • -
  • Adds in Assault Gear crate to cargo
  • -
  • Adds in military assault belt
  • -
  • Adds in spaceworthy swat suits
  • -
  • tweaks bandolier to hold 2 additional shotgun shells
  • -
  • bartender starts off with +2 additional shells
  • -
  • Reduces the cost of the space suit crate and doubles its contents
  • -
  • Refactors knives so their behavior is more universal
  • -
  • Fixes Hulk not properly being removed when your health drops below a threshold
  • -
  • Fixes flickering vision in a mining mech
  • -
-

Tastyfish updated:

-
    -
  • Poly has taken a seminar on the latest trends in engine operations.
  • -
  • Player-controller parrots can now hear their headsets.
  • -
-

Tigerbat2000 updated:

-
    -
  • The nuclear disk escaping on the shuttle no longer counts as a syndicate minor victory.
  • -
  • Cultists can once again actually greentext the escape objective.
  • -
- -

20 January 2016

-

DarkPyrolord updated:

-
    -
  • Adds in hardsuit sprites for Vulpkanin
  • -
-

FalseIncarnate updated:

-
    -
  • Allowed cheap lighters and individual matches to be put into cigarette packages at the cost of cigarette space.
  • -
  • Matches can now be lit and put out by striking the match on your shoes. Good for if you lose that matchbox, or want to just feel cool.
  • -
-

Fox McCloud updated:

-
    -
  • Fixes brute damage on weapons not knocking people down.
  • -
  • Tweaks implant behavior to be more consistent and unified.
  • -
  • Lowers the pAI cooldown from 60 seconds to 5 seconds.
  • -
  • Raw telecrystal can now be used to charge uplink implants.
  • -
  • Fixes being unable to holster the pulse pistol
  • -
  • Fixes being able to holster shotguns
  • -
-

KasparoVy updated:

-
    -
  • Improved shading on all Vulpkanin hardsuit tails.
  • -
  • Vulpkanin hardsuit helmet respriting (colour tweaks).
  • -
  • Vulpkanin hardsuit helmets with proper flashlight-on sprites.
  • -
-

Tastyfish updated:

-
    -
  • The ID computer Access Report printout now separates the access list with commas so it's actually readable.
  • -
  • The ID computer Access Report printout isn't blank if you don't have an authorization card in anymore.
  • -
  • In the supply ordering & shuttle consoles, one can now cancel an order at either the Reason or Amount input dialogs.
  • -
  • Table flipping uses correct sprites.
  • -
-

TheDZD updated:

-
    -
  • Adds world.Topic() handling so that users are notified in-game when pull requests are opened, closed, or merged on the Github repo.
  • -
- -

18 January 2016

-

Crazylemon updated:

-
    -
  • New classes of shapeshifters have been sighted around the NSS Cyberiad...
  • -
  • Wizards now can't teleport to other antag spawn points.
  • -
  • Removes an extruding pixel from the left-facing IPC glider monitor sprite.
  • -
  • Ragin' Mages now spawn every 7 minutes, instead of 5. Admins can further adjust this by modifying the 'delay_per_mage' variable.
  • -
  • Ragin' Mages are now made with 100% less in-use souls (Apprentices won't have their consciousness yoinked).
  • -
  • It takes half an hour for the REAL chaos of ragin' mages to start, for at least a semblance of normality.
  • -
-

Dave The Headcrab updated:

-
    -
  • Adds the advanced energy revolver, toggles between taser and laser modes.
  • -
  • Removes the detective's revolver from the blueshield's locker.
  • -
  • Changes the taser the blueshield starts with into an advanced energy revolver.
  • -
-

Deanthelis updated:

-
    -
  • Added the ability for the Magnetic Gripper to pick up and place light tiles.
  • -
-

Fethas updated:

-
    -
  • Readds the hud icon showing up for master and servent
  • -
  • adds mindslave datum hud thingy based on TGs gang huds
  • -
-

Fox McCloud updated:

-
    -
  • Fixes not being able to add/remove Weapon Permit from IDs.
  • -
  • Fixes the energy sword being invisible in-hand when turned on.
  • -
  • Fixes the telebaton being invisible in-hand when extended.
  • -
  • Fixes eye-stabbing not having an attack animation or hitsound.
  • -
  • Fixes some kitchen utensils playing the wrong hit-sound and playing twice in some cases.
  • -
  • Fixes the butcher cleaver sprite being backwards.
  • -
  • Fixes the telebaton sprite being missing from the side.
  • -
  • Fixes the meat cleaver being invisible in-hand.
  • -
  • Corrects some grammatical descriptive errors for the elite syndicate hardsuit.
  • -
  • completely overhauls implants to TG's standards.
  • -
  • Adds storage implant.
  • -
  • Adds microbomb and macrobomb implants.
  • -
  • Adds in support for removing implants directly into cases.
  • -
  • Removes Bay style explosive implants.
  • -
  • Removes compressed matter implants.
  • -
  • Tweaks the uplink to reflect removal of the old implants and inclusion of the new.
  • -
  • Fixes/cuts down on the lag caused by monkey cubes.
  • -
-

Jey updated:

-
    -
  • Inflatable walls and door can now be deflated by altclicking them
  • -
  • Fixed lag from expanding multiple monkeycubes at once.
  • -
-

KasparoVy updated:

-
    -
  • Adds blank icons with standardized timings for species tail wagging, used in icon generation.
  • -
  • Fixes tails overlapping arms/limbs + gloves, etc. when facing EAST or WEST.
  • -
  • Ensures tails will overlap stuff as normal only when facing NORTH so as to avoid unwanted interference with the base sprite.
  • -
  • Tails now appear in ID cards, overlays things correctly.
  • -
  • Tails now overlay and are overlaid by things correctly in preview icons.
  • -
  • Modifies the positioning of tail icon generation in the ID card preview icon generation file.
  • -
  • Modifies the positioning of tail icon generation in the player preferences preview icon generation file.
  • -
  • Breaks limb generation into its own layer, breaks tail generation into a second layer that can be overlaid by limbs.
  • -
  • If the user's species is flagged to have a tail that is overlapped, TAIL_LAYER will now overlay the NORTH direction sprite of a tail now, while TAIL_UNDERLIMBS_LAYER gets all remaining directions. Otherwise icons are generated in the traditional manner.
  • -
  • Adjusts the Unathi right arm east direction and animated tail sprites, recolouring a random pixel and fixing a floating tail respectively.
  • -
  • Adjusts position of tail layer such that tails' north direction sprites will overlay backpacks (more importantly, satchel straps).
  • -
  • Accommodates admin-overrides to the body_accessory species check by setting the default animation template to Vulpkanin.
  • -
  • Adjusts north-direction Unathi static tail sprite, now attaches to the body in the correct location.
  • -
  • Adds some TG underwear.
  • -
  • Adds an NV science goggles worn sprite.
  • -
  • Ports Bay/TG berets.
  • -
  • Adjusts beret sprite, recolours strange orange pixels.
  • -
  • Adjusts NV science goggles object icon. Removed strange border and centered it.
  • -
  • Ports Polaris' PRs 761 and 778, brings over Ragnie's awesome Ward-Takahashi prosthetics.
  • -
-

Kyep updated:

-
    -
  • Changing level to gamma/delta/epsilon now displays a special gamma/delta/epsilon sprite on status monitors
  • -
  • Changing level to green/blue now clears the status monitors, so they no longer show higher alert levels after the level is changed
  • -
-

NTSAM updated:

-
    -
  • Added a rainbow IPC screen.
  • -
-

PPI updated:

-
    -
  • Modifies the effective time limit to activate the Nuclear Challenge as Nukeops from two minutes to seven minutes
  • -
-

Tastyfish updated:

-
    -
  • The QM now actually has a QM stamp instead of a fake one, as well as an approved and denied stamp.
  • -
  • New area named 'Genetics Maintenance' solidifying/relabelling the confusing area between the morge and Mech Bay as being fully maintenance again, but working correctly and with proper doors.
  • -
  • Fixed a few maintenance door names to be in parity to the rest of the station.
  • -
  • Added the ability to print the records photo of a crew member from a security records console. Useful for Wanted notices!
  • -
-

Tigercat2000 updated:

-
    -
  • You can no longer use the gibber for monkies.
  • -
  • Cleaned up gibber.dm styling.
  • -
  • The fire alarm now uses NanoUI, with color coded alert levels.
  • -
  • Upgraded NanoUI (again), fancy FontAwesome icons.
  • -
  • Didn't add any butts. Yet.
  • -
- -

13 January 2016

-

Fox McCloud updated:

-
    -
  • Fixes Rezadone not clearing mutated organs.
  • -
  • Clone damage immunity removed from Slime People, Shadowlings, Golems, and Vox
  • -
  • Explosions will no longer destroy things underneath turfs until the turf is exposed.
  • -
  • fixes a runtime related to revolver spinning.
  • -
  • fixes server loading taking an abnormally long time.
  • -
-

Kyep updated:

-
    -
  • Blob, vine and virus outbreaks are now more clearly labeled as such, to avoid people confusing them with each other
  • -
-

Tastyfish updated:

-
    -
  • NT Rep fountain pens and magistrate gold pens can now write in 5 different colors. The IAA gets a cheap plastic equivalent.
  • -
- -

11 January 2016

-

CrAzYPiLoT updated:

-
    -
  • Fixes the footsteps sounds to the fullest.
  • -
-

Crazylemon updated:

-
    -
  • Bomb guardians now automatically notify their master when they've set something to boom, so there's less accidental friendly fire
  • -
  • Bomb guardians are only notified that their trap failed, if it ACTUALLY FAILED.
  • -
  • Bomb guardians now are more aware of what is primed to explode.
  • -
  • Bomb guardian summoners can now defuse their guardian's bombs without harm.
  • -
  • Brought RAGIN' MAGES back up to function.
  • -
-

Dave The Headcrab updated:

-
    -
  • Added a new icon for the soy and cafe latte drinks. Icons courtesy of Full Of Skittles, resident overlord of art.
  • -
-

Fox McCloud updated:

-
    -
  • Re-arranges the armory and changes its contents minorly.
  • -
  • Adds in rubbershot ammo boxes.
  • -
  • Fixes Mutadone incurring a massive cost on the server.
  • -
  • Positronic brains can no longer speak binary.
  • -
  • Positronic brains can be prevented from speaking (or allowed) by toggling their speaker on/off.
  • -
  • IPC's positronic brains start off toggled off.
  • -
  • Fixes the supermatter announcement causing massive amounts of server lag.
  • -
  • Adds in tradable telecrystals.
  • -
- -

08 January 2016

-

Crazylemon updated:

-
    -
  • Fully enables a system to allow species to have unique procs and verbs that come and go with the species.
  • -
  • IPCs lose their change monitor verb when changing species now. Gone are the days of recalling a past IPC life to perform self-barbery! Oh, woe is me!
  • -
  • Sleepers and Body Scanners will now reliably work when rotated
  • -
  • SSD humans should be asleep more reliably now.
  • -
-

Dave The Headcrab updated:

-
    -
  • Nerfs the damage the Detective's revolver does from 15 brute to 5 brute.
  • -
  • Adds a 300 round capacity buckshot magizine that fits into the L6 Saw.
  • -
  • Adds a 25 round capacity 40mm HE magizine that fits into the L6 Saw.
  • -
  • Adds the 'Devastator' L6 SAW, starts off loaded with the buckshot magizine.
  • -
  • Gives the SST the 'Devastator' L6 Saw, and one of each mag type in their bag.
  • -
-

FalseIncarnate updated:

-
    -
  • Plants will now begin to die over time if their age exceeds 5 times their TRAIT_MATURATION value.
  • -
  • Weed growth chance per process in trays has been slightly increased (Previously: 5% chance if no seed, 1% otherwise;Now: 6% / 3%).
  • -
  • Pest growth in trays has been slightly buffed. (Previously: 3% chance to increase by 0.1; Now: 5% chance to increase by 0.5)
  • -
-

Fethas updated:

-
    -
  • Due to Archmage Steve leaving the nya-cromantic stone near the microwave, the true power of the stone has been unleashed. Subjects of the stone are not only ressurected ... but resurrected as catgirls ... We fired steve.
  • -
-

Fox McCloud updated:

-
    -
  • fixes a bug relating to some brute/burn damage being dealt to human mobs.
  • -
  • Adds in overloading APCs, causing them to arc electricity to mobs in range.
  • -
  • Makes Engineering related APCs overload proof.
  • -
  • Implements the timestop spell.
  • -
  • Implements new sepia slime reaction which halts time in an AoE.
  • -
  • sentience potions no longer can make slimes sentient.
  • -
  • Removes Hulk instant stun.
  • -
  • Hulk damage increased.
  • -
  • Hulk wears off at a lower health threshold.
  • -
  • Fixes strange reagent not working on simple animals.
  • -
  • Reduces the amount shock damage and bounces for the Tesla engine.
  • -
  • Fixes Syndicate Cyborg's LMG being invisible.
  • -
  • Fixes the uplink kit having implanters that were both nameless and looked as if they had been used.
  • -
-

KasparoVy updated:

-
    -
  • Added the security gasmask, sexy mime mask, bandanas, balaclava, welding gas mask and wrestling masks for Vox. Added adjusted-state sprites for the Vox breath, medical, and surgical masks.
  • -
  • Removed a duplicate of the human balaclava sprite.
  • -
  • Modifies the Vox plague-doctor, fake moustache, sterile and medical mask sprites to fit the Vox anatomy and animates the Vox SWAT mask. Corrects the names of some Vox mask adjusted-state sprites.
  • -
-

Tastyfish updated:

-
    -
  • Fixed the pronouns in a few verbs and the door to 'Interrogation Observervtion'.
  • -
-

Tigercat2000 updated:

-
    -
  • Added 96x96 (3x) res option to icons menu
  • -
- -

06 January 2016

-

Certhic updated:

-
    -
  • Corrected some air alarms so that atmos computer can access them
  • -
  • Bodyscanner now sees mechanical parts in internal organs
  • -
-

Crazylemon64 updated:

-
    -
  • Sleeping simple animals should tick down sleeping as normal - deaf simple mobs are no longer a thing
  • -
-

Tastyfish updated:

-
    -
  • Instruments now use NanoUI.
  • -
  • Corrected the blueshield mission briefing.
  • -
- -

03 January 2016

-

TheDZD updated:

-
    -
  • Ports over changelog system from /tg/station.
  • -
-
- -GoonStation 13 Development Team -
- Coders: Stuntwaffle, Showtime, Pantaloons, Nannek, Keelin, Exadv1, hobnob, Justicefries, 0staf, sniperchance, AngriestIBM, BrianOBlivion
- Spriters: Supernorn, Haruhi, Stuntwaffle, Pantaloons, Rho, SynthOrange, I Said No
-
-
-

Creative Commons License
Except where otherwise noted, Goon Station 13 is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 License.
Rights are currently extended to SomethingAwful Goons only.

-

Some icons by Yusuke Kamiyamane. All rights reserved. Licensed under a Creative Commons Attribution 3.0 License.

-
- - + + + + Paradise Station Changelog + + + + + + + +
+ + + + +
+
Paradise Station
+ +

+ Visit our IRC channel: #crew on neko.sneeza.me +
+ + + + + +
+ Current Project Maintainers: -Click Here-
+ Currently Active GitHub contributor list: -Click Here-
+ Coders: ZomgPonies, DaveTheHeadcrab, tigercat2000, FalseIncarnate, AuroraBlade, Tastyfish, Crazylemon64, KasparoVy
+ Spriters: FullOfSkittles
+ Sounds:
+ Main Testers: Anyone who has submitted a bug to the issue tracker
+ Thanks to: Baystation 12, /tg/station, /vg/station, NTstation, CDK Station devs, FacepunchStation, GoonStation devs, the original SpaceStation developers and Radithor for the title image.
Also a thanks to anybody who has contributed who is not listed here :( Ask to be added here on irc.
+
Have a bug to report?
Visit our Issue Tracker.
+ Please ensure that the bug has not already been reported and be as descriptive as possible about the circumstances under which the bug occurred. +
+ + +
+

25 April 2016

+

CrAzYPiLoT updated:

+
    +
  • Adds buildable holographic gameboards that, when opened, produce a fully-functional JavaScript chess interface, which includes a chess AI. If you win, it will produce 80 tickets for your spending!
  • +
+

FlattestGuitar updated:

+
    +
  • a human's species is now visible on examination
  • +
+

Fox McCloud updated:

+
    +
  • Improves attack animations with items, making it more clear who's attacking you and with what
  • +
  • Updates Revolution game mode so it better scales with total player population
  • +
  • Head revs start off with a flash, spraycan, and chameleon security HUD
  • +
  • Add chameleon security hud, which is basically sec shades with the ability to disguise as a number of regular glasses
  • +
  • Updates mining loot crates to feature far more actual loot
  • +
  • Mining loot crates are now opened by inputting a 4 digit password and have 10 tries to guess the password string
  • +
  • Fixes bees, mech syringes, and darts not properly calling INGEST for a reagent
  • +
+

Meisaka updated:

+
    +
  • The light on/off function for drones works again, toggling between lowest setting and off.
  • +
  • Guardians can toggle their lights off and on again.
  • +
  • AI, pAI, robots and drones can now use *yes emote without extra ss on the end.
  • +
  • emote *help for silicons updated/added.
  • +
  • *twitch_s emote changed to *twitches, incorrect variations of some emotes can no longer be used.
  • +
+

tigercat2000 updated:

+
    +
  • Added 4 new HUD styles, "Operative", "Plasmafire", "Retro", and "Slimecore"
  • +
  • You can now view HUD changes in real-time, by going to Preferences (top right tab) > Game Preferences and changing the HUD style (limited to humans).
  • +
  • There are now three HUD styles you can get via the f12 button- Full, which contains all of your buttons, Minimal, which only contains a few essential buttons, and None, which is a completely blank screen.
  • +
  • Removed the remaining aiming code due to maintainability issues and incompatibility with HUD styles.
  • +
  • Mobs with HUD's now use a unique subtype instead of an anti-OOP else-if chain.
  • +
  • Refactored how objects (IE, stuff you pick up) is rendered to the HUD. This should fix the reoccuring "stuff on my screen that definately isn't meant to be there" bug, but keep an eye out for things that do not appear.
  • +
+ +

20 April 2016

+

Crazylemon64 updated:

+
    +
  • Bureaucracy crates now contain granted and denied stamps.
  • +
+

FalseIncarnate updated:

+
    +
  • Anomalies will now be properly neutralized by signals that match their code and frequency, instead of using the default frequency and their code.
  • +
+

FlattestGuitar updated:

+
    +
  • Adds shot glasses.
  • +
+

Fox McCloud updated:

+
    +
  • Removes the ability to put a pAI into securitrons and ED-209's
  • +
  • Drinking glasses now have an in-hand sprite
  • +
  • DNA injectors no longer have a delay when used on yourself
  • +
  • DNA injectors no longer delete on use, but become used, much like auto-injectors
  • +
  • Fixes a bug where you can exploit the genetic scanner to get multiple injectors
  • +
  • Fixes not being able to cancel creating an DNA injector
  • +
  • remove spacesuits causing injections to the head to take longer
  • +
  • FIxes heat resist mutation not making you immune to high pressure, fire, or high temperatures
  • +
  • removes some not-well-known damage resists from cold/heat mutations
  • +
  • Re-maps botany a bit to make it more bee and botanist friendly
  • +
  • Adds in Abductors Game Mode
  • +
+

MarsM0nd updated:

+
    +
  • Embeded object removal is now done with hemostat again
  • +
  • Borgs are able to do embeded object surgery
  • +
+

Tastyfish updated:

+
    +
  • Makes the server startup substantially faster.
  • +
+

monster860 updated:

+
    +
  • Crowbarring open a spesspod doors is no longer broken
  • +
+

tigercat2000 updated:

+
    +
  • -tg- thrown alerts have been added. This means you get an alert when buckled or handcuffed or many many other things happen to you. It then gives you a tool tip when you hover over it, and it may or may not do something when you click it. Have fun!
  • +
+ +

14 April 2016

+

Aurorablade updated:

+
    +
  • Removes the !!FUN!! of having headslugs gold core spawnable.
  • +
+

Fox McCloud updated:

+
    +
  • Added in sounds (instead of a chat-based message) for when airlocks are bolted/unbolted
  • +
  • Added in sound for when airlocks deny access
  • +
  • cutting/pulsing wires will play a sound
  • +
  • ups nuke ops game mode population requirement from 20 to 30
  • +
  • Adds in mining drone upgrade modules to increase their health, combat capability, or reduce their ranged cooldowns
  • +
  • Adds in mining drone "AI upgrade" a sentience potion that only works on mining bots
  • +
  • Mining bots should be less likely to shoot you when attacking hostile mobs
  • +
  • Killer tomatoes actually live up to their name now and are hostile mobs
  • +
  • Killer tomatoes are an actual fruit now; activate it in your hands to make them into a mob
  • +
  • Killer tomatoes are directly mutated from regular tomatoes instead of blood tomatoes
  • +
  • Increased the yield of regular tomatoes by 1
  • +
  • Tweak some stats on the killer tomato seeds
  • +
  • Fixes the blind player preference not doing anything
  • +
  • Adds portaseeder to R&D
  • +
  • Scythes will conduct electricity now
  • +
  • Mini hoes play a slice sound instead of bludgeon sound
  • +
  • Plant analyzer properly has a description and origin tech
  • +
  • Can have hulk+dwarf mutations together
  • +
  • Can have heat+cold resist together
  • +
  • Can only remotely view people who also have remote view
  • +
  • Fixes cold mutation not having an overlay
  • +
  • Hallucinations will no longer tick down twice as fast as they should nor will they spawn twice as many hallucinations as they should
  • +
  • Incendiary mitochondria no longer asks who you want to cast it on (it always is meant to be cast on yourself)
  • +
  • Fixes permanent nearsightedness even when wearing prescription glasses
  • +
+

KasparoVy updated:

+
    +
  • Head accessories now behave like facial hair: They will no longer be hidden by clothing items that BLOCKHEADHAIR (have the BLOCKHEADHAIR flag).
  • +
  • Wearing a piece of clothing that blocks head hair will no longer make head accessories (facial markings/horns/antennae) invisible until an icon update is triggered while the headwear is off.
  • +
+

Meisaka updated:

+
    +
  • law manager no longer freaks out with Malf law
  • +
+

Tastyfish updated:

+
    +
  • The /vg/ library computer interface has been ported, giving a much better use experience.
  • +
  • Books can now be flagged for inappropriate content.
  • +
+

TheDZD updated:

+
    +
  • Removes shitty Caelcode bees.
  • +
  • Hydroponics can now manage bee colonies, bees produce honeycombs that can be ground to obtain honey, a decent nutriment+healing chemical
  • +
  • Hydroponics can inject a queen bee with a syringe of a reagent to alter her DNA to match that reagent, meaning all honeycombs produced will contain that reagent in small amounts
  • +
  • Bees with reagents will attack with that reagent. It takes 5u of a reagent to give a bee that reagent.
  • +
  • Added the ability to make Apiaries and Honey frames with wood
  • +
  • Added the ability to make Royal Bee Jelly from 10 Mutagen and 40 Honey
  • +
  • Added the ability to make more Queen Bees from Royal Bee Jelly by using it on an existing Queen, to split her into two Queens
  • +
  • Removes some snowflakey mob behavior from bears, snakes and panthers.
  • +
  • Hudson is feeling punny.
  • +
  • Hostile mob AI should now be a bit more cost-efficient.
  • +
+

monster860 updated:

+
    +
  • Adds area editing, link mode, and fill mode to the buildmode tool
  • +
+ +

12 April 2016

+

FalseIncarnate updated:

+
    +
  • Adjusting the setting of a vendor circuit board is no longer random, but instead provides a select-able list.
  • +
  • Vendor Circuit Board design moved from the Circuit Imprinter to the Autolathe, acid requirement replaced by metal.
  • +
  • Burnt matches can no longer light cigarettes, pipes, or joints.
  • +
+

Fethas updated:

+
    +
  • Nukes the cargo train code rscadd:Adds simple vehicle framework and converts secway/janicart/snowmobiles/bikes/cars/ambulance to it rscadd:Adds space speedbike, red and blue versions, yes you WILL need a spacesuit rscadd:Maps janicart and secway onto metastation (but not ambulance no pareamedic garage, no i am not mapping that)
  • +
  • You should now be able to operate on IPC eyes, SHOULD bugfix:hopefully surgery on diona works right
  • +
+

Fox McCloud updated:

+
    +
  • Adds in TraitorVamp; game mode that's essentially like TraitorChan, but with a Vampire instead of a Changeling
  • +
  • Vampires cannot use holoparasites
  • +
  • Malf AI will automatically lose if it exits the station z-level
  • +
+

Tastyfish updated:

+
    +
  • All cats can kill mice now.
  • +
  • E-N can't suffocate.
  • +
  • Startup time is now shorter.
  • +
  • Removed the Station Collision away mission from rotation, due to multiple conceptual and technical issues.
  • +
+ +

07 April 2016

+

Crazylemon64 updated:

+
    +
  • Removes an offset from the advanced virus stealth calculation, causing viruses to be more stealthy than the sum of their symptoms.
  • +
  • Mulebots will now send announcements to relevant requests consoles on delivery again.
  • +
+

FalseIncarnate updated:

+
    +
  • Adds logic gates, for doing illogical things in a logical manner.
  • +
  • Adds buildable light switches, for all your light toggling needs.
  • +
  • Fixes a resource duplication bug with mass driver buttons.
  • +
+

Fethas updated:

+
    +
  • maybe makes them last longer...maybe..and fixes the event end message
  • +
+

Fox McCloud updated:

+
    +
  • Maps in the slime management console to Xenobio
  • +
  • Reduces Xenobio monkey box count from 4 to 2
  • +
  • Fixes weakeyes having a negligible impact
  • +
  • Can spawn friendly animals with a new gold core reaction by injection with water
  • +
  • Hostile animal spawn increased from 3 to 5 for hostile gold cores
  • +
  • Swarmers, revenants, and morphs no longer gold core spawnable
  • +
  • Fixes invisible animal spawns from gold core/life reactions
  • +
  • Adds tape to the ArtVend
  • +
  • Can no longer use sentience potions on bots
  • +
  • Added in Plasma Dust reagent, acquired by grinding plasma sheets; it's more toxic than regular plasma and generates plasma gas when spilled onto turfs.
  • +
  • Slimecore reactions now require plasma dust as opposed to dispenser plasma
  • +
  • Added in new Rainbow slime; inject with plasma dust to get a random colored slime. Acquire by having 100 mutation chance on a slime when it splits.
  • +
  • Monkey Recycler can produce different types of monkey cubes; change the cube type by using a multitool on the recycler
  • +
  • Epinephrine/plasma reagents changing mutation rate has been removed
  • +
  • Mutation chance is inherited from slime generation to slime generation as opposed to being purely random.
  • +
  • New reactions added for red and blue extracts: red generates mutator, which increases mutation chance, and blue generates stabilizer, which decreases mutation chance.
  • +
  • Slime glycerol reaction removed
  • +
  • Slime cells are now high capacity cells (more power than before)
  • +
  • extract enhancer increases the slime core usage by 1 as oppose to setting it to three
  • +
  • slime enhancer increases slime cores by 1 as opposed to setting the core amount to 3
  • +
  • Chill reaction lowers body temperature slightly more so it doesn't just wear off instantly
  • +
  • Reduces Xenobio plasma sheets from 8 to 3 and removes that pesky boombox
  • +
  • Processors no longer produce 1 more slime core than intended
  • +
  • Less blank/spriteless/empty foods from the silver core reaction
  • +
  • Virology mix reactions now use plasma dust as opposed to plasma
  • +
  • Statues can no longer move/attack people unless they're in total darkness or all mobs viewing them are blinded
  • +
  • statues are invincible to anything other than full out gibbing.
  • +
  • Statues flicker lights spell range increased
  • +
  • Blind spell no longer impacts silicons
  • +
  • Fixes statues being able to attack/move whenever they feel like it, regardless of client statues
  • +
  • Fixes blind spell impacting the statue
  • +
+

Tastyfish updated:

+
    +
  • Beepsky is no longer a pokemon.
  • +
  • pAI-controlled Bots now reliably speak human-understandable languages over the radio.
  • +
  • More floor blood for the blood gods. (Or rather, as much as there was supposed to be.)
  • +
+

tigercat2000 updated:

+
    +
  • Items in your off hand will now count towards access.
  • +
+ +

02 April 2016

+

Crazylemon64 updated:

+
    +
  • Metal foam walls will now produce flooring on space tiles
  • +
  • Syringes will now draw water from slime people.
  • +
+

FalseIncarnate updated:

+
    +
  • Let's you know when your container is full when filling from sinks.
  • +
  • Prevents splashing containers onto beakers and buckets that have a lid on them.
  • +
  • Pill bottles can now be labeled with a simple pen.
  • +
  • Beakers/buckets (and pill bottles) now accept 26 character labels from pens.
  • +
+

Fethas updated:

+
    +
  • Various spells have had a tweak to stun/reveal/cast, some other number stuff...
  • +
  • Nightvision
  • +
  • harvest code is now in the abilites file.
  • +
  • New fluff objectives
  • +
  • Hell has recently remapped its blood transit system and you can now once again crawl through blood. We are sorry for the-GIVE US YOUR SOUL!
  • +
+

FlattestGuitar updated:

+
    +
  • Alcoholic beverages now have proper levels of ethanol in them. Good luck passing out after a beer.
  • +
+

Fox McCloud updated:

+
    +
  • Adds in the Lusty Xenomorph Maid Mob; currently admin only.
  • +
  • Fixes xenomorph brains having the wrong sprite, no origin tech, and incorrect name
  • +
  • removes xenomorph egg from hotel
  • +
  • upgrades are no longer needed to for the available toys in the prize vendor
  • +
  • Implements Advanced Camera Consoles. A type of camera console that function like AI's vision style. Non-buildable/accessible.
  • +
  • Adds in Xenobiology Advance Cameras. A type of camera console that functions like advanced cameras, but only works in Xenobiology areas; can move around slimes and feed them with the console as well. Also non-buildable/accessible (for now).
  • +
  • Adds in cerulean slime reaction that generates a single use blueprint. On use it colors turfs a lavender color
  • +
  • Adds disease1 outbreak event
  • +
  • Adds appendecitis event
  • +
  • Roburgers now properly have nanomachines in them
  • +
  • Re-adds nanomachines
  • +
  • Experimentor properly generates nanomachines instead of itching powder
  • +
  • Fixes big roburgers having a healing reagent in them
  • +
  • Adds nanomachines to poison traitor bottles
  • +
  • Tajarans can now eat mice, chicks, parrots, and tribbles
  • +
  • Vulpkanin and Unathi can now eat mice, chicks, lizards, chickens, crabs, parrtos, and tribbles
  • +
  • fixes spawned changeling headcrab behavior
  • +
+

KasparoVy updated:

+
    +
  • Incisions made at the beginning of embedded object removal surgery can now be closed in the same procedure.
  • +
+

ProperPants updated:

+
    +
  • Maint drones have magboots.
  • +
  • Removed plastic from maint drones. Literally useless for station maintenance.
  • +
  • Increased starting amounts of some materials for maint drones and engi borgs.
  • +
  • Reduced the number of lines taken by Engineering cyborgs calling on materials stacks.
  • +
  • Operating tables can be deconstructed with a wrench.
  • +
  • Fixed and shortened description of metal sheets.
  • +
+

Tastyfish updated:

+
    +
  • Bots can now be controlled by players, by opening them up and inserting a pAI. *beep
  • +
  • MULEbots can now access the engineering destination.
  • +
  • All MULEbot destinations should now have the correct load/unload direction, meaning the crates won't be dumped inside the flaps.
  • +
  • Diagnostic HUD's now give health and status information about bots.
  • +
  • MULEbot rampage blood tracks are now rendered correctly and handle UE traces as appropriate.
  • +
  • Bots should (hopefully) lag the game less now.
  • +
  • Beepsky contains 30% more potato.
  • +
  • Action progress bars are now smooth.
  • +
  • Clicking a filled inventory slot's square with an open hand now clicks the item in the slot.
  • +
  • Status displays now display the time when in Shuttle ETA mode and no shuttle activity is happening.
  • +
  • Shuttle ETA countdowns on status displays are now amber.
  • +
  • pAI's can now use the PDA chatrooms.
  • +
  • Adds treadmills to brig cells, to give the prisoners something productive to do.
  • +
+

TheDZD updated:

+
    +
  • A lot of the guns and armor in the station collision, space hotel, academy, and wild west away missions have been removed/replaced.
  • +
  • Removes that fucking facehugger from station collision.
  • +
+

tigercat2000 updated:

+
    +
  • Virus2 has been removed.
  • +
  • Virus1 is back. Viva la revolution.
  • +
  • You can now have up to 20 characters.
  • +
+ +

26 March 2016

+

Fox McCloud updated:

+
    +
  • Adds in dental implant surgery. Implant pills into people's teeth.
  • +
  • Major rebalance and Shadowling update (https://github.com/ParadiseSS13/Paradise/pull/3986 for details). In general, Shadowlings can no longer enthrall or engage in Shadowling like behavior, pre-hatch. Post-hatch, shadowlings are much more powerful, with a ride array of New abilities such as extending the shuttle or making thralls into lesser shadowlings. Shadowling gameplay should not revolve almost entirely around darkness, as opposed to pre-hatch shenanigans.
  • +
  • Robotics now has a "sterile" surgical area for performing augmentations
  • +
  • Adds the FixOVein and Bone Gel to the autolathe
  • +
  • ensures all surgical tools have origin tech on them; lowers origin tech on FixoVein
  • +
+

KasparoVy updated:

+
    +
  • Slime People can now wear underwear.
  • +
  • Slime People can now wear undershirts.
  • +
+

TheDZD updated:

+
    +
  • NT has removed trace amounts of a highly-addictive substance from the "100% real" cheese used in cheese-flavored snacks. As a result, incidence rates of crewmembers becoming addicted to Cheesie Honkers should reduce to zero.
  • +
  • After receiving complaints about crewmembers often being unable to physically function without a back-mounted barrel of coffee, NT has replaced station all sources of coffee on the station, including coffee beans themselves with a largely decaffeinated version. It was funny the first time almost every crewmember aboard the NSS Cyberiad was lugging around their own oil barrel filled with coffee, it wasn't so funny, nor good for productivity the eighteenth.
  • +
+ +

25 March 2016

+

Crazylemon64 updated:

+
    +
  • You now will actually have the correct `real_name` on your DNA.
  • +
  • No more roundstart runtimes regarding IPC hair.
  • +
  • Mitocholide rejuv will work more usefully now.
  • +
  • Limbs and cyborg modules will no longer appear in your screen.
  • +
  • Cyborg module icons are now persistent throughout logging in and out.
  • +
  • Various cyborg modules, like engineering, now use the proper icon.
  • +
+

FlattestGuitar updated:

+
    +
  • Adds confetti grenades.
  • +
+

Fox McCloud updated:

+
    +
  • Fixes Sleeping Carp combos not having an attack animation
  • +
  • Fixes several chems not properly healing brute/burn damage, consistently, as intended
  • +
+

KasparoVy updated:

+
    +
  • Unbranded heads and groins no longer invisible.
  • +
  • Zeng-hu left leg will now be in line with the body when facing south.
  • +
+ +

22 March 2016

+

Crazylemon64 updated:

+
    +
  • Repairs all sorts of eldritch occurences that happen when you put an organic head on an IPC body, as well as some decapitation bugs
  • +
  • Makes heads keep hair on removal
  • +
  • Amputated limbs from a DNA-injected individual now will keep their appearance of the DNA-injected person
  • +
  • Wounds will vanish on their own now
  • +
  • Admins now have an "incarnate" option on the player panel when viewing ghosts for quick player instantiation
  • +
  • Fixes a runtime regarding failing a limb reconnection surgery
  • +
  • Copying a client's preferences now overrides the previous mob's DNA
  • +
  • A DNA injector is now more thorough, and affects the DNA of mobs' limbs and organs
  • +
  • DNA-lacking species can no longer be DNA-injected
  • +
  • Brains are now labeled again
  • +
  • Splashing mitocholide on dead organs will make them live again.
  • +
  • The body scanner now detects necrotic limbs and organs.
  • +
  • pAIs and Drones are now affected by EMPs and explosions while held.
  • +
+

Fethas updated:

+
    +
  • Adds a surgery for infection treatmne/autopsys that is simply cut open, retract, cauterize
  • +
  • fixes a dumb error in internal bleeeding surgerys
  • +
  • Chaos types no longer random teleport, but will make the target hallucinate everyone looks like the guardian.
  • +
+

FlattestGuitar updated:

+
    +
  • Adds a snow, navy and desert military jacket.
  • +
+

Fox McCloud updated:

+
    +
  • Removes random 1% chance to heal fire damage
  • +
  • Removes passive healing from resist heat mutation
  • +
  • Regen mutation heals every cycle (albeit less, on average), but doesn't cost hunger
  • +
  • Fixes not being able to speak over xeno common or hivemind when you receive the Xeno hive node
  • +
  • Adds in the ability to transfer non-locked metal+glass only designs from the protolathe to autolathe
  • +
  • Changes Outpost Mass Driver to prevent accidental spacings
  • +
  • Shadow people no longer dust on death, are rad immune+virus immune, and can be cloned. Slip immunity removed
  • +
  • Shadowlings no longer get hungry or fat and no longer dust on death
  • +
+

KasparoVy updated:

+
    +
  • The ability to change your head, torso and groin as an IPC in the character creator. Non-IPCs cannot access the parts.
  • +
  • Head, torso and groin sprites for all mechanical limb/bodypart brands but Morpheus and the unbranded ones (since those already exist) from Polaris.
  • +
  • Faux-eye optics for non-Morpheus heads.
  • +
  • The ability to change optic (eye) colour if you've got a non-Morpheus head.
  • +
  • The ability to choose human hair styles (wigs) and facial hair styles (postiche) with non-Morpheus heads. Non-Morpheus heads cannot choose screens. Conversely, Morpheus heads cannot choose wigs or facial hair.
  • +
  • Two hair styles from Polaris.
  • +
  • The ability for IPCs to wear undergarments (shirts and trousers).
  • +
  • Antennae (colourable) for IPCs.
  • +
  • IPC monitor adjustment verb will now adjust optic colour if the head is non-Morpheus.
  • +
  • Combat/SWAT boots can now be toecut and jacksandals can't.
  • +
  • ASAP fix to what would've broken the ability to configure prostheses in character creation.
  • +
  • Adjusted masks no longer block CPR (including bandanas).
  • +
  • You can no longer run internals from adjusted breath masks (or airtight adjustable masks in general).
  • +
+

Regens updated:

+
    +
  • Robotic hearts will now properly give the mob a heart attack instead of just damaging it when EMP'd
  • +
  • Assisted organs will now also take damage from EMP's
  • +
  • Internal robotic and assisted organs will now actually take damage from EMP's
  • +
+

Tastyfish updated:

+
    +
  • Adds PDA chatrooms. Post memes! Talk to your fellow collaborators! Get caught!
  • +
  • You can now set the PDA messenger to automatically scroll down to new messages.
  • +
  • Pet collars now act as death alarms and can have ID's attached to them.
  • +
  • All domestic animals can now wear collars.
  • +
  • You can now make video cameras at the autolathe.
  • +
+

TheDZD updated:

+
    +
  • Fixes an instance of old code being so incredibly, unbelievably, makes-me-want-to-stab-myself-in-the-eye-edly idiotic.
  • +
+

TravellingMerchant updated:

+
    +
  • Kidan have new sprites!
  • +
+

tigercat2000 updated:

+
    +
  • Nukeops now have an assault pod, they can use it for 30 TC. Loud and mean.
  • +
  • Lighting overlays can no longer go below 0 lum_r/g/b
  • +
  • Shuttles will work with lighting better.
  • +
  • Wizards can no longer teleport to prohibited areas such as Central Command.
  • +
+ +

16 March 2016

+

Crazylemon64 updated:

+
    +
  • Being in godmode now makes you immune to bombs
  • +
  • Science members now get compensated when they ship tech disks to centcomm.
  • +
  • Science crew are no longer paid when they "max" research.
  • +
  • Roboticists now get credit for making RIPLEYs and Firefighters
  • +
  • Slime people can now regrow limbs on a more lax nutrition requirement
  • +
  • Enhances the nutripump+ to let slime people regrow limbs with it active
  • +
  • Skeletons, slime people, IPCs, and Diona no longer leave blood when hit
  • +
  • Rejuvenating a slime person will no longer clog up their "blood"
  • +
  • Slime people will now regenerate "blood" from having water in their system
  • +
  • The decloner can now be created again
  • +
  • Environment smashing mobs can now destroy girders.
  • +
+

DaveTheHeadcrab updated:

+
    +
  • Removes the check for species on the update_markings proc.
  • +
+

FalseIncarnate updated:

+
    +
  • Xeno-botany is now more user-friendly, and less random letters/numbers.
  • +
  • Hydroponics now has a connector hooked up to the isolation tray and a new connector in their back room for those strange plants that like spewing plasma or eating nitrogen.
  • +
  • You can now (finally) build the xeno-botany machines, and science can print off their respective boards.
  • +
+

Fethas updated:

+
    +
  • Syringes are no longer sharp
  • +
  • byond likes direct pathing so item/organ/internal not item/organ even if it shouldn't be in the internal_organs list. This was preventing the list from doing stuff correctly.
  • +
  • fixed ipc organ manipulation surgery, you can now insert a replacment ipc organ directly instead of needing a screwdriver in your main hand
  • +
  • nanopaste now will repair organs with robotic >= 2 instead of > 2 cuase i am an idiot
  • +
  • Fix, hopefully, for a runtime for clientless mobs whos head are cut off...
  • +
  • Hopefully fixes issues with diona eyes
  • +
  • Though shalt not eat robotic organs..including cybernetic implants..
  • +
  • ITS SURGERY_STEP/DETHRALL NOT SURGERY_STEP/INTERNAL/DETHRALL
  • +
+

FlattestGuitar updated:

+
    +
  • Adds three new synthanol drinks
  • +
  • Drinking synthanol is now a bad idea if you're organic
  • +
  • A glass of holy water now looks like normal water
  • +
+

Fox McCloud updated:

+
    +
  • Adds in drink fizzing sound
  • +
  • Drink/bartender recipes use this new fizzing sound in addition to a few other recipes
  • +
  • Adds in a fuse burning sound
  • +
  • Bath salts, black powder, saltpetre, and charcoal use this sound now
  • +
  • Adds in a matchstrike+burning sound
  • +
  • Lighting a match triggers this new sound
  • +
  • Adds in scissors cutting sound
  • +
  • Cutting someone's hair uses this new sound
  • +
  • Adds in printer sounds
  • +
  • printing off papers from various devices typically uses these sounds
  • +
  • Adds computer ambience sounds
  • +
  • black box recorder and R&D core servers both play this sound at random rare intervals
  • +
  • Reduces the tech level (and requirement) for nanopaste
  • +
  • Reduces the tech level (and requirement) for the plasma pistol
  • +
  • Removes Nymph and drone tech levels
  • +
  • Reduces tech levels on the flora board
  • +
  • Adds tech level requirements to mech sleepers, mech syringe guns, mech tasers, and mech machine guns
  • +
  • Increases tech cost of the decloner
  • +
  • Removes the pacman generators
  • +
  • Removes emitter
  • +
  • Removes flora machine (functionless anyway)
  • +
  • Removes the pre-spawned nanopaste
  • +
  • Removes space suits
  • +
  • Removes excavation gear
  • +
  • Replaces the soil with actual hydroponic trays (more aesthetic than anything)
  • +
  • Removes most external asteroid access from the station
  • +
  • Excavation storage is now generic science storage
  • +
  • removed the plasma sheet
  • +
  • Fixes augments not showing up in R&D unless specifically searched for
  • +
  • Fixes some augments being unavailable in mech fabs
  • +
  • Fixes augments having no construction time
  • +
  • Fixes xenos not gaining plasma when breathing in plasma
  • +
  • Fixes plasma reagent not generating plasma for a person
  • +
  • Screaming has different sounds based on being male or female
  • +
  • Implements Goon's screaming sounds.
  • +
  • Screaming tone is now based on age of character instead of being random
  • +
  • Ups the cooldown on screaming from 2 seconds to 5 seconds
  • +
  • Removes chance for Whilhelm scream
  • +
  • Borgs can now scream
  • +
  • Monkey's now have a unique screaming sound
  • +
  • IPCs now scream like cyborgs
  • +
  • Updates slot machines to have higher jackpots and more payouts with more interesting sounds
  • +
  • Adds X-Ray, Thermal, Anti-tun, and Reviver implants to the nuke ops uplink (augments come with one auto-implanter) rcsadd: Adds in augment auto-implanter, which inserts and implant without surgery
  • +
  • tweaks a large number of chems; behaviors are largely retained, but new flavor messages, probabilities, etc may be present; overall, you can expect chems to do the same thing
  • +
  • Tabun re-replaced with Sarin rcsadd: New reagent: cholesterol: if overdosed on, it can cause a heart attack--fatty foods, cheese, eggs, and some meats all produce cholesterol in your body.
  • +
  • Mixing Sarin, Meth, or Cyanide will poison in a very small area of the reaction if you're not on internal OR not wearing a gas mask
  • +
  • Chemist warddrobe now has two gas masks
  • +
  • Teslium will now impact synthetics AND organics
  • +
  • Fixes facehuggers hugging already infected people
  • +
  • Fixes facehuggers hugging people while dead
  • +
  • Fixes Embryo's developing twice as fast as they should
  • +
  • Fixes up some behaviors with xeno eggs
  • +
  • Xeno acid can now melt through floors and the asteroid
  • +
  • Xeno's now play the gib sound when actually gibbed
  • +
  • Implements Changeling headcrabs/headspiders
  • +
  • Fixes xenos not throwing their organs when gibbed
  • +
  • Fixes swallowed mobs not being ejected when a human is gibbed
  • +
  • Adds in spider eggs reagent, an infectious reagent that requires surgery to correct
  • +
  • Fixes EMPs causing eye implant users to be permanently blind
  • +
  • Increases bag of holding's storage capacity
  • +
  • Removing a heart no longer kills the patient instantly, but induces a heart attack
  • +
  • Demon hearts will not work
  • +
  • Should now actually be able to re-insert hearts
  • +
  • Reworks addictions to bettter differentiate them betweeen overdosing and make them more realistic.
  • +
  • changes which chems are addictive, currently, the follow reagents are now addidctive: meth, crank, krokodil, bath salts, space drugs, perfluoradecalin, omnizine, coffee, nicotine, fliptonium, ultra lube, surge, fake cheese, weird cheese, ephedrine, diphenhydramine, teporone, and morphine
  • +
  • sleepers help you recover from addiction faster
  • +
  • Can now make cable coils in autolathes
  • +
  • Fixes the slot machine announcements not displaying properly
  • +
+

Tastyfish updated:

+
    +
  • The super fart mutation now gives you a spell-like ability instead of augmenting the emote.
  • +
  • Vampire abilities are now in their own Vampire tab, as well being action buttons at the top, like spells.
  • +
  • Cloning a vampire no longer makes them lose their abilities.
  • +
  • Vampires can no longer hypnotize chaplains.
  • +
  • Being a full vampire (500+ total blood) actually makes you immune to holy water reliably now.
  • +
  • Some old away missions are back: Academy, Black Market Packers, Space Hotel, Station Collision, and Wild West. Go out and round up some hostiles!
  • +
  • Shuttle consoles now pair up to the engineering, mining, research, or labor shuttle when built or used before pairing, as long as the shuttle is near the console, or the shuttle is moved to be nearby.
  • +
+

monster860 updated:

+
    +
  • Mining station now has a podbay.
  • +
  • Ore scooping module for the spacepod.
  • +
  • Three mining lasers for spacepod: Basic, normal, and burst.
  • +
  • Shooting weapons south or west of spacepod will actually hit adjacent targets now, and won't shoot through walls anymore.
  • +
+

taukausanake updated:

+
    +
  • Mice can now be picked up like diona
  • +
+ +

08 March 2016

+

Crazylemon64 updated:

+
    +
  • Slime people are now more vulnerable to low temperatures.
  • +
  • Slime people are able to slowly regrow limbs at a high nutrition cost.
  • +
  • Slime people now slowly shift color based on reagents inside of them - disabled by default, toggle it with an IC verb
  • +
  • Slime people's cores are more vulnerable to damage
  • +
  • Species-related abilities now properly are removed - no more vox hair stylists, unfortunately.
  • +
+

Fethas updated:

+
    +
  • the nest buckle now looks for the right organ path
  • +
  • Fixed some sprites.
  • +
  • No more putting no drops in rechargers,
  • +
+

Fox McCloud updated:

+
    +
  • Implement's goon's gibbing sound
  • +
  • Implement's goon's gibbing sound for robots/silicons
  • +
  • Removes old gibbing sound
  • +
+

Spacemanspark updated:

+
    +
  • Lazarus Injector's can now be emagged to activate their special features, alongside using EMPs on them.
  • +
+

Tastyfish updated:

+
    +
  • Mimes now have a new ore, Tranquillite, used to bring peace and quiet to the station.
  • +
  • There are also permanent invisible walls and silent floors that can be made from tranquillite.
  • +
  • The Recitence mech is now buildable!
  • +
  • The Recitence mech is now playable!
  • +
  • Mid-round selection for various creatures and antagonists now consistently asks permission.
  • +
+

TheDZD updated:

+
    +
  • Adds justice helmets with flashing lights and annoying sirens.
  • +
  • Adds crates containing said helmets.
  • +
  • Also includes a version of the helmet that can only be spawned by admins, and just has a single red light in the center instead of the stereotypical police blinkers.
  • +
+

monster860 updated:

+
    +
  • Space pod transitions are now fixed.
  • +
+ +

07 March 2016

+

Crazylemon64 updated:

+
    +
  • People with VAREDIT can now write matrix variables
  • +
  • People with VAREDIT can now modify path variables
  • +
  • Refactors the variable editor code somewhat.
  • +
  • The buildmode area tool now shows reticules of what you've selected.
  • +
  • Switching mobs while using the buildmode tool no longer screws up your UI.
  • +
  • Refactors buildmode so it's no longer a special-case system.
  • +
  • Adds a copy mode to build mode, which lets you duplicate objects.
  • +
  • Any mob in buildmode can work at the fastest possible rate.
  • +
  • Fixed a problem where the icons of a person would not correctly update when changing gender.
  • +
  • One's hairstyle only adjusts on gender change if it's incompatible with your new gender.
  • +
  • Fixed a bug where a person's icon would only be updated if their sprite had a new layer added or removed.
  • +
  • You no longer lose your name when monkeyized and reverted - you'll still look like a monkey while you're a monkey, though.
  • +
  • Your organs will now match your gender when you are cloned.
  • +
  • Skeletons (when a body rots) no longer retain a fleshy torso.
  • +
  • Putting people in an active cryotube now produces the message on insertion, rather than release.
  • +
  • An EMP'd cloning pod will now display its sprites correctly.
  • +
+

FalseIncarnate updated:

+
    +
  • Water Balloons can be filled from more sources than just beakers and watertanks.
  • +
+

Fox McCloud updated:

+
    +
  • Fixes the "yeah" glasses so the sound doesn't vary and a message is displayed, on use
  • +
  • Noir mode only activates when the glasses are equipped to your actual eyes
  • +
  • Noir Glasses mode can be toggled on or off (defaults to off)
  • +
  • Mimes can no longer use spells and continue speaking
  • +
  • Mime abilities are now spells with proper icons
  • +
  • Mime wall now last 30 seconds, up from 5
  • +
  • forecfields/invisible walls now block air currents
  • +
  • Adds the Sleeping Carp scroll to the uplink for 17 TC
  • +
  • Fixes Shadowlings being able to use guns
  • +
  • Fixes sleeping carp scroll users being able to use guns
  • +
  • Fixes the Experimentor throwing one item at a time
  • +
  • Experimentor menu now automatically refreshes after use
  • +
  • Lowers surgery times across the board
  • +
  • Removes scalpels causing 1 damage on successful surgery
  • +
  • Removes random chance to fracture ribs on a successful surgery
  • +
  • Mining drills now have an edge
  • +
+

KasparoVy updated:

+
    +
  • Jackets who have the verb available but are not intended to be adjusted will not have the action button available.
  • +
  • You can now adjust breath masks while buckled into beds and chairs.
  • +
  • Known issues with adjusted jackets using the wrong sprites.
  • +
  • Blueshield coat in hand and item icons.
  • +
  • Hulks now rip apart adjustable and droppable jackets. The items stored in the jackets get dropped on the ground.
  • +
+

Tastyfish updated:

+
    +
  • Infrared emitters can now be rotated while already in an assembly via the UI popup.
  • +
  • The infrared emitter can no longer be hidden inside of boxes and still work.
  • +
  • The beach now has a border and is splashier.
  • +
  • Gives Psychiatrist a paper bin, clipboard, and multicolored pen.
  • +
  • Gives the Librarian / Jouralist a multicolored pen.
  • +
  • Gives the NT Representative a clipboard.
  • +
  • The ethanol-based neurotoxin drink is now called Neuro-toxin to avoid being confused with the deadly toxin.
  • +
+

VampyrBytes updated:

+
    +
  • Fixes emotes ending with s needing 2. Emotes now work with grammatical options eg ping or pings, squish or squishes
  • +
  • Updated emote help with missing emotes. Help will also show any species specific emotes for your current species
  • +
+ +

26 February 2016

+

FalseIncarnate updated:

+
    +
  • Chocolate can now make you fat, as expected.
  • +
+

Fox McCloud updated:

+
    +
  • stamina damage now regenerates slightly faster
  • +
  • Adds in whetstones for sharpening objects
  • +
  • Kitchen vendor starts off with 5 salt+pepper shakers
  • +
  • Can now point while lying or buckled
  • +
  • Fixes Capulettium Plus not silencing
  • +
  • Fixes slurring, stuttering, drugginess, and silences last half of what they should
  • +
+

KasparoVy updated:

+
    +
  • Jackets that start open are recognized as actually being open already now. This fixes a bug with certain items that don't have an open state, or cases where it ended up giving an item the wrong icon (one that didn't exist)
  • +
+

Spacemanspark updated:

+
    +
  • Fixes synthetics from giving off the proper message in the chat box when using the *yes and *no emotes.
  • +
+

Tastyfish updated:

+
    +
  • Wheelchairs, janicarts, and ambulances can now go through doors according to the user's driver's access.
  • +
+ +

24 February 2016

+

Crazylemon64 updated:

+
    +
  • The defib should be more reliable on people who have ghosted
  • +
  • The defib will now give a message if the ghost is still haunting about
  • +
  • Attacking someone with an accessory will now let you put things on them without having to strip them.
  • +
  • Borers will now properly detach upon death of a mob they are controlling
  • +
  • Borers can now see their chemical count while in control of a mob
  • +
  • Borers can now silently communicate with their host - this is not available to the host until the borer has either begun to communicate, or has taken control at least once - this is to avoid spoiling that the borer exists
  • +
  • Borers won't be able to talk out loud inside of a host, by default - they can remove this safeguard with a verb under their borer tab. Borer hivespeak is unaffected.
  • +
  • Borers infesting and hiding are now silent.
  • +
  • Made borer's chem lists more nicely formatted
  • +
  • No more superspeed attacking simplemobs
  • +
  • New players now show up properly under the "who" verb when used as an admin
  • +
  • Mining drones will now automatically collect sand lying around
  • +
  • RIPLEYs can now drill asteroid turfs for sand
  • +
  • You can now load exosuit fuel generators with items containing their material - this means you can fuel yourself off of ores, but this will be highly inefficient and cost you mining points later on, as you can't take fuel back out.
  • +
  • You can now load the fuel generators from an ore box.
  • +
  • The plasma generator now produces 3x as much power from the same amount of fuel - this lets it even remotely compete with the uranium generator.
  • +
  • You can now light cigarettes off of burning mobs.
  • +
  • Exosuit tracking beacons now fit in boxes - prior, they were far too large for even a backpack, as they shared the same size as all other mecha equipment
  • +
  • Miners can now collect ore by walking over it with an ore satchel on.
  • +
+

FalseIncarnate updated:

+
    +
  • Adds prize tickets as a replacement for physical arcade prizes.
  • +
  • Adds a buildable prize counter to exchange tickets for prizes.
  • +
  • Adds a bike. Despite what Prof. Oak might claim, you can ride it indoors.
  • +
  • Adds colorful wallets, for that old school arcade pride.
  • +
  • Fixes accidental removal of plump helmet biscuit recipe.
  • +
  • Temporarily adds a prize counter to the bar (Cyberiad) or dorms (MetaStation), and adds a max upgrade one to the Ninja Holding Area (Cyberiad z2)
  • +
  • Fixes Metastation. Seriously fixed a lot, just read the PR description for the full list.
  • +
+

FlattestGuitar updated:

+
    +
  • Adds IPC alcohol and a few derivative drinks
  • +
  • IPCs can now drink and be fed from glasses
  • +
+

Fox McCloud updated:

+
    +
  • Laser eyes mutation no longer drains nutrition
  • +
  • splits the EMP kit into two things: the standard EMP kit (2 grenades and an implant), and the EMP flashlight by itself
  • +
  • nerfs heart attacks so they do less damage
  • +
  • Pickpocket gloves now put the item you strip into your hands as opposed to the floor
  • +
  • Picketpocket gloves can now silently strip accessories
  • +
  • Pickpocket gloves will no longer give a message for messing up a pickpocket
  • +
+

KasparoVy updated:

+
    +
  • Adjusting masks while they are not on the face will no longer turn off internals.
  • +
  • Adjusting masks while they are not on the face will now cause the mask to hide/reveal the wearer's identity the next time it's worn as intended.
  • +
  • Adds the ability to open/close bomber jackets.
  • +
  • Adds a security bomber jacket. This jacket inherits the protection and storage capabilities as a standard Security vest with additional bomber jacket benefits.
  • +
  • Adds UI button in top left of screen for jacket adjustment.
  • +
  • Replaces the standard bomber jacket in the Pod Pilot bay with the Security version.
  • +
  • Centralizes jacket/coat adjustment handling.
  • +
  • All jackets start closed by default.
  • +
  • Geneticist duffelbag on-mob sprite (for all species).
  • +
  • Vox-fitted backpacks, satchels, ERT backpacks, duffelbags and defib unit.
  • +
  • Refactors back-item icon generation.
  • +
  • Typo in the description of Santa's sack.
  • +
  • Missing punctuation and gender macros in the description of the bag of holding.
  • +
  • The tweak to back-icon generation fixes a bug where the wrong sprite name was being used to generate back-item icons.
  • +
+

PPI updated:

+
    +
  • Adds the ability to hide papers in vents. You can now leave a romantic love letter, exchange information in secret, or hide papers infused with the power of nar'sie from sight.
  • +
+

Regen1 updated:

+
    +
  • Adds the Immolator laser gun, a modified laser gun with 8 shots that will ignite mobs, can be made in R&D
  • +
+

Spacemanspark updated:

+
    +
  • Adds *yes and *no emotes to Synthetics. Glory to Synthetica.
  • +
+

Tastyfish updated:

+
    +
  • The PDA system has been completely redone behind the scenes! It should be functionally similar, although there is now a Home and Back button at the bottom as appropriate.
  • +
  • All of the heads now have multicolored pens.
  • +
  • EngiVend now has 10 camera assemblies.
  • +
  • Borgs can now use vending machines.
  • +
  • There are now picture frames that can be made from the autolathe or wood planks for papers, photos, posters, and canvases!
  • +
+

pinatacolada updated:

+
    +
  • Makes the Protect Station AI law board no longer consider people that damage the station crew, instead of human
  • +
+

ppi updated:

+
    +
  • When revealed Revenants will not be able to move at the maximum move speed, nor be able to pass through any solid object, like walls, windows, grills, computers and mechs.
  • +
+ +

13 February 2016

+

Crazylemon64 updated:

+
    +
  • Relaxes the check on what atoms you can follow to any movable atom
  • +
  • Mages are now more ragin
  • +
  • Admins can now adjust the total number of wizards at runtime by tweaking either max_mages, or players_per mage
  • +
+

DaveTheHeadcrab updated:

+
    +
  • Adds new worn icons for duffelbags to better reflect their size, compliments of WJohn at /tg/
  • +
+

FalseIncarnate updated:

+
    +
  • Adds burritos, made from cutlets, beans, rice, capsacin oil (hotsauce), cheese, and flat dough (because we lack proper tortillas) in the microwave.
  • +
  • Adds chimichangas. You know you want a deep-fried burrito.
  • +
+

Fox McCloud updated:

+
    +
  • Updates some spell icons with better/higher quality icons
  • +
  • Updates unarmed attacks to allow for more customization
  • +
  • Updates martial arts so they factor in specie's attack messages and sounds
  • +
  • Re-balances Sleeping Carp fighting style
  • +
  • Re-balances Bo Staff
  • +
  • Rebalances Golem: they should now be spaceproof, fire+cold proof, rad proof, virus immune, clonable, parapen+syringe gun immune, deal increased melee damage. Their armor has been reduced to 55 melee across the board, their slip immunity removed, pain immunity removed, and they're slightly slower
  • +
  • Fixes Ei Nath generating two brains
  • +
  • Ensures the Necromatic Stone generates actual skeletons
  • +
  • Can now strip PDA/IDs from Golems
  • +
  • Fixes sleeping carp grab not being an instant aggressive grab
  • +
  • Fixes an exploit with declaring war on the station
  • +
+

KasparoVy updated:

+
    +
  • Orange and purple bandanas for all station species.
  • +
  • The ability to colour bandanas with a crayon in a washing machine.
  • +
  • Refactors the bandana adjustment system.
  • +
  • Minor adjustments to Tajaran and Unathi bandana east/west sprites.
  • +
  • Adjusting a bandana will now take if off of your head/face and put it in an available hand. If both hands are available, it goes in the selected hand.
  • +
  • Adjusting a coloured bandana will no longer revert it to the original coloured icons anymore.
  • +
  • Adjusting a bandana from mask-style to hat-style means the bandana won't obscure your identity anymore.
  • +
  • Greys now use re-positioned smokeables. They no longer smoke out the eyes.
  • +
+

TheDZD updated:

+
    +
  • Fixes spacepods being able to shoot through walls.
  • +
  • Lowers spacepod weapons fire delay.
  • +
  • Increases spacepod weapons energy costs.
  • +
  • Makes spacepods move at speeds not rivaling those of photon beams. They are now a hair bit faster than a person with a jetpack.
  • +
  • Reduces battery costs for spacepod movement.
  • +
+ +

10 February 2016

+

Crazylemon64 updated:

+
    +
  • The cloner now checks for NO_SCAN on the brain when scanning - unclonable species are now truly unclonable. You are still able to revive them with a brain transplant and a defib, however.
  • +
  • A tier-4 DNA scanner linked to a cloning system will now be able to reproduce a body from a brain's DNA, in event of the original corpse being gibbed or similar.
  • +
  • Species with organic limbs and NO_BLOOD will no longer bleed (though still on hit - write that off as "bone powder")
  • +
  • Skeletons now lack internal organs, except for the runic mind which exists in their head - an analogue for the brain
  • +
  • Skeletons that drink milk will be regenerated at a moderate pace, have a small chance of mending bones, and will praise the great name of mr skeltal
  • +
  • Adds a reagent system for species reacting to specific reagents
  • +
  • Slime People can now select from all human hairstyles, and their "hair" will be tinted a shade of their body.
  • +
  • Increases the frequency of the cortical borer event.
  • +
  • People with borers cannot commit suicide - this applies to a controlling borer, too.
  • +
  • Borers can no longer overdose their hosts.
  • +
  • Borers can now inject Saline-Glucose, Spaceacillin, Hydrocodone, Mitocholide, Salbutamol, Capulettium+, and Charcoal. Styptic was removed, as it's pathetic at healing when directly injected. Salicyclic acid was removed too, as its functionality is duplicated by both hydrocodone and saline-glucose.
  • +
  • A mind trapped by a cortical borer can now understand things it could understand when normally in its body.
  • +
  • Changes chemistry's welding tank to a wall-mounted version, to increase the room available.
  • +
  • You can now gib butterflies and lizards with a knife
  • +
  • Ghosts can now follow mecha
  • +
  • You can now access an R&D console by emagging it - it did nothing before.
  • +
  • Walls will now properly smooth and show damage.
  • +
  • Fixes the dialog that occurs when the AI shuts off to actually do what it says it does
  • +
+

Fox McCloud updated:

+
    +
  • Fixes not being able to attach IEDs to beartraps
  • +
  • Can no longer spamclick someone to death using headslamming on a toilet/urimal
  • +
  • Toilet/urinal headslamming now plays a sound
  • +
  • Toilet headslamming damage reduced slightly
  • +
  • Can now fill open reagent containers in a toilet to receive "toilet water".
  • +
  • No more message spam when someone fills a container using a sink
  • +
  • Can now wash your face using a sink, which washes away lipstick and wakes you up slightly
  • +
  • Washing things will now use progress bars
  • +
  • Ensures consuming a single syndicate donk pocket won't get you addicted to meth
  • +
  • Kinetic Accelerators and E-bows automatically reload
  • +
+

Glorken updated:

+
    +
  • Added a Knight Arena for Holodeck.
  • +
  • Added red and blue claymore sprites.
  • +
  • Changed overrided to overrode when emagging Holodeck computer.
  • +
+

KasparoVy updated:

+
    +
  • Vox versions of the Officer SWAT sechailer + HOS SWAT sechailer + Warden SWAT sechailer.
  • +
  • Resprited versions of most Human masks to fit Unathi, Tajara and Vulpkanin.
  • +
  • Warden now gets their own version of the SWAT sechailer in their locker.
  • +
  • HOS now gets the appropriate version of the SWAT sechailer in their locker.
  • +
  • Repositioned smokeables now available for Vox, Unathi, Tajara and Vulpkanin.
  • +
  • Properly shades Vox bandana down-state sprites.
  • +
  • Readds Tajaran bald hairstyle.
  • +
  • Alternate style of non-Human breath mask (incl. surgical/sterile mask) down-state positioning.
  • +
  • Corrects all non-Human species' breath mask (incl. surgical/sterile mask) down-state icons to use the right position style.
  • +
  • Minor adjustments to Tajaran breath mask up-state sprites.
  • +
+

PPI updated:

+
    +
  • Adds a reconnect button to the File menu in the client.
  • +
  • Adds head patting
  • +
+

Regen updated:

+
    +
  • Powersink can now drain a lot more power before going boom
  • +
  • Buffed the powersinks drain rate
  • +
  • Buffed explosion from an overloaded powersink, try to find it instead of overloading the grid.
  • +
  • Admin log warning before the powersink explodes
  • +
+

Spacemanspark updated:

+
    +
  • Miners can now utilize the power of mob capsules to take along their lazarus injected mining creatures!
  • +
  • Store your Pokemo- er, sorry, I mean mining mobs that you've captured in the lazarus capsule belt.
  • +
+

Tastyfish updated:

+
    +
  • Species that don't breathe can kill themselves now!
  • +
  • Suicide messages are now catered to your species.
  • +
  • Shortened the default pill & patch name when using the ChemMaster.
  • +
  • The chaplain now has a service radio headset, as Space Jesus intended.
  • +
+

TheDZD updated:

+
    +
  • When Ahelping, "Question" is now "Mentorhelp" and "Player Complaint" is now "Adminhelp."
  • +
  • Mentorhelps and PM replies from mentors appear in a bold aqua blue color.
  • +
  • Adminhelps and PM replies from admins appear in a bold bright red color.
  • +
  • PM replies from players appear in a dull/dark purple color.
  • +
  • Adds admin attack log to players being converted to cult.
  • +
  • Adds shadowling thrall jobbans.
  • +
  • Jobbanned players who are converted to shadowling thrall, revolutionary, or cultist will have the control of their body offered up to eligible ghosts.
  • +
+ +

31 January 2016

+

Crazylemon64 updated:

+
    +
  • Syndicate borgs can now interact with station machinery
  • +
  • People with slime people limbs can now *squish
  • +
  • Skrell's vulnerability to alcohol is checked on their liver, now - a liver transplant will let them take alcohol like a champ - lacking a liver will have the same effect as being a skrell, when drinking
  • +
+

FalseIncarnate updated:

+
    +
  • Adds in the Magic Eight Ball toy, found in Claw Game prize orbs.
  • +
  • Adds in the Magic Conch Shell, an admin-only shell of power.
  • +
+

Fox McCloud updated:

+
    +
  • Updates Summon Guns and Magic to include many of the new guns
  • +
  • Summon Guns/Magic can no longer be used during Ragin' Mages
  • +
+

Tastyfish updated:

+
    +
  • The emergency shuttle status in the Status tab now has ETA/ETD/etc like before.
  • +
  • Code Gamma+ now has a 5 minute emergency shuttle call, like Red.
  • +
+

pinatacolada updated:

+
    +
  • Adds NanoUI to the operating computer
  • +
  • Adds health announcing, critical and oxygen damage aural alerts to the computer, with a menu to selectively turn them on and off
  • +
+ +

29 January 2016

+

Crazylemon updated:

+
    +
  • The DNA scanner has now undergone a seminar to recognize fake identities; It will now scan the actual person's identity, rather than their disguise (read: wearing a mask with or without someone else's ID).
  • +
  • Matter eater now allows you to eat humans as if you were fat.
  • +
  • Eating mobs with an aggressive grab now generates attack logs.
  • +
+

Crazylemon64 updated:

+
    +
  • For a short while, there was a clerical error where all AI communications equipment was replaced with bananas. This has now been fixed.
  • +
  • Ghosts can now see the contents of smartfridges and look at the drone console
  • +
  • Humans now only produce one message when shaken while SSD
  • +
  • The supermatter no longer will irradiate everyone, everywhere, when it explodes.
  • +
  • Writing on paper will now add hidden admin fingerprints, so that you can't forge mean notes in someone else's name.
  • +
  • Brains are no longer able to escape their brain by being a sorcerer.
  • +
  • Astral projecting with other runes on the same tile will now no longer prevent you from re-entering
  • +
  • Voxxy that is become ex-voxxy no longer carry voxxy appearance! yaya!
  • +
+

FalseIncarnate updated:

+
    +
  • Allows plants to be identified as enhanced*. Enhancing plants results from using reagents (like saltpetre) that affect the stats of a seed instead of using mutagens/machines. *May not meet standards for being classified as "organic produce". (This was already possible, just renames enhanced plants for easier differentiation)
  • +
+

Fox McCloud updated:

+
    +
  • Fixes mutadone not working with some genetic mutations
  • +
  • Fixes banana honk and silencer being alcoholic
  • +
  • Fixes Kahlua being non-alcoholic
  • +
  • Fixes polonium not metabolizing
  • +
  • Fixes being able to receive free unlimited boxes from the Merchandise store
  • +
  • Adds in wooden bucklers
  • +
  • Re-adds roman shield to the costume vendor
  • +
  • Buffs Riot shield damage from 8 to 10
  • +
  • Adds in a Skeleton race
  • +
  • Tweaks the skeletons colors to be more realistic and to blend in less with the floor
  • +
  • Adds in lichdom spell for the wizard
  • +
  • Adds in lesser summon guns spell for wizard
  • +
  • adds in Mjolnir and the singularity hammer as weapons the wizard can purchase
  • +
  • Wizard can purchase the charge spell from the spell book
  • +
  • Wizard can purchase a healing staff from the spell book
  • +
  • Tweaks and lowers spell costs of utility spells for wizard
  • +
  • Re-organizes the spellbook to be better divided into categories and have a better window size
  • +
  • Knock now opens+unlocks lockers
  • +
  • Magic Missile has a slightly longer cooldown and no longer deals damage, but has a lower cooldown is upgraded
  • +
+

KasparoVy updated:

+
    +
  • Navy blue Centcom Officer's beret for use by the Blueshield.
  • +
  • Adds the new navy blue beret to the Blueshield's locker.
  • +
  • Gives the Blueshield's berets (black and navy blue) the exact same strip delay and armour as the Security Officer's beret.
  • +
  • Adds TG energy katana back and belt sprite.
  • +
  • Bo staff back sprite.
  • +
  • Adjusts energy katana sprites to make the weapon stand out a bit more from the regular katana.
  • +
  • Cutting open the toes of footwear so species with feet-claws can wear them.
  • +
  • Toeless jackboots.
  • +
  • Cleans up glovesnipping and lighting a match with a shoe.
  • +
  • Lighting a match with a shoe produces a more appropriate message, handled at the same standard as glove-snippingboot-cutting.
  • +
+

Tastyfish updated:

+
    +
  • Cargonia now has its own section in the manifest.
  • +
+

TheDZD updated:

+
    +
  • Due to budget cuts and reports of operatives accidentally firing enough bullets to reach a state of what our scientists refer to as "enough dakka," Syndicate High Command has decided to restore the Syndicate Strike Team arsenal to using standard-issue L6 SAW ammunition.
  • +
+ +

24 January 2016

+

KasparoVy updated:

+
    +
  • Fixes markings overlaying underwear.
  • +
  • Nude icon in underwear.dmi
  • +
  • Fixes Vox robes not using the correct on-mob sprites.
  • +
  • Fixes unreported bug where there was a slim chance during character preview icon generation that a character with Security Officer set to high would get rendered with either the wrong beret sprite or no beret sprite at all.
  • +
  • Fixes an issue where Sigholt's fluff beret wasn't using the correct sprites.
  • +
+

Tastyfish updated:

+
    +
  • Passively power-consuming borg modules, such as the peacekeeper movement and shield module, won't spam the user infinitely if they're low on power anymore.
  • +
+ +

23 January 2016

+

Fox McCloud updated:

+
    +
  • Removes Vampire HUD
  • +
  • moves the Vampire blood counter to a more easy to see location
  • +
  • Adds in a Changeling chemical counter display
  • +
  • Adds in a Changeling sting counter display
  • +
  • Vampire total blood and usable blood will now appear under status
  • +
  • Changes vampire blood display to be similar to ling chemical counter
  • +
  • Fixes unnecessary toxin damage being dealt on severe bloodloss
  • +
  • Fixes human mobs not receiving proper random names
  • +
  • Adds in knight armor
  • +
  • Grants the chaplain a set of crusader knight armor
  • +
  • Adds in cult-resistant ERT paranormal space suit
  • +
  • Allows the Chaplain to convert his null rod into a holy sword with crusader knight armor
  • +
  • Chaplain's closet is now a secure closet
  • +
  • Adds in Assault Gear crate to cargo
  • +
  • Adds in military assault belt
  • +
  • Adds in spaceworthy swat suits
  • +
  • tweaks bandolier to hold 2 additional shotgun shells
  • +
  • bartender starts off with +2 additional shells
  • +
  • Reduces the cost of the space suit crate and doubles its contents
  • +
  • Refactors knives so their behavior is more universal
  • +
  • Fixes Hulk not properly being removed when your health drops below a threshold
  • +
  • Fixes flickering vision in a mining mech
  • +
+

Tastyfish updated:

+
    +
  • Poly has taken a seminar on the latest trends in engine operations.
  • +
  • Player-controller parrots can now hear their headsets.
  • +
+

Tigerbat2000 updated:

+
    +
  • The nuclear disk escaping on the shuttle no longer counts as a syndicate minor victory.
  • +
  • Cultists can once again actually greentext the escape objective.
  • +
+ +

20 January 2016

+

DarkPyrolord updated:

+
    +
  • Adds in hardsuit sprites for Vulpkanin
  • +
+

FalseIncarnate updated:

+
    +
  • Allowed cheap lighters and individual matches to be put into cigarette packages at the cost of cigarette space.
  • +
  • Matches can now be lit and put out by striking the match on your shoes. Good for if you lose that matchbox, or want to just feel cool.
  • +
+

Fox McCloud updated:

+
    +
  • Fixes brute damage on weapons not knocking people down.
  • +
  • Tweaks implant behavior to be more consistent and unified.
  • +
  • Lowers the pAI cooldown from 60 seconds to 5 seconds.
  • +
  • Raw telecrystal can now be used to charge uplink implants.
  • +
  • Fixes being unable to holster the pulse pistol
  • +
  • Fixes being able to holster shotguns
  • +
+

KasparoVy updated:

+
    +
  • Improved shading on all Vulpkanin hardsuit tails.
  • +
  • Vulpkanin hardsuit helmet respriting (colour tweaks).
  • +
  • Vulpkanin hardsuit helmets with proper flashlight-on sprites.
  • +
+

Tastyfish updated:

+
    +
  • The ID computer Access Report printout now separates the access list with commas so it's actually readable.
  • +
  • The ID computer Access Report printout isn't blank if you don't have an authorization card in anymore.
  • +
  • In the supply ordering & shuttle consoles, one can now cancel an order at either the Reason or Amount input dialogs.
  • +
  • Table flipping uses correct sprites.
  • +
+

TheDZD updated:

+
    +
  • Adds world.Topic() handling so that users are notified in-game when pull requests are opened, closed, or merged on the Github repo.
  • +
+ +

18 January 2016

+

Crazylemon updated:

+
    +
  • New classes of shapeshifters have been sighted around the NSS Cyberiad...
  • +
  • Wizards now can't teleport to other antag spawn points.
  • +
  • Removes an extruding pixel from the left-facing IPC glider monitor sprite.
  • +
  • Ragin' Mages now spawn every 7 minutes, instead of 5. Admins can further adjust this by modifying the 'delay_per_mage' variable.
  • +
  • Ragin' Mages are now made with 100% less in-use souls (Apprentices won't have their consciousness yoinked).
  • +
  • It takes half an hour for the REAL chaos of ragin' mages to start, for at least a semblance of normality.
  • +
+

Dave The Headcrab updated:

+
    +
  • Adds the advanced energy revolver, toggles between taser and laser modes.
  • +
  • Removes the detective's revolver from the blueshield's locker.
  • +
  • Changes the taser the blueshield starts with into an advanced energy revolver.
  • +
+

Deanthelis updated:

+
    +
  • Added the ability for the Magnetic Gripper to pick up and place light tiles.
  • +
+

Fethas updated:

+
    +
  • Readds the hud icon showing up for master and servent
  • +
  • adds mindslave datum hud thingy based on TGs gang huds
  • +
+

Fox McCloud updated:

+
    +
  • Fixes not being able to add/remove Weapon Permit from IDs.
  • +
  • Fixes the energy sword being invisible in-hand when turned on.
  • +
  • Fixes the telebaton being invisible in-hand when extended.
  • +
  • Fixes eye-stabbing not having an attack animation or hitsound.
  • +
  • Fixes some kitchen utensils playing the wrong hit-sound and playing twice in some cases.
  • +
  • Fixes the butcher cleaver sprite being backwards.
  • +
  • Fixes the telebaton sprite being missing from the side.
  • +
  • Fixes the meat cleaver being invisible in-hand.
  • +
  • Corrects some grammatical descriptive errors for the elite syndicate hardsuit.
  • +
  • completely overhauls implants to TG's standards.
  • +
  • Adds storage implant.
  • +
  • Adds microbomb and macrobomb implants.
  • +
  • Adds in support for removing implants directly into cases.
  • +
  • Removes Bay style explosive implants.
  • +
  • Removes compressed matter implants.
  • +
  • Tweaks the uplink to reflect removal of the old implants and inclusion of the new.
  • +
  • Fixes/cuts down on the lag caused by monkey cubes.
  • +
+

Jey updated:

+
    +
  • Inflatable walls and door can now be deflated by altclicking them
  • +
  • Fixed lag from expanding multiple monkeycubes at once.
  • +
+

KasparoVy updated:

+
    +
  • Adds blank icons with standardized timings for species tail wagging, used in icon generation.
  • +
  • Fixes tails overlapping arms/limbs + gloves, etc. when facing EAST or WEST.
  • +
  • Ensures tails will overlap stuff as normal only when facing NORTH so as to avoid unwanted interference with the base sprite.
  • +
  • Tails now appear in ID cards, overlays things correctly.
  • +
  • Tails now overlay and are overlaid by things correctly in preview icons.
  • +
  • Modifies the positioning of tail icon generation in the ID card preview icon generation file.
  • +
  • Modifies the positioning of tail icon generation in the player preferences preview icon generation file.
  • +
  • Breaks limb generation into its own layer, breaks tail generation into a second layer that can be overlaid by limbs.
  • +
  • If the user's species is flagged to have a tail that is overlapped, TAIL_LAYER will now overlay the NORTH direction sprite of a tail now, while TAIL_UNDERLIMBS_LAYER gets all remaining directions. Otherwise icons are generated in the traditional manner.
  • +
  • Adjusts the Unathi right arm east direction and animated tail sprites, recolouring a random pixel and fixing a floating tail respectively.
  • +
  • Adjusts position of tail layer such that tails' north direction sprites will overlay backpacks (more importantly, satchel straps).
  • +
  • Accommodates admin-overrides to the body_accessory species check by setting the default animation template to Vulpkanin.
  • +
  • Adjusts north-direction Unathi static tail sprite, now attaches to the body in the correct location.
  • +
  • Adds some TG underwear.
  • +
  • Adds an NV science goggles worn sprite.
  • +
  • Ports Bay/TG berets.
  • +
  • Adjusts beret sprite, recolours strange orange pixels.
  • +
  • Adjusts NV science goggles object icon. Removed strange border and centered it.
  • +
  • Ports Polaris' PRs 761 and 778, brings over Ragnie's awesome Ward-Takahashi prosthetics.
  • +
+

Kyep updated:

+
    +
  • Changing level to gamma/delta/epsilon now displays a special gamma/delta/epsilon sprite on status monitors
  • +
  • Changing level to green/blue now clears the status monitors, so they no longer show higher alert levels after the level is changed
  • +
+

NTSAM updated:

+
    +
  • Added a rainbow IPC screen.
  • +
+

PPI updated:

+
    +
  • Modifies the effective time limit to activate the Nuclear Challenge as Nukeops from two minutes to seven minutes
  • +
+

Tastyfish updated:

+
    +
  • The QM now actually has a QM stamp instead of a fake one, as well as an approved and denied stamp.
  • +
  • New area named 'Genetics Maintenance' solidifying/relabelling the confusing area between the morge and Mech Bay as being fully maintenance again, but working correctly and with proper doors.
  • +
  • Fixed a few maintenance door names to be in parity to the rest of the station.
  • +
  • Added the ability to print the records photo of a crew member from a security records console. Useful for Wanted notices!
  • +
+

Tigercat2000 updated:

+
    +
  • You can no longer use the gibber for monkies.
  • +
  • Cleaned up gibber.dm styling.
  • +
  • The fire alarm now uses NanoUI, with color coded alert levels.
  • +
  • Upgraded NanoUI (again), fancy FontAwesome icons.
  • +
  • Didn't add any butts. Yet.
  • +
+ +

13 January 2016

+

Fox McCloud updated:

+
    +
  • Fixes Rezadone not clearing mutated organs.
  • +
  • Clone damage immunity removed from Slime People, Shadowlings, Golems, and Vox
  • +
  • Explosions will no longer destroy things underneath turfs until the turf is exposed.
  • +
  • fixes a runtime related to revolver spinning.
  • +
  • fixes server loading taking an abnormally long time.
  • +
+

Kyep updated:

+
    +
  • Blob, vine and virus outbreaks are now more clearly labeled as such, to avoid people confusing them with each other
  • +
+

Tastyfish updated:

+
    +
  • NT Rep fountain pens and magistrate gold pens can now write in 5 different colors. The IAA gets a cheap plastic equivalent.
  • +
+ +

11 January 2016

+

CrAzYPiLoT updated:

+
    +
  • Fixes the footsteps sounds to the fullest.
  • +
+

Crazylemon updated:

+
    +
  • Bomb guardians now automatically notify their master when they've set something to boom, so there's less accidental friendly fire
  • +
  • Bomb guardians are only notified that their trap failed, if it ACTUALLY FAILED.
  • +
  • Bomb guardians now are more aware of what is primed to explode.
  • +
  • Bomb guardian summoners can now defuse their guardian's bombs without harm.
  • +
  • Brought RAGIN' MAGES back up to function.
  • +
+

Dave The Headcrab updated:

+
    +
  • Added a new icon for the soy and cafe latte drinks. Icons courtesy of Full Of Skittles, resident overlord of art.
  • +
+

Fox McCloud updated:

+
    +
  • Re-arranges the armory and changes its contents minorly.
  • +
  • Adds in rubbershot ammo boxes.
  • +
  • Fixes Mutadone incurring a massive cost on the server.
  • +
  • Positronic brains can no longer speak binary.
  • +
  • Positronic brains can be prevented from speaking (or allowed) by toggling their speaker on/off.
  • +
  • IPC's positronic brains start off toggled off.
  • +
  • Fixes the supermatter announcement causing massive amounts of server lag.
  • +
  • Adds in tradable telecrystals.
  • +
+ +

08 January 2016

+

Crazylemon updated:

+
    +
  • Fully enables a system to allow species to have unique procs and verbs that come and go with the species.
  • +
  • IPCs lose their change monitor verb when changing species now. Gone are the days of recalling a past IPC life to perform self-barbery! Oh, woe is me!
  • +
  • Sleepers and Body Scanners will now reliably work when rotated
  • +
  • SSD humans should be asleep more reliably now.
  • +
+

Dave The Headcrab updated:

+
    +
  • Nerfs the damage the Detective's revolver does from 15 brute to 5 brute.
  • +
  • Adds a 300 round capacity buckshot magizine that fits into the L6 Saw.
  • +
  • Adds a 25 round capacity 40mm HE magizine that fits into the L6 Saw.
  • +
  • Adds the 'Devastator' L6 SAW, starts off loaded with the buckshot magizine.
  • +
  • Gives the SST the 'Devastator' L6 Saw, and one of each mag type in their bag.
  • +
+

FalseIncarnate updated:

+
    +
  • Plants will now begin to die over time if their age exceeds 5 times their TRAIT_MATURATION value.
  • +
  • Weed growth chance per process in trays has been slightly increased (Previously: 5% chance if no seed, 1% otherwise;Now: 6% / 3%).
  • +
  • Pest growth in trays has been slightly buffed. (Previously: 3% chance to increase by 0.1; Now: 5% chance to increase by 0.5)
  • +
+

Fethas updated:

+
    +
  • Due to Archmage Steve leaving the nya-cromantic stone near the microwave, the true power of the stone has been unleashed. Subjects of the stone are not only ressurected ... but resurrected as catgirls ... We fired steve.
  • +
+

Fox McCloud updated:

+
    +
  • fixes a bug relating to some brute/burn damage being dealt to human mobs.
  • +
  • Adds in overloading APCs, causing them to arc electricity to mobs in range.
  • +
  • Makes Engineering related APCs overload proof.
  • +
  • Implements the timestop spell.
  • +
  • Implements new sepia slime reaction which halts time in an AoE.
  • +
  • sentience potions no longer can make slimes sentient.
  • +
  • Removes Hulk instant stun.
  • +
  • Hulk damage increased.
  • +
  • Hulk wears off at a lower health threshold.
  • +
  • Fixes strange reagent not working on simple animals.
  • +
  • Reduces the amount shock damage and bounces for the Tesla engine.
  • +
  • Fixes Syndicate Cyborg's LMG being invisible.
  • +
  • Fixes the uplink kit having implanters that were both nameless and looked as if they had been used.
  • +
+

KasparoVy updated:

+
    +
  • Added the security gasmask, sexy mime mask, bandanas, balaclava, welding gas mask and wrestling masks for Vox. Added adjusted-state sprites for the Vox breath, medical, and surgical masks.
  • +
  • Removed a duplicate of the human balaclava sprite.
  • +
  • Modifies the Vox plague-doctor, fake moustache, sterile and medical mask sprites to fit the Vox anatomy and animates the Vox SWAT mask. Corrects the names of some Vox mask adjusted-state sprites.
  • +
+

Tastyfish updated:

+
    +
  • Fixed the pronouns in a few verbs and the door to 'Interrogation Observervtion'.
  • +
+

Tigercat2000 updated:

+
    +
  • Added 96x96 (3x) res option to icons menu
  • +
+ +

06 January 2016

+

Certhic updated:

+
    +
  • Corrected some air alarms so that atmos computer can access them
  • +
  • Bodyscanner now sees mechanical parts in internal organs
  • +
+

Crazylemon64 updated:

+
    +
  • Sleeping simple animals should tick down sleeping as normal - deaf simple mobs are no longer a thing
  • +
+

Tastyfish updated:

+
    +
  • Instruments now use NanoUI.
  • +
  • Corrected the blueshield mission briefing.
  • +
+ +

03 January 2016

+

TheDZD updated:

+
    +
  • Ports over changelog system from /tg/station.
  • +
+
+ +GoonStation 13 Development Team +
+ Coders: Stuntwaffle, Showtime, Pantaloons, Nannek, Keelin, Exadv1, hobnob, Justicefries, 0staf, sniperchance, AngriestIBM, BrianOBlivion
+ Spriters: Supernorn, Haruhi, Stuntwaffle, Pantaloons, Rho, SynthOrange, I Said No
+
+
+

Creative Commons License
Except where otherwise noted, Goon Station 13 is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 License.
Rights are currently extended to SomethingAwful Goons only.

+

Some icons by Yusuke Kamiyamane. All rights reserved. Licensed under a Creative Commons Attribution 3.0 License.

+
+ + diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index e0f00de5a69..ccb9d83a458 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -1,1265 +1,1341 @@ -DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. ---- -2016-01-03: - TheDZD: - - rscadd: Ports over changelog system from /tg/station. -2016-01-06: - Certhic: - - bugfix: Corrected some air alarms so that atmos computer can access them - - bugfix: Bodyscanner now sees mechanical parts in internal organs - Crazylemon64: - - bugfix: Sleeping simple animals should tick down sleeping as normal - deaf simple - mobs are no longer a thing - Tastyfish: - - tweak: Instruments now use NanoUI. - - spellcheck: Corrected the blueshield mission briefing. -2016-01-08: - Crazylemon: - - rscadd: Fully enables a system to allow species to have unique procs and verbs - that come and go with the species. - - rscdel: IPCs lose their change monitor verb when changing species now. Gone are - the days of recalling a past IPC life to perform self-barbery! Oh, woe is me! - - bugfix: Sleepers and Body Scanners will now reliably work when rotated - - bugfix: SSD humans should be asleep more reliably now. - Dave The Headcrab: - - tweak: Nerfs the damage the Detective's revolver does from 15 brute to 5 brute. - - rscadd: Adds a 300 round capacity buckshot magizine that fits into the L6 Saw. - - rscadd: Adds a 25 round capacity 40mm HE magizine that fits into the L6 Saw. - - rscadd: Adds the 'Devastator' L6 SAW, starts off loaded with the buckshot magizine. - - rscadd: Gives the SST the 'Devastator' L6 Saw, and one of each mag type in their - bag. - FalseIncarnate: - - rscadd: Plants will now begin to die over time if their age exceeds 5 times their - TRAIT_MATURATION value. - - tweak: 'Weed growth chance per process in trays has been slightly increased (Previously: - 5% chance if no seed, 1% otherwise;Now: 6% / 3%).' - - tweak: 'Pest growth in trays has been slightly buffed. (Previously: 3% chance - to increase by 0.1; Now: 5% chance to increase by 0.5)' - Fethas: - - rscadd: Due to Archmage Steve leaving the nya-cromantic stone near the microwave, - the true power of the stone has been unleashed. Subjects of the stone are not - only ressurected ... but resurrected as catgirls ... We fired steve. - Fox McCloud: - - bugfix: fixes a bug relating to some brute/burn damage being dealt to human mobs. - - rscadd: Adds in overloading APCs, causing them to arc electricity to mobs in range. - - tweak: Makes Engineering related APCs overload proof. - - rscadd: Implements the timestop spell. - - rscadd: Implements new sepia slime reaction which halts time in an AoE. - - tweak: sentience potions no longer can make slimes sentient. - - tweak: Removes Hulk instant stun. - - tweak: Hulk damage increased. - - tweak: Hulk wears off at a lower health threshold. - - bugfix: Fixes strange reagent not working on simple animals. - - tweak: Reduces the amount shock damage and bounces for the Tesla engine. - - bugfix: Fixes Syndicate Cyborg's LMG being invisible. - - bugfix: Fixes the uplink kit having implanters that were both nameless and looked - as if they had been used. - KasparoVy: - - rscadd: Added the security gasmask, sexy mime mask, bandanas, balaclava, welding - gas mask and wrestling masks for Vox. Added adjusted-state sprites for the Vox - breath, medical, and surgical masks. - - rscdel: Removed a duplicate of the human balaclava sprite. - - tweak: Modifies the Vox plague-doctor, fake moustache, sterile and medical mask - sprites to fit the Vox anatomy and animates the Vox SWAT mask. Corrects the - names of some Vox mask adjusted-state sprites. - Tastyfish: - - spellcheck: Fixed the pronouns in a few verbs and the door to 'Interrogation Observervtion'. - Tigercat2000: - - rscadd: Added 96x96 (3x) res option to icons menu -2016-01-11: - CrAzYPiLoT: - - bugfix: Fixes the footsteps sounds to the fullest. - Crazylemon: - - rscadd: Bomb guardians now automatically notify their master when they've set - something to boom, so there's less accidental friendly fire - - bugfix: Bomb guardians are only notified that their trap failed, if it ACTUALLY - FAILED. - - rscadd: Bomb guardians now are more aware of what is primed to explode. - - rscadd: Bomb guardian summoners can now defuse their guardian's bombs without - harm. - - rscadd: Brought RAGIN' MAGES back up to function. - Dave The Headcrab: - - rscadd: Added a new icon for the soy and cafe latte drinks. Icons courtesy of - Full Of Skittles, resident overlord of art. - Fox McCloud: - - rscadd: Re-arranges the armory and changes its contents minorly. - - rscadd: Adds in rubbershot ammo boxes. - - bugfix: Fixes Mutadone incurring a massive cost on the server. - - tweak: Positronic brains can no longer speak binary. - - tweak: Positronic brains can be prevented from speaking (or allowed) by toggling - their speaker on/off. - - tweak: IPC's positronic brains start off toggled off. - - bugfix: Fixes the supermatter announcement causing massive amounts of server lag. - - rscadd: Adds in tradable telecrystals. -2016-01-13: - Fox McCloud: - - bugfix: Fixes Rezadone not clearing mutated organs. - - tweak: Clone damage immunity removed from Slime People, Shadowlings, Golems, and - Vox - - tweak: Explosions will no longer destroy things underneath turfs until the turf - is exposed. - - bugfix: fixes a runtime related to revolver spinning. - - bugfix: fixes server loading taking an abnormally long time. - Kyep: - - rscadd: Blob, vine and virus outbreaks are now more clearly labeled as such, to - avoid people confusing them with each other - Tastyfish: - - tweak: NT Rep fountain pens and magistrate gold pens can now write in 5 different - colors. The IAA gets a cheap plastic equivalent. -2016-01-18: - Crazylemon: - - rscadd: New classes of shapeshifters have been sighted around the NSS Cyberiad... - - bugfix: Wizards now can't teleport to other antag spawn points. - - bugfix: Removes an extruding pixel from the left-facing IPC glider monitor sprite. - - tweak: Ragin' Mages now spawn every 7 minutes, instead of 5. Admins can further - adjust this by modifying the 'delay_per_mage' variable. - - bugfix: Ragin' Mages are now made with 100% less in-use souls (Apprentices won't - have their consciousness yoinked). - - tweak: It takes half an hour for the REAL chaos of ragin' mages to start, for - at least a semblance of normality. - Dave The Headcrab: - - rscadd: Adds the advanced energy revolver, toggles between taser and laser modes. - - rscdel: Removes the detective's revolver from the blueshield's locker. - - tweak: Changes the taser the blueshield starts with into an advanced energy revolver. - Deanthelis: - - rscadd: Added the ability for the Magnetic Gripper to pick up and place light - tiles. - Fethas: - - bugfix: Readds the hud icon showing up for master and servent - - rscadd: adds mindslave datum hud thingy based on TGs gang huds - Fox McCloud: - - bugfix: Fixes not being able to add/remove Weapon Permit from IDs. - - bugfix: Fixes the energy sword being invisible in-hand when turned on. - - bugfix: Fixes the telebaton being invisible in-hand when extended. - - bugfix: Fixes eye-stabbing not having an attack animation or hitsound. - - bugfix: Fixes some kitchen utensils playing the wrong hit-sound and playing twice - in some cases. - - bugfix: Fixes the butcher cleaver sprite being backwards. - - bugfix: Fixes the telebaton sprite being missing from the side. - - bugfix: Fixes the meat cleaver being invisible in-hand. - - spellcheck: Corrects some grammatical descriptive errors for the elite syndicate - hardsuit. - - rscadd: completely overhauls implants to TG's standards. - - rscadd: Adds storage implant. - - rscadd: Adds microbomb and macrobomb implants. - - rscadd: Adds in support for removing implants directly into cases. - - rscdel: Removes Bay style explosive implants. - - rscdel: Removes compressed matter implants. - - tweak: Tweaks the uplink to reflect removal of the old implants and inclusion - of the new. - - bugfix: Fixes/cuts down on the lag caused by monkey cubes. - Jey: - - tweak: Inflatable walls and door can now be deflated by altclicking them - - bugfix: Fixed lag from expanding multiple monkeycubes at once. - KasparoVy: - - imageadd: Adds blank icons with standardized timings for species tail wagging, - used in icon generation. - - bugfix: Fixes tails overlapping arms/limbs + gloves, etc. when facing EAST or - WEST. - - bugfix: Ensures tails will overlap stuff as normal only when facing NORTH so as - to avoid unwanted interference with the base sprite. - - bugfix: Tails now appear in ID cards, overlays things correctly. - - bugfix: Tails now overlay and are overlaid by things correctly in preview icons. - - tweak: Modifies the positioning of tail icon generation in the ID card preview - icon generation file. - - tweak: Modifies the positioning of tail icon generation in the player preferences - preview icon generation file. - - tweak: Breaks limb generation into its own layer, breaks tail generation into - a second layer that can be overlaid by limbs. - - tweak: If the user's species is flagged to have a tail that is overlapped, TAIL_LAYER - will now overlay the NORTH direction sprite of a tail now, while TAIL_UNDERLIMBS_LAYER - gets all remaining directions. Otherwise icons are generated in the traditional - manner. - - tweak: Adjusts the Unathi right arm east direction and animated tail sprites, - recolouring a random pixel and fixing a floating tail respectively. - - tweak: Adjusts position of tail layer such that tails' north direction sprites - will overlay backpacks (more importantly, satchel straps). - - tweak: Accommodates admin-overrides to the body_accessory species check by setting - the default animation template to Vulpkanin. - - tweak: Adjusts north-direction Unathi static tail sprite, now attaches to the - body in the correct location. - - rscadd: Adds some TG underwear. - - rscadd: Adds an NV science goggles worn sprite. - - rscadd: Ports Bay/TG berets. - - tweak: Adjusts beret sprite, recolours strange orange pixels. - - tweak: Adjusts NV science goggles object icon. Removed strange border and centered - it. - - rscadd: Ports Polaris' PRs 761 and 778, brings over Ragnie's awesome Ward-Takahashi - prosthetics. - Kyep: - - rscadd: Changing level to gamma/delta/epsilon now displays a special gamma/delta/epsilon - sprite on status monitors - - bugfix: Changing level to green/blue now clears the status monitors, so they no - longer show higher alert levels after the level is changed - NTSAM: - - rscadd: Added a rainbow IPC screen. - PPI: - - tweak: Modifies the effective time limit to activate the Nuclear Challenge as - Nukeops from two minutes to seven minutes - Tastyfish: - - rscadd: The QM now actually has a QM stamp instead of a fake one, as well as an - approved and denied stamp. - - rscadd: New area named 'Genetics Maintenance' solidifying/relabelling the confusing - area between the morge and Mech Bay as being fully maintenance again, but working - correctly and with proper doors. - - spellcheck: Fixed a few maintenance door names to be in parity to the rest of - the station. - - rscadd: Added the ability to print the records photo of a crew member from a security - records console. Useful for Wanted notices! - Tigercat2000: - - rscdel: You can no longer use the gibber for monkies. - - spellcheck: Cleaned up gibber.dm styling. - - rscadd: The fire alarm now uses NanoUI, with color coded alert levels. - - tweak: Upgraded NanoUI (again), fancy FontAwesome icons. - - wip: Didn't add any butts. Yet. -2016-01-20: - DarkPyrolord: - - rscadd: Adds in hardsuit sprites for Vulpkanin - FalseIncarnate: - - rscadd: Allowed cheap lighters and individual matches to be put into cigarette - packages at the cost of cigarette space. - - rscadd: Matches can now be lit and put out by striking the match on your shoes. - Good for if you lose that matchbox, or want to just feel cool. - Fox McCloud: - - bugfix: Fixes brute damage on weapons not knocking people down. - - tweaks: Tweaks implant behavior to be more consistent and unified. - - tweak: Lowers the pAI cooldown from 60 seconds to 5 seconds. - - rscadd: Raw telecrystal can now be used to charge uplink implants. - - bugfix: Fixes being unable to holster the pulse pistol - - bugfix: Fixes being able to holster shotguns - KasparoVy: - - tweak: Improved shading on all Vulpkanin hardsuit tails. - - tweak: Vulpkanin hardsuit helmet respriting (colour tweaks). - - rscadd: Vulpkanin hardsuit helmets with proper flashlight-on sprites. - Tastyfish: - - tweak: The ID computer Access Report printout now separates the access list with - commas so it's actually readable. - - bugfix: The ID computer Access Report printout isn't blank if you don't have an - authorization card in anymore. - - rscadd: In the supply ordering & shuttle consoles, one can now cancel an order - at either the Reason or Amount input dialogs. - - bugfix: Table flipping uses correct sprites. - TheDZD: - - rscadd: Adds world.Topic() handling so that users are notified in-game when pull - requests are opened, closed, or merged on the Github repo. -2016-01-23: - Fox McCloud: - - rscdel: Removes Vampire HUD - - tweak: moves the Vampire blood counter to a more easy to see location - - rscadd: Adds in a Changeling chemical counter display - - rscadd: Adds in a Changeling sting counter display - - rscadd: Vampire total blood and usable blood will now appear under status - - tweak: Changes vampire blood display to be similar to ling chemical counter - - bugfix: Fixes unnecessary toxin damage being dealt on severe bloodloss - - bugfix: Fixes human mobs not receiving proper random names - - rscadd: Adds in knight armor - - rscadd: Grants the chaplain a set of crusader knight armor - - rscadd: Adds in cult-resistant ERT paranormal space suit - - rscadd: Allows the Chaplain to convert his null rod into a holy sword with crusader - knight armor - - tweak: Chaplain's closet is now a secure closet - - rscadd: Adds in Assault Gear crate to cargo - - rscadd: Adds in military assault belt - - rcsadd: Adds in spaceworthy swat suits - - tweak: tweaks bandolier to hold 2 additional shotgun shells - - tweak: bartender starts off with +2 additional shells - - tweak: Reduces the cost of the space suit crate and doubles its contents - - rscadd: Refactors knives so their behavior is more universal - - bugfix: Fixes Hulk not properly being removed when your health drops below a threshold - - bugfix: Fixes flickering vision in a mining mech - Tastyfish: - - rscadd: Poly has taken a seminar on the latest trends in engine operations. - - rscadd: Player-controller parrots can now hear their headsets. - Tigerbat2000: - - bugfix: The nuclear disk escaping on the shuttle no longer counts as a syndicate - minor victory. - - bugfix: Cultists can once again actually greentext the escape objective. -2016-01-24: - KasparoVy: - - bugfix: Fixes markings overlaying underwear. - - rscadd: Nude icon in underwear.dmi - - bugfix: Fixes Vox robes not using the correct on-mob sprites. - - bugfix: Fixes unreported bug where there was a slim chance during character preview - icon generation that a character with Security Officer set to high would get - rendered with either the wrong beret sprite or no beret sprite at all. - - bugfix: Fixes an issue where Sigholt's fluff beret wasn't using the correct sprites. - Tastyfish: - - bugfix: Passively power-consuming borg modules, such as the peacekeeper movement - and shield module, won't spam the user infinitely if they're low on power anymore. -2016-01-29: - Crazylemon: - - bugfix: 'The DNA scanner has now undergone a seminar to recognize fake identities; - It will now scan the actual person''s identity, rather than their disguise (read: - wearing a mask with or without someone else''s ID).' - - rscadd: Matter eater now allows you to eat humans as if you were fat. - - tweak: Eating mobs with an aggressive grab now generates attack logs. - Crazylemon64: - - bugfix: For a short while, there was a clerical error where all AI communications - equipment was replaced with bananas. This has now been fixed. - - tweak: Ghosts can now see the contents of smartfridges and look at the drone console - - tweak: Humans now only produce one message when shaken while SSD - - bugfix: The supermatter no longer will irradiate everyone, everywhere, when it - explodes. - - tweak: Writing on paper will now add hidden admin fingerprints, so that you can't - forge mean notes in someone else's name. - - bugfix: Brains are no longer able to escape their brain by being a sorcerer. - - bugfix: Astral projecting with other runes on the same tile will now no longer - prevent you from re-entering - - bugfix: Voxxy that is become ex-voxxy no longer carry voxxy appearance! yaya! - FalseIncarnate: - - tweak: Allows plants to be identified as enhanced*. Enhancing plants results from - using reagents (like saltpetre) that affect the stats of a seed instead of using - mutagens/machines. *May not meet standards for being classified as "organic - produce". (This was already possible, just renames enhanced plants for easier - differentiation) - Fox McCloud: - - bugfix: Fixes mutadone not working with some genetic mutations - - bugfix: Fixes banana honk and silencer being alcoholic - - bugfix: Fixes Kahlua being non-alcoholic - - bugfix: Fixes polonium not metabolizing - - bugfix: Fixes being able to receive free unlimited boxes from the Merchandise - store - - rscadd: Adds in wooden bucklers - - tweak: Re-adds roman shield to the costume vendor - - tweak: Buffs Riot shield damage from 8 to 10 - - rscadd: Adds in a Skeleton race - - tweak: Tweaks the skeletons colors to be more realistic and to blend in less with - the floor - - rscadd: Adds in lichdom spell for the wizard - - rscadd: Adds in lesser summon guns spell for wizard - - rscadd: adds in Mjolnir and the singularity hammer as weapons the wizard can purchase - - rscadd: Wizard can purchase the charge spell from the spell book - - rscadd: Wizard can purchase a healing staff from the spell book - - tweak: Tweaks and lowers spell costs of utility spells for wizard - - tweak: Re-organizes the spellbook to be better divided into categories and have - a better window size - - tweak: Knock now opens+unlocks lockers - - tweak: Magic Missile has a slightly longer cooldown and no longer deals damage, - but has a lower cooldown is upgraded - KasparoVy: - - rscadd: Navy blue Centcom Officer's beret for use by the Blueshield. - - rscadd: Adds the new navy blue beret to the Blueshield's locker. - - tweak: Gives the Blueshield's berets (black and navy blue) the exact same strip - delay and armour as the Security Officer's beret. - - rscadd: Adds TG energy katana back and belt sprite. - - rscadd: Bo staff back sprite. - - tweak: Adjusts energy katana sprites to make the weapon stand out a bit more from - the regular katana. - - rscadd: Cutting open the toes of footwear so species with feet-claws can wear - them. - - rscadd: Toeless jackboots. - - tweak: Cleans up glovesnipping and lighting a match with a shoe. - - tweak: Lighting a match with a shoe produces a more appropriate message, handled - at the same standard as glove-snippingboot-cutting. - Tastyfish: - - rscadd: Cargonia now has its own section in the manifest. - TheDZD: - - rscdel: Due to budget cuts and reports of operatives accidentally firing enough - bullets to reach a state of what our scientists refer to as "enough dakka," - Syndicate High Command has decided to restore the Syndicate Strike Team arsenal - to using standard-issue L6 SAW ammunition. -2016-01-31: - Crazylemon64: - - bugfix: Syndicate borgs can now interact with station machinery - - rscadd: People with slime people limbs can now *squish - - tweak: Skrell's vulnerability to alcohol is checked on their liver, now - a liver - transplant will let them take alcohol like a champ - lacking a liver will have - the same effect as being a skrell, when drinking - FalseIncarnate: - - rscadd: Adds in the Magic Eight Ball toy, found in Claw Game prize orbs. - - rscadd: Adds in the Magic Conch Shell, an admin-only shell of power. - Fox McCloud: - - rscadd: Updates Summon Guns and Magic to include many of the new guns - - tweak: Summon Guns/Magic can no longer be used during Ragin' Mages - Tastyfish: - - rscadd: The emergency shuttle status in the Status tab now has ETA/ETD/etc like - before. - - tweak: Code Gamma+ now has a 5 minute emergency shuttle call, like Red. - pinatacolada: - - rscadd: Adds NanoUI to the operating computer - - rscadd: Adds health announcing, critical and oxygen damage aural alerts to the - computer, with a menu to selectively turn them on and off -2016-02-10: - Crazylemon64: - - tweak: The cloner now checks for NO_SCAN on the brain when scanning - unclonable - species are now truly unclonable. You are still able to revive them with a brain - transplant and a defib, however. - - rscadd: A tier-4 DNA scanner linked to a cloning system will now be able to reproduce - a body from a brain's DNA, in event of the original corpse being gibbed or similar. - - bugfix: Species with organic limbs and NO_BLOOD will no longer bleed (though still - on hit - write that off as "bone powder") - - tweak: Skeletons now lack internal organs, except for the runic mind which exists - in their head - an analogue for the brain - - rscadd: Skeletons that drink milk will be regenerated at a moderate pace, have - a small chance of mending bones, and will praise the great name of mr skeltal - - tweak: Adds a reagent system for species reacting to specific reagents - - rscadd: Slime People can now select from all human hairstyles, and their "hair" - will be tinted a shade of their body. - - tweak: Increases the frequency of the cortical borer event. - - tweak: People with borers cannot commit suicide - this applies to a controlling - borer, too. - - tweak: Borers can no longer overdose their hosts. - - tweak: Borers can now inject Saline-Glucose, Spaceacillin, Hydrocodone, Mitocholide, - Salbutamol, Capulettium+, and Charcoal. Styptic was removed, as it's pathetic - at healing when directly injected. Salicyclic acid was removed too, as its functionality - is duplicated by both hydrocodone and saline-glucose. - - bugfix: A mind trapped by a cortical borer can now understand things it could - understand when normally in its body. - - rscadd: Changes chemistry's welding tank to a wall-mounted version, to increase - the room available. - - rscadd: You can now gib butterflies and lizards with a knife - - rscadd: Ghosts can now follow mecha - - bugfix: You can now access an R&D console by emagging it - it did nothing before. - - bugfix: Walls will now properly smooth and show damage. - - bugfix: Fixes the dialog that occurs when the AI shuts off to actually do what - it says it does - Fox McCloud: - - bugfix: Fixes not being able to attach IEDs to beartraps - - bugfix: Can no longer spamclick someone to death using headslamming on a toilet/urimal - - tweak: Toilet/urinal headslamming now plays a sound - - tweak: Toilet headslamming damage reduced slightly - - rscadd: Can now fill open reagent containers in a toilet to receive "toilet water". - - tweak: No more message spam when someone fills a container using a sink - - rscadd: Can now wash your face using a sink, which washes away lipstick and wakes - you up slightly - - tweak: Washing things will now use progress bars - - tweak: Ensures consuming a single syndicate donk pocket won't get you addicted - to meth - - tweak: Kinetic Accelerators and E-bows automatically reload - Glorken: - - rscadd: Added a Knight Arena for Holodeck. - - imageadd: Added red and blue claymore sprites. - - spellcheck: Changed overrided to overrode when emagging Holodeck computer. - KasparoVy: - - rscadd: Vox versions of the Officer SWAT sechailer + HOS SWAT sechailer + Warden - SWAT sechailer. - - rscadd: Resprited versions of most Human masks to fit Unathi, Tajara and Vulpkanin. - - rscadd: Warden now gets their own version of the SWAT sechailer in their locker. - - tweak: HOS now gets the appropriate version of the SWAT sechailer in their locker. - - tweak: Repositioned smokeables now available for Vox, Unathi, Tajara and Vulpkanin. - - tweak: Properly shades Vox bandana down-state sprites. - - rscadd: Readds Tajaran bald hairstyle. - - rscadd: Alternate style of non-Human breath mask (incl. surgical/sterile mask) - down-state positioning. - - tweak: Corrects all non-Human species' breath mask (incl. surgical/sterile mask) - down-state icons to use the right position style. - - tweak: Minor adjustments to Tajaran breath mask up-state sprites. - PPI: - - rscadd: Adds a reconnect button to the File menu in the client. - - rscadd: Adds head patting - Regen: - - tweak: Powersink can now drain a lot more power before going boom - - tweak: Buffed the powersinks drain rate - - tweak: Buffed explosion from an overloaded powersink, try to find it instead of - overloading the grid. - - rscadd: Admin log warning before the powersink explodes - Spacemanspark: - - rscadd: Miners can now utilize the power of mob capsules to take along their lazarus - injected mining creatures! - - rscadd: Store your Pokemo- er, sorry, I mean mining mobs that you've captured - in the lazarus capsule belt. - Tastyfish: - - bugfix: Species that don't breathe can kill themselves now! - - rscadd: Suicide messages are now catered to your species. - - tweak: Shortened the default pill & patch name when using the ChemMaster. - - rscadd: The chaplain now has a service radio headset, as Space Jesus intended. - TheDZD: - - tweak: When Ahelping, "Question" is now "Mentorhelp" and "Player Complaint" is - now "Adminhelp." - - tweak: Mentorhelps and PM replies from mentors appear in a bold aqua blue color. - - tweak: Adminhelps and PM replies from admins appear in a bold bright red color. - - tweak: PM replies from players appear in a dull/dark purple color. - - rscadd: Adds admin attack log to players being converted to cult. - - rscadd: Adds shadowling thrall jobbans. - - rscadd: Jobbanned players who are converted to shadowling thrall, revolutionary, - or cultist will have the control of their body offered up to eligible ghosts. -2016-02-13: - Crazylemon64: - - tweak: Relaxes the check on what atoms you can follow to any movable atom - - tweak: Mages are now more ragin - - tweak: Admins can now adjust the total number of wizards at runtime by tweaking - either max_mages, or players_per mage - DaveTheHeadcrab: - - rscadd: Adds new worn icons for duffelbags to better reflect their size, compliments - of WJohn at /tg/ - FalseIncarnate: - - rscadd: Adds burritos, made from cutlets, beans, rice, capsacin oil (hotsauce), - cheese, and flat dough (because we lack proper tortillas) in the microwave. - - rscadd: Adds chimichangas. You know you want a deep-fried burrito. - Fox McCloud: - - tweak: Updates some spell icons with better/higher quality icons - - tweak: Updates unarmed attacks to allow for more customization - - tweak: Updates martial arts so they factor in specie's attack messages and sounds - - tweak: Re-balances Sleeping Carp fighting style - - tweak: Re-balances Bo Staff - - tweak: 'Rebalances Golem: they should now be spaceproof, fire+cold proof, rad - proof, virus immune, clonable, parapen+syringe gun immune, deal increased melee - damage. Their armor has been reduced to 55 melee across the board, their slip - immunity removed, pain immunity removed, and they''re slightly slower' - - bugfix: Fixes Ei Nath generating two brains - - bugfix: Ensures the Necromatic Stone generates actual skeletons - - bugfix: Can now strip PDA/IDs from Golems - - bugfix: Fixes sleeping carp grab not being an instant aggressive grab - - bugfix: Fixes an exploit with declaring war on the station - KasparoVy: - - rscadd: Orange and purple bandanas for all station species. - - rscadd: The ability to colour bandanas with a crayon in a washing machine. - - tweak: Refactors the bandana adjustment system. - - tweak: Minor adjustments to Tajaran and Unathi bandana east/west sprites. - - tweak: Adjusting a bandana will now take if off of your head/face and put it in - an available hand. If both hands are available, it goes in the selected hand. - - bugfix: Adjusting a coloured bandana will no longer revert it to the original - coloured icons anymore. - - bugfix: Adjusting a bandana from mask-style to hat-style means the bandana won't - obscure your identity anymore. - - rscadd: Greys now use re-positioned smokeables. They no longer smoke out the eyes. - TheDZD: - - bugfix: Fixes spacepods being able to shoot through walls. - - tweak: Lowers spacepod weapons fire delay. - - tweak: Increases spacepod weapons energy costs. - - tweak: Makes spacepods move at speeds not rivaling those of photon beams. They - are now a hair bit faster than a person with a jetpack. - - tweak: Reduces battery costs for spacepod movement. -2016-02-24: - Crazylemon64: - - tweak: The defib should be more reliable on people who have ghosted - - tweak: The defib will now give a message if the ghost is still haunting about - - rscadd: Attacking someone with an accessory will now let you put things on them - without having to strip them. - - bugfix: Borers will now properly detach upon death of a mob they are controlling - - tweak: Borers can now see their chemical count while in control of a mob - - rscadd: Borers can now silently communicate with their host - this is not available - to the host until the borer has either begun to communicate, or has taken control - at least once - this is to avoid spoiling that the borer exists - - tweak: Borers won't be able to talk out loud inside of a host, by default - they - can remove this safeguard with a verb under their borer tab. Borer hivespeak - is unaffected. - - tweak: Borers infesting and hiding are now silent. - - tweak: Made borer's chem lists more nicely formatted - - bugfix: No more superspeed attacking simplemobs - - tweak: New players now show up properly under the "who" verb when used as an admin - - rscadd: Mining drones will now automatically collect sand lying around - - bugfix: RIPLEYs can now drill asteroid turfs for sand - - rscadd: You can now load exosuit fuel generators with items containing their material - - this means you can fuel yourself off of ores, but this will be highly inefficient - and cost you mining points later on, as you can't take fuel back out. - - rscadd: You can now load the fuel generators from an ore box. - - tweak: The plasma generator now produces 3x as much power from the same amount - of fuel - this lets it even remotely compete with the uranium generator. - - tweak: You can now light cigarettes off of burning mobs. - - tweak: Exosuit tracking beacons now fit in boxes - prior, they were far too large - for even a backpack, as they shared the same size as all other mecha equipment - - tweak: Miners can now collect ore by walking over it with an ore satchel on. - FalseIncarnate: - - rscadd: Adds prize tickets as a replacement for physical arcade prizes. - - rscadd: Adds a buildable prize counter to exchange tickets for prizes. - - rscadd: Adds a bike. Despite what Prof. Oak might claim, you can ride it indoors. - - rscadd: Adds colorful wallets, for that old school arcade pride. - - bugfix: Fixes accidental removal of plump helmet biscuit recipe. - - rscadd: Temporarily adds a prize counter to the bar (Cyberiad) or dorms (MetaStation), - and adds a max upgrade one to the Ninja Holding Area (Cyberiad z2) - - bugfix: Fixes Metastation. Seriously fixed a lot, just read the PR description - for the full list. - FlattestGuitar: - - rscadd: Adds IPC alcohol and a few derivative drinks - - tweak: IPCs can now drink and be fed from glasses - Fox McCloud: - - tweak: Laser eyes mutation no longer drains nutrition - - tweak: 'splits the EMP kit into two things: the standard EMP kit (2 grenades and - an implant), and the EMP flashlight by itself' - - tweak: nerfs heart attacks so they do less damage - - tweak: Pickpocket gloves now put the item you strip into your hands as opposed - to the floor - - tweak: Picketpocket gloves can now silently strip accessories - - tweak: Pickpocket gloves will no longer give a message for messing up a pickpocket - KasparoVy: - - bugfix: Adjusting masks while they are not on the face will no longer turn off - internals. - - bugfix: Adjusting masks while they are not on the face will now cause the mask - to hide/reveal the wearer's identity the next time it's worn as intended. - - rscadd: Adds the ability to open/close bomber jackets. - - rscadd: Adds a security bomber jacket. This jacket inherits the protection and - storage capabilities as a standard Security vest with additional bomber jacket - benefits. - - rscadd: Adds UI button in top left of screen for jacket adjustment. - - tweak: Replaces the standard bomber jacket in the Pod Pilot bay with the Security - version. - - tweak: Centralizes jacket/coat adjustment handling. - - tweak: All jackets start closed by default. - - rscadd: Geneticist duffelbag on-mob sprite (for all species). - - rscadd: Vox-fitted backpacks, satchels, ERT backpacks, duffelbags and defib unit. - - tweak: Refactors back-item icon generation. - - bugfix: Typo in the description of Santa's sack. - - bugfix: Missing punctuation and gender macros in the description of the bag of - holding. - - bugfix: The tweak to back-icon generation fixes a bug where the wrong sprite name - was being used to generate back-item icons. - PPI: - - rscadd: Adds the ability to hide papers in vents. You can now leave a romantic - love letter, exchange information in secret, or hide papers infused with the - power of nar'sie from sight. - Regen1: - - rscadd: Adds the Immolator laser gun, a modified laser gun with 8 shots that will - ignite mobs, can be made in R&D - Spacemanspark: - - rscadd: Adds *yes and *no emotes to Synthetics. Glory to Synthetica. - Tastyfish: - - tweak: The PDA system has been completely redone behind the scenes! It should - be functionally similar, although there is now a Home and Back button at the - bottom as appropriate. - - rscadd: All of the heads now have multicolored pens. - - rscadd: EngiVend now has 10 camera assemblies. - - tweak: Borgs can now use vending machines. - - rscadd: There are now picture frames that can be made from the autolathe or wood - planks for papers, photos, posters, and canvases! - pinatacolada: - - tweak: Makes the Protect Station AI law board no longer consider people that damage - the station crew, instead of human - ppi: - - tweak: When revealed Revenants will not be able to move at the maximum move speed, - nor be able to pass through any solid object, like walls, windows, grills, computers - and mechs. -2016-02-26: - FalseIncarnate: - - tweak: Chocolate can now make you fat, as expected. - Fox McCloud: - - tweak: stamina damage now regenerates slightly faster - - rscadd: Adds in whetstones for sharpening objects - - tweak: Kitchen vendor starts off with 5 salt+pepper shakers - - tweak: Can now point while lying or buckled - - bugfix: Fixes Capulettium Plus not silencing - - bugfix: Fixes slurring, stuttering, drugginess, and silences last half of what - they should - KasparoVy: - - bugfix: Jackets that start open are recognized as actually being open already - now. This fixes a bug with certain items that don't have an open state, or cases - where it ended up giving an item the wrong icon (one that didn't exist) - Spacemanspark: - - bugfix: Fixes synthetics from giving off the proper message in the chat box when - using the *yes and *no emotes. - Tastyfish: - - rscadd: Wheelchairs, janicarts, and ambulances can now go through doors according - to the user's driver's access. -2016-03-07: - Crazylemon64: - - rscadd: People with VAREDIT can now write matrix variables - - rscadd: People with VAREDIT can now modify path variables - - tweak: Refactors the variable editor code somewhat. - - rscadd: The buildmode area tool now shows reticules of what you've selected. - - bugfix: Switching mobs while using the buildmode tool no longer screws up your - UI. - - tweak: Refactors buildmode so it's no longer a special-case system. - - rscadd: Adds a copy mode to build mode, which lets you duplicate objects. - - tweak: Any mob in buildmode can work at the fastest possible rate. - - bugfix: Fixed a problem where the icons of a person would not correctly update - when changing gender. - - tweak: One's hairstyle only adjusts on gender change if it's incompatible with - your new gender. - - bugfix: Fixed a bug where a person's icon would only be updated if their sprite - had a new layer added or removed. - - bugfix: You no longer lose your name when monkeyized and reverted - you'll still - look like a monkey while you're a monkey, though. - - bugfix: Your organs will now match your gender when you are cloned. - - bugfix: Skeletons (when a body rots) no longer retain a fleshy torso. - - bugfix: Putting people in an active cryotube now produces the message on insertion, - rather than release. - - bugfix: An EMP'd cloning pod will now display its sprites correctly. - FalseIncarnate: - - tweak: Water Balloons can be filled from more sources than just beakers and watertanks. - Fox McCloud: - - bugfix: Fixes the "yeah" glasses so the sound doesn't vary and a message is displayed, - on use - - bugfix: Noir mode only activates when the glasses are equipped to your actual - eyes - - rscadd: Noir Glasses mode can be toggled on or off (defaults to off) - - bugfix: Mimes can no longer use spells and continue speaking - - tweak: Mime abilities are now spells with proper icons - - tweak: Mime wall now last 30 seconds, up from 5 - - tweak: forecfields/invisible walls now block air currents - - rscadd: Adds the Sleeping Carp scroll to the uplink for 17 TC - - bugfix: Fixes Shadowlings being able to use guns - - bugfix: Fixes sleeping carp scroll users being able to use guns - - bugfix: Fixes the Experimentor throwing one item at a time - - tweak: Experimentor menu now automatically refreshes after use - - tweak: Lowers surgery times across the board - - tweak: Removes scalpels causing 1 damage on successful surgery - - tweak: Removes random chance to fracture ribs on a successful surgery - - tweak: Mining drills now have an edge - KasparoVy: - - tweak: Jackets who have the verb available but are not intended to be adjusted - will not have the action button available. - - bugfix: You can now adjust breath masks while buckled into beds and chairs. - - bugfix: Known issues with adjusted jackets using the wrong sprites. - - rscadd: Blueshield coat in hand and item icons. - - rscadd: Hulks now rip apart adjustable and droppable jackets. The items stored - in the jackets get dropped on the ground. - Tastyfish: - - tweak: Infrared emitters can now be rotated while already in an assembly via the - UI popup. - - tweak: The infrared emitter can no longer be hidden inside of boxes and still - work. - - rscadd: The beach now has a border and is splashier. - - rscadd: Gives Psychiatrist a paper bin, clipboard, and multicolored pen. - - rscadd: Gives the Librarian / Jouralist a multicolored pen. - - rscadd: Gives the NT Representative a clipboard. - - tweak: The ethanol-based neurotoxin drink is now called Neuro-toxin to avoid being - confused with the deadly toxin. - VampyrBytes: - - bugfix: Fixes emotes ending with s needing 2. Emotes now work with grammatical - options eg ping or pings, squish or squishes - - tweak: Updated emote help with missing emotes. Help will also show any species - specific emotes for your current species -2016-03-08: - Crazylemon64: - - tweak: Slime people are now more vulnerable to low temperatures. - - rscadd: Slime people are able to slowly regrow limbs at a high nutrition cost. - - rscadd: Slime people now slowly shift color based on reagents inside of them - - disabled by default, toggle it with an IC verb - - tweak: Slime people's cores are more vulnerable to damage - - bugfix: Species-related abilities now properly are removed - no more vox hair - stylists, unfortunately. - Fethas: - - bugfix: the nest buckle now looks for the right organ path - - bugfix: Fixed some sprites. - - bugfix: No more putting no drops in rechargers, - Fox McCloud: - - soundadd: Implement's goon's gibbing sound - - soundadd: Implement's goon's gibbing sound for robots/silicons - - sounddel: Removes old gibbing sound - Spacemanspark: - - rscadd: Lazarus Injector's can now be emagged to activate their special features, - alongside using EMPs on them. - Tastyfish: - - rscadd: Mimes now have a new ore, Tranquillite, used to bring peace and quiet - to the station. - - rscadd: There are also permanent invisible walls and silent floors that can be - made from tranquillite. - - rscadd: The Recitence mech is now buildable! - - tweak: The Recitence mech is now playable! - - tweak: Mid-round selection for various creatures and antagonists now consistently - asks permission. - TheDZD: - - rscadd: Adds justice helmets with flashing lights and annoying sirens. - - rscadd: Adds crates containing said helmets. - - rscadd: Also includes a version of the helmet that can only be spawned by admins, - and just has a single red light in the center instead of the stereotypical police - blinkers. - monster860: - - bugfix: Space pod transitions are now fixed. -2016-03-16: - Crazylemon64: - - tweak: Being in godmode now makes you immune to bombs - - rscadd: Science members now get compensated when they ship tech disks to centcomm. - - rscdel: Science crew are no longer paid when they "max" research. - - bugfix: Roboticists now get credit for making RIPLEYs and Firefighters - - tweak: Slime people can now regrow limbs on a more lax nutrition requirement - - tweak: Enhances the nutripump+ to let slime people regrow limbs with it active - - bugfix: Skeletons, slime people, IPCs, and Diona no longer leave blood when hit - - bugfix: Rejuvenating a slime person will no longer clog up their "blood" - - tweak: Slime people will now regenerate "blood" from having water in their system - - tweak: The decloner can now be created again - - rscadd: Environment smashing mobs can now destroy girders. - DaveTheHeadcrab: - - tweak: Removes the check for species on the update_markings proc. - FalseIncarnate: - - tweak: Xeno-botany is now more user-friendly, and less random letters/numbers. - - rscadd: Hydroponics now has a connector hooked up to the isolation tray and a - new connector in their back room for those strange plants that like spewing - plasma or eating nitrogen. - - rscadd: You can now (finally) build the xeno-botany machines, and science can - print off their respective boards. - Fethas: - - tweak: Syringes are no longer sharp - - bugfix: byond likes direct pathing so item/organ/internal not item/organ even - if it shouldn't be in the internal_organs list. This was preventing the list - from doing stuff correctly. - - tweak: fixed ipc organ manipulation surgery, you can now insert a replacment ipc - organ directly instead of needing a screwdriver in your main hand - - bugfix: nanopaste now will repair organs with robotic >= 2 instead of > 2 cuase - i am an idiot - - bugfix: Fix, hopefully, for a runtime for clientless mobs whos head are cut off... - - bugfix: Hopefully fixes issues with diona eyes - - bugfix: Though shalt not eat robotic organs..including cybernetic implants.. - - bugfix: ITS SURGERY_STEP/DETHRALL NOT SURGERY_STEP/INTERNAL/DETHRALL - FlattestGuitar: - - rscadd: Adds three new synthanol drinks - - tweak: Drinking synthanol is now a bad idea if you're organic - - tweak: A glass of holy water now looks like normal water - Fox McCloud: - - soundadd: Adds in drink fizzing sound - - tweak: Drink/bartender recipes use this new fizzing sound in addition to a few - other recipes - - soundadd: Adds in a fuse burning sound - - tweak: Bath salts, black powder, saltpetre, and charcoal use this sound now - - soundadd: Adds in a matchstrike+burning sound - - tweak: Lighting a match triggers this new sound - - soundadd: Adds in scissors cutting sound - - tweak: Cutting someone's hair uses this new sound - - soundadd: Adds in printer sounds - - tweak: printing off papers from various devices typically uses these sounds - - soundadd: Adds computer ambience sounds - - tweak: black box recorder and R&D core servers both play this sound at random - rare intervals - - tweak: Reduces the tech level (and requirement) for nanopaste - - tweak: Reduces the tech level (and requirement) for the plasma pistol - - tweak: Removes Nymph and drone tech levels - - tweak: Reduces tech levels on the flora board - - tweak: Adds tech level requirements to mech sleepers, mech syringe guns, mech - tasers, and mech machine guns - - tweak: Increases tech cost of the decloner - - tweak: Removes the pacman generators - - tweak: Removes emitter - - tweak: Removes flora machine (functionless anyway) - - tweak: Removes the pre-spawned nanopaste - - tweak: Removes space suits - - tweak: Removes excavation gear - - tweak: Replaces the soil with actual hydroponic trays (more aesthetic than anything) - - tweak: Removes most external asteroid access from the station - - tweak: Excavation storage is now generic science storage - - tweak: removed the plasma sheet - - bugfix: Fixes augments not showing up in R&D unless specifically searched for - - bugfix: Fixes some augments being unavailable in mech fabs - - bugfix: Fixes augments having no construction time - - bugfix: Fixes xenos not gaining plasma when breathing in plasma - - bugfix: Fixes plasma reagent not generating plasma for a person - - rscadd: Screaming has different sounds based on being male or female - - soundadd: Implements Goon's screaming sounds. - - rscadd: Screaming tone is now based on age of character instead of being random - - tweak: Ups the cooldown on screaming from 2 seconds to 5 seconds - - tweak: Removes chance for Whilhelm scream - - rscadd: Borgs can now scream - - rscadd: Monkey's now have a unique screaming sound - - rscadd: IPCs now scream like cyborgs - - rscadd: Updates slot machines to have higher jackpots and more payouts with more - interesting sounds - - rscadd: 'Adds X-Ray, Thermal, Anti-tun, and Reviver implants to the nuke ops uplink - (augments come with one auto-implanter) rcsadd: Adds in augment auto-implanter, - which inserts and implant without surgery' - - tweak: tweaks a large number of chems; behaviors are largely retained, but new - flavor messages, probabilities, etc may be present; overall, you can expect - chems to do the same thing - - tweak: 'Tabun re-replaced with Sarin rcsadd: New reagent: cholesterol: if overdosed - on, it can cause a heart attack--fatty foods, cheese, eggs, and some meats all - produce cholesterol in your body.' - - rscadd: Mixing Sarin, Meth, or Cyanide will poison in a very small area of the - reaction if you're not on internal OR not wearing a gas mask - - rscadd: Chemist warddrobe now has two gas masks - - tweak: Teslium will now impact synthetics AND organics - - bugfix: Fixes facehuggers hugging already infected people - - bugfix: Fixes facehuggers hugging people while dead - - bugfix: Fixes Embryo's developing twice as fast as they should - - bugfix: Fixes up some behaviors with xeno eggs - - tweak: Xeno acid can now melt through floors and the asteroid - - rscadd: Xeno's now play the gib sound when actually gibbed - - rscadd: Implements Changeling headcrabs/headspiders - - bugfix: Fixes xenos not throwing their organs when gibbed - - bugfix: Fixes swallowed mobs not being ejected when a human is gibbed - - rscadd: Adds in spider eggs reagent, an infectious reagent that requires surgery - to correct - - bugfix: Fixes EMPs causing eye implant users to be permanently blind - - tweak: Increases bag of holding's storage capacity - - rscadd: Removing a heart no longer kills the patient instantly, but induces a - heart attack - - bugfix: Demon hearts will not work - - bugfix: Should now actually be able to re-insert hearts - - rscadd: Reworks addictions to bettter differentiate them betweeen overdosing and - make them more realistic. - - tweak: 'changes which chems are addictive, currently, the follow reagents are - now addidctive: meth, crank, krokodil, bath salts, space drugs, perfluoradecalin, - omnizine, coffee, nicotine, fliptonium, ultra lube, surge, fake cheese, weird - cheese, ephedrine, diphenhydramine, teporone, and morphine' - - rscadd: sleepers help you recover from addiction faster - - rscadd: Can now make cable coils in autolathes - - bugfix: Fixes the slot machine announcements not displaying properly - Tastyfish: - - tweak: The super fart mutation now gives you a spell-like ability instead of augmenting - the emote. - - tweak: Vampire abilities are now in their own Vampire tab, as well being action - buttons at the top, like spells. - - bugfix: Cloning a vampire no longer makes them lose their abilities. - - bugfix: Vampires can no longer hypnotize chaplains. - - bugfix: Being a full vampire (500+ total blood) actually makes you immune to holy - water reliably now. - - rscadd: 'Some old away missions are back: Academy, Black Market Packers, Space - Hotel, Station Collision, and Wild West. Go out and round up some hostiles!' - - bugfix: Shuttle consoles now pair up to the engineering, mining, research, or - labor shuttle when built or used before pairing, as long as the shuttle is near - the console, or the shuttle is moved to be nearby. - monster860: - - rscadd: Mining station now has a podbay. - - rscadd: Ore scooping module for the spacepod. - - rscadd: 'Three mining lasers for spacepod: Basic, normal, and burst.' - - bugfix: Shooting weapons south or west of spacepod will actually hit adjacent - targets now, and won't shoot through walls anymore. - taukausanake: - - rscadd: Mice can now be picked up like diona -2016-03-22: - Crazylemon64: - - bugfix: Repairs all sorts of eldritch occurences that happen when you put an organic - head on an IPC body, as well as some decapitation bugs - - bugfix: Makes heads keep hair on removal - - bugfix: Amputated limbs from a DNA-injected individual now will keep their appearance - of the DNA-injected person - - bugfix: Wounds will vanish on their own now - - rscadd: Admins now have an "incarnate" option on the player panel when viewing - ghosts for quick player instantiation - - bugfix: Fixes a runtime regarding failing a limb reconnection surgery - - bugfix: Copying a client's preferences now overrides the previous mob's DNA - - bugfix: A DNA injector is now more thorough, and affects the DNA of mobs' limbs - and organs - - bugfix: DNA-lacking species can no longer be DNA-injected - - bugfix: Brains are now labeled again - - rscadd: Splashing mitocholide on dead organs will make them live again. - - rscadd: The body scanner now detects necrotic limbs and organs. - - bugfix: pAIs and Drones are now affected by EMPs and explosions while held. - Fethas: - - rscadd: Adds a surgery for infection treatmne/autopsys that is simply cut open, - retract, cauterize - - bugfix: fixes a dumb error in internal bleeeding surgerys - - rscadd: Chaos types no longer random teleport, but will make the target hallucinate - everyone looks like the guardian. - FlattestGuitar: - - rscadd: Adds a snow, navy and desert military jacket. - Fox McCloud: - - tweak: Removes random 1% chance to heal fire damage - - tweak: Removes passive healing from resist heat mutation - - tweak: Regen mutation heals every cycle (albeit less, on average), but doesn't - cost hunger - - bugfix: Fixes not being able to speak over xeno common or hivemind when you receive - the Xeno hive node - - rscadd: Adds in the ability to transfer non-locked metal+glass only designs from - the protolathe to autolathe - - tweak: Changes Outpost Mass Driver to prevent accidental spacings - - tweak: Shadow people no longer dust on death, are rad immune+virus immune, and - can be cloned. Slip immunity removed - - tweak: Shadowlings no longer get hungry or fat and no longer dust on death - KasparoVy: - - rscadd: The ability to change your head, torso and groin as an IPC in the character - creator. Non-IPCs cannot access the parts. - - rscadd: Head, torso and groin sprites for all mechanical limb/bodypart brands - but Morpheus and the unbranded ones (since those already exist) from Polaris. - - rscadd: Faux-eye optics for non-Morpheus heads. - - rscadd: The ability to change optic (eye) colour if you've got a non-Morpheus - head. - - rscadd: The ability to choose human hair styles (wigs) and facial hair styles - (postiche) with non-Morpheus heads. Non-Morpheus heads cannot choose screens. - Conversely, Morpheus heads cannot choose wigs or facial hair. - - rscadd: Two hair styles from Polaris. - - rscadd: The ability for IPCs to wear undergarments (shirts and trousers). - - rscadd: Antennae (colourable) for IPCs. - - tweak: IPC monitor adjustment verb will now adjust optic colour if the head is - non-Morpheus. - - bugfix: Combat/SWAT boots can now be toecut and jacksandals can't. - - bugfix: ASAP fix to what would've broken the ability to configure prostheses in - character creation. - - bugfix: Adjusted masks no longer block CPR (including bandanas). - - bugfix: You can no longer run internals from adjusted breath masks (or airtight - adjustable masks in general). - Regens: - - tweak: Robotic hearts will now properly give the mob a heart attack instead of - just damaging it when EMP'd - - rscadd: Assisted organs will now also take damage from EMP's - - bugfix: Internal robotic and assisted organs will now actually take damage from - EMP's - Tastyfish: - - rscadd: Adds PDA chatrooms. Post memes! Talk to your fellow collaborators! Get - caught! - - tweak: You can now set the PDA messenger to automatically scroll down to new messages. - - rscadd: Pet collars now act as death alarms and can have ID's attached to them. - - tweak: All domestic animals can now wear collars. - - rscadd: You can now make video cameras at the autolathe. - TheDZD: - - bugfix: Fixes an instance of old code being so incredibly, unbelievably, makes-me-want-to-stab-myself-in-the-eye-edly - idiotic. - TravellingMerchant: - - imageadd: Kidan have new sprites! - tigercat2000: - - rscadd: Nukeops now have an assault pod, they can use it for 30 TC. Loud and mean. - - bugfix: Lighting overlays can no longer go below 0 lum_r/g/b - - bugfix: Shuttles will work with lighting better. - - bugfix: Wizards can no longer teleport to prohibited areas such as Central Command. -2016-03-25: - Crazylemon64: - - bugfix: You now will actually have the correct `real_name` on your DNA. - - bugfix: No more roundstart runtimes regarding IPC hair. - - bugfix: Mitocholide rejuv will work more usefully now. - - bugfix: Limbs and cyborg modules will no longer appear in your screen. - - bugfix: Cyborg module icons are now persistent throughout logging in and out. - - bugfix: Various cyborg modules, like engineering, now use the proper icon. - FlattestGuitar: - - rscadd: Adds confetti grenades. - Fox McCloud: - - bugfix: Fixes Sleeping Carp combos not having an attack animation - - bugfix: Fixes several chems not properly healing brute/burn damage, consistently, - as intended - KasparoVy: - - bugfix: Unbranded heads and groins no longer invisible. - - bugfix: Zeng-hu left leg will now be in line with the body when facing south. -2016-03-26: - Fox McCloud: - - rscadd: Adds in dental implant surgery. Implant pills into people's teeth. - - tweak: Major rebalance and Shadowling update (https://github.com/ParadiseSS13/Paradise/pull/3986 - for details). In general, Shadowlings can no longer enthrall or engage in Shadowling - like behavior, pre-hatch. Post-hatch, shadowlings are much more powerful, with - a ride array of New abilities such as extending the shuttle or making thralls - into lesser shadowlings. Shadowling gameplay should not revolve almost entirely - around darkness, as opposed to pre-hatch shenanigans. - - rscadd: Robotics now has a "sterile" surgical area for performing augmentations - - rscadd: Adds the FixOVein and Bone Gel to the autolathe - - tweak: ensures all surgical tools have origin tech on them; lowers origin tech - on FixoVein - KasparoVy: - - rscadd: Slime People can now wear underwear. - - rscadd: Slime People can now wear undershirts. - TheDZD: - - tweak: NT has removed trace amounts of a highly-addictive substance from the "100% - real" cheese used in cheese-flavored snacks. As a result, incidence rates of - crewmembers becoming addicted to Cheesie Honkers should reduce to zero. - - tweak: After receiving complaints about crewmembers often being unable to physically - function without a back-mounted barrel of coffee, NT has replaced station all - sources of coffee on the station, including coffee beans themselves with a largely - decaffeinated version. It was funny the first time almost every crewmember aboard - the NSS Cyberiad was lugging around their own oil barrel filled with coffee, - it wasn't so funny, nor good for productivity the eighteenth. -2016-04-02: - Crazylemon64: - - rscadd: Metal foam walls will now produce flooring on space tiles - - bugfix: Syringes will now draw water from slime people. - FalseIncarnate: - - tweak: Let's you know when your container is full when filling from sinks. - - tweak: Prevents splashing containers onto beakers and buckets that have a lid - on them. - - rscadd: Pill bottles can now be labeled with a simple pen. - - tweak: Beakers/buckets (and pill bottles) now accept 26 character labels from - pens. - Fethas: - - tweak: Various spells have had a tweak to stun/reveal/cast, some other number - stuff... - - rscadd: Nightvision - - tweak: harvest code is now in the abilites file. - - rscadd: New fluff objectives - - bugfix: Hell has recently remapped its blood transit system and you can now once - again crawl through blood. We are sorry for the-GIVE US YOUR SOUL! - FlattestGuitar: - - tweak: Alcoholic beverages now have proper levels of ethanol in them. Good luck - passing out after a beer. - Fox McCloud: - - rscadd: Adds in the Lusty Xenomorph Maid Mob; currently admin only. - - bugfix: Fixes xenomorph brains having the wrong sprite, no origin tech, and incorrect - name - - tweak: removes xenomorph egg from hotel - - tweak: upgrades are no longer needed to for the available toys in the prize vendor - - rscadd: Implements Advanced Camera Consoles. A type of camera console that function - like AI's vision style. Non-buildable/accessible. - - rscadd: Adds in Xenobiology Advance Cameras. A type of camera console that functions - like advanced cameras, but only works in Xenobiology areas; can move around - slimes and feed them with the console as well. Also non-buildable/accessible - (for now). - - rscadd: Adds in cerulean slime reaction that generates a single use blueprint. - On use it colors turfs a lavender color - - rscadd: Adds disease1 outbreak event - - rscadd: Adds appendecitis event - - rscadd: Roburgers now properly have nanomachines in them - - rscadd: Re-adds nanomachines - - tweak: Experimentor properly generates nanomachines instead of itching powder - - bugfix: Fixes big roburgers having a healing reagent in them - - rscadd: Adds nanomachines to poison traitor bottles - - rscadd: Tajarans can now eat mice, chicks, parrots, and tribbles - - rscadd: Vulpkanin and Unathi can now eat mice, chicks, lizards, chickens, crabs, - parrtos, and tribbles - - bugfix: fixes spawned changeling headcrab behavior - KasparoVy: - - bugfix: Incisions made at the beginning of embedded object removal surgery can - now be closed in the same procedure. - ProperPants: - - rscadd: Maint drones have magboots. - - rscdel: Removed plastic from maint drones. Literally useless for station maintenance. - - tweak: Increased starting amounts of some materials for maint drones and engi - borgs. - - experiment: Reduced the number of lines taken by Engineering cyborgs calling on - materials stacks. - - rscadd: Operating tables can be deconstructed with a wrench. - - spellcheck: Fixed and shortened description of metal sheets. - Tastyfish: - - rscadd: Bots can now be controlled by players, by opening them up and inserting - a pAI. *beep - - bugfix: MULEbots can now access the engineering destination. - - bugfix: All MULEbot destinations should now have the correct load/unload direction, - meaning the crates won't be dumped inside the flaps. - - rscadd: Diagnostic HUD's now give health and status information about bots. - - bugfix: MULEbot rampage blood tracks are now rendered correctly and handle UE - traces as appropriate. - - experiment: Bots should (hopefully) lag the game less now. - - tweak: Beepsky contains 30% more potato. - - tweak: Action progress bars are now smooth. - - tweak: Clicking a filled inventory slot's square with an open hand now clicks - the item in the slot. - - rscadd: Status displays now display the time when in Shuttle ETA mode and no shuttle - activity is happening. - - tweak: Shuttle ETA countdowns on status displays are now amber. - - rscadd: pAI's can now use the PDA chatrooms. - - rscadd: Adds treadmills to brig cells, to give the prisoners something productive - to do. - TheDZD: - - rscdel: A lot of the guns and armor in the station collision, space hotel, academy, - and wild west away missions have been removed/replaced. - - rscdel: Removes that fucking facehugger from station collision. - tigercat2000: - - rscdel: Virus2 has been removed. - - rscadd: Virus1 is back. Viva la revolution. - - rscadd: You can now have up to 20 characters. -2016-04-07: - Crazylemon64: - - bugfix: Removes an offset from the advanced virus stealth calculation, causing - viruses to be more stealthy than the sum of their symptoms. - - bugfix: Mulebots will now send announcements to relevant requests consoles on - delivery again. - FalseIncarnate: - - rscadd: Adds logic gates, for doing illogical things in a logical manner. - - rscadd: Adds buildable light switches, for all your light toggling needs. - - bugfix: Fixes a resource duplication bug with mass driver buttons. - Fethas: - - tweak: maybe makes them last longer...maybe..and fixes the event end message - Fox McCloud: - - rscadd: Maps in the slime management console to Xenobio - - tweak: Reduces Xenobio monkey box count from 4 to 2 - - bugfix: Fixes weakeyes having a negligible impact - - rscadd: Can spawn friendly animals with a new gold core reaction by injection - with water - - tweak: Hostile animal spawn increased from 3 to 5 for hostile gold cores - - tweak: Swarmers, revenants, and morphs no longer gold core spawnable - - bugfix: Fixes invisible animal spawns from gold core/life reactions - - rscadd: Adds tape to the ArtVend - - tweak: Can no longer use sentience potions on bots - - rscadd: Added in Plasma Dust reagent, acquired by grinding plasma sheets; it's - more toxic than regular plasma and generates plasma gas when spilled onto turfs. - - tweak: Slimecore reactions now require plasma dust as opposed to dispenser plasma - - rscadd: Added in new Rainbow slime; inject with plasma dust to get a random colored - slime. Acquire by having 100 mutation chance on a slime when it splits. - - rscadd: Monkey Recycler can produce different types of monkey cubes; change the - cube type by using a multitool on the recycler - - tweak: Epinephrine/plasma reagents changing mutation rate has been removed - - tweak: Mutation chance is inherited from slime generation to slime generation - as opposed to being purely random. - - tweak: 'New reactions added for red and blue extracts: red generates mutator, - which increases mutation chance, and blue generates stabilizer, which decreases - mutation chance.' - - tweak: Slime glycerol reaction removed - - tweak: Slime cells are now high capacity cells (more power than before) - - tweak: extract enhancer increases the slime core usage by 1 as oppose to setting - it to three - - tweak: slime enhancer increases slime cores by 1 as opposed to setting the core - amount to 3 - - tweak: Chill reaction lowers body temperature slightly more so it doesn't just - wear off instantly - - tweak: Reduces Xenobio plasma sheets from 8 to 3 and removes that pesky boombox - - bugfix: Processors no longer produce 1 more slime core than intended - - bugfix: Less blank/spriteless/empty foods from the silver core reaction - - tweak: Virology mix reactions now use plasma dust as opposed to plasma - - tweak: Statues can no longer move/attack people unless they're in total darkness - or all mobs viewing them are blinded - - tweak: statues are invincible to anything other than full out gibbing. - - tweak: Statues flicker lights spell range increased - - tweak: Blind spell no longer impacts silicons - - bugfix: Fixes statues being able to attack/move whenever they feel like it, regardless - of client statues - - bugfix: Fixes blind spell impacting the statue - Tastyfish: - - tweak: Beepsky is no longer a pokemon. - - tweak: pAI-controlled Bots now reliably speak human-understandable languages over - the radio. - - rscadd: More floor blood for the blood gods. (Or rather, as much as there was - supposed to be.) - tigercat2000: - - rscadd: Items in your off hand will now count towards access. -2016-04-12: - FalseIncarnate: - - tweak: Adjusting the setting of a vendor circuit board is no longer random, but - instead provides a select-able list. - - tweak: Vendor Circuit Board design moved from the Circuit Imprinter to the Autolathe, - acid requirement replaced by metal. - - bugfix: Burnt matches can no longer light cigarettes, pipes, or joints. - Fethas: - - rscdel: Nukes the cargo train code rscadd:Adds simple vehicle framework and converts - secway/janicart/snowmobiles/bikes/cars/ambulance to it rscadd:Adds space speedbike, - red and blue versions, yes you WILL need a spacesuit rscadd:Maps janicart and - secway onto metastation (but not ambulance no pareamedic garage, no i am not - mapping that) - - bugfix: You should now be able to operate on IPC eyes, SHOULD bugfix:hopefully - surgery on diona works right - Fox McCloud: - - rscadd: Adds in TraitorVamp; game mode that's essentially like TraitorChan, but - with a Vampire instead of a Changeling - - tweak: Vampires cannot use holoparasites - - tweak: Malf AI will automatically lose if it exits the station z-level - Tastyfish: - - tweak: All cats can kill mice now. - - tweak: E-N can't suffocate. - - tweak: Startup time is now shorter. - - rscdel: Removed the Station Collision away mission from rotation, due to multiple - conceptual and technical issues. -2016-04-14: - Aurorablade: - - rscdel: Removes the !!FUN!! of having headslugs gold core spawnable. - Fox McCloud: - - soundadd: Added in sounds (instead of a chat-based message) for when airlocks - are bolted/unbolted - - soundadd: Added in sound for when airlocks deny access - - tweak: cutting/pulsing wires will play a sound - - tweak: ups nuke ops game mode population requirement from 20 to 30 - - rscadd: Adds in mining drone upgrade modules to increase their health, combat - capability, or reduce their ranged cooldowns - - rscadd: Adds in mining drone "AI upgrade" a sentience potion that only works on - mining bots - - tweak: Mining bots should be less likely to shoot you when attacking hostile mobs - - tweak: Killer tomatoes actually live up to their name now and are hostile mobs - - tweak: Killer tomatoes are an actual fruit now; activate it in your hands to make - them into a mob - - tweak: Killer tomatoes are directly mutated from regular tomatoes instead of blood - tomatoes - - tweak: Increased the yield of regular tomatoes by 1 - - tweak: Tweak some stats on the killer tomato seeds - - bugfix: Fixes the blind player preference not doing anything - - rscadd: Adds portaseeder to R&D - - tweak: Scythes will conduct electricity now - - tweak: Mini hoes play a slice sound instead of bludgeon sound - - tweak: Plant analyzer properly has a description and origin tech - - tweak: Can have hulk+dwarf mutations together - - tweak: Can have heat+cold resist together - - tweak: Can only remotely view people who also have remote view - - bugfix: Fixes cold mutation not having an overlay - - bugfix: Hallucinations will no longer tick down twice as fast as they should nor - will they spawn twice as many hallucinations as they should - - bugfix: Incendiary mitochondria no longer asks who you want to cast it on (it - always is meant to be cast on yourself) - - bugfix: Fixes permanent nearsightedness even when wearing prescription glasses - KasparoVy: - - tweak: 'Head accessories now behave like facial hair: They will no longer be hidden - by clothing items that BLOCKHEADHAIR (have the BLOCKHEADHAIR flag).' - - bugfix: Wearing a piece of clothing that blocks head hair will no longer make - head accessories (facial markings/horns/antennae) invisible until an icon update - is triggered while the headwear is off. - Meisaka: - - bugfix: law manager no longer freaks out with Malf law - Tastyfish: - - tweak: The /vg/ library computer interface has been ported, giving a much better - use experience. - - rscadd: Books can now be flagged for inappropriate content. - TheDZD: - - rscdel: Removes shitty Caelcode bees. - - rscadd: Hydroponics can now manage bee colonies, bees produce honeycombs that - can be ground to obtain honey, a decent nutriment+healing chemical - - rscadd: Hydroponics can inject a queen bee with a syringe of a reagent to alter - her DNA to match that reagent, meaning all honeycombs produced will contain - that reagent in small amounts - - rscadd: Bees with reagents will attack with that reagent. It takes 5u of a reagent - to give a bee that reagent. - - rscadd: Added the ability to make Apiaries and Honey frames with wood - - rscadd: Added the ability to make Royal Bee Jelly from 10 Mutagen and 40 Honey - - rscadd: Added the ability to make more Queen Bees from Royal Bee Jelly by using - it on an existing Queen, to split her into two Queens - - rscdel: Removes some snowflakey mob behavior from bears, snakes and panthers. - - rscadd: Hudson is feeling punny. - - experiment: Hostile mob AI should now be a bit more cost-efficient. - monster860: - - rscadd: Adds area editing, link mode, and fill mode to the buildmode tool +DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. +--- +2016-01-03: + TheDZD: + - rscadd: Ports over changelog system from /tg/station. +2016-01-06: + Certhic: + - bugfix: Corrected some air alarms so that atmos computer can access them + - bugfix: Bodyscanner now sees mechanical parts in internal organs + Crazylemon64: + - bugfix: Sleeping simple animals should tick down sleeping as normal - deaf simple + mobs are no longer a thing + Tastyfish: + - tweak: Instruments now use NanoUI. + - spellcheck: Corrected the blueshield mission briefing. +2016-01-08: + Crazylemon: + - rscadd: Fully enables a system to allow species to have unique procs and verbs + that come and go with the species. + - rscdel: IPCs lose their change monitor verb when changing species now. Gone are + the days of recalling a past IPC life to perform self-barbery! Oh, woe is me! + - bugfix: Sleepers and Body Scanners will now reliably work when rotated + - bugfix: SSD humans should be asleep more reliably now. + Dave The Headcrab: + - tweak: Nerfs the damage the Detective's revolver does from 15 brute to 5 brute. + - rscadd: Adds a 300 round capacity buckshot magizine that fits into the L6 Saw. + - rscadd: Adds a 25 round capacity 40mm HE magizine that fits into the L6 Saw. + - rscadd: Adds the 'Devastator' L6 SAW, starts off loaded with the buckshot magizine. + - rscadd: Gives the SST the 'Devastator' L6 Saw, and one of each mag type in their + bag. + FalseIncarnate: + - rscadd: Plants will now begin to die over time if their age exceeds 5 times their + TRAIT_MATURATION value. + - tweak: 'Weed growth chance per process in trays has been slightly increased (Previously: + 5% chance if no seed, 1% otherwise;Now: 6% / 3%).' + - tweak: 'Pest growth in trays has been slightly buffed. (Previously: 3% chance + to increase by 0.1; Now: 5% chance to increase by 0.5)' + Fethas: + - rscadd: Due to Archmage Steve leaving the nya-cromantic stone near the microwave, + the true power of the stone has been unleashed. Subjects of the stone are not + only ressurected ... but resurrected as catgirls ... We fired steve. + Fox McCloud: + - bugfix: fixes a bug relating to some brute/burn damage being dealt to human mobs. + - rscadd: Adds in overloading APCs, causing them to arc electricity to mobs in range. + - tweak: Makes Engineering related APCs overload proof. + - rscadd: Implements the timestop spell. + - rscadd: Implements new sepia slime reaction which halts time in an AoE. + - tweak: sentience potions no longer can make slimes sentient. + - tweak: Removes Hulk instant stun. + - tweak: Hulk damage increased. + - tweak: Hulk wears off at a lower health threshold. + - bugfix: Fixes strange reagent not working on simple animals. + - tweak: Reduces the amount shock damage and bounces for the Tesla engine. + - bugfix: Fixes Syndicate Cyborg's LMG being invisible. + - bugfix: Fixes the uplink kit having implanters that were both nameless and looked + as if they had been used. + KasparoVy: + - rscadd: Added the security gasmask, sexy mime mask, bandanas, balaclava, welding + gas mask and wrestling masks for Vox. Added adjusted-state sprites for the Vox + breath, medical, and surgical masks. + - rscdel: Removed a duplicate of the human balaclava sprite. + - tweak: Modifies the Vox plague-doctor, fake moustache, sterile and medical mask + sprites to fit the Vox anatomy and animates the Vox SWAT mask. Corrects the + names of some Vox mask adjusted-state sprites. + Tastyfish: + - spellcheck: Fixed the pronouns in a few verbs and the door to 'Interrogation Observervtion'. + Tigercat2000: + - rscadd: Added 96x96 (3x) res option to icons menu +2016-01-11: + CrAzYPiLoT: + - bugfix: Fixes the footsteps sounds to the fullest. + Crazylemon: + - rscadd: Bomb guardians now automatically notify their master when they've set + something to boom, so there's less accidental friendly fire + - bugfix: Bomb guardians are only notified that their trap failed, if it ACTUALLY + FAILED. + - rscadd: Bomb guardians now are more aware of what is primed to explode. + - rscadd: Bomb guardian summoners can now defuse their guardian's bombs without + harm. + - rscadd: Brought RAGIN' MAGES back up to function. + Dave The Headcrab: + - rscadd: Added a new icon for the soy and cafe latte drinks. Icons courtesy of + Full Of Skittles, resident overlord of art. + Fox McCloud: + - rscadd: Re-arranges the armory and changes its contents minorly. + - rscadd: Adds in rubbershot ammo boxes. + - bugfix: Fixes Mutadone incurring a massive cost on the server. + - tweak: Positronic brains can no longer speak binary. + - tweak: Positronic brains can be prevented from speaking (or allowed) by toggling + their speaker on/off. + - tweak: IPC's positronic brains start off toggled off. + - bugfix: Fixes the supermatter announcement causing massive amounts of server lag. + - rscadd: Adds in tradable telecrystals. +2016-01-13: + Fox McCloud: + - bugfix: Fixes Rezadone not clearing mutated organs. + - tweak: Clone damage immunity removed from Slime People, Shadowlings, Golems, and + Vox + - tweak: Explosions will no longer destroy things underneath turfs until the turf + is exposed. + - bugfix: fixes a runtime related to revolver spinning. + - bugfix: fixes server loading taking an abnormally long time. + Kyep: + - rscadd: Blob, vine and virus outbreaks are now more clearly labeled as such, to + avoid people confusing them with each other + Tastyfish: + - tweak: NT Rep fountain pens and magistrate gold pens can now write in 5 different + colors. The IAA gets a cheap plastic equivalent. +2016-01-18: + Crazylemon: + - rscadd: New classes of shapeshifters have been sighted around the NSS Cyberiad... + - bugfix: Wizards now can't teleport to other antag spawn points. + - bugfix: Removes an extruding pixel from the left-facing IPC glider monitor sprite. + - tweak: Ragin' Mages now spawn every 7 minutes, instead of 5. Admins can further + adjust this by modifying the 'delay_per_mage' variable. + - bugfix: Ragin' Mages are now made with 100% less in-use souls (Apprentices won't + have their consciousness yoinked). + - tweak: It takes half an hour for the REAL chaos of ragin' mages to start, for + at least a semblance of normality. + Dave The Headcrab: + - rscadd: Adds the advanced energy revolver, toggles between taser and laser modes. + - rscdel: Removes the detective's revolver from the blueshield's locker. + - tweak: Changes the taser the blueshield starts with into an advanced energy revolver. + Deanthelis: + - rscadd: Added the ability for the Magnetic Gripper to pick up and place light + tiles. + Fethas: + - bugfix: Readds the hud icon showing up for master and servent + - rscadd: adds mindslave datum hud thingy based on TGs gang huds + Fox McCloud: + - bugfix: Fixes not being able to add/remove Weapon Permit from IDs. + - bugfix: Fixes the energy sword being invisible in-hand when turned on. + - bugfix: Fixes the telebaton being invisible in-hand when extended. + - bugfix: Fixes eye-stabbing not having an attack animation or hitsound. + - bugfix: Fixes some kitchen utensils playing the wrong hit-sound and playing twice + in some cases. + - bugfix: Fixes the butcher cleaver sprite being backwards. + - bugfix: Fixes the telebaton sprite being missing from the side. + - bugfix: Fixes the meat cleaver being invisible in-hand. + - spellcheck: Corrects some grammatical descriptive errors for the elite syndicate + hardsuit. + - rscadd: completely overhauls implants to TG's standards. + - rscadd: Adds storage implant. + - rscadd: Adds microbomb and macrobomb implants. + - rscadd: Adds in support for removing implants directly into cases. + - rscdel: Removes Bay style explosive implants. + - rscdel: Removes compressed matter implants. + - tweak: Tweaks the uplink to reflect removal of the old implants and inclusion + of the new. + - bugfix: Fixes/cuts down on the lag caused by monkey cubes. + Jey: + - tweak: Inflatable walls and door can now be deflated by altclicking them + - bugfix: Fixed lag from expanding multiple monkeycubes at once. + KasparoVy: + - imageadd: Adds blank icons with standardized timings for species tail wagging, + used in icon generation. + - bugfix: Fixes tails overlapping arms/limbs + gloves, etc. when facing EAST or + WEST. + - bugfix: Ensures tails will overlap stuff as normal only when facing NORTH so as + to avoid unwanted interference with the base sprite. + - bugfix: Tails now appear in ID cards, overlays things correctly. + - bugfix: Tails now overlay and are overlaid by things correctly in preview icons. + - tweak: Modifies the positioning of tail icon generation in the ID card preview + icon generation file. + - tweak: Modifies the positioning of tail icon generation in the player preferences + preview icon generation file. + - tweak: Breaks limb generation into its own layer, breaks tail generation into + a second layer that can be overlaid by limbs. + - tweak: If the user's species is flagged to have a tail that is overlapped, TAIL_LAYER + will now overlay the NORTH direction sprite of a tail now, while TAIL_UNDERLIMBS_LAYER + gets all remaining directions. Otherwise icons are generated in the traditional + manner. + - tweak: Adjusts the Unathi right arm east direction and animated tail sprites, + recolouring a random pixel and fixing a floating tail respectively. + - tweak: Adjusts position of tail layer such that tails' north direction sprites + will overlay backpacks (more importantly, satchel straps). + - tweak: Accommodates admin-overrides to the body_accessory species check by setting + the default animation template to Vulpkanin. + - tweak: Adjusts north-direction Unathi static tail sprite, now attaches to the + body in the correct location. + - rscadd: Adds some TG underwear. + - rscadd: Adds an NV science goggles worn sprite. + - rscadd: Ports Bay/TG berets. + - tweak: Adjusts beret sprite, recolours strange orange pixels. + - tweak: Adjusts NV science goggles object icon. Removed strange border and centered + it. + - rscadd: Ports Polaris' PRs 761 and 778, brings over Ragnie's awesome Ward-Takahashi + prosthetics. + Kyep: + - rscadd: Changing level to gamma/delta/epsilon now displays a special gamma/delta/epsilon + sprite on status monitors + - bugfix: Changing level to green/blue now clears the status monitors, so they no + longer show higher alert levels after the level is changed + NTSAM: + - rscadd: Added a rainbow IPC screen. + PPI: + - tweak: Modifies the effective time limit to activate the Nuclear Challenge as + Nukeops from two minutes to seven minutes + Tastyfish: + - rscadd: The QM now actually has a QM stamp instead of a fake one, as well as an + approved and denied stamp. + - rscadd: New area named 'Genetics Maintenance' solidifying/relabelling the confusing + area between the morge and Mech Bay as being fully maintenance again, but working + correctly and with proper doors. + - spellcheck: Fixed a few maintenance door names to be in parity to the rest of + the station. + - rscadd: Added the ability to print the records photo of a crew member from a security + records console. Useful for Wanted notices! + Tigercat2000: + - rscdel: You can no longer use the gibber for monkies. + - spellcheck: Cleaned up gibber.dm styling. + - rscadd: The fire alarm now uses NanoUI, with color coded alert levels. + - tweak: Upgraded NanoUI (again), fancy FontAwesome icons. + - wip: Didn't add any butts. Yet. +2016-01-20: + DarkPyrolord: + - rscadd: Adds in hardsuit sprites for Vulpkanin + FalseIncarnate: + - rscadd: Allowed cheap lighters and individual matches to be put into cigarette + packages at the cost of cigarette space. + - rscadd: Matches can now be lit and put out by striking the match on your shoes. + Good for if you lose that matchbox, or want to just feel cool. + Fox McCloud: + - bugfix: Fixes brute damage on weapons not knocking people down. + - tweaks: Tweaks implant behavior to be more consistent and unified. + - tweak: Lowers the pAI cooldown from 60 seconds to 5 seconds. + - rscadd: Raw telecrystal can now be used to charge uplink implants. + - bugfix: Fixes being unable to holster the pulse pistol + - bugfix: Fixes being able to holster shotguns + KasparoVy: + - tweak: Improved shading on all Vulpkanin hardsuit tails. + - tweak: Vulpkanin hardsuit helmet respriting (colour tweaks). + - rscadd: Vulpkanin hardsuit helmets with proper flashlight-on sprites. + Tastyfish: + - tweak: The ID computer Access Report printout now separates the access list with + commas so it's actually readable. + - bugfix: The ID computer Access Report printout isn't blank if you don't have an + authorization card in anymore. + - rscadd: In the supply ordering & shuttle consoles, one can now cancel an order + at either the Reason or Amount input dialogs. + - bugfix: Table flipping uses correct sprites. + TheDZD: + - rscadd: Adds world.Topic() handling so that users are notified in-game when pull + requests are opened, closed, or merged on the Github repo. +2016-01-23: + Fox McCloud: + - rscdel: Removes Vampire HUD + - tweak: moves the Vampire blood counter to a more easy to see location + - rscadd: Adds in a Changeling chemical counter display + - rscadd: Adds in a Changeling sting counter display + - rscadd: Vampire total blood and usable blood will now appear under status + - tweak: Changes vampire blood display to be similar to ling chemical counter + - bugfix: Fixes unnecessary toxin damage being dealt on severe bloodloss + - bugfix: Fixes human mobs not receiving proper random names + - rscadd: Adds in knight armor + - rscadd: Grants the chaplain a set of crusader knight armor + - rscadd: Adds in cult-resistant ERT paranormal space suit + - rscadd: Allows the Chaplain to convert his null rod into a holy sword with crusader + knight armor + - tweak: Chaplain's closet is now a secure closet + - rscadd: Adds in Assault Gear crate to cargo + - rscadd: Adds in military assault belt + - rcsadd: Adds in spaceworthy swat suits + - tweak: tweaks bandolier to hold 2 additional shotgun shells + - tweak: bartender starts off with +2 additional shells + - tweak: Reduces the cost of the space suit crate and doubles its contents + - rscadd: Refactors knives so their behavior is more universal + - bugfix: Fixes Hulk not properly being removed when your health drops below a threshold + - bugfix: Fixes flickering vision in a mining mech + Tastyfish: + - rscadd: Poly has taken a seminar on the latest trends in engine operations. + - rscadd: Player-controller parrots can now hear their headsets. + Tigerbat2000: + - bugfix: The nuclear disk escaping on the shuttle no longer counts as a syndicate + minor victory. + - bugfix: Cultists can once again actually greentext the escape objective. +2016-01-24: + KasparoVy: + - bugfix: Fixes markings overlaying underwear. + - rscadd: Nude icon in underwear.dmi + - bugfix: Fixes Vox robes not using the correct on-mob sprites. + - bugfix: Fixes unreported bug where there was a slim chance during character preview + icon generation that a character with Security Officer set to high would get + rendered with either the wrong beret sprite or no beret sprite at all. + - bugfix: Fixes an issue where Sigholt's fluff beret wasn't using the correct sprites. + Tastyfish: + - bugfix: Passively power-consuming borg modules, such as the peacekeeper movement + and shield module, won't spam the user infinitely if they're low on power anymore. +2016-01-29: + Crazylemon: + - bugfix: 'The DNA scanner has now undergone a seminar to recognize fake identities; + It will now scan the actual person''s identity, rather than their disguise (read: + wearing a mask with or without someone else''s ID).' + - rscadd: Matter eater now allows you to eat humans as if you were fat. + - tweak: Eating mobs with an aggressive grab now generates attack logs. + Crazylemon64: + - bugfix: For a short while, there was a clerical error where all AI communications + equipment was replaced with bananas. This has now been fixed. + - tweak: Ghosts can now see the contents of smartfridges and look at the drone console + - tweak: Humans now only produce one message when shaken while SSD + - bugfix: The supermatter no longer will irradiate everyone, everywhere, when it + explodes. + - tweak: Writing on paper will now add hidden admin fingerprints, so that you can't + forge mean notes in someone else's name. + - bugfix: Brains are no longer able to escape their brain by being a sorcerer. + - bugfix: Astral projecting with other runes on the same tile will now no longer + prevent you from re-entering + - bugfix: Voxxy that is become ex-voxxy no longer carry voxxy appearance! yaya! + FalseIncarnate: + - tweak: Allows plants to be identified as enhanced*. Enhancing plants results from + using reagents (like saltpetre) that affect the stats of a seed instead of using + mutagens/machines. *May not meet standards for being classified as "organic + produce". (This was already possible, just renames enhanced plants for easier + differentiation) + Fox McCloud: + - bugfix: Fixes mutadone not working with some genetic mutations + - bugfix: Fixes banana honk and silencer being alcoholic + - bugfix: Fixes Kahlua being non-alcoholic + - bugfix: Fixes polonium not metabolizing + - bugfix: Fixes being able to receive free unlimited boxes from the Merchandise + store + - rscadd: Adds in wooden bucklers + - tweak: Re-adds roman shield to the costume vendor + - tweak: Buffs Riot shield damage from 8 to 10 + - rscadd: Adds in a Skeleton race + - tweak: Tweaks the skeletons colors to be more realistic and to blend in less with + the floor + - rscadd: Adds in lichdom spell for the wizard + - rscadd: Adds in lesser summon guns spell for wizard + - rscadd: adds in Mjolnir and the singularity hammer as weapons the wizard can purchase + - rscadd: Wizard can purchase the charge spell from the spell book + - rscadd: Wizard can purchase a healing staff from the spell book + - tweak: Tweaks and lowers spell costs of utility spells for wizard + - tweak: Re-organizes the spellbook to be better divided into categories and have + a better window size + - tweak: Knock now opens+unlocks lockers + - tweak: Magic Missile has a slightly longer cooldown and no longer deals damage, + but has a lower cooldown is upgraded + KasparoVy: + - rscadd: Navy blue Centcom Officer's beret for use by the Blueshield. + - rscadd: Adds the new navy blue beret to the Blueshield's locker. + - tweak: Gives the Blueshield's berets (black and navy blue) the exact same strip + delay and armour as the Security Officer's beret. + - rscadd: Adds TG energy katana back and belt sprite. + - rscadd: Bo staff back sprite. + - tweak: Adjusts energy katana sprites to make the weapon stand out a bit more from + the regular katana. + - rscadd: Cutting open the toes of footwear so species with feet-claws can wear + them. + - rscadd: Toeless jackboots. + - tweak: Cleans up glovesnipping and lighting a match with a shoe. + - tweak: Lighting a match with a shoe produces a more appropriate message, handled + at the same standard as glove-snippingboot-cutting. + Tastyfish: + - rscadd: Cargonia now has its own section in the manifest. + TheDZD: + - rscdel: Due to budget cuts and reports of operatives accidentally firing enough + bullets to reach a state of what our scientists refer to as "enough dakka," + Syndicate High Command has decided to restore the Syndicate Strike Team arsenal + to using standard-issue L6 SAW ammunition. +2016-01-31: + Crazylemon64: + - bugfix: Syndicate borgs can now interact with station machinery + - rscadd: People with slime people limbs can now *squish + - tweak: Skrell's vulnerability to alcohol is checked on their liver, now - a liver + transplant will let them take alcohol like a champ - lacking a liver will have + the same effect as being a skrell, when drinking + FalseIncarnate: + - rscadd: Adds in the Magic Eight Ball toy, found in Claw Game prize orbs. + - rscadd: Adds in the Magic Conch Shell, an admin-only shell of power. + Fox McCloud: + - rscadd: Updates Summon Guns and Magic to include many of the new guns + - tweak: Summon Guns/Magic can no longer be used during Ragin' Mages + Tastyfish: + - rscadd: The emergency shuttle status in the Status tab now has ETA/ETD/etc like + before. + - tweak: Code Gamma+ now has a 5 minute emergency shuttle call, like Red. + pinatacolada: + - rscadd: Adds NanoUI to the operating computer + - rscadd: Adds health announcing, critical and oxygen damage aural alerts to the + computer, with a menu to selectively turn them on and off +2016-02-10: + Crazylemon64: + - tweak: The cloner now checks for NO_SCAN on the brain when scanning - unclonable + species are now truly unclonable. You are still able to revive them with a brain + transplant and a defib, however. + - rscadd: A tier-4 DNA scanner linked to a cloning system will now be able to reproduce + a body from a brain's DNA, in event of the original corpse being gibbed or similar. + - bugfix: Species with organic limbs and NO_BLOOD will no longer bleed (though still + on hit - write that off as "bone powder") + - tweak: Skeletons now lack internal organs, except for the runic mind which exists + in their head - an analogue for the brain + - rscadd: Skeletons that drink milk will be regenerated at a moderate pace, have + a small chance of mending bones, and will praise the great name of mr skeltal + - tweak: Adds a reagent system for species reacting to specific reagents + - rscadd: Slime People can now select from all human hairstyles, and their "hair" + will be tinted a shade of their body. + - tweak: Increases the frequency of the cortical borer event. + - tweak: People with borers cannot commit suicide - this applies to a controlling + borer, too. + - tweak: Borers can no longer overdose their hosts. + - tweak: Borers can now inject Saline-Glucose, Spaceacillin, Hydrocodone, Mitocholide, + Salbutamol, Capulettium+, and Charcoal. Styptic was removed, as it's pathetic + at healing when directly injected. Salicyclic acid was removed too, as its functionality + is duplicated by both hydrocodone and saline-glucose. + - bugfix: A mind trapped by a cortical borer can now understand things it could + understand when normally in its body. + - rscadd: Changes chemistry's welding tank to a wall-mounted version, to increase + the room available. + - rscadd: You can now gib butterflies and lizards with a knife + - rscadd: Ghosts can now follow mecha + - bugfix: You can now access an R&D console by emagging it - it did nothing before. + - bugfix: Walls will now properly smooth and show damage. + - bugfix: Fixes the dialog that occurs when the AI shuts off to actually do what + it says it does + Fox McCloud: + - bugfix: Fixes not being able to attach IEDs to beartraps + - bugfix: Can no longer spamclick someone to death using headslamming on a toilet/urimal + - tweak: Toilet/urinal headslamming now plays a sound + - tweak: Toilet headslamming damage reduced slightly + - rscadd: Can now fill open reagent containers in a toilet to receive "toilet water". + - tweak: No more message spam when someone fills a container using a sink + - rscadd: Can now wash your face using a sink, which washes away lipstick and wakes + you up slightly + - tweak: Washing things will now use progress bars + - tweak: Ensures consuming a single syndicate donk pocket won't get you addicted + to meth + - tweak: Kinetic Accelerators and E-bows automatically reload + Glorken: + - rscadd: Added a Knight Arena for Holodeck. + - imageadd: Added red and blue claymore sprites. + - spellcheck: Changed overrided to overrode when emagging Holodeck computer. + KasparoVy: + - rscadd: Vox versions of the Officer SWAT sechailer + HOS SWAT sechailer + Warden + SWAT sechailer. + - rscadd: Resprited versions of most Human masks to fit Unathi, Tajara and Vulpkanin. + - rscadd: Warden now gets their own version of the SWAT sechailer in their locker. + - tweak: HOS now gets the appropriate version of the SWAT sechailer in their locker. + - tweak: Repositioned smokeables now available for Vox, Unathi, Tajara and Vulpkanin. + - tweak: Properly shades Vox bandana down-state sprites. + - rscadd: Readds Tajaran bald hairstyle. + - rscadd: Alternate style of non-Human breath mask (incl. surgical/sterile mask) + down-state positioning. + - tweak: Corrects all non-Human species' breath mask (incl. surgical/sterile mask) + down-state icons to use the right position style. + - tweak: Minor adjustments to Tajaran breath mask up-state sprites. + PPI: + - rscadd: Adds a reconnect button to the File menu in the client. + - rscadd: Adds head patting + Regen: + - tweak: Powersink can now drain a lot more power before going boom + - tweak: Buffed the powersinks drain rate + - tweak: Buffed explosion from an overloaded powersink, try to find it instead of + overloading the grid. + - rscadd: Admin log warning before the powersink explodes + Spacemanspark: + - rscadd: Miners can now utilize the power of mob capsules to take along their lazarus + injected mining creatures! + - rscadd: Store your Pokemo- er, sorry, I mean mining mobs that you've captured + in the lazarus capsule belt. + Tastyfish: + - bugfix: Species that don't breathe can kill themselves now! + - rscadd: Suicide messages are now catered to your species. + - tweak: Shortened the default pill & patch name when using the ChemMaster. + - rscadd: The chaplain now has a service radio headset, as Space Jesus intended. + TheDZD: + - tweak: When Ahelping, "Question" is now "Mentorhelp" and "Player Complaint" is + now "Adminhelp." + - tweak: Mentorhelps and PM replies from mentors appear in a bold aqua blue color. + - tweak: Adminhelps and PM replies from admins appear in a bold bright red color. + - tweak: PM replies from players appear in a dull/dark purple color. + - rscadd: Adds admin attack log to players being converted to cult. + - rscadd: Adds shadowling thrall jobbans. + - rscadd: Jobbanned players who are converted to shadowling thrall, revolutionary, + or cultist will have the control of their body offered up to eligible ghosts. +2016-02-13: + Crazylemon64: + - tweak: Relaxes the check on what atoms you can follow to any movable atom + - tweak: Mages are now more ragin + - tweak: Admins can now adjust the total number of wizards at runtime by tweaking + either max_mages, or players_per mage + DaveTheHeadcrab: + - rscadd: Adds new worn icons for duffelbags to better reflect their size, compliments + of WJohn at /tg/ + FalseIncarnate: + - rscadd: Adds burritos, made from cutlets, beans, rice, capsacin oil (hotsauce), + cheese, and flat dough (because we lack proper tortillas) in the microwave. + - rscadd: Adds chimichangas. You know you want a deep-fried burrito. + Fox McCloud: + - tweak: Updates some spell icons with better/higher quality icons + - tweak: Updates unarmed attacks to allow for more customization + - tweak: Updates martial arts so they factor in specie's attack messages and sounds + - tweak: Re-balances Sleeping Carp fighting style + - tweak: Re-balances Bo Staff + - tweak: 'Rebalances Golem: they should now be spaceproof, fire+cold proof, rad + proof, virus immune, clonable, parapen+syringe gun immune, deal increased melee + damage. Their armor has been reduced to 55 melee across the board, their slip + immunity removed, pain immunity removed, and they''re slightly slower' + - bugfix: Fixes Ei Nath generating two brains + - bugfix: Ensures the Necromatic Stone generates actual skeletons + - bugfix: Can now strip PDA/IDs from Golems + - bugfix: Fixes sleeping carp grab not being an instant aggressive grab + - bugfix: Fixes an exploit with declaring war on the station + KasparoVy: + - rscadd: Orange and purple bandanas for all station species. + - rscadd: The ability to colour bandanas with a crayon in a washing machine. + - tweak: Refactors the bandana adjustment system. + - tweak: Minor adjustments to Tajaran and Unathi bandana east/west sprites. + - tweak: Adjusting a bandana will now take if off of your head/face and put it in + an available hand. If both hands are available, it goes in the selected hand. + - bugfix: Adjusting a coloured bandana will no longer revert it to the original + coloured icons anymore. + - bugfix: Adjusting a bandana from mask-style to hat-style means the bandana won't + obscure your identity anymore. + - rscadd: Greys now use re-positioned smokeables. They no longer smoke out the eyes. + TheDZD: + - bugfix: Fixes spacepods being able to shoot through walls. + - tweak: Lowers spacepod weapons fire delay. + - tweak: Increases spacepod weapons energy costs. + - tweak: Makes spacepods move at speeds not rivaling those of photon beams. They + are now a hair bit faster than a person with a jetpack. + - tweak: Reduces battery costs for spacepod movement. +2016-02-24: + Crazylemon64: + - tweak: The defib should be more reliable on people who have ghosted + - tweak: The defib will now give a message if the ghost is still haunting about + - rscadd: Attacking someone with an accessory will now let you put things on them + without having to strip them. + - bugfix: Borers will now properly detach upon death of a mob they are controlling + - tweak: Borers can now see their chemical count while in control of a mob + - rscadd: Borers can now silently communicate with their host - this is not available + to the host until the borer has either begun to communicate, or has taken control + at least once - this is to avoid spoiling that the borer exists + - tweak: Borers won't be able to talk out loud inside of a host, by default - they + can remove this safeguard with a verb under their borer tab. Borer hivespeak + is unaffected. + - tweak: Borers infesting and hiding are now silent. + - tweak: Made borer's chem lists more nicely formatted + - bugfix: No more superspeed attacking simplemobs + - tweak: New players now show up properly under the "who" verb when used as an admin + - rscadd: Mining drones will now automatically collect sand lying around + - bugfix: RIPLEYs can now drill asteroid turfs for sand + - rscadd: You can now load exosuit fuel generators with items containing their material + - this means you can fuel yourself off of ores, but this will be highly inefficient + and cost you mining points later on, as you can't take fuel back out. + - rscadd: You can now load the fuel generators from an ore box. + - tweak: The plasma generator now produces 3x as much power from the same amount + of fuel - this lets it even remotely compete with the uranium generator. + - tweak: You can now light cigarettes off of burning mobs. + - tweak: Exosuit tracking beacons now fit in boxes - prior, they were far too large + for even a backpack, as they shared the same size as all other mecha equipment + - tweak: Miners can now collect ore by walking over it with an ore satchel on. + FalseIncarnate: + - rscadd: Adds prize tickets as a replacement for physical arcade prizes. + - rscadd: Adds a buildable prize counter to exchange tickets for prizes. + - rscadd: Adds a bike. Despite what Prof. Oak might claim, you can ride it indoors. + - rscadd: Adds colorful wallets, for that old school arcade pride. + - bugfix: Fixes accidental removal of plump helmet biscuit recipe. + - rscadd: Temporarily adds a prize counter to the bar (Cyberiad) or dorms (MetaStation), + and adds a max upgrade one to the Ninja Holding Area (Cyberiad z2) + - bugfix: Fixes Metastation. Seriously fixed a lot, just read the PR description + for the full list. + FlattestGuitar: + - rscadd: Adds IPC alcohol and a few derivative drinks + - tweak: IPCs can now drink and be fed from glasses + Fox McCloud: + - tweak: Laser eyes mutation no longer drains nutrition + - tweak: 'splits the EMP kit into two things: the standard EMP kit (2 grenades and + an implant), and the EMP flashlight by itself' + - tweak: nerfs heart attacks so they do less damage + - tweak: Pickpocket gloves now put the item you strip into your hands as opposed + to the floor + - tweak: Picketpocket gloves can now silently strip accessories + - tweak: Pickpocket gloves will no longer give a message for messing up a pickpocket + KasparoVy: + - bugfix: Adjusting masks while they are not on the face will no longer turn off + internals. + - bugfix: Adjusting masks while they are not on the face will now cause the mask + to hide/reveal the wearer's identity the next time it's worn as intended. + - rscadd: Adds the ability to open/close bomber jackets. + - rscadd: Adds a security bomber jacket. This jacket inherits the protection and + storage capabilities as a standard Security vest with additional bomber jacket + benefits. + - rscadd: Adds UI button in top left of screen for jacket adjustment. + - tweak: Replaces the standard bomber jacket in the Pod Pilot bay with the Security + version. + - tweak: Centralizes jacket/coat adjustment handling. + - tweak: All jackets start closed by default. + - rscadd: Geneticist duffelbag on-mob sprite (for all species). + - rscadd: Vox-fitted backpacks, satchels, ERT backpacks, duffelbags and defib unit. + - tweak: Refactors back-item icon generation. + - bugfix: Typo in the description of Santa's sack. + - bugfix: Missing punctuation and gender macros in the description of the bag of + holding. + - bugfix: The tweak to back-icon generation fixes a bug where the wrong sprite name + was being used to generate back-item icons. + PPI: + - rscadd: Adds the ability to hide papers in vents. You can now leave a romantic + love letter, exchange information in secret, or hide papers infused with the + power of nar'sie from sight. + Regen1: + - rscadd: Adds the Immolator laser gun, a modified laser gun with 8 shots that will + ignite mobs, can be made in R&D + Spacemanspark: + - rscadd: Adds *yes and *no emotes to Synthetics. Glory to Synthetica. + Tastyfish: + - tweak: The PDA system has been completely redone behind the scenes! It should + be functionally similar, although there is now a Home and Back button at the + bottom as appropriate. + - rscadd: All of the heads now have multicolored pens. + - rscadd: EngiVend now has 10 camera assemblies. + - tweak: Borgs can now use vending machines. + - rscadd: There are now picture frames that can be made from the autolathe or wood + planks for papers, photos, posters, and canvases! + pinatacolada: + - tweak: Makes the Protect Station AI law board no longer consider people that damage + the station crew, instead of human + ppi: + - tweak: When revealed Revenants will not be able to move at the maximum move speed, + nor be able to pass through any solid object, like walls, windows, grills, computers + and mechs. +2016-02-26: + FalseIncarnate: + - tweak: Chocolate can now make you fat, as expected. + Fox McCloud: + - tweak: stamina damage now regenerates slightly faster + - rscadd: Adds in whetstones for sharpening objects + - tweak: Kitchen vendor starts off with 5 salt+pepper shakers + - tweak: Can now point while lying or buckled + - bugfix: Fixes Capulettium Plus not silencing + - bugfix: Fixes slurring, stuttering, drugginess, and silences last half of what + they should + KasparoVy: + - bugfix: Jackets that start open are recognized as actually being open already + now. This fixes a bug with certain items that don't have an open state, or cases + where it ended up giving an item the wrong icon (one that didn't exist) + Spacemanspark: + - bugfix: Fixes synthetics from giving off the proper message in the chat box when + using the *yes and *no emotes. + Tastyfish: + - rscadd: Wheelchairs, janicarts, and ambulances can now go through doors according + to the user's driver's access. +2016-03-07: + Crazylemon64: + - rscadd: People with VAREDIT can now write matrix variables + - rscadd: People with VAREDIT can now modify path variables + - tweak: Refactors the variable editor code somewhat. + - rscadd: The buildmode area tool now shows reticules of what you've selected. + - bugfix: Switching mobs while using the buildmode tool no longer screws up your + UI. + - tweak: Refactors buildmode so it's no longer a special-case system. + - rscadd: Adds a copy mode to build mode, which lets you duplicate objects. + - tweak: Any mob in buildmode can work at the fastest possible rate. + - bugfix: Fixed a problem where the icons of a person would not correctly update + when changing gender. + - tweak: One's hairstyle only adjusts on gender change if it's incompatible with + your new gender. + - bugfix: Fixed a bug where a person's icon would only be updated if their sprite + had a new layer added or removed. + - bugfix: You no longer lose your name when monkeyized and reverted - you'll still + look like a monkey while you're a monkey, though. + - bugfix: Your organs will now match your gender when you are cloned. + - bugfix: Skeletons (when a body rots) no longer retain a fleshy torso. + - bugfix: Putting people in an active cryotube now produces the message on insertion, + rather than release. + - bugfix: An EMP'd cloning pod will now display its sprites correctly. + FalseIncarnate: + - tweak: Water Balloons can be filled from more sources than just beakers and watertanks. + Fox McCloud: + - bugfix: Fixes the "yeah" glasses so the sound doesn't vary and a message is displayed, + on use + - bugfix: Noir mode only activates when the glasses are equipped to your actual + eyes + - rscadd: Noir Glasses mode can be toggled on or off (defaults to off) + - bugfix: Mimes can no longer use spells and continue speaking + - tweak: Mime abilities are now spells with proper icons + - tweak: Mime wall now last 30 seconds, up from 5 + - tweak: forecfields/invisible walls now block air currents + - rscadd: Adds the Sleeping Carp scroll to the uplink for 17 TC + - bugfix: Fixes Shadowlings being able to use guns + - bugfix: Fixes sleeping carp scroll users being able to use guns + - bugfix: Fixes the Experimentor throwing one item at a time + - tweak: Experimentor menu now automatically refreshes after use + - tweak: Lowers surgery times across the board + - tweak: Removes scalpels causing 1 damage on successful surgery + - tweak: Removes random chance to fracture ribs on a successful surgery + - tweak: Mining drills now have an edge + KasparoVy: + - tweak: Jackets who have the verb available but are not intended to be adjusted + will not have the action button available. + - bugfix: You can now adjust breath masks while buckled into beds and chairs. + - bugfix: Known issues with adjusted jackets using the wrong sprites. + - rscadd: Blueshield coat in hand and item icons. + - rscadd: Hulks now rip apart adjustable and droppable jackets. The items stored + in the jackets get dropped on the ground. + Tastyfish: + - tweak: Infrared emitters can now be rotated while already in an assembly via the + UI popup. + - tweak: The infrared emitter can no longer be hidden inside of boxes and still + work. + - rscadd: The beach now has a border and is splashier. + - rscadd: Gives Psychiatrist a paper bin, clipboard, and multicolored pen. + - rscadd: Gives the Librarian / Jouralist a multicolored pen. + - rscadd: Gives the NT Representative a clipboard. + - tweak: The ethanol-based neurotoxin drink is now called Neuro-toxin to avoid being + confused with the deadly toxin. + VampyrBytes: + - bugfix: Fixes emotes ending with s needing 2. Emotes now work with grammatical + options eg ping or pings, squish or squishes + - tweak: Updated emote help with missing emotes. Help will also show any species + specific emotes for your current species +2016-03-08: + Crazylemon64: + - tweak: Slime people are now more vulnerable to low temperatures. + - rscadd: Slime people are able to slowly regrow limbs at a high nutrition cost. + - rscadd: Slime people now slowly shift color based on reagents inside of them - + disabled by default, toggle it with an IC verb + - tweak: Slime people's cores are more vulnerable to damage + - bugfix: Species-related abilities now properly are removed - no more vox hair + stylists, unfortunately. + Fethas: + - bugfix: the nest buckle now looks for the right organ path + - bugfix: Fixed some sprites. + - bugfix: No more putting no drops in rechargers, + Fox McCloud: + - soundadd: Implement's goon's gibbing sound + - soundadd: Implement's goon's gibbing sound for robots/silicons + - sounddel: Removes old gibbing sound + Spacemanspark: + - rscadd: Lazarus Injector's can now be emagged to activate their special features, + alongside using EMPs on them. + Tastyfish: + - rscadd: Mimes now have a new ore, Tranquillite, used to bring peace and quiet + to the station. + - rscadd: There are also permanent invisible walls and silent floors that can be + made from tranquillite. + - rscadd: The Recitence mech is now buildable! + - tweak: The Recitence mech is now playable! + - tweak: Mid-round selection for various creatures and antagonists now consistently + asks permission. + TheDZD: + - rscadd: Adds justice helmets with flashing lights and annoying sirens. + - rscadd: Adds crates containing said helmets. + - rscadd: Also includes a version of the helmet that can only be spawned by admins, + and just has a single red light in the center instead of the stereotypical police + blinkers. + monster860: + - bugfix: Space pod transitions are now fixed. +2016-03-16: + Crazylemon64: + - tweak: Being in godmode now makes you immune to bombs + - rscadd: Science members now get compensated when they ship tech disks to centcomm. + - rscdel: Science crew are no longer paid when they "max" research. + - bugfix: Roboticists now get credit for making RIPLEYs and Firefighters + - tweak: Slime people can now regrow limbs on a more lax nutrition requirement + - tweak: Enhances the nutripump+ to let slime people regrow limbs with it active + - bugfix: Skeletons, slime people, IPCs, and Diona no longer leave blood when hit + - bugfix: Rejuvenating a slime person will no longer clog up their "blood" + - tweak: Slime people will now regenerate "blood" from having water in their system + - tweak: The decloner can now be created again + - rscadd: Environment smashing mobs can now destroy girders. + DaveTheHeadcrab: + - tweak: Removes the check for species on the update_markings proc. + FalseIncarnate: + - tweak: Xeno-botany is now more user-friendly, and less random letters/numbers. + - rscadd: Hydroponics now has a connector hooked up to the isolation tray and a + new connector in their back room for those strange plants that like spewing + plasma or eating nitrogen. + - rscadd: You can now (finally) build the xeno-botany machines, and science can + print off their respective boards. + Fethas: + - tweak: Syringes are no longer sharp + - bugfix: byond likes direct pathing so item/organ/internal not item/organ even + if it shouldn't be in the internal_organs list. This was preventing the list + from doing stuff correctly. + - tweak: fixed ipc organ manipulation surgery, you can now insert a replacment ipc + organ directly instead of needing a screwdriver in your main hand + - bugfix: nanopaste now will repair organs with robotic >= 2 instead of > 2 cuase + i am an idiot + - bugfix: Fix, hopefully, for a runtime for clientless mobs whos head are cut off... + - bugfix: Hopefully fixes issues with diona eyes + - bugfix: Though shalt not eat robotic organs..including cybernetic implants.. + - bugfix: ITS SURGERY_STEP/DETHRALL NOT SURGERY_STEP/INTERNAL/DETHRALL + FlattestGuitar: + - rscadd: Adds three new synthanol drinks + - tweak: Drinking synthanol is now a bad idea if you're organic + - tweak: A glass of holy water now looks like normal water + Fox McCloud: + - soundadd: Adds in drink fizzing sound + - tweak: Drink/bartender recipes use this new fizzing sound in addition to a few + other recipes + - soundadd: Adds in a fuse burning sound + - tweak: Bath salts, black powder, saltpetre, and charcoal use this sound now + - soundadd: Adds in a matchstrike+burning sound + - tweak: Lighting a match triggers this new sound + - soundadd: Adds in scissors cutting sound + - tweak: Cutting someone's hair uses this new sound + - soundadd: Adds in printer sounds + - tweak: printing off papers from various devices typically uses these sounds + - soundadd: Adds computer ambience sounds + - tweak: black box recorder and R&D core servers both play this sound at random + rare intervals + - tweak: Reduces the tech level (and requirement) for nanopaste + - tweak: Reduces the tech level (and requirement) for the plasma pistol + - tweak: Removes Nymph and drone tech levels + - tweak: Reduces tech levels on the flora board + - tweak: Adds tech level requirements to mech sleepers, mech syringe guns, mech + tasers, and mech machine guns + - tweak: Increases tech cost of the decloner + - tweak: Removes the pacman generators + - tweak: Removes emitter + - tweak: Removes flora machine (functionless anyway) + - tweak: Removes the pre-spawned nanopaste + - tweak: Removes space suits + - tweak: Removes excavation gear + - tweak: Replaces the soil with actual hydroponic trays (more aesthetic than anything) + - tweak: Removes most external asteroid access from the station + - tweak: Excavation storage is now generic science storage + - tweak: removed the plasma sheet + - bugfix: Fixes augments not showing up in R&D unless specifically searched for + - bugfix: Fixes some augments being unavailable in mech fabs + - bugfix: Fixes augments having no construction time + - bugfix: Fixes xenos not gaining plasma when breathing in plasma + - bugfix: Fixes plasma reagent not generating plasma for a person + - rscadd: Screaming has different sounds based on being male or female + - soundadd: Implements Goon's screaming sounds. + - rscadd: Screaming tone is now based on age of character instead of being random + - tweak: Ups the cooldown on screaming from 2 seconds to 5 seconds + - tweak: Removes chance for Whilhelm scream + - rscadd: Borgs can now scream + - rscadd: Monkey's now have a unique screaming sound + - rscadd: IPCs now scream like cyborgs + - rscadd: Updates slot machines to have higher jackpots and more payouts with more + interesting sounds + - rscadd: 'Adds X-Ray, Thermal, Anti-tun, and Reviver implants to the nuke ops uplink + (augments come with one auto-implanter) rcsadd: Adds in augment auto-implanter, + which inserts and implant without surgery' + - tweak: tweaks a large number of chems; behaviors are largely retained, but new + flavor messages, probabilities, etc may be present; overall, you can expect + chems to do the same thing + - tweak: 'Tabun re-replaced with Sarin rcsadd: New reagent: cholesterol: if overdosed + on, it can cause a heart attack--fatty foods, cheese, eggs, and some meats all + produce cholesterol in your body.' + - rscadd: Mixing Sarin, Meth, or Cyanide will poison in a very small area of the + reaction if you're not on internal OR not wearing a gas mask + - rscadd: Chemist warddrobe now has two gas masks + - tweak: Teslium will now impact synthetics AND organics + - bugfix: Fixes facehuggers hugging already infected people + - bugfix: Fixes facehuggers hugging people while dead + - bugfix: Fixes Embryo's developing twice as fast as they should + - bugfix: Fixes up some behaviors with xeno eggs + - tweak: Xeno acid can now melt through floors and the asteroid + - rscadd: Xeno's now play the gib sound when actually gibbed + - rscadd: Implements Changeling headcrabs/headspiders + - bugfix: Fixes xenos not throwing their organs when gibbed + - bugfix: Fixes swallowed mobs not being ejected when a human is gibbed + - rscadd: Adds in spider eggs reagent, an infectious reagent that requires surgery + to correct + - bugfix: Fixes EMPs causing eye implant users to be permanently blind + - tweak: Increases bag of holding's storage capacity + - rscadd: Removing a heart no longer kills the patient instantly, but induces a + heart attack + - bugfix: Demon hearts will not work + - bugfix: Should now actually be able to re-insert hearts + - rscadd: Reworks addictions to bettter differentiate them betweeen overdosing and + make them more realistic. + - tweak: 'changes which chems are addictive, currently, the follow reagents are + now addidctive: meth, crank, krokodil, bath salts, space drugs, perfluoradecalin, + omnizine, coffee, nicotine, fliptonium, ultra lube, surge, fake cheese, weird + cheese, ephedrine, diphenhydramine, teporone, and morphine' + - rscadd: sleepers help you recover from addiction faster + - rscadd: Can now make cable coils in autolathes + - bugfix: Fixes the slot machine announcements not displaying properly + Tastyfish: + - tweak: The super fart mutation now gives you a spell-like ability instead of augmenting + the emote. + - tweak: Vampire abilities are now in their own Vampire tab, as well being action + buttons at the top, like spells. + - bugfix: Cloning a vampire no longer makes them lose their abilities. + - bugfix: Vampires can no longer hypnotize chaplains. + - bugfix: Being a full vampire (500+ total blood) actually makes you immune to holy + water reliably now. + - rscadd: 'Some old away missions are back: Academy, Black Market Packers, Space + Hotel, Station Collision, and Wild West. Go out and round up some hostiles!' + - bugfix: Shuttle consoles now pair up to the engineering, mining, research, or + labor shuttle when built or used before pairing, as long as the shuttle is near + the console, or the shuttle is moved to be nearby. + monster860: + - rscadd: Mining station now has a podbay. + - rscadd: Ore scooping module for the spacepod. + - rscadd: 'Three mining lasers for spacepod: Basic, normal, and burst.' + - bugfix: Shooting weapons south or west of spacepod will actually hit adjacent + targets now, and won't shoot through walls anymore. + taukausanake: + - rscadd: Mice can now be picked up like diona +2016-03-22: + Crazylemon64: + - bugfix: Repairs all sorts of eldritch occurences that happen when you put an organic + head on an IPC body, as well as some decapitation bugs + - bugfix: Makes heads keep hair on removal + - bugfix: Amputated limbs from a DNA-injected individual now will keep their appearance + of the DNA-injected person + - bugfix: Wounds will vanish on their own now + - rscadd: Admins now have an "incarnate" option on the player panel when viewing + ghosts for quick player instantiation + - bugfix: Fixes a runtime regarding failing a limb reconnection surgery + - bugfix: Copying a client's preferences now overrides the previous mob's DNA + - bugfix: A DNA injector is now more thorough, and affects the DNA of mobs' limbs + and organs + - bugfix: DNA-lacking species can no longer be DNA-injected + - bugfix: Brains are now labeled again + - rscadd: Splashing mitocholide on dead organs will make them live again. + - rscadd: The body scanner now detects necrotic limbs and organs. + - bugfix: pAIs and Drones are now affected by EMPs and explosions while held. + Fethas: + - rscadd: Adds a surgery for infection treatmne/autopsys that is simply cut open, + retract, cauterize + - bugfix: fixes a dumb error in internal bleeeding surgerys + - rscadd: Chaos types no longer random teleport, but will make the target hallucinate + everyone looks like the guardian. + FlattestGuitar: + - rscadd: Adds a snow, navy and desert military jacket. + Fox McCloud: + - tweak: Removes random 1% chance to heal fire damage + - tweak: Removes passive healing from resist heat mutation + - tweak: Regen mutation heals every cycle (albeit less, on average), but doesn't + cost hunger + - bugfix: Fixes not being able to speak over xeno common or hivemind when you receive + the Xeno hive node + - rscadd: Adds in the ability to transfer non-locked metal+glass only designs from + the protolathe to autolathe + - tweak: Changes Outpost Mass Driver to prevent accidental spacings + - tweak: Shadow people no longer dust on death, are rad immune+virus immune, and + can be cloned. Slip immunity removed + - tweak: Shadowlings no longer get hungry or fat and no longer dust on death + KasparoVy: + - rscadd: The ability to change your head, torso and groin as an IPC in the character + creator. Non-IPCs cannot access the parts. + - rscadd: Head, torso and groin sprites for all mechanical limb/bodypart brands + but Morpheus and the unbranded ones (since those already exist) from Polaris. + - rscadd: Faux-eye optics for non-Morpheus heads. + - rscadd: The ability to change optic (eye) colour if you've got a non-Morpheus + head. + - rscadd: The ability to choose human hair styles (wigs) and facial hair styles + (postiche) with non-Morpheus heads. Non-Morpheus heads cannot choose screens. + Conversely, Morpheus heads cannot choose wigs or facial hair. + - rscadd: Two hair styles from Polaris. + - rscadd: The ability for IPCs to wear undergarments (shirts and trousers). + - rscadd: Antennae (colourable) for IPCs. + - tweak: IPC monitor adjustment verb will now adjust optic colour if the head is + non-Morpheus. + - bugfix: Combat/SWAT boots can now be toecut and jacksandals can't. + - bugfix: ASAP fix to what would've broken the ability to configure prostheses in + character creation. + - bugfix: Adjusted masks no longer block CPR (including bandanas). + - bugfix: You can no longer run internals from adjusted breath masks (or airtight + adjustable masks in general). + Regens: + - tweak: Robotic hearts will now properly give the mob a heart attack instead of + just damaging it when EMP'd + - rscadd: Assisted organs will now also take damage from EMP's + - bugfix: Internal robotic and assisted organs will now actually take damage from + EMP's + Tastyfish: + - rscadd: Adds PDA chatrooms. Post memes! Talk to your fellow collaborators! Get + caught! + - tweak: You can now set the PDA messenger to automatically scroll down to new messages. + - rscadd: Pet collars now act as death alarms and can have ID's attached to them. + - tweak: All domestic animals can now wear collars. + - rscadd: You can now make video cameras at the autolathe. + TheDZD: + - bugfix: Fixes an instance of old code being so incredibly, unbelievably, makes-me-want-to-stab-myself-in-the-eye-edly + idiotic. + TravellingMerchant: + - imageadd: Kidan have new sprites! + tigercat2000: + - rscadd: Nukeops now have an assault pod, they can use it for 30 TC. Loud and mean. + - bugfix: Lighting overlays can no longer go below 0 lum_r/g/b + - bugfix: Shuttles will work with lighting better. + - bugfix: Wizards can no longer teleport to prohibited areas such as Central Command. +2016-03-25: + Crazylemon64: + - bugfix: You now will actually have the correct `real_name` on your DNA. + - bugfix: No more roundstart runtimes regarding IPC hair. + - bugfix: Mitocholide rejuv will work more usefully now. + - bugfix: Limbs and cyborg modules will no longer appear in your screen. + - bugfix: Cyborg module icons are now persistent throughout logging in and out. + - bugfix: Various cyborg modules, like engineering, now use the proper icon. + FlattestGuitar: + - rscadd: Adds confetti grenades. + Fox McCloud: + - bugfix: Fixes Sleeping Carp combos not having an attack animation + - bugfix: Fixes several chems not properly healing brute/burn damage, consistently, + as intended + KasparoVy: + - bugfix: Unbranded heads and groins no longer invisible. + - bugfix: Zeng-hu left leg will now be in line with the body when facing south. +2016-03-26: + Fox McCloud: + - rscadd: Adds in dental implant surgery. Implant pills into people's teeth. + - tweak: Major rebalance and Shadowling update (https://github.com/ParadiseSS13/Paradise/pull/3986 + for details). In general, Shadowlings can no longer enthrall or engage in Shadowling + like behavior, pre-hatch. Post-hatch, shadowlings are much more powerful, with + a ride array of New abilities such as extending the shuttle or making thralls + into lesser shadowlings. Shadowling gameplay should not revolve almost entirely + around darkness, as opposed to pre-hatch shenanigans. + - rscadd: Robotics now has a "sterile" surgical area for performing augmentations + - rscadd: Adds the FixOVein and Bone Gel to the autolathe + - tweak: ensures all surgical tools have origin tech on them; lowers origin tech + on FixoVein + KasparoVy: + - rscadd: Slime People can now wear underwear. + - rscadd: Slime People can now wear undershirts. + TheDZD: + - tweak: NT has removed trace amounts of a highly-addictive substance from the "100% + real" cheese used in cheese-flavored snacks. As a result, incidence rates of + crewmembers becoming addicted to Cheesie Honkers should reduce to zero. + - tweak: After receiving complaints about crewmembers often being unable to physically + function without a back-mounted barrel of coffee, NT has replaced station all + sources of coffee on the station, including coffee beans themselves with a largely + decaffeinated version. It was funny the first time almost every crewmember aboard + the NSS Cyberiad was lugging around their own oil barrel filled with coffee, + it wasn't so funny, nor good for productivity the eighteenth. +2016-04-02: + Crazylemon64: + - rscadd: Metal foam walls will now produce flooring on space tiles + - bugfix: Syringes will now draw water from slime people. + FalseIncarnate: + - tweak: Let's you know when your container is full when filling from sinks. + - tweak: Prevents splashing containers onto beakers and buckets that have a lid + on them. + - rscadd: Pill bottles can now be labeled with a simple pen. + - tweak: Beakers/buckets (and pill bottles) now accept 26 character labels from + pens. + Fethas: + - tweak: Various spells have had a tweak to stun/reveal/cast, some other number + stuff... + - rscadd: Nightvision + - tweak: harvest code is now in the abilites file. + - rscadd: New fluff objectives + - bugfix: Hell has recently remapped its blood transit system and you can now once + again crawl through blood. We are sorry for the-GIVE US YOUR SOUL! + FlattestGuitar: + - tweak: Alcoholic beverages now have proper levels of ethanol in them. Good luck + passing out after a beer. + Fox McCloud: + - rscadd: Adds in the Lusty Xenomorph Maid Mob; currently admin only. + - bugfix: Fixes xenomorph brains having the wrong sprite, no origin tech, and incorrect + name + - tweak: removes xenomorph egg from hotel + - tweak: upgrades are no longer needed to for the available toys in the prize vendor + - rscadd: Implements Advanced Camera Consoles. A type of camera console that function + like AI's vision style. Non-buildable/accessible. + - rscadd: Adds in Xenobiology Advance Cameras. A type of camera console that functions + like advanced cameras, but only works in Xenobiology areas; can move around + slimes and feed them with the console as well. Also non-buildable/accessible + (for now). + - rscadd: Adds in cerulean slime reaction that generates a single use blueprint. + On use it colors turfs a lavender color + - rscadd: Adds disease1 outbreak event + - rscadd: Adds appendecitis event + - rscadd: Roburgers now properly have nanomachines in them + - rscadd: Re-adds nanomachines + - tweak: Experimentor properly generates nanomachines instead of itching powder + - bugfix: Fixes big roburgers having a healing reagent in them + - rscadd: Adds nanomachines to poison traitor bottles + - rscadd: Tajarans can now eat mice, chicks, parrots, and tribbles + - rscadd: Vulpkanin and Unathi can now eat mice, chicks, lizards, chickens, crabs, + parrtos, and tribbles + - bugfix: fixes spawned changeling headcrab behavior + KasparoVy: + - bugfix: Incisions made at the beginning of embedded object removal surgery can + now be closed in the same procedure. + ProperPants: + - rscadd: Maint drones have magboots. + - rscdel: Removed plastic from maint drones. Literally useless for station maintenance. + - tweak: Increased starting amounts of some materials for maint drones and engi + borgs. + - experiment: Reduced the number of lines taken by Engineering cyborgs calling on + materials stacks. + - rscadd: Operating tables can be deconstructed with a wrench. + - spellcheck: Fixed and shortened description of metal sheets. + Tastyfish: + - rscadd: Bots can now be controlled by players, by opening them up and inserting + a pAI. *beep + - bugfix: MULEbots can now access the engineering destination. + - bugfix: All MULEbot destinations should now have the correct load/unload direction, + meaning the crates won't be dumped inside the flaps. + - rscadd: Diagnostic HUD's now give health and status information about bots. + - bugfix: MULEbot rampage blood tracks are now rendered correctly and handle UE + traces as appropriate. + - experiment: Bots should (hopefully) lag the game less now. + - tweak: Beepsky contains 30% more potato. + - tweak: Action progress bars are now smooth. + - tweak: Clicking a filled inventory slot's square with an open hand now clicks + the item in the slot. + - rscadd: Status displays now display the time when in Shuttle ETA mode and no shuttle + activity is happening. + - tweak: Shuttle ETA countdowns on status displays are now amber. + - rscadd: pAI's can now use the PDA chatrooms. + - rscadd: Adds treadmills to brig cells, to give the prisoners something productive + to do. + TheDZD: + - rscdel: A lot of the guns and armor in the station collision, space hotel, academy, + and wild west away missions have been removed/replaced. + - rscdel: Removes that fucking facehugger from station collision. + tigercat2000: + - rscdel: Virus2 has been removed. + - rscadd: Virus1 is back. Viva la revolution. + - rscadd: You can now have up to 20 characters. +2016-04-07: + Crazylemon64: + - bugfix: Removes an offset from the advanced virus stealth calculation, causing + viruses to be more stealthy than the sum of their symptoms. + - bugfix: Mulebots will now send announcements to relevant requests consoles on + delivery again. + FalseIncarnate: + - rscadd: Adds logic gates, for doing illogical things in a logical manner. + - rscadd: Adds buildable light switches, for all your light toggling needs. + - bugfix: Fixes a resource duplication bug with mass driver buttons. + Fethas: + - tweak: maybe makes them last longer...maybe..and fixes the event end message + Fox McCloud: + - rscadd: Maps in the slime management console to Xenobio + - tweak: Reduces Xenobio monkey box count from 4 to 2 + - bugfix: Fixes weakeyes having a negligible impact + - rscadd: Can spawn friendly animals with a new gold core reaction by injection + with water + - tweak: Hostile animal spawn increased from 3 to 5 for hostile gold cores + - tweak: Swarmers, revenants, and morphs no longer gold core spawnable + - bugfix: Fixes invisible animal spawns from gold core/life reactions + - rscadd: Adds tape to the ArtVend + - tweak: Can no longer use sentience potions on bots + - rscadd: Added in Plasma Dust reagent, acquired by grinding plasma sheets; it's + more toxic than regular plasma and generates plasma gas when spilled onto turfs. + - tweak: Slimecore reactions now require plasma dust as opposed to dispenser plasma + - rscadd: Added in new Rainbow slime; inject with plasma dust to get a random colored + slime. Acquire by having 100 mutation chance on a slime when it splits. + - rscadd: Monkey Recycler can produce different types of monkey cubes; change the + cube type by using a multitool on the recycler + - tweak: Epinephrine/plasma reagents changing mutation rate has been removed + - tweak: Mutation chance is inherited from slime generation to slime generation + as opposed to being purely random. + - tweak: 'New reactions added for red and blue extracts: red generates mutator, + which increases mutation chance, and blue generates stabilizer, which decreases + mutation chance.' + - tweak: Slime glycerol reaction removed + - tweak: Slime cells are now high capacity cells (more power than before) + - tweak: extract enhancer increases the slime core usage by 1 as oppose to setting + it to three + - tweak: slime enhancer increases slime cores by 1 as opposed to setting the core + amount to 3 + - tweak: Chill reaction lowers body temperature slightly more so it doesn't just + wear off instantly + - tweak: Reduces Xenobio plasma sheets from 8 to 3 and removes that pesky boombox + - bugfix: Processors no longer produce 1 more slime core than intended + - bugfix: Less blank/spriteless/empty foods from the silver core reaction + - tweak: Virology mix reactions now use plasma dust as opposed to plasma + - tweak: Statues can no longer move/attack people unless they're in total darkness + or all mobs viewing them are blinded + - tweak: statues are invincible to anything other than full out gibbing. + - tweak: Statues flicker lights spell range increased + - tweak: Blind spell no longer impacts silicons + - bugfix: Fixes statues being able to attack/move whenever they feel like it, regardless + of client statues + - bugfix: Fixes blind spell impacting the statue + Tastyfish: + - tweak: Beepsky is no longer a pokemon. + - tweak: pAI-controlled Bots now reliably speak human-understandable languages over + the radio. + - rscadd: More floor blood for the blood gods. (Or rather, as much as there was + supposed to be.) + tigercat2000: + - rscadd: Items in your off hand will now count towards access. +2016-04-12: + FalseIncarnate: + - tweak: Adjusting the setting of a vendor circuit board is no longer random, but + instead provides a select-able list. + - tweak: Vendor Circuit Board design moved from the Circuit Imprinter to the Autolathe, + acid requirement replaced by metal. + - bugfix: Burnt matches can no longer light cigarettes, pipes, or joints. + Fethas: + - rscdel: Nukes the cargo train code rscadd:Adds simple vehicle framework and converts + secway/janicart/snowmobiles/bikes/cars/ambulance to it rscadd:Adds space speedbike, + red and blue versions, yes you WILL need a spacesuit rscadd:Maps janicart and + secway onto metastation (but not ambulance no pareamedic garage, no i am not + mapping that) + - bugfix: You should now be able to operate on IPC eyes, SHOULD bugfix:hopefully + surgery on diona works right + Fox McCloud: + - rscadd: Adds in TraitorVamp; game mode that's essentially like TraitorChan, but + with a Vampire instead of a Changeling + - tweak: Vampires cannot use holoparasites + - tweak: Malf AI will automatically lose if it exits the station z-level + Tastyfish: + - tweak: All cats can kill mice now. + - tweak: E-N can't suffocate. + - tweak: Startup time is now shorter. + - rscdel: Removed the Station Collision away mission from rotation, due to multiple + conceptual and technical issues. +2016-04-14: + Aurorablade: + - rscdel: Removes the !!FUN!! of having headslugs gold core spawnable. + Fox McCloud: + - soundadd: Added in sounds (instead of a chat-based message) for when airlocks + are bolted/unbolted + - soundadd: Added in sound for when airlocks deny access + - tweak: cutting/pulsing wires will play a sound + - tweak: ups nuke ops game mode population requirement from 20 to 30 + - rscadd: Adds in mining drone upgrade modules to increase their health, combat + capability, or reduce their ranged cooldowns + - rscadd: Adds in mining drone "AI upgrade" a sentience potion that only works on + mining bots + - tweak: Mining bots should be less likely to shoot you when attacking hostile mobs + - tweak: Killer tomatoes actually live up to their name now and are hostile mobs + - tweak: Killer tomatoes are an actual fruit now; activate it in your hands to make + them into a mob + - tweak: Killer tomatoes are directly mutated from regular tomatoes instead of blood + tomatoes + - tweak: Increased the yield of regular tomatoes by 1 + - tweak: Tweak some stats on the killer tomato seeds + - bugfix: Fixes the blind player preference not doing anything + - rscadd: Adds portaseeder to R&D + - tweak: Scythes will conduct electricity now + - tweak: Mini hoes play a slice sound instead of bludgeon sound + - tweak: Plant analyzer properly has a description and origin tech + - tweak: Can have hulk+dwarf mutations together + - tweak: Can have heat+cold resist together + - tweak: Can only remotely view people who also have remote view + - bugfix: Fixes cold mutation not having an overlay + - bugfix: Hallucinations will no longer tick down twice as fast as they should nor + will they spawn twice as many hallucinations as they should + - bugfix: Incendiary mitochondria no longer asks who you want to cast it on (it + always is meant to be cast on yourself) + - bugfix: Fixes permanent nearsightedness even when wearing prescription glasses + KasparoVy: + - tweak: 'Head accessories now behave like facial hair: They will no longer be hidden + by clothing items that BLOCKHEADHAIR (have the BLOCKHEADHAIR flag).' + - bugfix: Wearing a piece of clothing that blocks head hair will no longer make + head accessories (facial markings/horns/antennae) invisible until an icon update + is triggered while the headwear is off. + Meisaka: + - bugfix: law manager no longer freaks out with Malf law + Tastyfish: + - tweak: The /vg/ library computer interface has been ported, giving a much better + use experience. + - rscadd: Books can now be flagged for inappropriate content. + TheDZD: + - rscdel: Removes shitty Caelcode bees. + - rscadd: Hydroponics can now manage bee colonies, bees produce honeycombs that + can be ground to obtain honey, a decent nutriment+healing chemical + - rscadd: Hydroponics can inject a queen bee with a syringe of a reagent to alter + her DNA to match that reagent, meaning all honeycombs produced will contain + that reagent in small amounts + - rscadd: Bees with reagents will attack with that reagent. It takes 5u of a reagent + to give a bee that reagent. + - rscadd: Added the ability to make Apiaries and Honey frames with wood + - rscadd: Added the ability to make Royal Bee Jelly from 10 Mutagen and 40 Honey + - rscadd: Added the ability to make more Queen Bees from Royal Bee Jelly by using + it on an existing Queen, to split her into two Queens + - rscdel: Removes some snowflakey mob behavior from bears, snakes and panthers. + - rscadd: Hudson is feeling punny. + - experiment: Hostile mob AI should now be a bit more cost-efficient. + monster860: + - rscadd: Adds area editing, link mode, and fill mode to the buildmode tool +2016-04-20: + Crazylemon64: + - rscadd: Bureaucracy crates now contain granted and denied stamps. + FalseIncarnate: + - bugfix: Anomalies will now be properly neutralized by signals that match their + code and frequency, instead of using the default frequency and their code. + FlattestGuitar: + - rscadd: Adds shot glasses. + Fox McCloud: + - tweak: Removes the ability to put a pAI into securitrons and ED-209's + - imageadd: Drinking glasses now have an in-hand sprite + - tweak: DNA injectors no longer have a delay when used on yourself + - tweak: DNA injectors no longer delete on use, but become used, much like auto-injectors + - bugfix: Fixes a bug where you can exploit the genetic scanner to get multiple + injectors + - bugfix: Fixes not being able to cancel creating an DNA injector + - tweak: remove spacesuits causing injections to the head to take longer + - bugfix: FIxes heat resist mutation not making you immune to high pressure, fire, + or high temperatures + - tweak: removes some not-well-known damage resists from cold/heat mutations + - tweak: Re-maps botany a bit to make it more bee and botanist friendly + - rscadd: Adds in Abductors Game Mode + MarsM0nd: + - tweak: Embeded object removal is now done with hemostat again + - rscadd: Borgs are able to do embeded object surgery + Tastyfish: + - tweak: Makes the server startup substantially faster. + monster860: + - bugfix: Crowbarring open a spesspod doors is no longer broken + tigercat2000: + - rscadd: -tg- thrown alerts have been added. This means you get an alert when buckled + or handcuffed or many many other things happen to you. It then gives you a tool + tip when you hover over it, and it may or may not do something when you click + it. Have fun! +2016-04-25: + CrAzYPiLoT: + - rscadd: Adds buildable holographic gameboards that, when opened, produce a fully-functional + JavaScript chess interface, which includes a chess AI. If you win, it will produce + 80 tickets for your spending! + FlattestGuitar: + - tweak: a human's species is now visible on examination + Fox McCloud: + - rscadd: Improves attack animations with items, making it more clear who's attacking + you and with what + - tweak: Updates Revolution game mode so it better scales with total player population + - tweak: Head revs start off with a flash, spraycan, and chameleon security HUD + - rscadd: Add chameleon security hud, which is basically sec shades with the ability + to disguise as a number of regular glasses + - rscadd: Updates mining loot crates to feature far more actual loot + - tweak: Mining loot crates are now opened by inputting a 4 digit password and have + 10 tries to guess the password string + - bugfix: Fixes bees, mech syringes, and darts not properly calling INGEST for a + reagent + Meisaka: + - bugfix: The light on/off function for drones works again, toggling between lowest + setting and off. + - bugfix: Guardians can toggle their lights off and on again. + - bugfix: AI, pAI, robots and drones can now use *yes emote without extra ss on + the end. + - rscadd: emote *help for silicons updated/added. + - tweak: '*twitch_s emote changed to *twitches, incorrect variations of some emotes + can no longer be used.' + tigercat2000: + - rscadd: Added 4 new HUD styles, "Operative", "Plasmafire", "Retro", and "Slimecore" + - rscadd: You can now view HUD changes in real-time, by going to Preferences (top + right tab) > Game Preferences and changing the HUD style (limited to humans). + - rscadd: There are now three HUD styles you can get via the f12 button- Full, which + contains all of your buttons, Minimal, which only contains a few essential buttons, + and None, which is a completely blank screen. + - rscdel: Removed the remaining aiming code due to maintainability issues and incompatibility + with HUD styles. + - tweak: Mobs with HUD's now use a unique subtype instead of an anti-OOP else-if + chain. + - tweak: Refactored how objects (IE, stuff you pick up) is rendered to the HUD. + This should fix the reoccuring "stuff on my screen that definately isn't meant + to be there" bug, but keep an eye out for things that do not appear. diff --git a/html/changelogs/AutoChangeLog-pr-4098.yml b/html/changelogs/AutoChangeLog-pr-4098.yml deleted file mode 100644 index 7374cf5beba..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4098.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Fox McCloud -delete-after: True -changes: - - tweak: "Removes the ability to put a pAI into securitrons and ED-209's" diff --git a/html/changelogs/AutoChangeLog-pr-4141.yml b/html/changelogs/AutoChangeLog-pr-4141.yml deleted file mode 100644 index 539e7ab800c..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4141.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: monster860 -delete-after: True -changes: - - bugfix: "Crowbarring open a spesspod doors is no longer broken" diff --git a/html/changelogs/AutoChangeLog-pr-4233.yml b/html/changelogs/AutoChangeLog-pr-4189.yml similarity index 50% rename from html/changelogs/AutoChangeLog-pr-4233.yml rename to html/changelogs/AutoChangeLog-pr-4189.yml index f32871dbcaf..ae3c546108d 100644 --- a/html/changelogs/AutoChangeLog-pr-4233.yml +++ b/html/changelogs/AutoChangeLog-pr-4189.yml @@ -1,4 +1,4 @@ author: Fox McCloud delete-after: True changes: - - rscadd: "Adds in Abductors Game Mode" + - rscadd: "Slime batteries now self-recharge." diff --git a/html/changelogs/AutoChangeLog-pr-4199.yml b/html/changelogs/AutoChangeLog-pr-4199.yml deleted file mode 100644 index 26299204641..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4199.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Fox McCloud -delete-after: True -changes: - - imageadd: "Drinking glasses now have an in-hand sprite" diff --git a/html/changelogs/AutoChangeLog-pr-4201.yml b/html/changelogs/AutoChangeLog-pr-4201.yml deleted file mode 100644 index bc3b71de5f8..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4201.yml +++ /dev/null @@ -1,7 +0,0 @@ -author: Fox McCloud -delete-after: True -changes: - - tweak: "DNA injectors no longer have a delay when used on yourself" - - tweak: "DNA injectors no longer delete on use, but become used, much like auto-injectors" - - bugfix: "Fixes a bug where you can exploit the genetic scanner to get multiple injectors" - - bugfix: "Fixes not being able to cancel creating an DNA injector" diff --git a/html/changelogs/AutoChangeLog-pr-4202.yml b/html/changelogs/AutoChangeLog-pr-4202.yml deleted file mode 100644 index 5e17860d043..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4202.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Crazylemon64 -delete-after: True -changes: - - rscadd: "Bureaucracy crates now contain granted and denied stamps." diff --git a/html/changelogs/AutoChangeLog-pr-4203.yml b/html/changelogs/AutoChangeLog-pr-4203.yml deleted file mode 100644 index 472a358b7d9..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4203.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: FlattestGuitar -delete-after: True -changes: - - rscadd: "Adds shot glasses." diff --git a/html/changelogs/AutoChangeLog-pr-4207.yml b/html/changelogs/AutoChangeLog-pr-4207.yml deleted file mode 100644 index 23b0a448894..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4207.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Fox McCloud -delete-after: True -changes: - - tweak: "remove spacesuits causing injections to the head to take longer" diff --git a/html/changelogs/AutoChangeLog-pr-4208.yml b/html/changelogs/AutoChangeLog-pr-4208.yml deleted file mode 100644 index 71f857100cc..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4208.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: FalseIncarnate -delete-after: True -changes: - - bugfix: "Anomalies will now be properly neutralized by signals that match their code and frequency, instead of using the default frequency and their code." diff --git a/html/changelogs/AutoChangeLog-pr-4215.yml b/html/changelogs/AutoChangeLog-pr-4215.yml deleted file mode 100644 index 7b57ddd6412..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4215.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Fox McCloud -delete-after: True -changes: - - tweak: "Re-maps botany a bit to make it more bee and botanist friendly" diff --git a/html/changelogs/AutoChangeLog-pr-4219.yml b/html/changelogs/AutoChangeLog-pr-4219.yml deleted file mode 100644 index f8023f38494..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4219.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: MarsM0nd -delete-after: True -changes: - - tweak: "Embeded object removal is now done with hemostat again" - - rscadd: "Borgs are able to do embeded object surgery" diff --git a/html/changelogs/AutoChangeLog-pr-4221.yml b/html/changelogs/AutoChangeLog-pr-4221.yml deleted file mode 100644 index 782ad4b8619..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4221.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: tigercat2000 -delete-after: True -changes: - - rscadd: "-tg- thrown alerts have been added. This means you get an alert when buckled or handcuffed or many many other things happen to you. It then gives you a tool tip when you hover over it, and it may or may not do something when you click it. Have fun!" diff --git a/html/changelogs/AutoChangeLog-pr-4223.yml b/html/changelogs/AutoChangeLog-pr-4223.yml deleted file mode 100644 index f22e657dec5..00000000000 --- a/html/changelogs/AutoChangeLog-pr-4223.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Tastyfish -delete-after: True -changes: - - tweak: "Makes the server startup substantially faster." diff --git a/html/changelogs/AutoChangeLog-pr-4258.yml b/html/changelogs/AutoChangeLog-pr-4258.yml new file mode 100644 index 00000000000..c8511011210 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4258.yml @@ -0,0 +1,5 @@ +author: pinatacolada +delete-after: True +changes: + - tweak: "Makes fridge boards be selectable by screwdriving them" + - bugfix: "Virology fridge now accepts syringes, beakers, and bottles" diff --git a/html/changelogs/AutoChangeLog-pr-4262.yml b/html/changelogs/AutoChangeLog-pr-4262.yml new file mode 100644 index 00000000000..72bc64e4537 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4262.yml @@ -0,0 +1,14 @@ +author: KasparoVy +delete-after: True +changes: + - bugfix: "Disembodied prosthetic heads that aren't monitors won't make you go bald when they're re-attached." + - bugfix: "'Optic' markings will disappear when your head gets removed, and reappear if it gets re-attached." + - bugfix: "Disembodied prosthetic heads that aren't monitors will now be rendered with hair & facial hair." + - bugfix: "Disembodied prosthetic heads with optical markings (markings with the head set as the origin) will be rendered with those markings." + - bugfix: "Animated hair styles (e.g. screens) and head accessories (e.g. 2/3 new antennae) will now be animated properly." + - rscadd: "3 more antennae." + - rscadd: "An alt. and monitor head model for every prosthetic brand but Zeng-hu. Morpheus only gets an alt model, not another monitor." + - rscadd: "Animated optical markings to fit the new alt. heads." + - rscadd: "Screen styles for the alt. Hesphiastos head." + - tweak: "Companies that make prosthetic body parts can (and do) now offer separate models for qualified recipients." + - tweak: "Removed the frames from screen styles in order to allow the same styles to be applied to all monitor heads." diff --git a/html/changelogs/AutoChangeLog-pr-4282.yml b/html/changelogs/AutoChangeLog-pr-4282.yml new file mode 100644 index 00000000000..1049f7ff047 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4282.yml @@ -0,0 +1,4 @@ +author: QuinnAggeler +delete-after: True +changes: + - bugfix: "Adds a check for brain death (brain damage of 120 or more) to the proc responsible for reviving IPCs" diff --git a/html/changelogs/AutoChangeLog-pr-4285.yml b/html/changelogs/AutoChangeLog-pr-4285.yml new file mode 100644 index 00000000000..3bdc7140b0d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4285.yml @@ -0,0 +1,4 @@ +author: Norgad +delete-after: True +changes: + - rscadd: "Adds a disposals chute to the Mechanic's Workshop" diff --git a/html/changelogs/AutoChangeLog-pr-4288.yml b/html/changelogs/AutoChangeLog-pr-4288.yml new file mode 100644 index 00000000000..dd83c5181da --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4288.yml @@ -0,0 +1,5 @@ +author: Fox McCloud +delete-after: True +changes: + - rscadd: "Adds in door wands--control doors from range" + - rscadd: "Each head of staff (and the QM) starts off with a door wand to control the doors in their respective departments" diff --git a/html/changelogs/AutoChangeLog-pr-4292.yml b/html/changelogs/AutoChangeLog-pr-4292.yml new file mode 100644 index 00000000000..3a713925e7a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4292.yml @@ -0,0 +1,4 @@ +author: Fox McCloud +delete-after: True +changes: + - bugfix: "Fixes nutrition alert icon kicking in too early" diff --git a/html/chess.html b/html/chess.html new file mode 100644 index 00000000000..d135be94ac7 --- /dev/null +++ b/html/chess.html @@ -0,0 +1,31 @@ + + + +
+
+ New game + + Time per move: ms + Undo +
+
+
+
+
+ + +
+
+ Close +
+
\ No newline at end of file diff --git a/icons/chess_pieces/bishop_black.png b/icons/chess_pieces/bishop_black.png new file mode 100644 index 00000000000..0fd2f0a15c5 Binary files /dev/null and b/icons/chess_pieces/bishop_black.png differ diff --git a/icons/chess_pieces/bishop_white.png b/icons/chess_pieces/bishop_white.png new file mode 100644 index 00000000000..34ded58a666 Binary files /dev/null and b/icons/chess_pieces/bishop_white.png differ diff --git a/icons/chess_pieces/blank.gif b/icons/chess_pieces/blank.gif new file mode 100644 index 00000000000..eaeb7b37d5e Binary files /dev/null and b/icons/chess_pieces/blank.gif differ diff --git a/icons/chess_pieces/king_black.png b/icons/chess_pieces/king_black.png new file mode 100644 index 00000000000..68db4084314 Binary files /dev/null and b/icons/chess_pieces/king_black.png differ diff --git a/icons/chess_pieces/king_white.png b/icons/chess_pieces/king_white.png new file mode 100644 index 00000000000..fb4a71ec33c Binary files /dev/null and b/icons/chess_pieces/king_white.png differ diff --git a/icons/chess_pieces/knight_black.png b/icons/chess_pieces/knight_black.png new file mode 100644 index 00000000000..18fa86f2f8a Binary files /dev/null and b/icons/chess_pieces/knight_black.png differ diff --git a/icons/chess_pieces/knight_white.png b/icons/chess_pieces/knight_white.png new file mode 100644 index 00000000000..989bf85cba3 Binary files /dev/null and b/icons/chess_pieces/knight_white.png differ diff --git a/icons/chess_pieces/pawn_black.png b/icons/chess_pieces/pawn_black.png new file mode 100644 index 00000000000..47b6a161fe2 Binary files /dev/null and b/icons/chess_pieces/pawn_black.png differ diff --git a/icons/chess_pieces/pawn_white.png b/icons/chess_pieces/pawn_white.png new file mode 100644 index 00000000000..f0a324b835a Binary files /dev/null and b/icons/chess_pieces/pawn_white.png differ diff --git a/icons/chess_pieces/queen_black.png b/icons/chess_pieces/queen_black.png new file mode 100644 index 00000000000..a6a971c8f86 Binary files /dev/null and b/icons/chess_pieces/queen_black.png differ diff --git a/icons/chess_pieces/queen_white.png b/icons/chess_pieces/queen_white.png new file mode 100644 index 00000000000..ac3335f6fff Binary files /dev/null and b/icons/chess_pieces/queen_white.png differ diff --git a/icons/chess_pieces/rook_black.png b/icons/chess_pieces/rook_black.png new file mode 100644 index 00000000000..0c603e3d4d1 Binary files /dev/null and b/icons/chess_pieces/rook_black.png differ diff --git a/icons/chess_pieces/rook_white.png b/icons/chess_pieces/rook_white.png new file mode 100644 index 00000000000..9600ad0d42e Binary files /dev/null and b/icons/chess_pieces/rook_white.png differ diff --git a/icons/chess_pieces/sprites.png b/icons/chess_pieces/sprites.png new file mode 100644 index 00000000000..0f3dc31dcca Binary files /dev/null and b/icons/chess_pieces/sprites.png differ diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi index 16d20417d2d..82f08fbb101 100644 Binary files a/icons/mob/actions.dmi and b/icons/mob/actions.dmi differ diff --git a/icons/mob/body_accessory.dmi b/icons/mob/body_accessory.dmi index 16d6b2f03f9..c315fbbdc2f 100644 Binary files a/icons/mob/body_accessory.dmi and b/icons/mob/body_accessory.dmi differ diff --git a/icons/mob/eyes.dmi b/icons/mob/eyes.dmi index d7cfb2d1889..28399ab1ce1 100644 Binary files a/icons/mob/eyes.dmi and b/icons/mob/eyes.dmi differ diff --git a/icons/mob/hands.dmi b/icons/mob/hands.dmi index a4934926809..d4f0b3ac57a 100644 Binary files a/icons/mob/hands.dmi and b/icons/mob/hands.dmi differ diff --git a/icons/mob/human_races/cyberlimbs/bishop/bishop_alt1.dmi b/icons/mob/human_races/cyberlimbs/bishop/bishop_alt1.dmi new file mode 100644 index 00000000000..3443d18b0a3 Binary files /dev/null and b/icons/mob/human_races/cyberlimbs/bishop/bishop_alt1.dmi differ diff --git a/icons/mob/human_races/cyberlimbs/bishop.dmi b/icons/mob/human_races/cyberlimbs/bishop/bishop_main.dmi similarity index 100% rename from icons/mob/human_races/cyberlimbs/bishop.dmi rename to icons/mob/human_races/cyberlimbs/bishop/bishop_main.dmi diff --git a/icons/mob/human_races/cyberlimbs/bishop/bishop_monitor.dmi b/icons/mob/human_races/cyberlimbs/bishop/bishop_monitor.dmi new file mode 100644 index 00000000000..45d5ba48841 Binary files /dev/null and b/icons/mob/human_races/cyberlimbs/bishop/bishop_monitor.dmi differ diff --git a/icons/mob/human_races/cyberlimbs/hesphiastos/hesphiastos_alt1.dmi b/icons/mob/human_races/cyberlimbs/hesphiastos/hesphiastos_alt1.dmi new file mode 100644 index 00000000000..4e8e5658f4f Binary files /dev/null and b/icons/mob/human_races/cyberlimbs/hesphiastos/hesphiastos_alt1.dmi differ diff --git a/icons/mob/human_races/cyberlimbs/hesphaistos.dmi b/icons/mob/human_races/cyberlimbs/hesphiastos/hesphiastos_main.dmi similarity index 100% rename from icons/mob/human_races/cyberlimbs/hesphaistos.dmi rename to icons/mob/human_races/cyberlimbs/hesphiastos/hesphiastos_main.dmi diff --git a/icons/mob/human_races/cyberlimbs/hesphiastos/hesphiastos_monitor.dmi b/icons/mob/human_races/cyberlimbs/hesphiastos/hesphiastos_monitor.dmi new file mode 100644 index 00000000000..cc46f848343 Binary files /dev/null and b/icons/mob/human_races/cyberlimbs/hesphiastos/hesphiastos_monitor.dmi differ diff --git a/icons/mob/human_races/cyberlimbs/morpheus/morpheus_alt1.dmi b/icons/mob/human_races/cyberlimbs/morpheus/morpheus_alt1.dmi new file mode 100644 index 00000000000..685871568a7 Binary files /dev/null and b/icons/mob/human_races/cyberlimbs/morpheus/morpheus_alt1.dmi differ diff --git a/icons/mob/human_races/cyberlimbs/ipc.dmi b/icons/mob/human_races/cyberlimbs/morpheus/morpheus_main.dmi similarity index 100% rename from icons/mob/human_races/cyberlimbs/ipc.dmi rename to icons/mob/human_races/cyberlimbs/morpheus/morpheus_main.dmi diff --git a/icons/mob/human_races/cyberlimbs/wardtakahashi/wardtakahashi_alt1.dmi b/icons/mob/human_races/cyberlimbs/wardtakahashi/wardtakahashi_alt1.dmi new file mode 100644 index 00000000000..54e7295cd39 Binary files /dev/null and b/icons/mob/human_races/cyberlimbs/wardtakahashi/wardtakahashi_alt1.dmi differ diff --git a/icons/mob/human_races/cyberlimbs/wardtakahashi.dmi b/icons/mob/human_races/cyberlimbs/wardtakahashi/wardtakahashi_main.dmi similarity index 100% rename from icons/mob/human_races/cyberlimbs/wardtakahashi.dmi rename to icons/mob/human_races/cyberlimbs/wardtakahashi/wardtakahashi_main.dmi diff --git a/icons/mob/human_races/cyberlimbs/wardtakahashi/wardtakahashi_monitor.dmi b/icons/mob/human_races/cyberlimbs/wardtakahashi/wardtakahashi_monitor.dmi new file mode 100644 index 00000000000..06e518be95b Binary files /dev/null and b/icons/mob/human_races/cyberlimbs/wardtakahashi/wardtakahashi_monitor.dmi differ diff --git a/icons/mob/human_races/cyberlimbs/xion/xion_alt1.dmi b/icons/mob/human_races/cyberlimbs/xion/xion_alt1.dmi new file mode 100644 index 00000000000..9f5b8f3cd15 Binary files /dev/null and b/icons/mob/human_races/cyberlimbs/xion/xion_alt1.dmi differ diff --git a/icons/mob/human_races/cyberlimbs/xion.dmi b/icons/mob/human_races/cyberlimbs/xion/xion_main.dmi similarity index 100% rename from icons/mob/human_races/cyberlimbs/xion.dmi rename to icons/mob/human_races/cyberlimbs/xion/xion_main.dmi diff --git a/icons/mob/human_races/cyberlimbs/xion/xion_monitor.dmi b/icons/mob/human_races/cyberlimbs/xion/xion_monitor.dmi new file mode 100644 index 00000000000..dee73558711 Binary files /dev/null and b/icons/mob/human_races/cyberlimbs/xion/xion_monitor.dmi differ diff --git a/icons/mob/human_races/cyberlimbs/zenghu.dmi b/icons/mob/human_races/cyberlimbs/zenghu.dmi deleted file mode 100644 index 85f49f50873..00000000000 Binary files a/icons/mob/human_races/cyberlimbs/zenghu.dmi and /dev/null differ diff --git a/icons/mob/human_races/cyberlimbs/zenghu/zenghu_main.dmi b/icons/mob/human_races/cyberlimbs/zenghu/zenghu_main.dmi new file mode 100644 index 00000000000..0d74250a3ea Binary files /dev/null and b/icons/mob/human_races/cyberlimbs/zenghu/zenghu_main.dmi differ diff --git a/icons/mob/screen1.dmi b/icons/mob/screen1.dmi deleted file mode 100644 index 27f7a09e530..00000000000 Binary files a/icons/mob/screen1.dmi and /dev/null differ diff --git a/icons/mob/screen1_Midnight.dmi b/icons/mob/screen1_Midnight.dmi deleted file mode 100644 index 808734a832e..00000000000 Binary files a/icons/mob/screen1_Midnight.dmi and /dev/null differ diff --git a/icons/mob/screen1_Orange.dmi b/icons/mob/screen1_Orange.dmi deleted file mode 100644 index 15964ad65d0..00000000000 Binary files a/icons/mob/screen1_Orange.dmi and /dev/null differ diff --git a/icons/mob/screen1_White.dmi b/icons/mob/screen1_White.dmi deleted file mode 100644 index 2b6e99bbb33..00000000000 Binary files a/icons/mob/screen1_White.dmi and /dev/null differ diff --git a/icons/mob/screen1_alien.dmi b/icons/mob/screen1_alien.dmi deleted file mode 100644 index 0ca5b617c7e..00000000000 Binary files a/icons/mob/screen1_alien.dmi and /dev/null differ diff --git a/icons/mob/screen1_corgi.dmi b/icons/mob/screen1_corgi.dmi deleted file mode 100644 index dafa9ae2b44..00000000000 Binary files a/icons/mob/screen1_corgi.dmi and /dev/null differ diff --git a/icons/mob/screen1_old.dmi b/icons/mob/screen1_old.dmi deleted file mode 100644 index 7da629f1dae..00000000000 Binary files a/icons/mob/screen1_old.dmi and /dev/null differ diff --git a/icons/mob/screen_alien.dmi b/icons/mob/screen_alien.dmi index 822cbec7d0e..c254b276bc5 100644 Binary files a/icons/mob/screen_alien.dmi and b/icons/mob/screen_alien.dmi differ diff --git a/icons/mob/screen1_bot.dmi b/icons/mob/screen_bot.dmi similarity index 100% rename from icons/mob/screen1_bot.dmi rename to icons/mob/screen_bot.dmi diff --git a/icons/mob/screen_corgi.dmi b/icons/mob/screen_corgi.dmi new file mode 100644 index 00000000000..81a8a2ab890 Binary files /dev/null and b/icons/mob/screen_corgi.dmi differ diff --git a/icons/mob/screen_gen.dmi b/icons/mob/screen_gen.dmi index a97f1abc5a0..4936936afde 100644 Binary files a/icons/mob/screen_gen.dmi and b/icons/mob/screen_gen.dmi differ diff --git a/icons/mob/screen_midnight.dmi b/icons/mob/screen_midnight.dmi new file mode 100644 index 00000000000..25b3d7355d9 Binary files /dev/null and b/icons/mob/screen_midnight.dmi differ diff --git a/icons/mob/screen1_NinjaHUD.dmi b/icons/mob/screen_ninja.dmi similarity index 100% rename from icons/mob/screen1_NinjaHUD.dmi rename to icons/mob/screen_ninja.dmi diff --git a/icons/mob/screen_operative.dmi b/icons/mob/screen_operative.dmi new file mode 100644 index 00000000000..d14e354d7f4 Binary files /dev/null and b/icons/mob/screen_operative.dmi differ diff --git a/icons/mob/screen_plasmafire.dmi b/icons/mob/screen_plasmafire.dmi new file mode 100644 index 00000000000..9e22298fc27 Binary files /dev/null and b/icons/mob/screen_plasmafire.dmi differ diff --git a/icons/mob/screen_retro.dmi b/icons/mob/screen_retro.dmi new file mode 100644 index 00000000000..ec36561ea0c Binary files /dev/null and b/icons/mob/screen_retro.dmi differ diff --git a/icons/mob/screen1_robot.dmi b/icons/mob/screen_robot.dmi similarity index 100% rename from icons/mob/screen1_robot.dmi rename to icons/mob/screen_robot.dmi diff --git a/icons/mob/screen_slimecore.dmi b/icons/mob/screen_slimecore.dmi new file mode 100644 index 00000000000..0e412d41c9c Binary files /dev/null and b/icons/mob/screen_slimecore.dmi differ diff --git a/icons/mob/screen_white.dmi b/icons/mob/screen_white.dmi new file mode 100644 index 00000000000..a30d30bd3ef Binary files /dev/null and b/icons/mob/screen_white.dmi differ diff --git a/icons/obj/clothing/glasses.dmi b/icons/obj/clothing/glasses.dmi index 894d49a9adf..6ad7d94bda7 100644 Binary files a/icons/obj/clothing/glasses.dmi and b/icons/obj/clothing/glasses.dmi differ diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi index cf82594e6c6..4a41556989a 100644 Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 37026b153be..46a4a974316 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/icons/obj/stationobjs.dmi b/icons/obj/stationobjs.dmi index d737faf3b0d..72084b5675b 100755 Binary files a/icons/obj/stationobjs.dmi and b/icons/obj/stationobjs.dmi differ diff --git a/icons/turf/floors/seadrop-o.dmi b/icons/turf/floors/seadrop-o.dmi new file mode 100644 index 00000000000..9a352fa85ed Binary files /dev/null and b/icons/turf/floors/seadrop-o.dmi differ diff --git a/icons/turf/floors/seadrop.dmi b/icons/turf/floors/seadrop.dmi index d15d9c727e4..29622fa1064 100644 Binary files a/icons/turf/floors/seadrop.dmi and b/icons/turf/floors/seadrop.dmi differ diff --git a/paradise.dme b/paradise.dme index 48b4a5fefca..f13c3f5ea9b 100644 --- a/paradise.dme +++ b/paradise.dme @@ -37,6 +37,7 @@ #include "code\__DEFINES\process_scheduler.dm" #include "code\__DEFINES\qdel.dm" #include "code\__DEFINES\role_preferences.dm" +#include "code\__DEFINES\rolebans.dm" #include "code\__DEFINES\sight.dm" #include "code\__DEFINES\snpc.dm" #include "code\__DEFINES\stat.dm" @@ -103,6 +104,7 @@ #include "code\_onclick\hud\alien_larva.dm" #include "code\_onclick\hud\bot.dm" #include "code\_onclick\hud\fullscreen.dm" +#include "code\_onclick\hud\guardian.dm" #include "code\_onclick\hud\hud.dm" #include "code\_onclick\hud\human.dm" #include "code\_onclick\hud\monkey.dm" @@ -110,6 +112,7 @@ #include "code\_onclick\hud\other_mobs.dm" #include "code\_onclick\hud\robot.dm" #include "code\_onclick\hud\screen_objects.dm" +#include "code\_onclick\hud\swarmer.dm" #include "code\ATMOSPHERICS\atmospherics.dm" #include "code\ATMOSPHERICS\datum_icon_manager.dm" #include "code\ATMOSPHERICS\datum_pipeline.dm" @@ -189,7 +192,6 @@ #include "code\datums\datumvars.dm" #include "code\datums\gas_mixture.dm" #include "code\datums\hud.dm" -#include "code\datums\martial.dm" #include "code\datums\material_container.dm" #include "code\datums\mind.dm" #include "code\datums\mixed.dm" @@ -444,14 +446,12 @@ #include "code\game\gamemodes\nuclear\nuclearbomb.dm" #include "code\game\gamemodes\nuclear\pinpointer.dm" #include "code\game\gamemodes\revolution\revolution.dm" -#include "code\game\gamemodes\revolution\rp_revolution.dm" #include "code\game\gamemodes\shadowling\ascendant_shadowling.dm" #include "code\game\gamemodes\shadowling\shadowling.dm" #include "code\game\gamemodes\shadowling\shadowling_abilities.dm" #include "code\game\gamemodes\shadowling\shadowling_items.dm" #include "code\game\gamemodes\shadowling\special_shadowling_abilities.dm" #include "code\game\gamemodes\traitor\traitor.dm" -#include "code\game\gamemodes\vampire\hud.dm" #include "code\game\gamemodes\vampire\traitor_vamp.dm" #include "code\game\gamemodes\vampire\vampire.dm" #include "code\game\gamemodes\vampire\vampire_powers.dm" @@ -501,6 +501,7 @@ #include "code\game\machinery\flasher.dm" #include "code\game\machinery\floodlight.dm" #include "code\game\machinery\Freezer.dm" +#include "code\game\machinery\gameboard.dm" #include "code\game\machinery\guestpass.dm" #include "code\game\machinery\hologram.dm" #include "code\game\machinery\holosign.dm" @@ -698,6 +699,7 @@ #include "code\game\objects\items\candle.dm" #include "code\game\objects\items\changestone.dm" #include "code\game\objects\items\contraband.dm" +#include "code\game\objects\items\control_wand.dm" #include "code\game\objects\items\crayons.dm" #include "code\game\objects\items\dehy_carp.dm" #include "code\game\objects\items\documents.dm" @@ -838,6 +840,7 @@ #include "code\game\objects\items\weapons\implants\implant_death_alarm.dm" #include "code\game\objects\items\weapons\implants\implant_explosive.dm" #include "code\game\objects\items\weapons\implants\implant_freedom.dm" +#include "code\game\objects\items\weapons\implants\implant_krav_maga.dm" #include "code\game\objects\items\weapons\implants\implant_loyality.dm" #include "code\game\objects\items\weapons\implants\implant_misc.dm" #include "code\game\objects\items\weapons\implants\implant_storage.dm" @@ -1349,6 +1352,14 @@ #include "code\modules\logic\dual_input.dm" #include "code\modules\logic\logic_base.dm" #include "code\modules\logic\mono_input.dm" +#include "code\modules\martial_arts\adminfu.dm" +#include "code\modules\martial_arts\brawling.dm" +#include "code\modules\martial_arts\krav_maga.dm" +#include "code\modules\martial_arts\martial.dm" +#include "code\modules\martial_arts\mimejutsu.dm" +#include "code\modules\martial_arts\plasma_fist.dm" +#include "code\modules\martial_arts\sleeping_carp.dm" +#include "code\modules\martial_arts\wrestleing.dm" #include "code\modules\media\jukebox.dm" #include "code\modules\media\machinery.dm" #include "code\modules\media\mediamanager.dm" @@ -1493,7 +1504,6 @@ #include "code\modules\mob\living\carbon\slime\emote.dm" #include "code\modules\mob\living\carbon\slime\examine.dm" #include "code\modules\mob\living\carbon\slime\life.dm" -#include "code\modules\mob\living\carbon\slime\login.dm" #include "code\modules\mob\living\carbon\slime\powers.dm" #include "code\modules\mob\living\carbon\slime\say.dm" #include "code\modules\mob\living\carbon\slime\slime.dm" @@ -1737,7 +1747,6 @@ #include "code\modules\projectiles\gun.dm" #include "code\modules\projectiles\medbeam.dm" #include "code\modules\projectiles\projectile.dm" -#include "code\modules\projectiles\targeting.dm" #include "code\modules\projectiles\ammunition\ammo_casings.dm" #include "code\modules\projectiles\ammunition\boxes.dm" #include "code\modules\projectiles\ammunition\magazines.dm" diff --git a/sound/effects/hit_kick.ogg b/sound/effects/hit_kick.ogg new file mode 100644 index 00000000000..850642de699 Binary files /dev/null and b/sound/effects/hit_kick.ogg differ diff --git a/sound/effects/hit_punch.ogg b/sound/effects/hit_punch.ogg new file mode 100644 index 00000000000..e4b38e9627a Binary files /dev/null and b/sound/effects/hit_punch.ogg differ