diff --git a/SQL/paradise_schema.sql b/SQL/paradise_schema.sql index 1069dd6b2d6..9bfc6fa90b0 100644 --- a/SQL/paradise_schema.sql +++ b/SQL/paradise_schema.sql @@ -140,6 +140,25 @@ CREATE TABLE `death` ( ) ENGINE=MyISAM AUTO_INCREMENT=166546 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `donators` +-- + +DROP TABLE IF EXISTS `donators`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `donators` ( + `patreon_name` varchar(32) NOT NULL, + `tier` int(2), + `ckey` varchar(32) COMMENT 'Manual Field', + `start_date` datetime, + `end_date` datetime, + `active` boolean, + PRIMARY KEY (`patreon_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + + -- -- Table structure for table `admin` -- diff --git a/SQL/paradise_schema_prefixed.sql b/SQL/paradise_schema_prefixed.sql index 55e71aa2aab..c0cc8c86d6b 100644 --- a/SQL/paradise_schema_prefixed.sql +++ b/SQL/paradise_schema_prefixed.sql @@ -140,6 +140,24 @@ CREATE TABLE `SS13_death` ( ) ENGINE=MyISAM AUTO_INCREMENT=166546 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `donators` +-- + +DROP TABLE IF EXISTS `SS13_donators`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `donators` ( + `patreon_name` varchar(32) NOT NULL, + `tier` int(2), + `ckey` varchar(32) COMMENT 'Manual Field', + `start_date` datetime, + `end_date` datetime, + `active` boolean, + PRIMARY KEY (`patreon_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `SS13_admin` -- diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index dcb4501ce6e..049019a32d2 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -288,5 +288,10 @@ #define SHELTER_DEPLOY_BAD_AREA "bad area" #define SHELTER_DEPLOY_ANCHORED_OBJECTS "anchored objects" +// Client donator levels +#define DONATOR_LEVEL_NONE 0 +#define DONATOR_LEVEL_ONE 1 +#define DONATOR_LEVEL_TWO 2 + // The cooldown on OOC messages such as OOC, LOOC, praying and adminhelps #define OOC_COOLDOWN 5 diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index 703b3e6b205..d39cc600221 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -24,5 +24,6 @@ #define DISABLE_KARMA_REMINDER 4096 #define MEMBER_PUBLIC 8192 #define CHAT_NO_ADMINLOGS 16384 +#define DONATOR_PUBLIC 32768 -#define TOGGLES_DEFAULT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_ATTACKLOGS|CHAT_LOOC|MEMBER_PUBLIC) +#define TOGGLES_DEFAULT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_ATTACKLOGS|CHAT_LOOC|MEMBER_PUBLIC|DONATOR_PUBLIC) diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm index f209e652b38..38abe4b5fd0 100644 --- a/code/game/verbs/ooc.dm +++ b/code/game/verbs/ooc.dm @@ -61,16 +61,24 @@ var/global/admin_ooc_colour = "#b82e00" for(var/client/C in clients) if(C.prefs.toggles & CHAT_OOC) var/display_name = src.key + if(prefs.unlock_content) if(prefs.toggles & MEMBER_PUBLIC) var/icon/byond = icon('icons/member_content.dmi', "blag") display_name = "[bicon(byond)][display_name]" + + if(donator_level >= DONATOR_LEVEL_ONE) + if((prefs.toggles & DONATOR_PUBLIC)) + var/icon/donator = icon('icons/ooc_tag_16x.dmi', "donator") + display_name = "[bicon(donator)][display_name]" + if(holder) if(holder.fakekey) if(C.holder) display_name = "[holder.fakekey]/([src.key])" else display_name = holder.fakekey + to_chat(C, "OOC: [display_name]: [msg]") /proc/toggle_ooc() diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm index 8f2adef5a1b..bb243c3e6aa 100644 --- a/code/modules/client/client defines.dm +++ b/code/modules/client/client defines.dm @@ -89,4 +89,7 @@ // Their chat window, sort of important. // See /goon/code/datums/browserOutput.dm - var/datum/chatOutput/chatOutput \ No newline at end of file + var/datum/chatOutput/chatOutput + + // Donator stuff. + var/donator_level = DONATOR_LEVEL_NONE \ No newline at end of file diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 17c454bb7e2..0cf9b0a0915 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -305,6 +305,8 @@ admins += src holder.owner = src + donator_check() + //preferences datum - also holds some persistant data for the client (because we may as well keep these datums to a minimum) prefs = preferences_datums[ckey] if(!prefs) @@ -378,10 +380,27 @@ return ..() +/client/proc/donator_check() + if(IsGuestKey(key)) + return + + establish_db_connection() + if(!dbcon.IsConnected()) + return + + //Donator stuff. + var/DBQuery/query_donor_select = dbcon.NewQuery("SELECT ckey, tier, active FROM `[format_table_name("donators")]` WHERE ckey = '[ckey]'") + query_donor_select.Execute() + while(query_donor_select.NextRow()) + if(!text2num(query_donor_select.item[3])) + // Inactive donator. + donator_level = DONATOR_LEVEL_NONE + return + donator_level = text2num(query_donor_select.item[2]) + break /client/proc/log_client_to_db() - - if( IsGuestKey(src.key) ) + if(IsGuestKey(key)) return establish_db_connection() diff --git a/code/modules/client/preference/loadout/loadout.dm b/code/modules/client/preference/loadout/loadout.dm index 010fc54564c..b42c5d5abf1 100644 --- a/code/modules/client/preference/loadout/loadout.dm +++ b/code/modules/client/preference/loadout/loadout.dm @@ -4,6 +4,7 @@ var/list/gear_datums = list() /datum/loadout_category var/category = "" var/list/gear = list() + var/donor_only = FALSE /datum/loadout_category/New(cat) category = cat @@ -33,6 +34,8 @@ var/list/gear_datums = list() if(!loadout_categories[use_category]) loadout_categories[use_category] = new /datum/loadout_category(use_category) var/datum/loadout_category/LC = loadout_categories[use_category] + if(initial(G.donor_only)) + LC.donor_only = TRUE gear_datums[use_name] = new geartype LC.gear[use_name] = gear_datums[use_name] @@ -54,6 +57,7 @@ var/list/gear_datums = list() var/list/gear_tweaks = list() //List of datums which will alter the item after it has been spawned. var/subtype_path = /datum/gear //for skipping organizational subtypes (optional) var/subtype_cost_overlap = TRUE //if subtypes can take points at the same time + var/donor_only = FALSE // if it's only available to donors /datum/gear/New() ..() @@ -76,4 +80,4 @@ var/list/gear_datums = list() var/item = new gd.path(gd.location) for(var/datum/gear_tweak/gt in gear_tweaks) gt.tweak_item(item, metadata["[gt]"]) - return item \ No newline at end of file + return item diff --git a/code/modules/client/preference/loadout/loadout_donor.dm b/code/modules/client/preference/loadout/loadout_donor.dm new file mode 100644 index 00000000000..edf7e173730 --- /dev/null +++ b/code/modules/client/preference/loadout/loadout_donor.dm @@ -0,0 +1,90 @@ +/datum/gear/donor + donor_only = TRUE + sort_category = "Donor" + subtype_path = /datum/gear/donor + +/datum/gear/donor/furgloves + display_name = "Fur Gloves" + path = /obj/item/clothing/gloves/furgloves + +/datum/gear/donor/furboots + display_name = "Fur Boots" + path = /obj/item/clothing/shoes/furboots + +/datum/gear/donor/noble_boot + display_name = "Noble Boots" + path = /obj/item/clothing/shoes/fluff/noble_boot + +/datum/gear/donor/furcape + display_name = "Fur Cape" + path = /obj/item/clothing/suit/furcape + cost = 2 + +/datum/gear/donor/furcoat + display_name = "Fur Coat" + path = /obj/item/clothing/suit/furcoat + cost = 2 + +/datum/gear/donor/lord_admiral + display_name = "Lord Admiral Coat" + path = /obj/item/clothing/suit/lordadmiral + +/datum/gear/donor/lord_admiral_hat + display_name = "Lord Admiral Hat" + path = /obj/item/clothing/head/lordadmiralhat + +/datum/gear/donor/kamina + display_name = "Spiky Orange-tinted Shades" + path = /obj/item/clothing/glasses/fluff/kamina + +/datum/gear/donor/green + display_name = "Spiky Green-tinted Shades" + path = /obj/item/clothing/glasses/fluff/kamina/green + +/datum/gear/donor/hipster + display_name = "Hipster Glasses" + path = /obj/item/clothing/glasses/regular/hipster + +/datum/gear/donor/threedglasses + display_name = "Threed Glasses" + path = /obj/item/clothing/glasses/threedglasses + +/datum/gear/donor/blacksombrero + display_name = "Black Sombrero" + path = /obj/item/clothing/head/fluff/blacksombrero + +/datum/gear/donor/guardhelm + display_name = "Plastic Guard helm" + path = /obj/item/clothing/head/fluff/guardhelm + +/datum/gear/donor/goldtophat + display_name = "Gold-trimmed Top Hat" + path = /obj/item/clothing/head/fluff/goldtophat + +/datum/gear/donor/goldtophat/red + display_name = "Red Gold-trimmed Top Hat" + path = /obj/item/clothing/head/fluff/goldtophat/red + +/datum/gear/donor/goldtophat/blue + display_name = "Blue Gold-trimmed Top Hat" + path = /obj/item/clothing/head/fluff/goldtophat/blue + +/datum/gear/donor/mushhat + display_name = "Mushroom Hat" + path = /obj/item/clothing/head/fluff/mushhat + +/datum/gear/donor/furcap + display_name = "Fur Cap" + path = /obj/item/clothing/head/furcap + +/datum/gear/donor/mouse + display_name = "Mouse Headband" + path = /obj/item/clothing/head/kitty/mouse + +/datum/gear/donor/fawkes + display_name = "Guy Fawkes mask" + path = /obj/item/clothing/mask/fawkes + +/datum/gear/donor/noble_clothes + display_name = "Noble Clothes" + path = /obj/item/clothing/under/noble_clothes diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index 72ec8f101d2..415a6f05d3f 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -61,7 +61,6 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts #define MAX_SAVE_SLOTS 20 // Save slots for regular players #define MAX_SAVE_SLOTS_MEMBER 20 // Save slots for BYOND members -#define MAX_GEAR_COST config.max_loadout_points #define TAB_CHAR 0 #define TAB_GAME 1 @@ -73,6 +72,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used // var/savefile_version = 0 var/max_save_slots = MAX_SAVE_SLOTS + var/max_gear_slots = 0 //non-preference stuff var/warns = 0 @@ -212,11 +212,17 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts /datum/preferences/New(client/C) b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+") + if(istype(C)) if(!IsGuestKey(C.key)) unlock_content = C.IsByondMember() if(unlock_content) max_save_slots = MAX_SAVE_SLOTS_MEMBER + + max_gear_slots = config.max_loadout_points + if(C.donator_level >= DONATOR_LEVEL_ONE) + max_gear_slots += 5 + var/loaded_preferences_successfully = load_preferences(C) if(loaded_preferences_successfully) if(load_character(C)) @@ -428,6 +434,8 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts dat += "OOC notes: Edit
" if(unlock_content) dat += "BYOND Membership Publicity: [(toggles & MEMBER_PUBLIC) ? "Public" : "Hidden"]
" + if(user.client.donator_level >= DONATOR_LEVEL_ONE) + dat += "Donator Publicity: [(toggles & DONATOR_PUBLIC) ? "Public" : "Hidden"]
" dat += "Randomized character slot: [randomslot ? "Yes" : "No"]
" dat += "Ghost ears: [(toggles & CHAT_GHOSTEARS) ? "Nearest Creatures" : "All Speech"]
" @@ -464,14 +472,18 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts total_cost += G.cost var/fcolor = "#3366CC" - if(total_cost < MAX_GEAR_COST) + if(total_cost < max_gear_slots) fcolor = "#E67300" dat += "" - dat += "" + dat += "" dat += "
[total_cost]/[MAX_GEAR_COST] loadout points spent. \[Clear Loadout\]
[total_cost]/[max_gear_slots] loadout points spent. \[Clear Loadout\]
" var/firstcat = 1 for(var/category in loadout_categories) + var/datum/loadout_category/LC = loadout_categories[category] + if(LC.donor_only) + if(user.client.donator_level < DONATOR_LEVEL_TWO) // level two donators get the donator loadout, so don't show it to anyone with less than that + continue if(firstcat) firstcat = 0 else @@ -1097,6 +1109,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if(TG.display_name in gear) gear -= TG.display_name else + if(TG.donor_only) + if(user.client.donator_level < DONATOR_LEVEL_TWO) // donator items are locked to > tier 2 + //they normally can't even get this far- but just in case of href exploits, we check them here + return var/total_cost = 0 var/list/type_blacklist = list() for(var/gear_name in gear) @@ -1108,7 +1124,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts type_blacklist += G.subtype_path total_cost += G.cost - if((total_cost + TG.cost) <= MAX_GEAR_COST) + if((total_cost + TG.cost) <= max_gear_slots) gear += TG.display_name else if(href_list["gear"] && href_list["tweak"]) @@ -1875,6 +1891,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if(unlock_content) toggles ^= MEMBER_PUBLIC + if("donor_public") + if(user.client.donator_level >= DONATOR_LEVEL_ONE) + toggles ^= DONATOR_PUBLIC + if("gender") if(gender == MALE) gender = FEMALE diff --git a/icons/ooc_tag_16x.dmi b/icons/ooc_tag_16x.dmi new file mode 100644 index 00000000000..2165a593220 Binary files /dev/null and b/icons/ooc_tag_16x.dmi differ diff --git a/paradise.dme b/paradise.dme index fc6303fd746..b66cc8dd006 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1116,6 +1116,7 @@ #include "code\modules\client\preference\loadout\loadout.dm" #include "code\modules\client\preference\loadout\loadout_accessories.dm" #include "code\modules\client\preference\loadout\loadout_cosmetics.dm" +#include "code\modules\client\preference\loadout\loadout_donor.dm" #include "code\modules\client\preference\loadout\loadout_general.dm" #include "code\modules\client\preference\loadout\loadout_hat.dm" #include "code\modules\client\preference\loadout\loadout_shoes.dm" @@ -1141,6 +1142,8 @@ #include "code\modules\clothing\masks\gasmask.dm" #include "code\modules\clothing\masks\miscellaneous.dm" #include "code\modules\clothing\masks\voice.dm" +#include "code\modules\clothing\patreon\glasses.dm" +#include "code\modules\clothing\patreon\hats.dm" #include "code\modules\clothing\shoes\colour.dm" #include "code\modules\clothing\shoes\magboots.dm" #include "code\modules\clothing\shoes\miscellaneous.dm"