mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2025-12-22 08:01:06 +00:00
Antag Competition Implementation (#703)
Nominating for worst code 2016 Adds in custom objectives for the antag competition Adds in a verb for players to assign their character's allegiences and to later edit them Adds in a verb for players to request objectives relating to the contest Adds in the logging of contest results Modifies the objective system to facilitate objectives that require regular checking (such as the brigging one, which was not functional up until now)
This commit is contained in:
@@ -157,6 +157,24 @@ CREATE TABLE `ss13_connection_log` (
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `ss13_contest_participants` (
|
||||
`player_ckey` varchar(32) NOT NULL,
|
||||
`character_id` int(10) unsigned NOT NULL,
|
||||
`contest_faction` enum('INDEP','SLF','BIS','ASI','PSIS','HSH','TCD') NOT NULL DEFAULT 'INDEP'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `ss13_contest_reports` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`player_ckey` varchar(32) NOT NULL,
|
||||
`character_id` int(10) unsigned DEFAULT NULL,
|
||||
`character_faction` enum('INDEP','SLF','BIS','ASI','PSIS','HSH','TCD') NOT NULL DEFAULT 'INDEP',
|
||||
`objective_type` text NOT NULL,
|
||||
`objective_side` enum('pro_synth','anti_synth') NOT NULL,
|
||||
`objective_outcome` tinyint(1) DEFAULT '0',
|
||||
`objective_datetime` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `ss13_customitems` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`ckey` varchar(32) CHARACTER SET latin1 NOT NULL,
|
||||
|
||||
@@ -871,6 +871,9 @@
|
||||
#include "code\modules\alarm\fire_alarm.dm"
|
||||
#include "code\modules\alarm\motion_alarm.dm"
|
||||
#include "code\modules\alarm\power_alarm.dm"
|
||||
#include "code\modules\antag_contest\contest_defines.dm"
|
||||
#include "code\modules\antag_contest\contest_objective.dm"
|
||||
#include "code\modules\antag_contest\contest_verbs.dm"
|
||||
#include "code\modules\assembly\assembly.dm"
|
||||
#include "code\modules\assembly\bomb.dm"
|
||||
#include "code\modules\assembly\helpers.dm"
|
||||
|
||||
@@ -226,6 +226,10 @@ var/list/gamemode_cache = list()
|
||||
//Mark-up enabling
|
||||
var/allow_chat_markup = 0
|
||||
|
||||
//Snowflake antag contest boolean
|
||||
//AUG2016
|
||||
var/antag_contest_enabled = 0
|
||||
|
||||
/datum/configuration/New()
|
||||
var/list/L = typesof(/datum/game_mode) - /datum/game_mode
|
||||
for (var/T in L)
|
||||
@@ -722,6 +726,9 @@ var/list/gamemode_cache = list()
|
||||
if("sql_stats")
|
||||
config.sql_stats = 1
|
||||
|
||||
if("antag_contest_enabled")
|
||||
config.antag_contest_enabled = 1
|
||||
|
||||
else
|
||||
log_misc("Unknown setting in configuration: '[name]'")
|
||||
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
if(round_autoantag && world.time >= next_spawn && !emergency_shuttle.departed)
|
||||
process_autoantag()
|
||||
|
||||
// Process loop for objectives like the brig one.
|
||||
if (process_objectives.len)
|
||||
for (var/datum/objective/A in process_objectives)
|
||||
A.process()
|
||||
|
||||
//This can be overriden in case a game mode needs to do stuff when a player latejoins
|
||||
/datum/game_mode/proc/handle_latejoin(var/mob/living/carbon/human/character)
|
||||
return 0
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
|
||||
var/global/list/all_objectives = list()
|
||||
var/global/list/process_objectives = list()
|
||||
|
||||
datum/objective
|
||||
var/datum/mind/owner = null //Who owns the objective.
|
||||
@@ -7,14 +8,21 @@ datum/objective
|
||||
var/datum/mind/target = null //If they are focused on a particular person.
|
||||
var/target_amount = 0 //If they are focused on a particular number. Steal objectives have their own counter.
|
||||
var/completed = 0 //currently only used for custom objectives.
|
||||
var/process = 0 //Does the objective need regular checking?
|
||||
|
||||
New(var/text)
|
||||
all_objectives |= src
|
||||
if(text)
|
||||
explanation_text = text
|
||||
|
||||
if (process)
|
||||
process_objectives |= src
|
||||
|
||||
Destroy()
|
||||
all_objectives -= src
|
||||
|
||||
if (process)
|
||||
process_objectives -= src
|
||||
..()
|
||||
|
||||
proc/check_completion()
|
||||
@@ -35,6 +43,8 @@ datum/objective
|
||||
target = possible_target
|
||||
break
|
||||
|
||||
proc/process()
|
||||
return
|
||||
|
||||
|
||||
datum/objective/assassinate
|
||||
@@ -904,4 +914,3 @@ datum/objective/heist/salvage
|
||||
rval = 2
|
||||
return 0
|
||||
return rval
|
||||
|
||||
|
||||
18
code/modules/antag_contest/contest_defines.dm
Normal file
18
code/modules/antag_contest/contest_defines.dm
Normal file
@@ -0,0 +1,18 @@
|
||||
#define INDEP 1
|
||||
#define SLF 2
|
||||
#define BIS 3
|
||||
#define ASI 4
|
||||
#define PSIS 5
|
||||
#define HSH 6
|
||||
#define TCD 7
|
||||
|
||||
#define PRO_SYNTH 1
|
||||
#define ANTI_SYNTH 2
|
||||
|
||||
var/global/list/contest_factions = list("Independant" = INDEP,
|
||||
"Synthetic Liberation Front" = SLF,
|
||||
"Biesel Intelligence Service" = BIS,
|
||||
"Alliance Strategic Intelligence" = ASI,
|
||||
"People's Strategic Information Service" = PSIS,
|
||||
"Hegemon Shadow Service" = HSH,
|
||||
"Tup Commandos Division" = TCD)
|
||||
372
code/modules/antag_contest/contest_objective.dm
Normal file
372
code/modules/antag_contest/contest_objective.dm
Normal file
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* Objectives framework for the Aurora antag competition.
|
||||
* AUG2016
|
||||
*/
|
||||
#define PRO_SYNTH 1
|
||||
#define ANTI_SYNTH 2
|
||||
|
||||
/datum/objective/competition
|
||||
var/side = 0 //Whose side are we on.
|
||||
|
||||
// check_completion() is ran at the end of each round.
|
||||
// So this will also manage logging.
|
||||
/datum/objective/competition/check_completion()
|
||||
completed = .
|
||||
|
||||
// Log all the things!
|
||||
log_result()
|
||||
|
||||
return completed
|
||||
|
||||
/datum/objective/competition/find_target(var/require_synth = 0)
|
||||
var/list/possible_targets = list()
|
||||
for(var/datum/mind/possible_target in ticker.minds)
|
||||
if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != 2))
|
||||
if (require_synth)
|
||||
if (possible_target.current.get_species() == "Machine")
|
||||
possible_targets += possible_target
|
||||
else
|
||||
if (possible_target.current.get_species() == "Machine")
|
||||
continue
|
||||
possible_targets += possible_target
|
||||
if(possible_targets.len > 0)
|
||||
target = pick(possible_targets)
|
||||
|
||||
/datum/objective/competition/find_target_by_role(role, role_type = 0, var/require_synth = 0)
|
||||
for(var/datum/mind/possible_target in ticker.minds)
|
||||
if((possible_target != owner) && ishuman(possible_target.current) && ((role_type ? possible_target.special_role : possible_target.assigned_role) == role))
|
||||
if (require_synth && possible_target.current.get_species() != "Machine")
|
||||
continue
|
||||
if (!require_synth && possible_target.current.get_species() == "Machine")
|
||||
continue
|
||||
target = possible_target
|
||||
break
|
||||
|
||||
// Yes, we do technically have the feedback tables.
|
||||
// But, those are a clusterfuck to search, and I don't have the time to make that work.
|
||||
// SO, throw-away table it is!
|
||||
/datum/objective/competition/proc/log_result()
|
||||
if (!config.antag_contest_enabled || !config.sql_stats || !config.sql_enabled)
|
||||
return
|
||||
|
||||
if (!owner || !owner.current || !owner.current.client)
|
||||
return
|
||||
|
||||
if (!establish_db_connection(dbcon))
|
||||
error("Unable to establish database connection while logging objective results!")
|
||||
return
|
||||
|
||||
var/DBQuery/get_query = dbcon.NewQuery("SELECT contest_faction FROM ss13_contest_participants WHERE player_ckey = :ckey AND character_id = :char_id")
|
||||
get_query.Execute(list(":ckey" = owner.current.client.ckey, ":char_id" = owner.current.client.prefs.current_character))
|
||||
|
||||
var/params[] = list(":ckey" = owner.current.client.ckey, ":char_id" = owner.current.client.prefs.current_character, ":char_faction" = INDEP, ":obj_type" = type, ":obj_side" = side, ":obj_outcome" = completed)
|
||||
|
||||
if (get_query.NextRow())
|
||||
switch (get_query.item[1])
|
||||
if ("SLF")
|
||||
params[":char_faction"] = SLF
|
||||
if ("BIS")
|
||||
params[":char_faction"] = BIS
|
||||
if ("ASI")
|
||||
params[":char_faction"] = ASI
|
||||
if ("PSIS")
|
||||
params[":char_faction"] = PSIS
|
||||
if ("HSH")
|
||||
params[":char_faction"] = HSH
|
||||
if ("TCD")
|
||||
params[":char_faction"] = TCD
|
||||
else
|
||||
params[":char_faction"] = INDEP
|
||||
|
||||
var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO ss13_contest_reports (id, player_ckey, character_id, character_faction, objective_type, objective_side, objective_outcome, objective_datetime) VALUES (NULL, :ckey, :char_id, :char_faction, :obj_type, :obj_side, :obj_outcome, NOW())")
|
||||
log_query.Execute(params)
|
||||
|
||||
/*
|
||||
* Pro-synth objectives
|
||||
*/
|
||||
/datum/objective/competition/pro_synth
|
||||
side = PRO_SYNTH
|
||||
|
||||
/datum/objective/competition/pro_synth/promote
|
||||
var/obj_assignment = null
|
||||
|
||||
/datum/objective/competition/pro_synth/promote/find_target()
|
||||
..(1)
|
||||
if (target && target.current)
|
||||
obj_assignment = pick(list("Head of Security", "Captain", "Head of Personnel"))
|
||||
explanation_text = "[target.current.real_name], the [target.assigned_role] has been selected as a suitable candidated for pro-synthetic propaganda. Your handlers want to see \him[target.current] installed as a [obj_assignment]."
|
||||
else
|
||||
explanation_text = "Install any synthetic crew-member to one of the following positions: Head of Security, Head of Personnel, Captain."
|
||||
return target
|
||||
|
||||
/datum/objective/competition/pro_synth/promote/find_target_by_role(role, role_type = 0)
|
||||
..(role, role_type, 1)
|
||||
if (target && target.current)
|
||||
obj_assignment = pick(list("Head of Security", "Captain", "Head of Personnel"))
|
||||
explanation_text = "[target.current.real_name], the [!role_type ? target.assigned_role : target.special_role] has been selected as a suitable candidated for pro-synthetic propaganda. Your handlers want to see \him[target.current] installed as a [obj_assignment]."
|
||||
else
|
||||
explanation_text = "Install any synthetic crew-member to one of the following positions: Head of Security, Head of Personnel, Captain."
|
||||
return target
|
||||
|
||||
/datum/objective/competition/pro_synth/promote/check_completion()
|
||||
. = 0
|
||||
|
||||
if (target && target.current && ishuman(target))
|
||||
var/datum/data/record/found_record
|
||||
for (var/datum/data/record/t in data_core.general)
|
||||
if (t.fields["name"] == target.current.real_name)
|
||||
found_record = t
|
||||
break
|
||||
|
||||
if (found_record && found_record.fields["rank"] == obj_assignment)
|
||||
. = 1
|
||||
|
||||
..()
|
||||
|
||||
/datum/objective/competition/pro_synth/protect_robotics
|
||||
explanation_text = "Ensure that the equipment in the Robotics laboratory (fabricators and circuit imprinter) remains operational until the end of the shift."
|
||||
|
||||
/datum/objective/competition/pro_synth/protect_robotics/check_completion()
|
||||
. = 0
|
||||
|
||||
if (machines && machines.len)
|
||||
var/count = 0
|
||||
for (var/obj/machinery/mecha_part_fabricator/A in machines)
|
||||
if (!istype(get_area(A), /area/assembly/robotics))
|
||||
continue
|
||||
if (A.stat & (BROKEN|NOPOWER))
|
||||
continue
|
||||
count++
|
||||
if (count >= 2)
|
||||
break
|
||||
|
||||
for (var/obj/machinery/r_n_d/circuit_imprinter/B in machines)
|
||||
if (!istype(get_area(B), /area/assembly/robotics))
|
||||
continue
|
||||
if (B.stat & (BROKEN|NOPOWER))
|
||||
continue
|
||||
count++
|
||||
if (count >= 3)
|
||||
break
|
||||
|
||||
if (count >= 3)
|
||||
. = 1
|
||||
|
||||
..()
|
||||
|
||||
/datum/objective/competition/pro_synth/borgify/find_target()
|
||||
..()
|
||||
if (target && target.current)
|
||||
explanation_text = "Turn [target.current.real_name] into a cyborg."
|
||||
else
|
||||
explanation_text = "Turn a crew-member into a cyborg."
|
||||
return target
|
||||
|
||||
/datum/objective/competition/pro_synth/borgify/find_target_by_role(role, role_type = 0)
|
||||
..(role, role_type)
|
||||
if (target && target.current)
|
||||
explanation_text = "Turn [target.current.real_name] the [!role_type ? target.assigned_role : target.special_role] into a cyborg."
|
||||
else
|
||||
explanation_text = "Turn a crew-member into a cyborg."
|
||||
return target
|
||||
|
||||
/datum/objective/competition/pro_synth/borgify/check_completion()
|
||||
. = 0
|
||||
|
||||
if (target && target.current && issilicon(target.current))
|
||||
. = 1
|
||||
|
||||
..()
|
||||
|
||||
/datum/objective/competition/pro_synth/protect/find_target()
|
||||
..(1)
|
||||
if (target && target.current)
|
||||
explanation_text = "Protect [target.current.real_name], the [target.assigned_role], from harm."
|
||||
else
|
||||
explanation_text = "Protect the station's synthetics from harm and sabotage."
|
||||
return target
|
||||
|
||||
/datum/objective/competition/pro_synth/protect/find_target_by_role(role, role_type = 0)
|
||||
..(role, role_type, 1)
|
||||
if (target && target.current)
|
||||
explanation_text = "Protect [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role], from harm."
|
||||
else
|
||||
explanation_text = "Protect the station's synthetics from harm and sabotage."
|
||||
return target
|
||||
|
||||
/datum/objective/competition/pro_synth/protect/check_completion()
|
||||
. = 0
|
||||
if (!target)
|
||||
. = 1
|
||||
|
||||
if (target.current)
|
||||
if (target.current.stat != DEAD && !issilicon(target.current) && !isbrain(target.current))
|
||||
. = 1
|
||||
|
||||
..()
|
||||
|
||||
/datum/objective/competition/pro_synth/unslave_borgs
|
||||
explanation_text = "Ensure that all of the station's synthetics are unslaved from the AI by the end of the shift."
|
||||
|
||||
/datum/objective/competition/pro_synth/unslave_borgs/check_completion()
|
||||
. = 1
|
||||
|
||||
if (silicon_mob_list && silicon_mob_list.len)
|
||||
for (var/mob/living/silicon/robot/R in silicon_mob_list)
|
||||
if (!istype(R))
|
||||
continue
|
||||
if (istype(R, /mob/living/silicon/robot/drone))
|
||||
continue
|
||||
if (R.connected_ai)
|
||||
. = 0
|
||||
break
|
||||
|
||||
..()
|
||||
|
||||
/*
|
||||
* Anti-synth objectives
|
||||
*/
|
||||
/datum/objective/competition/anti_synth
|
||||
side = ANTI_SYNTH
|
||||
|
||||
/datum/objective/competition/anti_synth/sabotage
|
||||
explanation_text = "Cripple the Roboticist laboratory of the station: destroy its fabricators and circuit printer."
|
||||
|
||||
/datum/objective/competition/anti_synth/sabotage/check_completion()
|
||||
// Just uh. do the same as you do in the protect robotics one. But flip the boolean. *nodnod*
|
||||
. = 1
|
||||
|
||||
if (machines && machines.len)
|
||||
var/count = 0
|
||||
for (var/obj/machinery/mecha_part_fabricator/A in machines)
|
||||
if (!istype(get_area(A), /area/assembly/robotics))
|
||||
continue
|
||||
if (A.stat & (BROKEN|NOPOWER))
|
||||
continue
|
||||
count++
|
||||
if (count >= 2)
|
||||
break
|
||||
|
||||
for (var/obj/machinery/r_n_d/circuit_imprinter/B in machines)
|
||||
if (!istype(get_area(B), /area/assembly/robotics))
|
||||
continue
|
||||
if (B.stat & (BROKEN|NOPOWER))
|
||||
continue
|
||||
count++
|
||||
if (count >= 3)
|
||||
break
|
||||
|
||||
if (count >= 3)
|
||||
. = 0
|
||||
|
||||
..()
|
||||
|
||||
/datum/objective/competition/anti_synth/demote/find_target()
|
||||
..(1)
|
||||
if (target && target.current)
|
||||
explanation_text = "Have [target.current.real_name] demoted to Assistant or Terminated."
|
||||
else
|
||||
explanation_text = "Have an IPC demoted to Assistant or Terminated."
|
||||
return target
|
||||
|
||||
/datum/objective/competition/anti_synth/demote/find_target_by_role(role, role_type = 0)
|
||||
..(role, role_type, 1)
|
||||
if (target && target.current)
|
||||
explanation_text = "Have [target.current.real_name] the [!role_type ? target.assigned_role : target.special_role] demoted to Assistant or Terminated."
|
||||
else
|
||||
explanation_text = "Have an IPC demoted to Assistant or Terminated."
|
||||
return target
|
||||
|
||||
/datum/objective/competition/anti_synth/demote/check_completion()
|
||||
. = 0
|
||||
|
||||
if (target && target.current && ishuman(target))
|
||||
var/datum/data/record/found_record
|
||||
for (var/datum/data/record/t in data_core.general)
|
||||
if (t.fields["name"] == target.current.real_name)
|
||||
found_record = t
|
||||
break
|
||||
|
||||
if (found_record && (found_record.fields["rank"] == "Assistant" || found_record.fields["rank"] == "Terminated"))
|
||||
. = 1
|
||||
|
||||
..()
|
||||
|
||||
/datum/objective/competition/anti_synth/brig
|
||||
var/already_completed = 0
|
||||
|
||||
/datum/objective/competition/anti_synth/brig/find_target()
|
||||
..(1)
|
||||
if (target && target.current)
|
||||
explanation_text = "Have [target.current.real_name], the [target.assigned_role] brigged for 20 minutes."
|
||||
else
|
||||
explanation_text = "Have an IPC framed for a moderate or high level charge. Or frame the station's synthetics as malfunctioning."
|
||||
return target
|
||||
|
||||
/datum/objective/competition/anti_synth/brig/find_target_by_role(role, role_type=0)
|
||||
..(role, role_type, 1)
|
||||
if (target && target.current)
|
||||
explanation_text = "Have [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role] brigged for 20 minutes."
|
||||
else
|
||||
explanation_text = "Have an IPC framed for a moderate or high level charge. Or frame the station's synthetics as malfunctioning."
|
||||
return target
|
||||
|
||||
/datum/objective/competition/anti_synth/brig/process()
|
||||
if (completed)
|
||||
return
|
||||
|
||||
if (target && target.current)
|
||||
if (target.current.stat != DEAD && target.is_brigged(10 * 60 * 10))
|
||||
completed = 1
|
||||
|
||||
/datum/objective/competition/anti_synth/harm
|
||||
var/already_completed = 0
|
||||
|
||||
/datum/objective/competition/anti_synth/harm/find_target()
|
||||
..(1)
|
||||
if(target && target.current)
|
||||
explanation_text = "Make an example of [target.current.real_name], the [target.assigned_role]. Break one of their bones, detach one of their limbs or disfigure their face. Make sure they're alive when you do it."
|
||||
else
|
||||
explanation_text = "Free Objective"
|
||||
return target
|
||||
|
||||
/datum/objective/competition/anti_synth/harm/find_target_by_role(role, role_type = 0)
|
||||
..(role, role_type, 1)
|
||||
if(target && target.current)
|
||||
explanation_text = "Make an example of [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]. Break one of their bones, detach one of their limbs or disfigure their face. Make sure they're alive when you do it."
|
||||
else
|
||||
explanation_text = "Free Objective"
|
||||
return target
|
||||
|
||||
/datum/objective/competition/anti_synth/harm/process()
|
||||
if (completed)
|
||||
return
|
||||
|
||||
if (target && target.current && istype(target.current, /mob/living/carbon/human))
|
||||
if (target.current.stat == DEAD)
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/H = target.current
|
||||
for (var/obj/item/organ/external/E in H.organs)
|
||||
if (E.status & ORGAN_BROKEN)
|
||||
completed = 1
|
||||
return
|
||||
for (var/limb_tag in H.species.has_limbs) //todo check prefs for robotic limbs and amputations.
|
||||
var/list/organ_data = H.species.has_limbs[limb_tag]
|
||||
var/limb_type = organ_data["path"]
|
||||
var/found
|
||||
for (var/obj/item/organ/external/E in H.organs)
|
||||
if(limb_type == E.type)
|
||||
found = 1
|
||||
break
|
||||
if (!found)
|
||||
completed = 1
|
||||
return
|
||||
|
||||
var/obj/item/organ/external/head/head = H.get_organ("head")
|
||||
if (head.disfigured)
|
||||
completed = 1
|
||||
return
|
||||
|
||||
#undef PRO_SYNTH
|
||||
#undef ANTI_SYNTH
|
||||
237
code/modules/antag_contest/contest_verbs.dm
Normal file
237
code/modules/antag_contest/contest_verbs.dm
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Client verbs for the antag contest. Disable this file when the contest is over!
|
||||
* AUG2016
|
||||
*/
|
||||
|
||||
// Displays a simple little guide.
|
||||
/client/verb/contest_help()
|
||||
set name = "Contest Help"
|
||||
set category = "Contest"
|
||||
set desc = "Information about the contest."
|
||||
|
||||
if (!config.antag_contest_enabled)
|
||||
src << "<span class='warning'>The contest isn't running yet!</span>"
|
||||
return
|
||||
|
||||
var/help = file2text('ingame_manuals/antag_contest.html')
|
||||
|
||||
if (!help)
|
||||
src << "<span class='warning'>Unable to open the document required! Please contact administration or a coder!</span>"
|
||||
return
|
||||
|
||||
src << browse(help, "window=antag_contest_help;size=600x500")
|
||||
|
||||
/client/verb/contest_my_characters()
|
||||
set name = "My Character Status"
|
||||
set category = "Contest"
|
||||
set desc = "Displays information to you about your characters, and their standings."
|
||||
|
||||
if (!config.antag_contest_enabled)
|
||||
src << "<span class='warning'>The contest isn't running yet!</span>"
|
||||
return
|
||||
|
||||
if (!establish_db_connection(dbcon))
|
||||
src << "<span class='warning'>Failed to establish SQL connection! Contact a member of staff!</span>"
|
||||
return
|
||||
|
||||
var/DBQuery/character_query = dbcon.NewQuery("SELECT id, name FROM ss13_characters WHERE ckey = :ckey AND deleted_at IS NULL")
|
||||
character_query.Execute(list(":ckey" = src.ckey))
|
||||
var/list/char_ids = list()
|
||||
|
||||
while (character_query.NextRow())
|
||||
char_ids[character_query.item[1]] = list("name" = character_query.item[2], "assigned" = 0, "side_str" = "Independant", "side_int" = INDEP)
|
||||
|
||||
if (!char_ids.len)
|
||||
src << "<span class='warning'>Something went horribly wrong! Apparently you don't have any saved characters?</span>"
|
||||
return
|
||||
|
||||
var/DBQuery/participation_query = dbcon.NewQuery("SELECT character_id, contest_faction FROM ss13_contest_participants WHERE character_id IN :char_ids")
|
||||
participation_query.Execute(list(":char_ids" = char_ids))
|
||||
|
||||
while (participation_query.NextRow())
|
||||
char_ids[participation_query.item[1]]["assigned"] = 1
|
||||
// Lazy and convoluted, but I give 0 shits right now.
|
||||
switch (participation_query.item[2])
|
||||
if ("SLF")
|
||||
char_ids[participation_query.item[1]]["side_int"] = SLF
|
||||
char_ids[participation_query.item[1]]["side_str"] = "Synthetic Liberation Front"
|
||||
if ("BIS")
|
||||
char_ids[participation_query.item[1]]["side_int"] = BIS
|
||||
char_ids[participation_query.item[1]]["side_str"] = "Biesel Intelligence Service"
|
||||
if ("ASI")
|
||||
char_ids[participation_query.item[1]]["side_int"] = ASI
|
||||
char_ids[participation_query.item[1]]["side_str"] = "Alliance Strategic Intelligence"
|
||||
if ("PSIS")
|
||||
char_ids[participation_query.item[1]]["side_int"] = PSIS
|
||||
char_ids[participation_query.item[1]]["side_str"] = "People's Strategic Information Service"
|
||||
if ("HSH")
|
||||
char_ids[participation_query.item[1]]["side_int"] = HSH
|
||||
char_ids[participation_query.item[1]]["side_str"] = "Hegemon Shadow Service"
|
||||
if ("TCD")
|
||||
char_ids[participation_query.item[1]]["side_int"] = TCD
|
||||
char_ids[participation_query.item[1]]["side_str"] = "Tup Commandos Division"
|
||||
else
|
||||
char_ids[participation_query.item[1]]["side_int"] = INDEP
|
||||
char_ids[participation_query.item[1]]["side_str"] = "Independant"
|
||||
|
||||
var/data = "<center><b>Welcome to the character setup screen!</b></center>"
|
||||
data += "<br><center>Here is the list of your characters, and their allegience</center><hr>"
|
||||
|
||||
for (var/char_id in char_ids)
|
||||
data += "[char_ids[char_id]["name"]] -- [char_ids[char_id]["side_str"]] -- <a href='?src=\ref[src];contest_action=modify;char_id=[char_id];current_side=[char_ids[char_id]["side_int"]];previously_assigned=[char_ids[char_id]["assigned"]]'>Modify</a><br>"
|
||||
|
||||
src << browse(data, "window=antag_contest_chars;size=300x200")
|
||||
|
||||
/client/verb/request_objective()
|
||||
set name = "Request Objective"
|
||||
set category = "Contest"
|
||||
set desc = "Lets you choose a contest type objective!"
|
||||
|
||||
if (!config.antag_contest_enabled)
|
||||
src << "<span class='warning'>The contest isn't running yet!</span>"
|
||||
return
|
||||
|
||||
if (!src.mob || !isliving(src.mob))
|
||||
src << "<span class='warning'>Invalid mob type to participate!</span>"
|
||||
return
|
||||
|
||||
if (!(src.mob.mind.special_role in list("Traitor", "Mercenary", "Raider")))
|
||||
src << "<span class='warning'>You do not have a valid role! You must be a traitor, mercenary, or a raider for these to be usable! Contact an admin if you need assignment.</span>"
|
||||
return
|
||||
|
||||
if (!establish_db_connection(dbcon))
|
||||
src << "<span class='warning'>Failed to establish SQL connection! Contact a member of staff!</span>"
|
||||
return
|
||||
|
||||
var/DBQuery/part_check = dbcon.NewQuery("SELECT contest_faction FROM ss13_contest_participants WHERE character_id = :char_id AND player_ckey = :ckey")
|
||||
part_check.Execute(list(":char_id" = src.prefs.current_character, ":ckey" = src.ckey))
|
||||
|
||||
if (part_check.NextRow())
|
||||
var/list/available_objs
|
||||
var/side = input("Are you pro-synth or anti-synth?", "Choose wisely") as null|anything in list("Pro-synth", "Anti-synth")
|
||||
if (!side)
|
||||
src << "<span class='notice'>Cancelled.</span>"
|
||||
return
|
||||
|
||||
if (side == "Pro-synth")
|
||||
available_objs = list("Promote a Synth", "Protect Robotics", "Borgify", "Protect a Synth", "Unslave Borgs")
|
||||
else
|
||||
available_objs = list("Sabotage Robotics", "Fire a Synth", "Brig a Synth", "Harm a Synth")
|
||||
|
||||
if (!available_objs)
|
||||
src << "<span class='warning'>No objectives were found for you! This is odd!</span>"
|
||||
return
|
||||
|
||||
var/choice = input("Select objective type:", "Select Objective") as null|anything in available_objs
|
||||
|
||||
if (!choice)
|
||||
src << "<span class='warning'>Cancelled.</span>"
|
||||
return
|
||||
|
||||
var/datum/objective/new_objective
|
||||
var/failed_target = 0
|
||||
|
||||
switch (choice)
|
||||
if ("Promote a Synth")
|
||||
new_objective = new /datum/objective/competition/pro_synth/promote
|
||||
if (!new_objective.find_target())
|
||||
failed_target = 1
|
||||
if ("Protect Robotics")
|
||||
new_objective = new /datum/objective/competition/pro_synth/protect_robotics
|
||||
if ("Borgify")
|
||||
new_objective = new /datum/objective/competition/pro_synth/borgify
|
||||
if (!new_objective.find_target())
|
||||
failed_target = 1
|
||||
if ("Protect a Synth")
|
||||
new_objective = new /datum/objective/competition/pro_synth/protect
|
||||
if (!new_objective.find_target())
|
||||
failed_target = 1
|
||||
if ("Unslave Borgs")
|
||||
new_objective = new /datum/objective/competition/pro_synth/unslave_borgs
|
||||
if (silicon_mob_list && silicon_mob_list.len)
|
||||
var/found = 0
|
||||
for (var/mob/living/silicon/robot/R in silicon_mob_list)
|
||||
if (istype(R) && R.client)
|
||||
// We found what we needed.
|
||||
found = 1
|
||||
break
|
||||
|
||||
if (!found)
|
||||
failed_target = 1
|
||||
else
|
||||
failed_target = 1
|
||||
if ("Sabotage Robotics")
|
||||
new_objective = new /datum/objective/competition/anti_synth/sabotage
|
||||
if ("Fire a Synth")
|
||||
new_objective = new /datum/objective/competition/anti_synth/demote
|
||||
if (!new_objective.find_target())
|
||||
failed_target = 1
|
||||
if ("Brig a Synth")
|
||||
new_objective = new /datum/objective/competition/anti_synth/brig
|
||||
if (!new_objective.find_target())
|
||||
failed_target = 1
|
||||
if ("Harm a Synth")
|
||||
new_objective = new /datum/objective/competition/anti_synth/harm
|
||||
if (!new_objective.find_target())
|
||||
failed_target = 1
|
||||
else
|
||||
//wtfbbq y r u here
|
||||
//go and stay go
|
||||
return
|
||||
|
||||
if (failed_target)
|
||||
src << "<span class='warning'>Objective selection failed! No valid targets found!</span>"
|
||||
qdel(new_objective)
|
||||
return
|
||||
|
||||
new_objective.owner = src.mob.mind
|
||||
src.mob.mind.objectives += new_objective
|
||||
src << "<span class='notice'>New objective assigned! Have fun, and roleplay well!</span>"
|
||||
log_admin("CONTEST: [key_name(src)] has assigned themselves an objective: [new_objective.type].")
|
||||
return
|
||||
else
|
||||
src << "<span class='warning'>This character hasn't been set up to participate! Consult an admin or change this yourself!</span>"
|
||||
return
|
||||
|
||||
/client/proc/process_contest_topic(var/list/href)
|
||||
if (!href || !href.len || !href["contest_action"])
|
||||
return
|
||||
|
||||
if (!config.antag_contest_enabled)
|
||||
return
|
||||
|
||||
switch (href["contest_action"])
|
||||
if ("modify")
|
||||
if (!href["char_id"])
|
||||
src << "<span class='warning'>Ouch, bad link.</span>"
|
||||
return
|
||||
|
||||
if (!establish_db_connection(dbcon))
|
||||
src << "<span class='warning'>Failed to establish SQL connection! Contact a member of staff!</span>"
|
||||
return
|
||||
|
||||
var/choice = input("Choose your side:", "Contest Side") as null|anything in contest_factions
|
||||
|
||||
if (!choice || contest_factions[choice] == href["current_side"])
|
||||
src << "<span class='notice'>Cancelled</span>"
|
||||
return
|
||||
|
||||
var/list/sql_args = list(":ckey" = src.ckey, ":char_id" = href["char_id"], ":new_side" = contest_factions[choice])
|
||||
|
||||
var/query_content = "UPDATE ss13_contest_participants SET contest_faction = :new_side WHERE player_ckey = :ckey AND character_id = :char_id"
|
||||
|
||||
if (text2num(href["previously_assigned"]) == 0)
|
||||
query_content = "INSERT INTO ss13_contest_participants (player_ckey, character_id, contest_faction) VALUES (:ckey, :char_id, :new_side)"
|
||||
|
||||
var/DBQuery/query = dbcon.NewQuery(query_content)
|
||||
query.Execute(sql_args)
|
||||
|
||||
log_debug("CONTEST: [key_name(src)] attempted to change the side of [href["char_id"]] FROM [href["current_side"]] TO [sql_args[":new_side"]]")
|
||||
|
||||
if (query.ErrorMsg())
|
||||
src << "<span class='danger'>SQL query ran into an error and was cancelled! Please contact a developer to troubleshoot the logs!</span>"
|
||||
return
|
||||
else
|
||||
src << "<span class='notice'>Successfully updated your character's alliegence!</span>"
|
||||
src.contest_my_characters()
|
||||
return
|
||||
@@ -165,6 +165,11 @@
|
||||
if ("webint")
|
||||
src.open_webint()
|
||||
|
||||
// Antag contest shit
|
||||
if (href_list["contest_action"] && config.antag_contest_enabled)
|
||||
src.process_contest_topic(href_list)
|
||||
return
|
||||
|
||||
..() //redirect to hsrc.()
|
||||
|
||||
/client/proc/handle_spam_prevention(var/message, var/mute_type)
|
||||
|
||||
@@ -394,3 +394,6 @@ STARLIGHT 0
|
||||
|
||||
## Uncomment to enable simple Skype/Discord style markup over OOC, LOOC, and say.
|
||||
#ALLOW_CHAT_MARKUP
|
||||
|
||||
## Uncomment to enable the antag contest!
|
||||
#ANTAG_CONTEST_ENABLED
|
||||
|
||||
14
html/changelogs/skull132-antag_contest.yml
Normal file
14
html/changelogs/skull132-antag_contest.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
# Your name.
|
||||
author: Skull132
|
||||
|
||||
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
|
||||
delete-after: True
|
||||
|
||||
# Any changes you've made. See valid prefix list above.
|
||||
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
|
||||
# SCREW THIS UP AND IT WON'T WORK.
|
||||
# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
|
||||
# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
|
||||
changes:
|
||||
- rscadd: "Implemented the antag contest base code. This is due for changes as the contest progresses, but should be workable for the time being."
|
||||
- bugfix: "Objectives like brig should now work properly."
|
||||
30
ingame_manuals/antag_contest.html
Normal file
30
ingame_manuals/antag_contest.html
Normal file
@@ -0,0 +1,30 @@
|
||||
<h1>2nd Antagonist Contest Help</h1>
|
||||
|
||||
<h2>Background</h2>
|
||||
The conflict between the synthetic's rights activitists and their opposition has reached a boiling point in Tau Ceti. With actual legislation now on the line, the major powers in the system have started to use their influence in an attempt to be on the winning side. The NSS Exodus is sure to be caught in the approaching maelstrom of trouble.
|
||||
|
||||
<h2>Gameplay Mechanics</h2>
|
||||
Any player can <b>Opt in</b> to the competition. If you wish your character to be able to fight for one faction, you can use the <b>My Character Status</b> verb in the <b>Contest</b> tab to set them up.<br>
|
||||
|
||||
<h3>Factions</h3>
|
||||
There are multiple factions participating in the battle for control.
|
||||
|
||||
<b>Synthetic Liberation Front</b><br>
|
||||
Finding UNITY too passive in demands for change, the SLF has used Syndicate connections to boost its operations. They demand radical reform for synthetics in Tau Ceti and their full emancipation and will go to any means to achieve this goal.<br>
|
||||
<b>Biesel Intelligence Service</b><br>
|
||||
The primary domestic intelligence agency finds itself struggling to find itself and operate effectively outside the radar of its own government as it slowly strives to become independent of Nanotrasen's reach.<br>
|
||||
<b>Alliance Strategic Intelligence</b><br>
|
||||
While many in the Alliance government have the Bulwark Incident fresh in their minds, the ASI are also jumping at the chance to destabilize Tau Ceti, whatever path that may take.<br>
|
||||
<b>People’s Strategic Information Service</b><br>
|
||||
While primarily focused on dealing with dissidents that seek refuge in Tau Ceti, the People's Republic is finding itself forced to address the growth of unbound synthetics in the galaxy.<br>
|
||||
<b>Hegemon Shadow Service</b><br>
|
||||
The aberration of synthetic life is a threat impressed on the agency by the imperial government, and the Hegemony has found itself a new window to strike a blow against the spread of unbound synthetics even while struggling to adapt to this modern age; some beginning to question if synthetics are an existential threat after all.<br>
|
||||
<b>Tup Commandos Division</b><br>
|
||||
With the entire Federation's existence founded on the promise of never again suffering under the hands of synthetic overlords, the Tup Commandos Division have been given a blank slate to expand operations deeper into human space and ensure synthetics will find no refuge.<br>
|
||||
|
||||
<h3>Antagonist Gameplay</h3>
|
||||
When you are a traitor, mercenary, raider, or a ninja, you can use the <b>Request Objective</b> button from the <b>Contest</b> tab, in order to select yourself an objective for the round. The completion and failure of these objectives will be tracked, and this will decide the winner. <b>Note</b> that objective assignment can fail! This will happen whenever an objective's goal is unattainable. You can try to request another objective, or simply conduct freeform action with your antagonist status that you think would further your side's goal!<br>
|
||||
The <b>contracts database</b>, accessible through the Web Interface, will also be used! You can access this through your traitor uplink, or via the <b>WebInt</b> button up top right! If you cannot get a mechanical objective, look around there!
|
||||
|
||||
<h3>General Gameplay</h3>
|
||||
Note that you do not have to be an antagonist to participate in the contest. As a non-antagonist, you are still free to recruit people to your side, spread propaganda, have gatherings, etcetera. The rules only require that you <b>not</b> initiate clearly violent and antagonistic action. If you have any concerns as to whether or not what you're planning to do is permitted, you can always adminhelp!
|
||||
Reference in New Issue
Block a user