diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index c5408f1c2a6..abb8d1813a4 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -180,7 +180,7 @@ var/list/uplink_items = list()
/datum/uplink_item/dangerous/syndieborg
name = "Syndicate Cyborg"
desc = "A cyborg designed and programmed for systematic extermination of non-Syndicate personnel."
- item = /obj/item/weapon/syndieborg_teleport
+ item = /obj/item/weapon/antag_spawner/borg_tele
cost = 25
gamemodes = list(/datum/game_mode/nuclear)
diff --git a/code/game/gamemodes/antag_spawner.dm b/code/game/gamemodes/antag_spawner.dm
new file mode 100644
index 00000000000..351e882d3ac
--- /dev/null
+++ b/code/game/gamemodes/antag_spawner.dm
@@ -0,0 +1,142 @@
+/obj/item/weapon/antag_spawner
+ throw_speed = 1
+ throw_range = 5
+ w_class = 1.0
+ var/used = 0
+
+/obj/item/weapon/antag_spawner/contract
+ name = "contract"
+ desc = "A magic contract previously signed by an apprentice. In exchange for instruction in the magical arts, they are bound to answer your call for aid."
+ icon = 'icons/obj/wizard.dmi'
+ icon_state ="scroll2"
+
+/obj/item/weapon/antag_spawner/contract/attack_self(mob/user as mob)
+ user.set_machine(src)
+ var/dat
+ if(used)
+ dat = "You have already summoned your apprentice.
"
+ else
+ dat = "Contract of Apprenticeship:
"
+ dat += "Using this contract, you may summon an apprentice to aid you on your mission.
"
+ dat += "If you are unable to establish contact with your apprentice, you can feed the contract back to the spellbook to refund your points.
"
+ dat += "Which school of magic is your apprentice studying?:
"
+ dat += "Destruction
"
+ dat += "Your apprentice is skilled in offensive magic. They know Magic Missile and Fireball.
"
+ dat += "Bluespace Manipulation
"
+ dat += "Your apprentice is able to defy physics, melting through solid objects and travelling great distances in the blink of an eye. They know Teleport and Ethereal Jaunt.
"
+ dat += "Healing
"
+ dat += "Your apprentice is training to cast spells that will aid your survival. They know Forcewall and Charge and come with a Staff of Healing.
"
+ dat += "Robeless
"
+ dat += "Your apprentice is training to cast spells without their robes. They know Knock and Mindswap.
"
+ user << browse(dat, "window=radio")
+ onclose(user, "radio")
+ return
+
+/obj/item/weapon/antag_spawner/contract/Topic(href, href_list)
+ ..()
+ var/mob/living/carbon/human/H = usr
+
+ if(H.stat || H.restrained())
+ return
+ if(!istype(H, /mob/living/carbon/human))
+ return 1
+
+ if(loc == H || (in_range(src, H) && istype(loc, /turf)))
+ H.set_machine(src)
+ if(href_list["school"])
+ if (used)
+ H << "You already used this contract!"
+ return
+ var/list/candidates = get_candidates(BE_WIZARD)
+ if(candidates.len)
+ src.used = 1
+ var/client/C = pick(candidates)
+ spawn_antag(C, get_turf(H.loc), href_list["school"])
+ else
+ H << "Unable to reach your apprentice! You can either attack the spellbook with the contract to refund your points, or wait and try again later."
+
+/obj/item/weapon/antag_spawner/borg_tele
+ name = "Syndicate Cyborg Teleporter"
+ desc = "A single-use teleporter used to deploy a Syndicate Cyborg on the field."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "locator"
+ var/TC_cost = 25
+
+/obj/item/weapon/antag_spawner/borg_tele/attack_self(mob/user as mob)
+ if(used)
+ user << "The teleporter is out of power."
+ return
+ var/list/borg_candicates = get_candidates(BE_OPERATIVE)
+ if(borg_candicates.len > 0)
+ used = 1
+ var/client/C = pick(borg_candicates)
+ spawn_antag(C, get_turf(src.loc), "syndieborg")
+ else
+ user << "Unable to connect to Syndicate Command. Please wait and try again later or use the teleporter on your uplink to get your points refunded."
+
+/obj/item/weapon/antag_spawner/proc/spawn_antag(var/client/C, var/turf/T, var/type = "")
+ return
+
+/obj/item/weapon/antag_spawner/contract/spawn_antag(var/client/C, var/turf/T, var/type = "")
+ new /obj/effect/effect/harmless_smoke(T)
+ var/mob/living/carbon/human/M = new/mob/living/carbon/human(T)
+ M.key = C.key
+ M << "You are the [usr.real_name]'s apprentice! You are bound by magic contract to follow their orders and help them in accomplishing their goals."
+ switch(type)
+ if("destruction")
+ M.spell_list += new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile(M)
+ M.spell_list += new /obj/effect/proc_holder/spell/dumbfire/fireball(M)
+ M << "Your service has not gone unrewarded, however. Studying under [usr.real_name], you have learned powerful, destructive spells. You are able to cast magic missile and fireball."
+ if("bluespace")
+ M.spell_list += new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(M)
+ M.spell_list += new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(M)
+ M << "Your service has not gone unrewarded, however. Studying under [usr.real_name], you have learned reality bending mobility spells. You are able to cast teleport and ethereal jaunt."
+ if("healing")
+ M.spell_list += new /obj/effect/proc_holder/spell/targeted/charge(M)
+ M.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/forcewall(M)
+ M.equip_to_slot_or_del(new /obj/item/weapon/gun/magic/staff/healing(M), slot_r_hand)
+ M << "Your service has not gone unrewarded, however. Studying under [usr.real_name], you have learned livesaving survival spells. You are able to cast charge and forcewall."
+ if("robeless")
+ M.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/knock(M)
+ M.spell_list += new /obj/effect/proc_holder/spell/targeted/mind_transfer(M)
+ M << "Your service has not gone unrewarded, however. Studying under [usr.real_name], you have learned stealthy, robeless spells. You are able to cast knock and mindswap."
+
+ equip_antag(M)
+ var/wizard_name_first = pick(wizard_first)
+ var/wizard_name_second = pick(wizard_second)
+ var/randomname = "[wizard_name_first] [wizard_name_second]"
+ var/newname = copytext(sanitize(input(M, "You are the wizard's apprentice. Would you like to change your name to something else?", "Name change", randomname) as null|text),1,MAX_NAME_LEN)
+ if (!newname)
+ newname = randomname
+ M.mind.name = newname
+ M.real_name = newname
+ M.name = newname
+ var/datum/objective/protect/new_objective = new /datum/objective/protect
+ new_objective.owner = M:mind
+ new_objective:target = usr:mind
+ new_objective.explanation_text = "Protect [usr.real_name], the wizard."
+ M.mind.objectives += new_objective
+ ticker.mode.traitors += M.mind
+ M.mind.special_role = "apprentice"
+
+/obj/item/weapon/antag_spawner/borg_tele/spawn_antag(var/client/C, var/turf/T, var/type = "")
+ var/datum/effect/effect/system/spark_spread/S = new /datum/effect/effect/system/spark_spread
+ S.set_up(4, 1, src)
+ S.start()
+ var/mob/living/silicon/robot/R = new /mob/living/silicon/robot/syndicate(T)
+ R.key = C.key
+ ticker.mode.traitors += R.mind
+ R.mind.special_role = "syndicate"
+
+/obj/item/weapon/antag_spawner/proc/equip_antag(mob/target as mob)
+ return
+
+/obj/item/weapon/antag_spawner/contract/equip_antag(mob/target as mob)
+ target.equip_to_slot_or_del(new /obj/item/device/radio/headset(target), slot_ears)
+ target.equip_to_slot_or_del(new /obj/item/clothing/under/lightpurple(target), slot_w_uniform)
+ target.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(target), slot_shoes)
+ target.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(target), slot_wear_suit)
+ target.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(target), slot_head)
+ target.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(target), slot_back)
+ target.equip_to_slot_or_del(new /obj/item/weapon/storage/box(target), slot_in_backpack)
+ target.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll/apprentice(target), slot_r_store)
\ No newline at end of file
diff --git a/code/game/gamemodes/nuclear/syndieborg.dm b/code/game/gamemodes/nuclear/syndieborg.dm
deleted file mode 100644
index d5ad7b0de05..00000000000
--- a/code/game/gamemodes/nuclear/syndieborg.dm
+++ /dev/null
@@ -1,28 +0,0 @@
-/obj/item/weapon/syndieborg_teleport
- name = "Syndicate Cyborg Teleporter"
- desc = "A single-use teleporter used to deploy a Syndicate Cyborg on the field."
- icon = 'icons/obj/device.dmi'
- icon_state = "locator"
- throw_speed = 1
- throw_range = 5
- w_class = 1.0
- var/used = 0
- var/TC_cost = 25
-
-/obj/item/weapon/syndieborg_teleport/attack_self(mob/user as mob)
- if(used)
- user << "The teleporter is out of power."
- return
- var/list/borg_candicates = get_candidates(BE_OPERATIVE)
- if(borg_candicates.len > 0)
- used = 1
- var/client/C = pick(borg_candicates)
- var/datum/effect/effect/system/spark_spread/S = new /datum/effect/effect/system/spark_spread
- S.set_up(4, 1, src)
- S.start()
- var/mob/living/silicon/robot/R = new /mob/living/silicon/robot/syndicate(loc)
- R.key = C.key
- ticker.mode.traitors += R.mind
- R.mind.special_role = "syndicate"
- else
- user << "Unable to connect to Syndicate Command. Please wait and try again later or use the teleporter on your uplink to get your points refunded."
diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm
index 27b164554a3..5199e4212c8 100644
--- a/code/game/gamemodes/wizard/artefact.dm
+++ b/code/game/gamemodes/wizard/artefact.dm
@@ -1,111 +1,5 @@
-/////////Apprentice Contract//////////
-
-/obj/item/weapon/contract
- name = "contract"
- desc = "A magic contract previously signed by an apprentice. In exchange for instruction in the magical arts, they are bound to answer your call for aid."
- icon = 'icons/obj/wizard.dmi'
- icon_state ="scroll2"
- throw_speed = 1
- throw_range = 5
- w_class = 1.0
- var/used = 0
-
-
-/obj/item/weapon/contract/attack_self(mob/user as mob)
- user.set_machine(src)
- var/dat
- if(used)
- dat = "You have already summoned your apprentice.
"
- else
- dat = "Contract of Apprenticeship:
"
- dat += "Using this contract, you may summon an apprentice to aid you on your mission.
"
- dat += "If you are unable to establish contact with your apprentice, you can feed the contract back to the spellbook to refund your points.
"
- dat += "Which school of magic is your apprentice studying?:
"
- dat += "Destruction
"
- dat += "Your apprentice is skilled in offensive magic. They know Magic Missile and Fireball.
"
- dat += "Bluespace Manipulation
"
- dat += "Your apprentice is able to defy physics, melting through solid objects and travelling great distances in the blink of an eye. They know Teleport and Ethereal Jaunt.
"
- dat += "Healing
"
- dat += "Your apprentice is training to cast spells that will aid your survival. They know Forcewall and Charge and come with a Staff of Healing.
"
- dat += "Robeless
"
- dat += "Your apprentice is training to cast spells without their robes. They know Knock and Mindswap.
"
- user << browse(dat, "window=radio")
- onclose(user, "radio")
- return
-
-
-/obj/item/weapon/contract/Topic(href, href_list)
- ..()
- var/mob/living/carbon/human/H = usr
-
- if(H.stat || H.restrained())
- return
- if(!istype(H, /mob/living/carbon/human))
- return 1
-
- if(loc == H || (in_range(src, H) && istype(loc, /turf)))
- H.set_machine(src)
- if(href_list["school"])
- if (used)
- H << "You already used this contract!"
- return
- var/list/candidates = get_candidates(BE_WIZARD)
- if(candidates.len)
- src.used = 1
- var/client/C = pick(candidates)
- new /obj/effect/effect/harmless_smoke(H.loc)
- var/mob/living/carbon/human/M = new/mob/living/carbon/human(H.loc)
- M.key = C.key
- M << "You are the [H.real_name]'s apprentice! You are bound by magic contract to follow their orders and help them in accomplishing their goals."
- switch(href_list["school"])
- if("destruction")
- M.spell_list += new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile(M)
- M.spell_list += new /obj/effect/proc_holder/spell/dumbfire/fireball(M)
- M << "Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned powerful, destructive spells. You are able to cast magic missile and fireball."
- if("bluespace")
- M.spell_list += new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(M)
- M.spell_list += new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(M)
- M << "Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned reality bending mobility spells. You are able to cast teleport and ethereal jaunt."
- if("healing")
- M.spell_list += new /obj/effect/proc_holder/spell/targeted/charge(M)
- M.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/forcewall(M)
- M.equip_to_slot_or_del(new /obj/item/weapon/gun/magic/staff/healing(M), slot_r_hand)
- M << "Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned livesaving survival spells. You are able to cast charge and forcewall."
- if("robeless")
- M.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/knock(M)
- M.spell_list += new /obj/effect/proc_holder/spell/targeted/mind_transfer(M)
- M << "Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned stealthy, robeless spells. You are able to cast knock and mindswap."
- M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears)
- M.equip_to_slot_or_del(new /obj/item/clothing/under/lightpurple(M), slot_w_uniform)
- M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(M), slot_shoes)
- M.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(M), slot_wear_suit)
- M.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(M), slot_head)
- M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back)
- M.equip_to_slot_or_del(new /obj/item/weapon/storage/box(M), slot_in_backpack)
- M.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll/apprentice(M), slot_r_store)
- var/wizard_name_first = pick(wizard_first)
- var/wizard_name_second = pick(wizard_second)
- var/randomname = "[wizard_name_first] [wizard_name_second]"
- var/newname = copytext(sanitize(input(M, "You are the wizard's apprentice. Would you like to change your name to something else?", "Name change", randomname) as null|text),1,MAX_NAME_LEN)
-
- if (!newname)
- newname = randomname
- M.mind.name = newname
- M.real_name = newname
- M.name = newname
- var/datum/objective/protect/new_objective = new /datum/objective/protect
- new_objective.owner = M:mind
- new_objective:target = H:mind
- new_objective.explanation_text = "Protect [H.real_name], the wizard."
- M.mind.objectives += new_objective
- ticker.mode.traitors += M.mind
- M.mind.special_role = "apprentice"
-
- else
- H << "Unable to reach your apprentice! You can either attack the spellbook with the contract to refund your points, or wait and try again later."
- return
-
+//Apprenticeship contract - moved to antag_spawner.dm
///////////////////////////Veil Render//////////////////////
diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm
index 879134be58a..3ccd3b2ea7c 100644
--- a/code/game/gamemodes/wizard/spellbook.dm
+++ b/code/game/gamemodes/wizard/spellbook.dm
@@ -12,8 +12,8 @@
var/op = 1
/obj/item/weapon/spellbook/attackby(obj/item/O as obj, mob/user as mob)
- if(istype(O, /obj/item/weapon/contract))
- var/obj/item/weapon/contract/contract = O
+ if(istype(O, /obj/item/weapon/antag_spawner/contract))
+ var/obj/item/weapon/antag_spawner/contract/contract = O
if(contract.used)
user << "The contract has been used, you can't get your points back now."
else
@@ -282,7 +282,7 @@
max_uses--
if("contract")
feedback_add_details("wizard_spell_learned","CT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- new /obj/item/weapon/contract(get_turf(H))
+ new /obj/item/weapon/antag_spawner/contract(get_turf(H))
temp = "You have purchased a contract of apprenticeship."
max_uses--
if("scrying")
diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm
index 1650eb1183e..4fe679b6ec1 100644
--- a/code/game/objects/items/devices/uplinks.dm
+++ b/code/game/objects/items/devices/uplinks.dm
@@ -163,8 +163,8 @@ A list of items and costs is stored under the datum of every game mode, alongsid
return 0
//Refund proc for the borg teleporter (later I'll make a general refund proc if there is demand for it)
/obj/item/device/radio/uplink/attackby(obj/item/weapon/W as obj, mob/user as mob)
- if(istype(W, /obj/item/weapon/syndieborg_teleport))
- var/obj/item/weapon/syndieborg_teleport/S = W
+ if(istype(W, /obj/item/weapon/antag_spawner/borg_tele))
+ var/obj/item/weapon/antag_spawner/borg_tele/S = W
if(!S.used)
hidden_uplink.uses += S.TC_cost
del(S)
diff --git a/tgstation.dme b/tgstation.dme
index 58d214d58eb..4a1cd48528e 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -224,6 +224,7 @@
#include "code\game\area\ai_monitored.dm"
#include "code\game\area\areas.dm"
#include "code\game\area\Space Station 13 areas.dm"
+#include "code\game\gamemodes\antag_spawner.dm"
#include "code\game\gamemodes\events.dm"
#include "code\game\gamemodes\factions.dm"
#include "code\game\gamemodes\game_mode.dm"
@@ -260,7 +261,6 @@
#include "code\game\gamemodes\nuclear\nuclear.dm"
#include "code\game\gamemodes\nuclear\nuclearbomb.dm"
#include "code\game\gamemodes\nuclear\pinpointer.dm"
-#include "code\game\gamemodes\nuclear\syndieborg.dm"
#include "code\game\gamemodes\revolution\revolution.dm"
#include "code\game\gamemodes\sandbox\airlock_maker.dm"
#include "code\game\gamemodes\sandbox\h_sandbox.dm"