From 946fd5329fb1d200deaea0dbfa7fdfa7bb2db8e6 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 2 May 2014 15:59:47 -0400 Subject: [PATCH 01/11] Fixed null flag for cigarette type --- code/game/objects/items/weapons/cigs_lighters.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm index 5ec7f97d6d..f9e0d48bca 100644 --- a/code/game/objects/items/weapons/cigs_lighters.dm +++ b/code/game/objects/items/weapons/cigs_lighters.dm @@ -62,7 +62,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM throw_speed = 0.5 item_state = "cigoff" w_class = 1 - body_parts_covered = null + body_parts_covered = 0 attack_verb = list("burnt", "singed") var/lit = 0 var/icon_on = "cigon" //Note - these are in masks.dmi not in cigarette.dmi From 673f4ca1bcb6730d4699d7ec5704e0df782ae3c3 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 2 May 2014 16:09:13 -0400 Subject: [PATCH 02/11] Hardsuits Adjusted hardsuit values to match descriptions a little better. Returned some atmos hardsuit values to eng ones since they don't seem to have reduced slowdown after all, instead they trade radiation protection for thermal protection. Updated syndie hardsuit species excludes as those species now have their own syndie hardsuits. --- code/modules/clothing/spacesuits/rig.dm | 18 ++++++++++-------- code/setup.dm | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm index 6479f9875e..1876d70d03 100644 --- a/code/modules/clothing/spacesuits/rig.dm +++ b/code/modules/clothing/spacesuits/rig.dm @@ -75,13 +75,14 @@ icon_state = "rig0-mining" item_state = "mining_helm" item_color = "mining" + armor = list(melee = 50, bullet = 5, laser = 20,energy = 5, bomb = 55, bio = 100, rad = 20) /obj/item/clothing/suit/space/rig/mining icon_state = "rig-mining" name = "mining hardsuit" desc = "A special suit that protects against hazardous, low pressure environments. Has reinforced plating." item_state = "mining_hardsuit" - + armor = list(melee = 50, bullet = 5, laser = 20,energy = 5, bomb = 55, bio = 100, rad = 80) //Syndicate rig @@ -94,7 +95,7 @@ armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 35, bio = 100, rad = 60) siemens_coefficient = 0.6 var/obj/machinery/camera/camera - species_restricted = list("exclude","Vox") + species_restricted = list("exclude","Unathi","Tajaran","Skrell","Vox") /obj/item/clothing/head/helmet/space/rig/syndi/attack_self(mob/user) if(camera) ..(user) @@ -120,7 +121,7 @@ armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 60) allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs) siemens_coefficient = 0.6 - species_restricted = list("exclude","Vox") + species_restricted = list("exclude","Unathi","Tajaran","Skrell","Vox") //Wizard Rig @@ -153,6 +154,7 @@ icon_state = "rig0-medical" item_state = "medical_helm" item_color = "medical" + armor = list(melee = 30, bullet = 5, laser = 20,energy = 5, bomb = 25, bio = 100, rad = 50) /obj/item/clothing/suit/space/rig/medical icon_state = "rig-medical" @@ -160,7 +162,7 @@ desc = "A special suit that protects against hazardous, low pressure environments. Has minor radiation shielding." item_state = "medical_hardsuit" allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/storage/firstaid,/obj/item/device/healthanalyzer,/obj/item/stack/medical) - + armor = list(melee = 30, bullet = 5, laser = 20,energy = 5, bomb = 25, bio = 100, rad = 50) //Security /obj/item/clothing/head/helmet/space/rig/security @@ -184,18 +186,18 @@ //Atmospherics Rig (BS12) /obj/item/clothing/head/helmet/space/rig/atmos - desc = "A special helmet designed for work in a hazardous, low pressure environments. Has reduced radiation shielding and protective plating to allow for greater mobility." + desc = "A special helmet designed for work in a hazardous, low pressure environments. Has improved thermal protection and minor radiation shielding." name = "atmospherics hardsuit helmet" icon_state = "rig0-atmos" item_state = "atmos_helm" item_color = "atmos" - armor = list(melee = 40, bullet = 0, laser = 0, energy = 0, bomb = 25, bio = 100, rad = 0) + armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 50) max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE /obj/item/clothing/suit/space/rig/atmos - desc = "A special suit that protects against hazardous, low pressure environments. Has reduced radiation shielding to allow for greater mobility." + desc = "A special suit that protects against hazardous, low pressure environments. Has improved thermal protection and minor radiation shielding." icon_state = "rig-atmos" name = "atmos hardsuit" item_state = "atmos_hardsuit" - armor = list(melee = 40, bullet = 0, laser = 0, energy = 0, bomb = 25, bio = 100, rad = 0) + armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 50) max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE diff --git a/code/setup.dm b/code/setup.dm index c56aefde1d..7d8abb759a 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -46,7 +46,7 @@ #define SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE 2.0 //what min_cold_protection_temperature is set to for space-helmet quality headwear. MUST NOT BE 0. #define SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE 2.0 //what min_cold_protection_temperature is set to for space-suit quality jumpsuits or suits. MUST NOT BE 0. -#define SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE 5000 //These need better heat protect +#define SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE 5000 //These need better heat protect, but not as good heat protect as firesuits. #define FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE 30000 //what max_heat_protection_temperature is set to for firesuit quality headwear. MUST NOT BE 0. #define FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE 30000 //for fire helmet quality items (red and white hardhats) #define HELMET_MIN_COLD_PROTECTION_TEMPERATURE 160 //For normal helmets From 15fef1380452678ab4faf9dc5c6789288ab05042 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 2 May 2014 16:11:41 -0400 Subject: [PATCH 03/11] Space suit description text --- code/modules/clothing/clothing.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 8dfa25d0a6..f29be70ed1 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -206,7 +206,7 @@ BLIND // can't see anything /obj/item/clothing/suit/space name = "Space suit" - desc = "A suit that protects against low pressure environments. Has a big 13 on the back." + desc = "A suit that protects against low pressure environments. Has a \"NSS EXODUS\" written in big block letters on the back." icon_state = "space" item_state = "s_suit" w_class = 4//bulky item From bc1a52968346e2ba7863b6790e5768be358d8146 Mon Sep 17 00:00:00 2001 From: Mike Date: Sat, 3 May 2014 11:40:20 -0400 Subject: [PATCH 04/11] Fixes for last two commits. --- code/modules/clothing/clothing.dm | 2 +- code/modules/clothing/spacesuits/rig.dm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index f29be70ed1..b670d1a295 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -206,7 +206,7 @@ BLIND // can't see anything /obj/item/clothing/suit/space name = "Space suit" - desc = "A suit that protects against low pressure environments. Has a \"NSS EXODUS\" written in big block letters on the back." + desc = "A suit that protects against low pressure environments. \"NSS EXODUS\" is written in large block letters on the back." icon_state = "space" item_state = "s_suit" w_class = 4//bulky item diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm index 1876d70d03..9a527b3213 100644 --- a/code/modules/clothing/spacesuits/rig.dm +++ b/code/modules/clothing/spacesuits/rig.dm @@ -82,7 +82,7 @@ name = "mining hardsuit" desc = "A special suit that protects against hazardous, low pressure environments. Has reinforced plating." item_state = "mining_hardsuit" - armor = list(melee = 50, bullet = 5, laser = 20,energy = 5, bomb = 55, bio = 100, rad = 80) + armor = list(melee = 50, bullet = 5, laser = 20,energy = 5, bomb = 55, bio = 100, rad = 20) //Syndicate rig From fe4f9b0df92a75e16f7a9de8cdfbe73ca1385ad2 Mon Sep 17 00:00:00 2001 From: Ccomp5950 Date: Fri, 2 May 2014 21:31:30 -0500 Subject: [PATCH 05/11] Adds Mentors. Adds a config option MENTORS which sets the variable config.mods_are_mentors Adds a rights level of R_MENTOR which gets msay, private message, aghost, notes, and a new proc for checking for new players (requires database support). If the confic option for mentors is set then the ckeys listed in moderators.txt file will instead be set as mentors, you can still make moderators by adding them in admins.txt staffwho will show Mentors instead of Moderators as the heading above the listing of non-admins. Also: Players now get a message gently reminding them to click the name of the staff member to reply instead of ahelping over and over. --- code/__HELPERS/type2type.dm | 1 + code/controllers/configuration.dm | 4 ++++ code/game/verbs/who.dm | 12 +++++----- code/modules/admin/admin_ranks.dm | 2 +- code/modules/admin/admin_verbs.dm | 18 ++++++++++++-- code/modules/admin/verbs/adminhelp.dm | 4 ++++ code/modules/admin/verbs/adminpm.dm | 7 ++++-- code/modules/admin/verbs/adminsay.dm | 10 +++++--- code/modules/admin/verbs/deadsay.dm | 5 +++- code/modules/admin/verbs/randomverbs.dm | 31 +++++++++++++++++++++++++ code/modules/client/client defines.dm | 1 + code/setup.dm | 3 ++- code/world.dm | 7 ++++-- config/example/admin_ranks.txt | 4 +++- config/example/config.txt | 6 +++++ 15 files changed, 96 insertions(+), 19 deletions(-) diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 4e6287a5d2..885de82c44 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -315,6 +315,7 @@ proc/tg_list2text(list/list, glue=",") if(rights & R_SOUNDS) . += "[seperator]+SOUND" if(rights & R_SPAWN) . += "[seperator]+SPAWN" if(rights & R_MOD) . += "[seperator]+MODERATOR" + if(rights & R_MENTOR) . += "[seperator]+MENTOR" return . /proc/ui_style2icon(ui_style) diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 30db610e3c..ac0d47a3ce 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -60,6 +60,7 @@ var/respawn = 1 var/guest_jobban = 1 var/usewhitelist = 0 + var/mods_are_mentors = 0 var/kick_inactive = 0 //force disconnect for inactive players var/load_jobs_from_txt = 0 var/ToRban = 0 @@ -252,6 +253,9 @@ if ("log_runtime") config.log_runtime = 1 + if ("mentors") + config.mods_are_mentors = 1 + if("allow_admin_ooccolor") config.allow_admin_ooccolor = 1 diff --git a/code/game/verbs/who.dm b/code/game/verbs/who.dm index b8ff0e1991..4eba07f447 100644 --- a/code/game/verbs/who.dm +++ b/code/game/verbs/who.dm @@ -52,7 +52,7 @@ var/num_admins_online = 0 if(holder) for(var/client/C in admins) - if(R_ADMIN & C.holder.rights || !(R_MOD & C.holder.rights)) + if(R_ADMIN & C.holder.rights || (!R_MOD & C.holder.rights && !R_MENTOR & C.holder.rights)) msg += "\t[C] is a [C.holder.rank]" if(C.holder.fakekey) @@ -70,7 +70,7 @@ msg += "\n" num_admins_online++ - else + else if(R_MOD & C.holder.rights || R_MENTOR & C.holder.rights) modmsg += "\t[C] is a [C.holder.rank]" if(isobserver(C.mob)) @@ -87,13 +87,13 @@ else for(var/client/C in admins) - if(R_ADMIN & C.holder.rights || !(R_MOD & C.holder.rights)) + if(R_ADMIN & C.holder.rights || (!R_MOD & C.holder.rights && !R_MENTOR & C.holder.rights)) if(!C.holder.fakekey) msg += "\t[C] is a [C.holder.rank]\n" num_admins_online++ - else + else if (R_MOD & C.holder.rights || R_MENTOR & C.holder.rights) modmsg += "\t[C] is a [C.holder.rank]\n" num_mods_online++ - msg = "Current Admins ([num_admins_online]):\n" + msg + "\n Current Moderators([num_mods_online]):\n" + modmsg - src << msg \ No newline at end of file + msg = "Current Admins ([num_admins_online]):\n" + msg + "\n Current [config.mods_are_mentors ? "Mentors" : "Moderators"]([num_mods_online]):\n" + modmsg + src << msg diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm index 5e8af02474..a9e428953b 100644 --- a/code/modules/admin/admin_ranks.dm +++ b/code/modules/admin/admin_ranks.dm @@ -41,6 +41,7 @@ var/list/admin_ranks = list() //list of all ranks with associated rights if("sound","sounds") rights |= R_SOUNDS if("spawn","create") rights |= R_SPAWN if("mod") rights |= R_MOD + if("mentor") rights |= R_MENTOR admin_ranks[rank] = rights previous_rights = rights @@ -52,7 +53,6 @@ var/list/admin_ranks = list() //list of all ranks with associated rights testing(msg) #endif - /hook/startup/proc/loadAdmins() load_admins() return 1 diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 0258ddb50a..17a7b03e91 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -1,12 +1,13 @@ //admin verb groups - They can overlap if you so wish. Only one of each verb will exist in the verbs list regardless var/list/admin_verbs_default = list( - /datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags*/ +// /datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags*/ /client/proc/toggleadminhelpsound, /*toggles whether we hear a sound when adminhelps/PMs are used*/ /client/proc/deadmin_self, /*destroys our own admin datum so we can play as a regular player*/ /client/proc/hide_verbs, /*hides all our adminverbs*/ /client/proc/hide_most_verbs, /*hides all our hideable adminverbs*/ /client/proc/debug_variables, /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/ - /client/proc/check_antagonists /*shows all antags*/ + /client/proc/check_antagonists, /*shows all antags*/ + /client/proc/cmd_mentor_check_new_players // /client/proc/deadchat /*toggles deadchat on/off*/ ) var/list/admin_verbs_admin = list( @@ -245,6 +246,18 @@ var/list/admin_verbs_mod = list( /client/proc/jobbans, /client/proc/cmd_admin_subtle_message /*send an message to somebody as a 'voice in their head'*/ ) + +var/list/admin_verbs_mentor = list( + /client/proc/cmd_admin_pm_context, + /client/proc/cmd_admin_pm_panel, + /datum/admins/proc/PlayerNotes, + /client/proc/admin_ghost, + /client/proc/cmd_mod_say, + /datum/admins/proc/show_player_info, +// /client/proc/dsay, + /client/proc/cmd_admin_subtle_message +) + /client/proc/add_admin_verbs() if(holder) verbs += admin_verbs_default @@ -261,6 +274,7 @@ var/list/admin_verbs_mod = list( if(holder.rights & R_SOUNDS) verbs += admin_verbs_sounds if(holder.rights & R_SPAWN) verbs += admin_verbs_spawn if(holder.rights & R_MOD) verbs += admin_verbs_mod + if(holder.rights & R_MENTOR) verbs += admin_verbs_mentor /client/proc/remove_admin_verbs() verbs.Remove( diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index e2504a0465..726361fe00 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -18,6 +18,8 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey"," if(src.handle_spam_prevention(msg,MUTE_ADMINHELP)) return + adminhelped = 1 //Determines if they get the message to reply by clicking the name. + /**src.verbs -= /client/verb/adminhelp spawn(1200) @@ -31,6 +33,8 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey"," if(!msg) return var/original_msg = msg + + //explode the input msg into a list var/list/msglist = text2list(msg, " ") diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index 8e3f5e29bb..0044309157 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -94,7 +94,10 @@ var/recieve_message = "" if(holder && !C.holder) - recieve_message = "-- Administrator private message --\n" + recieve_message = "-- Click the [recieve_pm_type]'s name to reply --\n" + if(C.adminhelped) + C << recieve_message + C.adminhelped = 0 //AdminPM popup for ApocStation and anybody else who wants to use it. Set it with POPUP_ADMIN_PM in config.txt ~Carn if(config.popup_admin_pm) @@ -180,5 +183,5 @@ //check client/X is an admin and isn't the sender or recipient if(X == C || X == src) continue - if(X.key!=key && X.key!=C.key && (X.holder.rights & R_ADMIN) || (X.holder.rights & R_MOD) ) + if(X.key!=key && X.key!=C.key && (X.holder.rights & R_ADMIN) || (X.holder.rights & (R_MOD|R_MENTOR)) ) X << "PM: [key_name(src, X, 0)]->[key_name(C, X, 0)]: \blue [msg]" //inform X diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm index 086baa5877..70fcdbf444 100644 --- a/code/modules/admin/verbs/adminsay.dm +++ b/code/modules/admin/verbs/adminsay.dm @@ -22,7 +22,7 @@ set name = "Msay" set hidden = 1 - if(!check_rights(R_ADMIN|R_MOD)) return + if(!check_rights(R_ADMIN|R_MOD|R_MENTOR)) return msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN) log_admin("MOD: [key_name(src)] : [msg]") @@ -32,6 +32,10 @@ var/color = "mod" if (check_rights(R_ADMIN,0)) color = "adminmod" + + var/channel = "MOD:" + if(config.mods_are_mentors) + channel = "MENTOR:" for(var/client/C in admins) - if((R_ADMIN|R_MOD) & C.holder.rights) - C << "MOD: [key_name(src,1)] (JMP): [msg]" + if((R_ADMIN|R_MOD|R_MENTOR) & C.holder.rights) + C << "[channel] [key_name(src,1)] (JMP): [msg]" diff --git a/code/modules/admin/verbs/deadsay.dm b/code/modules/admin/verbs/deadsay.dm index 0d13bb1c76..d05bb3d9e7 100644 --- a/code/modules/admin/verbs/deadsay.dm +++ b/code/modules/admin/verbs/deadsay.dm @@ -23,6 +23,9 @@ if (src.holder.rights & R_MOD) stafftype = "MOD" + if (src.holder.rights & R_MENTOR) + stafftype = "MENTOR" + if (src.holder.rights & R_ADMIN) stafftype = "ADMIN" @@ -44,4 +47,4 @@ else if(M.stat == DEAD && (M.client.prefs.toggles & CHAT_DEAD)) // show the message to regular ghosts who have deadchat toggled on M.show_message(rendered, 2) - feedback_add_details("admin_verb","D") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! \ No newline at end of file + feedback_add_details("admin_verb","D") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 77c972a40d..b85bba2720 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -65,6 +65,37 @@ message_admins("\blue \bold SubtleMessage: [key_name_admin(usr)] -> [key_name_admin(M)] : [msg]", 1) feedback_add_details("admin_verb","SMS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/client/proc/cmd_mentor_check_new_players() //Allows mentors / admins to determine who the newer players are. + set category = "Admin" + set name = "Check new Players" + if(!holder) + src << "Only staff members may use this command." + + var/age = alert(src, "Age check", "Show accounts yonger then _____ days","7", "30" , "All") + + if(age == "All") + age = 9999999 + else + age = text2num(age) + + var/missing_ages = 0 + var/msg = "" + for(var/client/C in clients) + if(C.player_age == "Requires database") + missing_ages = 1 + continue + if(C.player_age < age) + msg += "[key_name_admin(C)]: account is [C.player_age] days old
" + + if(missing_ages) + src << "Some accounts did not have proper ages set in their clients. This function requires database to be present" + + if(msg != "") + src << browse(msg, "window=Player_age_check") + else + src << "No matches for that age range found." + + /client/proc/cmd_admin_world_narrate() // Allows administrators to fluff events a little easier -- TLE set category = "Special Verbs" set name = "Global Narrate" diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm index c85ee0159c..d92a67af28 100644 --- a/code/modules/client/client defines.dm +++ b/code/modules/client/client defines.dm @@ -18,6 +18,7 @@ var/area = null var/time_died_as_mouse = null //when the client last died as a mouse + var/adminhelped = 0 /////////////// //SOUND STUFF// diff --git a/code/setup.dm b/code/setup.dm index c56aefde1d..b87ac264c9 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -620,8 +620,9 @@ var/list/TAGGERLOCATIONS = list("Disposals", #define R_SOUNDS 2048 #define R_SPAWN 4096 #define R_MOD 8192 +#define R_MENTOR 16384 -#define R_MAXPERMISSION 8192 //This holds the maximum value for a permission. It is used in iteration, so keep it updated. +#define R_MAXPERMISSION 16384 //This holds the maximum value for a permission. It is used in iteration, so keep it updated. #define R_HOST 65535 diff --git a/code/world.dm b/code/world.dm index 4793e47c16..0a0e33c9a0 100644 --- a/code/world.dm +++ b/code/world.dm @@ -191,9 +191,12 @@ if (copytext(line, 1, 2) == ";") continue - var/rights = admin_ranks["Moderator"] + var/title = "Moderator" + if(config.mods_are_mentors) title = "Mentor" + var/rights = admin_ranks[title] + var/ckey = copytext(line, 1, length(line)+1) - var/datum/admins/D = new /datum/admins("Moderator", rights, ckey) + var/datum/admins/D = new /datum/admins(title, rights, ckey) D.associate(directory[ckey]) /world/proc/update_status() diff --git a/config/example/admin_ranks.txt b/config/example/admin_ranks.txt index 031b5f6b13..e02a56df04 100644 --- a/config/example/admin_ranks.txt +++ b/config/example/admin_ranks.txt @@ -29,6 +29,8 @@ Admin Observer Moderator +MOD +Mentor +MENTOR + Admin Candidate +ADMIN Trial Admin +@ +SPAWN +REJUV +VAREDIT +BAN Badmin +@ +POSSESS +BUILDMODE +SERVER +FUN @@ -40,4 +42,4 @@ Retired Admin +ADMIN +STEALTH Host +EVERYTHING Developer +DEBUG +VAREDIT +SERVER +SPAWN +REJUV +POSSESS +BUILDMODE -Dev Mod +@ +MOD \ No newline at end of file +Dev Mod +@ +MOD diff --git a/config/example/config.txt b/config/example/config.txt index 300c23d34f..fa8613e21d 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -73,6 +73,12 @@ LOG_PDA ## disconnect players who did nothing during 10 minutes # KICK_INACTIVE +## Use Mentors instead of Moderators. Mentors are designed with the idea that +###they help in pushing new people to be better at roleplay. If you uncomment +###this it will reduce the rights that your mods have. +#MENTORS + + ## probablities for game modes chosen in "secret" and "random" modes ## ## default probablity is 1, increase to make that mode more likely to be picked From 48262ae9dc902809352e21fddee740a114276287 Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Mon, 5 May 2014 14:49:25 +0930 Subject: [PATCH 06/11] Robots will now take burn damage from appropriate projectiles, rather than recieving brute. --- code/modules/mob/living/silicon/silicon.dm | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 6f770c8a71..afdeeb81d4 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -113,8 +113,17 @@ return 1 /mob/living/silicon/bullet_act(var/obj/item/projectile/Proj) - if(!Proj.nodamage) adjustBruteLoss(Proj.damage) + + + if(!Proj.nodamage) + switch(Proj.damage_type) + if(BRUTE) + adjustBruteLoss(Proj.damage) + if(BURN) + adjustFireLoss(Proj.damage) + Proj.on_hit(src,2) + return 2 /mob/living/silicon/apply_effect(var/effect = 0,var/effecttype = STUN, var/blocked = 0) From ffdba855fafa90149f913891240a516468ecc912 Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Mon, 5 May 2014 14:50:22 +0930 Subject: [PATCH 07/11] Fixes #3741 --- .../mob/living/silicon/robot/component.dm | 3 ++- .../modules/mob/living/silicon/robot/robot.dm | 20 +++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm index a82ad65500..fba4477b1d 100644 --- a/code/modules/mob/living/silicon/robot/component.dm +++ b/code/modules/mob/living/silicon/robot/component.dm @@ -135,7 +135,8 @@ icon_state = "working" construction_time = 200 construction_cost = list("metal"=5000) - + var/brute = 0 + var/burn = 0 // TODO: actual icons ;) /obj/item/robot_parts/robot_component/binary_communication_device diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 13db34f58c..35341f111d 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -127,7 +127,7 @@ var/datum/robot_component/cell_component = components["power cell"] cell_component.wrapped = cell cell_component.installed = 1 - + hud_list[HEALTH_HUD] = image('icons/mob/hud.dmi', src, "hudblank") hud_list[STATUS_HUD] = image('icons/mob/hud.dmi', src, "hudhealth100") hud_list[ID_HUD] = image('icons/mob/hud.dmi', src, "hudblank") @@ -136,9 +136,9 @@ hud_list[IMPCHEM_HUD] = image('icons/mob/hud.dmi', src, "hudblank") hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank") hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - - + + playsound(loc, 'sound/voice/liveagain.ogg', 75, 1) @@ -579,6 +579,14 @@ user.drop_item() W.loc = null + var/obj/item/robot_parts/robot_component/WC = W + if(istype(WC)) + C.brute_damage = WC.brute + C.electronics_damage = WC.burn + else //This will nominally mean that removing and replacing a power cell will repair the mount, but I don't care at this point. ~Z + C.brute_damage = 0 + C.electronics_damage = 0 + usr << "\blue You install the [W.name]." return @@ -641,8 +649,12 @@ if(!remove) return var/datum/robot_component/C = components[remove] - var/obj/item/I = C.wrapped + var/obj/item/robot_parts/robot_component/I = C.wrapped user << "You remove \the [I]." + if(istype(I)) + I.brute = C.brute_damage + I.burn = C.electronics_damage + I.loc = src.loc if(C.installed == 1) From c44e7b0e5668d2d8bcd7da123f6cecc2ea21da6d Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Mon, 5 May 2014 16:14:59 +0930 Subject: [PATCH 08/11] Fixes #4495. --- code/game/gamemodes/changeling/changeling.dm | 2 + .../gamemodes/changeling/changeling_powers.dm | 76 +++++++++++++++++++ .../gamemodes/changeling/modularchangling.dm | 6 ++ 3 files changed, 84 insertions(+) diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 1978df1ae4..8a3b7d075e 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -215,6 +215,8 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" /datum/changeling //stores changeling powers, changeling recharge thingie, changeling absorbed DNA and changeling ID (for changeling hivemind) var/list/absorbed_dna = list() + var/list/absorbed_species = list() + var/list/absorbed_languages = list() var/absorbedcount = 0 var/chem_charges = 20 var/chem_recharge_rate = 0.5 diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index fb01c76588..53b2c36ea8 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -1,5 +1,6 @@ //Restores our verbs. It will only restore verbs allowed during lesser (monkey) form if we are not human /mob/proc/make_changeling() + if(!mind) return if(!mind.changeling) mind.changeling = new /datum/changeling(gender) verbs += /datum/changeling/proc/EvolutionMenu @@ -23,6 +24,15 @@ src.verbs += P.verbpath mind.changeling.absorbed_dna |= dna + + var/mob/living/carbon/human/H = src + if(istype(H)) + mind.changeling.absorbed_species += H.species.name + + for(var/language in languages) + if(!(language in mind.changeling.absorbed_languages)) + mind.changeling.absorbed_languages += language + return 1 //removes our changeling verbs @@ -63,6 +73,54 @@ return changeling +//Used to dump the languages from the changeling datum into the actual mob. +/mob/proc/changeling_update_languages(var/updated_languages) + + languages = list() + for(var/language in updated_languages) + languages += language + + return + +//Used to switch species based on the changeling datum. +/mob/proc/changeling_change_species() + + set category = "Changeling" + set name = "Change Species (5)" + + var/mob/living/carbon/human/H = src + if(!istype(H)) + src << "We may only use this power while in humanoid form." + return + + var/datum/changeling/changeling = changeling_power(5,1,0) + if(!changeling) return + + if(changeling.absorbed_species.len < 2) + src << "We do not know of any other species genomes to use." + return + + var/S = input("Select the target species: ", "Target Species", null) as null|anything in changeling.absorbed_species + if(!S) return + + domutcheck(src, null) + + changeling.chem_charges -= 5 + changeling.geneticdamage = 30 + + src.visible_message("[src] transforms!") + + src.verbs -= /mob/proc/changeling_change_species + spawn(10) src.verbs += /mob/proc/changeling_change_species + + H.set_species(S) + + changeling_update_languages(changeling.absorbed_languages) + + feedback_add_details("changeling_powers","TR") + + return 1 + //Absorbs the victim's DNA making them uncloneable. Requires a strong grip on the victim. //Doesn't cost anything as it's the most basic ability. /mob/proc/changeling_absorb_dna() @@ -82,6 +140,10 @@ src << "[T] is not compatible with our biology." return + if(T.species.flags & NO_SCAN) + src << "We do not know how to parse this creature's DNA!" + return + if(NOCLONE in T.mutations) src << "This creature's DNA is ruined beyond useability!" return @@ -127,6 +189,17 @@ changeling.chem_charges += 10 changeling.geneticpoints += 2 + //Steal all of their languages! + for(var/language in T.languages) + if(!(language in changeling.absorbed_languages)) + changeling.absorbed_languages += language + + changeling_update_languages(changeling.absorbed_languages) + + //Steal their species! + if(T.species && !(T.species.name in changeling.absorbed_species)) + changeling.absorbed_species += T.species.name + if(T.mind && T.mind.changeling) if(T.mind.changeling.absorbed_dna) for(var/dna_data in T.mind.changeling.absorbed_dna) //steal all their loot @@ -260,6 +333,8 @@ O.make_changeling(1) O.verbs += /mob/proc/changeling_lesser_transform + O.changeling_update_languages(changeling.absorbed_languages) + feedback_add_details("changeling_powers","LF") del(C) return 1 @@ -344,6 +419,7 @@ C.mind.transfer_to(O) O.make_changeling() + O.changeling_update_languages(changeling.absorbed_languages) feedback_add_details("changeling_powers","LFT") del(C) diff --git a/code/game/gamemodes/changeling/modularchangling.dm b/code/game/gamemodes/changeling/modularchangling.dm index 9d1d94adf3..5048977789 100644 --- a/code/game/gamemodes/changeling/modularchangling.dm +++ b/code/game/gamemodes/changeling/modularchangling.dm @@ -26,6 +26,12 @@ var/list/datum/power/changeling/powerinstances = list() genomecost = 0 verbpath = /mob/proc/changeling_transform +/datum/power/changeling/change_species + name = "Change Species" + desc = "We take on the apperance of a species that we have absorbed." + genomecost = 0 + verbpath = /mob/proc/changeling_change_species + /datum/power/changeling/fakedeath name = "Regenerative Stasis" desc = "We become weakened to a death-like state, where we will rise again from death." From 051edb4fc18673b70f1488430325d840b831bc0e Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Mon, 5 May 2014 16:57:27 +0930 Subject: [PATCH 09/11] Fixes #4421 --- code/modules/mob/living/carbon/monkey/diona.dm | 16 ++++++++-------- code/modules/mob/living/living.dm | 13 +++++++++---- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/code/modules/mob/living/carbon/monkey/diona.dm b/code/modules/mob/living/carbon/monkey/diona.dm index eb8dedb4f0..ec84e74a1e 100644 --- a/code/modules/mob/living/carbon/monkey/diona.dm +++ b/code/modules/mob/living/carbon/monkey/diona.dm @@ -21,20 +21,20 @@ processing_objects.Add(src) /obj/item/weapon/holder/Del() - //Hopefully this will stop the icon from remaining on human mobs. - if(istype(loc,/mob/living)) - var/mob/living/A = src.loc - src.loc = null - A.update_icons() processing_objects.Remove(src) ..() /obj/item/weapon/holder/process() - if(!loc) del(src) if(istype(loc,/turf) || !(contents.len)) + for(var/mob/M in contents) - M.loc = get_turf(src) + + var/atom/movable/mob_container + mob_container = M + mob_container.forceMove(get_turf(src)) + M.reset_view() + del(src) /obj/item/weapon/holder/attackby(obj/item/weapon/W as obj, mob/user as mob) @@ -188,7 +188,7 @@ return src.split() - src.visible_message("\red [src] begins to shift and quiver, and erupts in a shower of shed bark and twigs!","\red You begin to shift and quiver, then erupt in a shower of shed bark and twigs, attaining your adult form!") + src.visible_message("\red [src] begins to shift and quiver, and erupts in a shower of shed bark as it splits into a tangle of nearly a dozen new dionaea.","\red You begin to shift and quiver, feeling your awareness splinter. All at once, we consume our stored nutrients to surge with growth, splitting into a tangle of at least a dozen new dionaea. We have attained our gestalt form.") var/mob/living/carbon/human/adult = new(get_turf(src.loc)) adult.set_species("Diona") diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 7f31d737a2..93a3298b89 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -312,7 +312,7 @@ // make the icons look correct regenerate_icons() - + hud_updateflag |= 1 << HEALTH_HUD hud_updateflag |= 1 << STATUS_HUD return @@ -447,9 +447,14 @@ //Getting out of someone's inventory. if(istype(src.loc,/obj/item/weapon/holder)) - var/obj/item/weapon/holder/H = src.loc - src.loc = get_turf(src.loc) - del(H) + var/obj/item/weapon/holder/H = src.loc //Get our item holder. + var/mob/M = H.loc //Get our mob holder (if any). + + if(istype(M)) + M.drop_from_inventory(H) + M << "[H] wriggles out of your grip!" + src << "You wriggle out of [M]'s grip!" + return //Resisting control by an alien mind. From 54925310943edd9487a3e300533f24b8c580dd93 Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Mon, 5 May 2014 17:18:55 +0930 Subject: [PATCH 10/11] Fixes #4534 --- code/game/machinery/adv_med.dm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index b7d6ad8ef7..c400185a45 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -282,6 +282,7 @@ dat += "" for(var/datum/organ/external/e in occupant.organs) + dat += "" var/AN = "" var/open = "" @@ -307,13 +308,15 @@ robot = "Prosthetic:" if(e.open) open = "Open:" + var/unknown_body = 0 for(var/I in e.implants) if(is_type_in_list(I,known_implants)) imp += "[I] implanted:" else unknown_body++ - if(unknown_body) + + if(unknown_body || e.hidden) imp += "Unknown body present:" if(!AN && !open && !infected & !imp) AN = "None:" From 3dfe1dd1961ff598fe25108fb5456a353aad3445 Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Tue, 6 May 2014 04:46:48 +0930 Subject: [PATCH 11/11] Replacement dionaea sprites intended to be pushed a long while back. --- icons/mob/human_races/r_diona.dmi | Bin 14986 -> 2650 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/mob/human_races/r_diona.dmi b/icons/mob/human_races/r_diona.dmi index ef55275d5a96e89a02b92c1e29b476e0f368fb0c..c09acaa953844bf97d494e0d1005a9477ab9c8a8 100644 GIT binary patch literal 2650 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

4&s&Bu-6 z7QhQ%j!YCX#v_X^VYJ?){UN{dizq%QMp!6Rz$PgYgn4aSU)_kDEZQw${lM=a&@P6K za~1RAAcdsq6~6g1qZBsM@zr4Ouy}wD|O3{J;qpU#;v?OI3?|io|e)m-EPupLw za7?3{!*%t217*H>EuzS=6%z*N>?{5XZf%{(gW~|z@dz6O+T*NNB=Xu91Mc9=nik!o zS)lDB8JY)|px!?x4}4TOplgq$r%x6C2IR2C-7tW8tt-{+9z=w4(R(FZ=OKQryj$cT zm3X-1kq~-{W&&J^>oES-ZGVT$T=i&{o}{1AIp3F@dFv@Or>LwP;K{Uj;H|jMyj(UA zG{3p@M@%40q_VGpXY^(+B-PpPwDcWnO48|jg^;|dFDS(D=Kh&-#Z$pN~S}rJRd~Tfd;U~gP~A+bp03x05=3))djRnHFSvX^q?P2Z(-T; z1{#^8vw_zv5*eQsJn)2{nXJhJrV#x829vi+i2qi!4fX5?dmqlVC+)<$RoVF;#R+Af zEX(PwmmRMm(a}dUFo1Pw>s*2#NEn?zG z4QMA{)~|;D+_*ESS6g#Mi}2i!@FwYS_z~GhW}XCJv{EZ(elxJz(&2IYp#B>1B$H7c6!5ZYUmt>^&UHa5^JVfI06I3jZq0 zH;{v5b@vBYHIieMwt&Y>2NR-$;&=+9wGX(XSO;LiL|c0%7d_vspMaV)W&VRnyE=PI z{A1h_UU^9I+|f?>QpD673$^)5Tm1xwEp6X&pP+13bWRz(=^4{e#v_Q}avx6rS; zy;q@+|2vLf)pH+$p8VB1Z+Qeo-2i^V&Q!_#UqtnZmzTHtnlZH=qr2IO&W?zJMKz z#cr^jircfL{av^SW$E~jnfA@&C7!5+L*-(rsetcy`aa?CMEu&aZen;1UwZAT!Lrn9 zv);Z&{fKg67rp(iv%^+RU1}{-F&bqQO6vU4(g9-`xx+=c+lJAY2Kc_bBD>=jk=65B z!pc9f?Q`edwgp`S2?m=n6dW+lbkTsQt2fY8OQrI-!%|?d`*8`1xv98mv~Zp|L5A^2 z|Mv3@hfQSA_5QNbydtUCxp*~9`gOeV(V#k06I5T(aQFPFh}HZI4JqT9c~4YqXauI7 zh=x9Na-om;fTGl4_Sk! z(O$Z7{*o1801)LaNK#|7`=Bdqap~MuY-X(zzg*Hc3;aG06Nt?X zV^I%yc`zdC<7Lwj^~8qyaOVRd3Q9)sY+0tTTdo+}F64VDt&;pxt?SSu;*#yDCp1Dg SAN+DD@K#bmqD0If;C}(YD#!Q$