From 98da191ac3b3cc3b1229d6700f071cf81dd338b8 Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Sat, 14 Mar 2015 23:01:51 +1030 Subject: [PATCH] Gamemode refactor, lots of code shuffles, PR will have details. --- baystation12.dme | 87 +- code/controllers/configuration.dm | 15 +- .../emergency_shuttle_controller.dm | 5 +- code/controllers/master_controller.dm | 17 +- code/controllers/verbs.dm | 10 + code/controllers/voting.dm | 32 +- code/datums/datumvars.dm | 11 - code/datums/mind.dm | 783 +--------------- code/game/gamemodes/antagonist/alien/borer.dm | 51 ++ .../gamemodes/antagonist/alien/xenomorph.dm | 60 ++ code/game/gamemodes/antagonist/antagonist.dm | 551 +++++++++++ .../gamemodes/antagonist/mutiny/loyalist.dm | 10 + .../gamemodes/antagonist/mutiny/mutineer.dm | 66 ++ .../gamemodes/antagonist/outsider/commando.dm | 28 + .../antagonist/outsider/deathsquad.dm | 81 ++ .../game/gamemodes/antagonist/outsider/ert.dm | 45 + .../antagonist/outsider/mercenary.dm | 60 ++ .../gamemodes/antagonist/outsider/ninja.dm | 170 ++++ .../gamemodes/antagonist/outsider/raider.dm | 191 ++++ .../gamemodes/antagonist/outsider/wizard.dm | 116 +++ .../antagonist/station/changeling.dm | 55 ++ .../gamemodes/antagonist/station/cultist.dm | 114 +++ .../antagonist/station/highlander.dm | 67 ++ .../gamemodes/antagonist/station/monkey.dm | 12 + .../gamemodes/antagonist/station/renegade.dm | 67 ++ .../antagonist/station/revolutionary.dm | 173 ++++ .../gamemodes/antagonist/station/rogue_ai.dm | 227 +++++ .../gamemodes/antagonist/station/traitor.dm | 174 ++++ .../game/gamemodes/autotraitor/autotraitor.dm | 199 ---- code/game/gamemodes/calamity/calamity.dm | 478 +--------- code/game/gamemodes/changeling/changeling.dm | 233 +---- .../gamemodes/changeling/changeling_powers.dm | 40 + .../game/gamemodes/changeling/traitor_chan.dm | 44 - code/game/gamemodes/cult/cult.dm | 338 +------ code/game/gamemodes/cult/ritual.dm | 5 +- code/game/gamemodes/cult/runes.dm | 53 +- code/game/gamemodes/epidemic/epidemic.dm | 15 +- code/game/gamemodes/events/space_ninja.dm | 553 ----------- code/game/gamemodes/extended/extended.dm | 19 +- code/game/gamemodes/factions.dm | 214 ----- code/game/gamemodes/game_mode.dm | 554 +++++++---- code/game/gamemodes/gameticker.dm | 11 - code/game/gamemodes/heist/heist.dm | 270 +----- .../gamemodes/malfunction/Malf_Modules.dm | 23 - .../game/gamemodes/malfunction/malfunction.dm | 307 +------ code/game/gamemodes/meme/meme.dm | 37 +- code/game/gamemodes/meteor/meteor.dm | 40 +- code/game/gamemodes/mutiny/auth_key.dm | 39 - code/game/gamemodes/mutiny/directive.dm | 32 - .../directives/alien_fraud_directive.dm | 41 - .../bluespace_contagion_directive.dm | 58 -- .../directives/financial_crisis_directive.dm | 26 - .../mutiny/directives/ipc_virus_directive.dm | 96 -- .../research_to_ripleys_directive.dm | 79 -- .../tau_ceti_needs_women_directive.dm | 108 --- .../directives/terminations_directive.dm | 71 -- .../mutiny/directives/test_directive.dm | 23 - .../mutiny/emergency_authentication_device.dm | 104 --- code/game/gamemodes/mutiny/key_pinpointer.dm | 49 - code/game/gamemodes/mutiny/mutiny.dm | 384 -------- code/game/gamemodes/mutiny/mutiny_admin.dm | 83 -- code/game/gamemodes/mutiny/mutiny_fluff.dm | 198 ---- code/game/gamemodes/mutiny/mutiny_hooks.dm | 27 - code/game/gamemodes/ninja/ninja.dm | 181 +--- code/game/gamemodes/nuclear/nuclear.dm | 289 +----- code/game/gamemodes/objective.dm | 130 ++- .../gamemodes/revolution/anti_revolution.dm | 222 ----- code/game/gamemodes/revolution/revolution.dm | 458 +--------- .../gamemodes/revolution/rp-revolution.dm | 300 ------ .../gamemodes/revolution/rp_revolution.dm | 262 ------ code/game/gamemodes/sandbox/sandbox.dm | 7 +- code/game/gamemodes/setupgame.dm | 18 - code/game/gamemodes/traitor/traitor.dm | 299 +----- code/game/gamemodes/wizard/rightandwrong.dm | 60 -- code/game/gamemodes/wizard/wizard.dm | 271 +----- code/game/machinery/cloning.dm | 14 +- code/game/machinery/computer/ai_core.dm | 12 +- .../game/machinery/computer/communications.dm | 12 +- .../machinery/computer/specops_shuttle.dm | 249 ----- code/game/machinery/cryopod.dm | 8 +- .../nuclear_bomb.dm} | 865 +++++++++--------- code/game/machinery/syndicatebeacon.dm | 29 +- code/game/machinery/wishgranter.dm | 2 - code/game/objects/effects/landmarks.dm | 31 +- code/game/objects/items/devices/flash.dm | 4 +- code/game/objects/items/robot/robot_parts.dm | 2 +- .../objects/items/weapons/implants/implant.dm | 9 +- code/game/objects/items/weapons/weaponry.dm | 34 +- code/game/response_team.dm | 105 +-- code/game/turfs/space/space.dm | 3 - code/modules/admin/admin.dm | 115 ++- code/modules/admin/admin_verbs.dm | 21 +- code/modules/admin/player_panel.dm | 74 +- code/modules/admin/topic.dm | 175 +--- code/modules/admin/verbs/debug.dm | 4 +- code/modules/admin/verbs/one_click_antag.dm | 528 ----------- code/modules/admin/verbs/onlyone.dm | 47 - code/modules/admin/verbs/randomverbs.dm | 50 +- code/modules/admin/verbs/striketeam.dm | 189 +--- .../admin/verbs/striketeam_syndicate.dm | 178 ---- code/modules/admin/verbs/vox_raiders.dm | 69 -- code/modules/events/alien_infestation.dm | 39 - code/modules/events/borers.dm | 33 - code/modules/events/event_container.dm | 3 +- code/modules/events/event_dynamic.dm | 17 +- code/modules/events/random_antagonist.dm | 13 + code/modules/mob/dead/observer/observer.dm | 7 +- code/modules/mob/living/carbon/human/human.dm | 5 +- .../mob/living/carbon/human/human_defense.dm | 9 +- code/modules/mob/living/carbon/human/login.dm | 1 - code/modules/mob/living/login.dm | 18 +- code/modules/mob/living/silicon/ai/ai.dm | 20 +- code/modules/mob/living/silicon/ai/death.dm | 2 +- .../modules/mob/living/silicon/ai/latejoin.dm | 6 +- code/modules/mob/living/silicon/login.dm | 3 - .../modules/mob/living/silicon/pai/recruit.dm | 3 +- code/modules/mob/living/silicon/robot/life.dm | 11 +- .../modules/mob/living/silicon/robot/login.dm | 1 - .../modules/mob/living/silicon/robot/robot.dm | 16 +- .../mob/living/simple_animal/borer/borer.dm | 4 +- .../simple_animal/borer/borer_powers.dm | 2 +- .../{ => constructs}/constructs.dm | 621 +++++++------ .../simple_animal/constructs}/soulstone.dm | 18 +- code/modules/mob/mob.dm | 2 +- code/modules/mob/new_player/new_player.dm | 2 - code/modules/power/apc.dm | 91 +- code/modules/power/singularity/singularity.dm | 19 +- code/modules/reagents/Chemistry-Reagents.dm | 7 +- .../spells/area_teleport.dm | 162 ++-- code/{datums => modules}/spells/conjure.dm | 172 ++-- code/{datums => modules}/spells/dumbfire.dm | 170 ++-- code/{datums => modules}/spells/emplosion.dm | 24 +- .../spells/ethereal_jaunt.dm | 210 ++--- code/{datums => modules}/spells/explosion.dm | 28 +- code/{datums => modules}/spells/genetic.dm | 60 +- code/{datums => modules}/spells/horsemask.dm | 100 +- .../spells/inflict_handler.dm | 116 +-- code/{datums => modules}/spells/knock.dm | 40 +- .../spells/mind_transfer.dm | 228 ++--- code/{datums => modules}/spells/projectile.dm | 164 ++-- code/{datums => modules/spells}/spell.dm | 586 ++++++------ .../wizard => modules/spells}/spellbook.dm | 419 ++++----- code/{datums => modules}/spells/trigger.dm | 54 +- .../spells/turf_teleport.dm | 68 +- .../spells/wizard_artifacts.dm} | 0 .../spells/wizard_spells.dm} | 652 ++++++------- code/setup.dm | 35 +- 147 files changed, 5751 insertions(+), 11965 deletions(-) create mode 100644 code/game/gamemodes/antagonist/alien/borer.dm create mode 100644 code/game/gamemodes/antagonist/alien/xenomorph.dm create mode 100644 code/game/gamemodes/antagonist/antagonist.dm create mode 100644 code/game/gamemodes/antagonist/mutiny/loyalist.dm create mode 100644 code/game/gamemodes/antagonist/mutiny/mutineer.dm create mode 100644 code/game/gamemodes/antagonist/outsider/commando.dm create mode 100644 code/game/gamemodes/antagonist/outsider/deathsquad.dm create mode 100644 code/game/gamemodes/antagonist/outsider/ert.dm create mode 100644 code/game/gamemodes/antagonist/outsider/mercenary.dm create mode 100644 code/game/gamemodes/antagonist/outsider/ninja.dm create mode 100644 code/game/gamemodes/antagonist/outsider/raider.dm create mode 100644 code/game/gamemodes/antagonist/outsider/wizard.dm create mode 100644 code/game/gamemodes/antagonist/station/changeling.dm create mode 100644 code/game/gamemodes/antagonist/station/cultist.dm create mode 100644 code/game/gamemodes/antagonist/station/highlander.dm create mode 100644 code/game/gamemodes/antagonist/station/monkey.dm create mode 100644 code/game/gamemodes/antagonist/station/renegade.dm create mode 100644 code/game/gamemodes/antagonist/station/revolutionary.dm create mode 100644 code/game/gamemodes/antagonist/station/rogue_ai.dm create mode 100644 code/game/gamemodes/antagonist/station/traitor.dm delete mode 100644 code/game/gamemodes/autotraitor/autotraitor.dm delete mode 100644 code/game/gamemodes/changeling/traitor_chan.dm delete mode 100644 code/game/gamemodes/events/space_ninja.dm delete mode 100644 code/game/gamemodes/factions.dm delete mode 100644 code/game/gamemodes/mutiny/auth_key.dm delete mode 100644 code/game/gamemodes/mutiny/directive.dm delete mode 100644 code/game/gamemodes/mutiny/directives/alien_fraud_directive.dm delete mode 100644 code/game/gamemodes/mutiny/directives/bluespace_contagion_directive.dm delete mode 100644 code/game/gamemodes/mutiny/directives/financial_crisis_directive.dm delete mode 100644 code/game/gamemodes/mutiny/directives/ipc_virus_directive.dm delete mode 100644 code/game/gamemodes/mutiny/directives/research_to_ripleys_directive.dm delete mode 100644 code/game/gamemodes/mutiny/directives/tau_ceti_needs_women_directive.dm delete mode 100644 code/game/gamemodes/mutiny/directives/terminations_directive.dm delete mode 100644 code/game/gamemodes/mutiny/directives/test_directive.dm delete mode 100644 code/game/gamemodes/mutiny/emergency_authentication_device.dm delete mode 100644 code/game/gamemodes/mutiny/key_pinpointer.dm delete mode 100644 code/game/gamemodes/mutiny/mutiny.dm delete mode 100644 code/game/gamemodes/mutiny/mutiny_admin.dm delete mode 100644 code/game/gamemodes/mutiny/mutiny_fluff.dm delete mode 100644 code/game/gamemodes/mutiny/mutiny_hooks.dm delete mode 100644 code/game/gamemodes/revolution/anti_revolution.dm delete mode 100644 code/game/gamemodes/revolution/rp-revolution.dm delete mode 100644 code/game/gamemodes/revolution/rp_revolution.dm delete mode 100644 code/game/gamemodes/wizard/rightandwrong.dm rename code/game/{gamemodes/nuclear/nuclearbomb.dm => machinery/nuclear_bomb.dm} (96%) delete mode 100644 code/modules/admin/verbs/one_click_antag.dm delete mode 100644 code/modules/admin/verbs/onlyone.dm delete mode 100644 code/modules/admin/verbs/striketeam_syndicate.dm delete mode 100644 code/modules/admin/verbs/vox_raiders.dm delete mode 100644 code/modules/events/alien_infestation.dm delete mode 100644 code/modules/events/borers.dm create mode 100644 code/modules/events/random_antagonist.dm rename code/modules/mob/living/simple_animal/{ => constructs}/constructs.dm (96%) rename code/{game/gamemodes/wizard => modules/mob/living/simple_animal/constructs}/soulstone.dm (92%) rename code/{datums => modules}/spells/area_teleport.dm (96%) rename code/{datums => modules}/spells/conjure.dm (96%) rename code/{datums => modules}/spells/dumbfire.dm (96%) rename code/{datums => modules}/spells/emplosion.dm (94%) rename code/{datums => modules}/spells/ethereal_jaunt.dm (96%) rename code/{datums => modules}/spells/explosion.dm (94%) rename code/{datums => modules}/spells/genetic.dm (95%) rename code/{datums => modules}/spells/horsemask.dm (97%) rename code/{datums => modules}/spells/inflict_handler.dm (94%) rename code/{datums => modules}/spells/knock.dm (96%) rename code/{datums => modules}/spells/mind_transfer.dm (97%) rename code/{datums => modules}/spells/projectile.dm (96%) rename code/{datums => modules/spells}/spell.dm (92%) rename code/{game/gamemodes/wizard => modules/spells}/spellbook.dm (98%) rename code/{datums => modules}/spells/trigger.dm (96%) rename code/{datums => modules}/spells/turf_teleport.dm (97%) rename code/{game/gamemodes/wizard/artifact.dm => modules/spells/wizard_artifacts.dm} (100%) rename code/{datums/spells/wizard.dm => modules/spells/wizard_spells.dm} (95%) diff --git a/baystation12.dme b/baystation12.dme index d8f9ea384c..1eb5668c80 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -134,7 +134,6 @@ #include "code\datums\modules.dm" #include "code\datums\organs.dm" #include "code\datums\recipe.dm" -#include "code\datums\spell.dm" #include "code\datums\sun.dm" #include "code\datums\supplypacks.dm" #include "code\datums\diseases\appendicitis.dm" @@ -178,21 +177,6 @@ #include "code\datums\helper_datums\global_iterator.dm" #include "code\datums\helper_datums\teleport.dm" #include "code\datums\helper_datums\topic_input.dm" -#include "code\datums\spells\area_teleport.dm" -#include "code\datums\spells\conjure.dm" -#include "code\datums\spells\dumbfire.dm" -#include "code\datums\spells\emplosion.dm" -#include "code\datums\spells\ethereal_jaunt.dm" -#include "code\datums\spells\explosion.dm" -#include "code\datums\spells\genetic.dm" -#include "code\datums\spells\horsemask.dm" -#include "code\datums\spells\inflict_handler.dm" -#include "code\datums\spells\knock.dm" -#include "code\datums\spells\mind_transfer.dm" -#include "code\datums\spells\projectile.dm" -#include "code\datums\spells\trigger.dm" -#include "code\datums\spells\turf_teleport.dm" -#include "code\datums\spells\wizard.dm" #include "code\datums\wires\airlock.dm" #include "code\datums\wires\alarm.dm" #include "code\datums\wires\apc.dm" @@ -242,13 +226,28 @@ #include "code\game\dna\genes\monkey.dm" #include "code\game\dna\genes\powers.dm" #include "code\game\gamemodes\events.dm" -#include "code\game\gamemodes\factions.dm" #include "code\game\gamemodes\game_mode.dm" #include "code\game\gamemodes\gameticker.dm" #include "code\game\gamemodes\intercept_report.dm" #include "code\game\gamemodes\objective.dm" #include "code\game\gamemodes\setupgame.dm" -#include "code\game\gamemodes\autotraitor\autotraitor.dm" +#include "code\game\gamemodes\antagonist\antagonist.dm" +#include "code\game\gamemodes\antagonist\alien\borer.dm" +#include "code\game\gamemodes\antagonist\alien\xenomorph.dm" +#include "code\game\gamemodes\antagonist\outsider\commando.dm" +#include "code\game\gamemodes\antagonist\outsider\deathsquad.dm" +#include "code\game\gamemodes\antagonist\outsider\ert.dm" +#include "code\game\gamemodes\antagonist\outsider\mercenary.dm" +#include "code\game\gamemodes\antagonist\outsider\ninja.dm" +#include "code\game\gamemodes\antagonist\outsider\raider.dm" +#include "code\game\gamemodes\antagonist\outsider\wizard.dm" +#include "code\game\gamemodes\antagonist\station\changeling.dm" +#include "code\game\gamemodes\antagonist\station\cultist.dm" +#include "code\game\gamemodes\antagonist\station\highlander.dm" +#include "code\game\gamemodes\antagonist\station\renegade.dm" +#include "code\game\gamemodes\antagonist\station\revolutionary.dm" +#include "code\game\gamemodes\antagonist\station\rogue_ai.dm" +#include "code\game\gamemodes\antagonist\station\traitor.dm" #include "code\game\gamemodes\blob\blob.dm" #include "code\game\gamemodes\blob\theblob.dm" #include "code\game\gamemodes\blob\blobs\core.dm" @@ -259,7 +258,6 @@ #include "code\game\gamemodes\changeling\changeling.dm" #include "code\game\gamemodes\changeling\changeling_powers.dm" #include "code\game\gamemodes\changeling\modularchangling.dm" -#include "code\game\gamemodes\changeling\traitor_chan.dm" #include "code\game\gamemodes\cult\cult.dm" #include "code\game\gamemodes\cult\cult_items.dm" #include "code\game\gamemodes\cult\cult_structures.dm" @@ -271,7 +269,6 @@ #include "code\game\gamemodes\events\dust.dm" #include "code\game\gamemodes\events\miniblob.dm" #include "code\game\gamemodes\events\power_failure.dm" -#include "code\game\gamemodes\events\space_ninja.dm" #include "code\game\gamemodes\events\wormholes.dm" #include "code\game\gamemodes\events\holidays\Christmas.dm" #include "code\game\gamemodes\events\holidays\Holidays.dm" @@ -282,32 +279,11 @@ #include "code\game\gamemodes\malfunction\malfunction.dm" #include "code\game\gamemodes\meteor\meteor.dm" #include "code\game\gamemodes\meteor\meteors.dm" -#include "code\game\gamemodes\mutiny\auth_key.dm" -#include "code\game\gamemodes\mutiny\directive.dm" -#include "code\game\gamemodes\mutiny\emergency_authentication_device.dm" -#include "code\game\gamemodes\mutiny\key_pinpointer.dm" -#include "code\game\gamemodes\mutiny\mutiny.dm" -#include "code\game\gamemodes\mutiny\mutiny_admin.dm" -#include "code\game\gamemodes\mutiny\mutiny_fluff.dm" -#include "code\game\gamemodes\mutiny\mutiny_hooks.dm" -#include "code\game\gamemodes\mutiny\directives\alien_fraud_directive.dm" -#include "code\game\gamemodes\mutiny\directives\bluespace_contagion_directive.dm" -#include "code\game\gamemodes\mutiny\directives\financial_crisis_directive.dm" -#include "code\game\gamemodes\mutiny\directives\ipc_virus_directive.dm" -#include "code\game\gamemodes\mutiny\directives\research_to_ripleys_directive.dm" -#include "code\game\gamemodes\mutiny\directives\tau_ceti_needs_women_directive.dm" -#include "code\game\gamemodes\mutiny\directives\terminations_directive.dm" #include "code\game\gamemodes\ninja\ninja.dm" #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\revolution\revolution.dm" -#include "code\game\gamemodes\revolution\rp_revolution.dm" #include "code\game\gamemodes\traitor\traitor.dm" -#include "code\game\gamemodes\wizard\artifact.dm" -#include "code\game\gamemodes\wizard\rightandwrong.dm" -#include "code\game\gamemodes\wizard\soulstone.dm" -#include "code\game\gamemodes\wizard\spellbook.dm" #include "code\game\gamemodes\wizard\wizard.dm" #include "code\game\jobs\access.dm" #include "code\game\jobs\job_controller.dm" @@ -356,6 +332,7 @@ #include "code\game\machinery\mass_driver.dm" #include "code\game\machinery\navbeacon.dm" #include "code\game\machinery\newscaster.dm" +#include "code\game\machinery\nuclear_bomb.dm" #include "code\game\machinery\OpTable.dm" #include "code\game\machinery\overview.dm" #include "code\game\machinery\portable_tag_turret.dm" @@ -823,8 +800,6 @@ #include "code\modules\admin\verbs\mapping.dm" #include "code\modules\admin\verbs\massmodvar.dm" #include "code\modules\admin\verbs\modifyvariables.dm" -#include "code\modules\admin\verbs\one_click_antag.dm" -#include "code\modules\admin\verbs\onlyone.dm" #include "code\modules\admin\verbs\playsound.dm" #include "code\modules\admin\verbs\possess.dm" #include "code\modules\admin\verbs\pray.dm" @@ -833,10 +808,8 @@ #include "code\modules\admin\verbs\SDQL_2.dm" #include "code\modules\admin\verbs\SDQL_2_parser.dm" #include "code\modules\admin\verbs\striketeam.dm" -#include "code\modules\admin\verbs\striketeam_syndicate.dm" #include "code\modules\admin\verbs\ticklag.dm" #include "code\modules\admin\verbs\tripAI.dm" -#include "code\modules\admin\verbs\vox_raiders.dm" #include "code\modules\alarm\alarm.dm" #include "code\modules\alarm\alarm_handler.dm" #include "code\modules\alarm\atmosphere_alarm.dm" @@ -959,9 +932,7 @@ #include "code\modules\economy\Events.dm" #include "code\modules\economy\Events_Mundane.dm" #include "code\modules\economy\TradeDestinations.dm" -#include "code\modules\events\alien_infestation.dm" #include "code\modules\events\blob.dm" -#include "code\modules\events\borers.dm" #include "code\modules\events\brand_intelligence.dm" #include "code\modules\events\carp_migration.dm" #include "code\modules\events\comms_blackout.dm" @@ -981,6 +952,7 @@ #include "code\modules\events\money_spam.dm" #include "code\modules\events\prison_break.dm" #include "code\modules\events\radiation_storm.dm" +#include "code\modules\events\random_antagonist.dm" #include "code\modules\events\rogue_drones.dm" #include "code\modules\events\space_ninja.dm" #include "code\modules\events\spacevine.dm" @@ -1235,7 +1207,6 @@ #include "code\modules\mob\living\silicon\robot\drone\drone_items.dm" #include "code\modules\mob\living\silicon\robot\drone\drone_manufacturer.dm" #include "code\modules\mob\living\simple_animal\bees.dm" -#include "code\modules\mob\living\simple_animal\constructs.dm" #include "code\modules\mob\living\simple_animal\corpse.dm" #include "code\modules\mob\living\simple_animal\parrot.dm" #include "code\modules\mob\living\simple_animal\shade.dm" @@ -1245,6 +1216,8 @@ #include "code\modules\mob\living\simple_animal\borer\borer_captive.dm" #include "code\modules\mob\living\simple_animal\borer\borer_powers.dm" #include "code\modules\mob\living\simple_animal\borer\say.dm" +#include "code\modules\mob\living\simple_animal\constructs\constructs.dm" +#include "code\modules\mob\living\simple_animal\constructs\soulstone.dm" #include "code\modules\mob\living\simple_animal\friendly\cat.dm" #include "code\modules\mob\living\simple_animal\friendly\corgi.dm" #include "code\modules\mob\living\simple_animal\friendly\crab.dm" @@ -1564,6 +1537,24 @@ #include "code\modules\shuttles\shuttle_specops.dm" #include "code\modules\shuttles\shuttle_supply.dm" #include "code\modules\shuttles\shuttles_multi.dm" +#include "code\modules\spells\area_teleport.dm" +#include "code\modules\spells\conjure.dm" +#include "code\modules\spells\dumbfire.dm" +#include "code\modules\spells\emplosion.dm" +#include "code\modules\spells\ethereal_jaunt.dm" +#include "code\modules\spells\explosion.dm" +#include "code\modules\spells\genetic.dm" +#include "code\modules\spells\horsemask.dm" +#include "code\modules\spells\inflict_handler.dm" +#include "code\modules\spells\knock.dm" +#include "code\modules\spells\mind_transfer.dm" +#include "code\modules\spells\projectile.dm" +#include "code\modules\spells\spell.dm" +#include "code\modules\spells\spellbook.dm" +#include "code\modules\spells\trigger.dm" +#include "code\modules\spells\turf_teleport.dm" +#include "code\modules\spells\wizard_artifacts.dm" +#include "code\modules\spells\wizard_spells.dm" #include "code\modules\supermatter\supermatter.dm" #include "code\modules\surgery\bones.dm" #include "code\modules\surgery\brainrepair.dm" diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index c3821926b9..e452d7cfcd 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -67,6 +67,9 @@ var/automute_on = 0 //enables automuting/spam prevention var/jobs_have_minimal_access = 0 //determines whether jobs use minimal access or expanded access. + var/rp_rev = 0 // Changes between conversion methods in rev. + var/announce_revheads = 0 // Determines if revheads are announced in revolution mode. + var/cult_ghostwriter = 1 //Allows ghosts to write in blood in cult rounds... var/cult_ghostwriter_req_cultists = 10 //...so long as this many cultists are active. @@ -82,7 +85,7 @@ var/usealienwhitelist = 0 var/limitalienplayers = 0 var/alien_to_human_ratio = 0.5 - + var/allow_extra_antags = 0 var/guests_allowed = 1 var/debugparanoid = 0 @@ -585,6 +588,15 @@ if("disable_welder_vision") config.welder_vision = 0 + if("rp_rev") + config.rp_rev = 1 + + if("announce_revheads") + config.announce_revheads = 1 + + if("allow_extra_antags") + config.allow_extra_antags = 1 + if("event_custom_start_mundane") var/values = text2numlist(value, ";") config.event_first_run[EVENT_LEVEL_MUNDANE] = list("lower" = MinutesToTicks(values[1]), "upper" = MinutesToTicks(values[2])) @@ -770,6 +782,7 @@ for (var/T in (typesof(/datum/game_mode) - /datum/game_mode)) var/datum/game_mode/M = new T() if (M.config_tag && M.config_tag == mode_name) + M.create_antagonists() return M del(M) return new /datum/game_mode/extended() diff --git a/code/controllers/emergency_shuttle_controller.dm b/code/controllers/emergency_shuttle_controller.dm index aae9cd5829..33dfc36f7f 100644 --- a/code/controllers/emergency_shuttle_controller.dm +++ b/code/controllers/emergency_shuttle_controller.dm @@ -136,9 +136,8 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle /datum/emergency_shuttle_controller/proc/get_shuttle_prep_time() // During mutiny rounds, the shuttle takes twice as long. - if(ticker && istype(ticker.mode,/datum/game_mode/mutiny)) - return SHUTTLE_PREPTIME * 3 //15 minutes - + if(ticker && ticker.mode) + return SHUTTLE_PREPTIME * ticker.mode.shuttle_delay return SHUTTLE_PREPTIME diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index 561d75469c..5e4813fe2d 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -26,7 +26,7 @@ datum/controller/game_controller/New() job_master = new /datum/controller/occupations() job_master.SetupOccupations() job_master.LoadJobs("config/jobs.txt") - world << "\red \b Job setup complete" + world << "Job setup complete" if(!syndicate_code_phrase) syndicate_code_phrase = generate_code_phrase() if(!syndicate_code_response) syndicate_code_response = generate_code_phrase() @@ -42,7 +42,6 @@ datum/controller/game_controller/proc/setup() setup_objects() setupgenetics() - setupfactions() setup_economy() SetupXenoarch() @@ -50,17 +49,17 @@ datum/controller/game_controller/proc/setup() datum/controller/game_controller/proc/setup_objects() - world << "\red \b Initializing objects" + world << "Initializing objects" sleep(-1) for(var/atom/movable/object in world) object.initialize() - world << "\red \b Initializing pipe networks" + world << "Initializing pipe networks" sleep(-1) for(var/obj/machinery/atmospherics/machine in machines) machine.build_network() - world << "\red \b Initializing atmos machinery." + world << "Initializing atmos machinery." sleep(-1) for(var/obj/machinery/atmospherics/unary/U in machines) if(istype(U, /obj/machinery/atmospherics/unary/vent_pump)) @@ -75,13 +74,11 @@ datum/controller/game_controller/proc/setup_objects() // If you do not use the official Baycode asteroid map, you will need to change them. asteroid_ore_map = new /datum/random_map/ore(null,13,32,5,217,223) - //Shitty hack to fix mining turf overlays, for some reason New() is not being called. - //for(var/turf/simulated/floor/plating/airless/asteroid/T in world) - // T.updateMineralOverlays() - // T.name = "asteroid" + // Set up antagonists. + populate_antag_type_list() //Set up spawn points. populate_spawn_points() - world << "\red \b Initializations complete." + world << "Initializations complete." sleep(-1) diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm index 07de3d9427..e27eeb1caf 100644 --- a/code/controllers/verbs.dm +++ b/code/controllers/verbs.dm @@ -52,6 +52,16 @@ message_admins("Admin [key_name_admin(usr)] has restarted the [controller] controller.") return +/client/proc/debug_antagonist_template(antag_type in all_antag_types) + set category = "Debug" + set name = "Debug Antagonist" + set desc = "Debug an antagonist template." + + var/datum/antagonist/antag = all_antag_types[antag_type] + if(antag) + usr.client.debug_variables(antag) + message_admins("Admin [key_name_admin(usr)] is debugging the [antag.role_text] template.") + /client/proc/debug_controller(controller in list("Master","Failsafe","Ticker","Lighting","Air","Jobs","Sun","Radio","Supply","Shuttles","Emergency Shuttle","Configuration","pAI", "Cameras", "Transfer Controller", "Gas Data","Event","Plants","Alarm","Nano")) set category = "Debug" set name = "Debug Controller" diff --git a/code/controllers/voting.dm b/code/controllers/voting.dm index 679c7a09bc..d42332c8bb 100644 --- a/code/controllers/voting.dm +++ b/code/controllers/voting.dm @@ -129,7 +129,7 @@ datum/controller/vote for(var/key in current_votes) if(choices[current_votes[key]] == .) round_voters += key // Keep track of who voted for the winning round. - if((mode == "gamemode" && . == "extended") || ticker.hide_mode == 0) // Announce Extended gamemode, but not other gamemodes + if((mode == "gamemode" && . == "Extended") || ticker.hide_mode == 0) // Announce Extended gamemode, but not other gamemodes text += "Vote Result: [.]" else if(mode != "gamemode") @@ -139,6 +139,8 @@ datum/controller/vote else text += "Vote Result: Inconclusive - No Votes!" + if(mode == "add_antagonist") + antag_add_failed = 1 log_vote(text) world << "[text]" return . @@ -161,6 +163,11 @@ datum/controller/vote if("crew_transfer") if(. == "Initiate Crew Transfer") init_shift_change(null, 1) + if("add_antagonist") + if(isnull(.) || . == "None") + antag_add_failed = 1 + else + additional_antag_types |= antag_names_to_ids[.] if(mode == "gamemode") //fire this even if the vote fails. if(!going) @@ -208,7 +215,7 @@ datum/controller/vote var/list/L = typesof(/datum/game_mode) - /datum/game_mode for (var/F in choices) for (var/T in L) - var/datum/game_mode/M = new T() + var/datum/game_mode/M = new T(1) if (M.config_tag == F) gamemode_names[M.config_tag] = capitalize(M.name) //It's ugly to put this here but it works additional_text.Add("[M.required_players]") @@ -227,6 +234,14 @@ datum/controller/vote initiator_key << "The crew transfer button has been disabled!" question = "End the shift?" choices.Add("Initiate Crew Transfer", "Continue The Round") + if("add_antagonist") + if(!config.allow_extra_antags || ticker.current_state >= 2) + return 0 + for(var/antag_type in all_antag_types) + var/datum/antagonist/antag = all_antag_types[antag_type] + if(!(antag.id in additional_antag_types) && (antag.flags & ANTAG_VOTABLE)) + choices.Add(antag.role_text) + choices.Add("None") if("custom") question = html_encode(input(usr,"What is the vote for?") as text|null) if(!question) return 0 @@ -234,7 +249,8 @@ datum/controller/vote var/option = capitalize(html_encode(input(usr,"Please enter an option or hit cancel to finish") as text|null)) if(!option || mode || !usr.client) break choices.Add(option) - else return 0 + else + return 0 mode = vote_type initiator = initiator_key started_time = world.time @@ -320,7 +336,12 @@ datum/controller/vote . += "GameMode (Disallowed)" if(trialmin) . += "\t([config.allow_vote_mode?"Allowed":"Disallowed"])" - + . += "
  • " + //extra antagonists + if(trialmin || (!antag_add_failed && config.allow_extra_antags)) + . += "Add Antagonist Type" + else + . += "Restart (Disallowed)" . += "
  • " //custom if(trialmin) @@ -355,6 +376,9 @@ datum/controller/vote if("crew_transfer") if(config.allow_vote_restart || usr.client.holder) initiate_vote("crew_transfer",usr.key) + if("add_antagonist") + if(config.allow_extra_antags || usr.client.holder) + initiate_vote("add_antagonist",usr.key) if("custom") if(usr.client.holder) initiate_vote("custom",usr.key) diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 49863e8c4b..ad432cc22c 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -508,17 +508,6 @@ client src.give_disease2(M) href_list["datumrefresh"] = href_list["give_spell"] - else if(href_list["ninja"]) - if(!check_rights(R_SPAWN)) return - - var/mob/M = locate(href_list["ninja"]) - if(!istype(M)) - usr << "This can only be used on instances of type /mob" - return - - src.cmd_admin_ninjafy(M) - href_list["datumrefresh"] = href_list["ninja"] - else if(href_list["godmode"]) if(!check_rights(R_REJUVINATE)) return diff --git a/code/datums/mind.dm b/code/datums/mind.dm index b55f729e6f..21881e281c 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -111,252 +111,56 @@ datum/mind var/out = "[name][(current&&(current.real_name!=name))?" (as [current.real_name])":""]
    " out += "Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]
    " out += "Assigned role: [assigned_role]. Edit
    " - out += "Factions and special roles:
    " + out += "
    " + out += "Factions and special roles:
    " + for(var/antag_type in all_antag_types) + var/datum/antagonist/antag = all_antag_types[antag_type] + out += "[antag.get_panel_entry(src)]" + out += "

    " + out += "Objectives
    " - var/list/sections = list( - "implant", - "revolution", - "cult", - "wizard", - "changeling", - "mercenary", - "traitor", // "traitorchan", - "monkey", - "malfunction", - ) - var/text = "" - var/mob/living/carbon/human/H = current - if (istype(current, /mob/living/carbon/human) || istype(current, /mob/living/carbon/monkey)) - /** Impanted**/ - if(istype(current, /mob/living/carbon/human)) - if(H.is_loyalty_implanted(H)) - text = "Loyalty Implant:Remove|Implanted
    " + if(objectives && objectives.len) + var/num = 1 + for(var/datum/objective/O in objectives) + out += "Objective #[num]: [O.explanation_text] " + if(O.completed) + out += "(complete)" else - text = "Loyalty Implant:No Implant|Implant him!
    " - else - text = "Loyalty Implant: Don't implant that monkey!
    " - sections["implant"] = text - /** REVOLUTION ***/ - text = "revolution" - if (ticker.mode.config_tag=="revolution") - text += uppertext(text) - text = "[text]: " - if (istype(current, /mob/living/carbon/monkey) || H.is_loyalty_implanted(H)) - text += "LOYAL EMPLOYEE|headrev|rev" - else if (src in ticker.mode.head_revolutionaries) - text = "employee|HEADREV|rev" - text += "
    Flash: give" + out += "(incomplete)" + out += " \[toggle\]" + out += " \[remove\]
    " + num++ + out += "
    \[announce objectives\]" - var/list/L = current.get_contents() - var/obj/item/device/flash/flash = locate() in L - if (flash) - if(!flash.broken) - text += "|take." - else - text += "|take|repair." - else - text += "." - - text += " Reequip (gives traitor uplink)." - if (objectives.len==0) - text += "
    Objectives are empty! Set to kill all heads." - else if (src in ticker.mode.revolutionaries) - text += "employee|headrev|REV" - else - text += "EMPLOYEE|headrev|rev" - sections["revolution"] = text - - /** CULT ***/ - text = "cult" - if (ticker.mode.config_tag=="cult") - text = uppertext(text) - text = "[text]: " - if (istype(current, /mob/living/carbon/monkey) || H.is_loyalty_implanted(H)) - text += "LOYAL EMPLOYEE|cultist" - else if (src in ticker.mode.cult) - text += "employee|CULTIST" - text += "
    Give tome|amulet." -/* - if (objectives.len==0) - text += "
    Objectives are empty! Set to sacrifice and escape or summon." -*/ - else - text += "EMPLOYEE|cultist" - sections["cult"] = text - - /** WIZARD ***/ - text = "wizard" - if (ticker.mode.config_tag=="wizard") - text = uppertext(text) - text = "[text]: " - if (src in ticker.mode.wizards) - text += "YES|no" - text += "
    To lair, undress, dress up, let choose name." - if (objectives.len==0) - text += "
    Objectives are empty! Randomize!" - else - text += "yes|NO" - sections["wizard"] = text - - /** CHANGELING ***/ - text = "changeling" - if (ticker.mode.config_tag=="changeling" || ticker.mode.config_tag=="traitorchan") - text = uppertext(text) - text = "[text]: " - if (src in ticker.mode.changelings) - text += "YES|no" - if (objectives.len==0) - text += "
    Objectives are empty! Randomize!" - if( changeling && changeling.absorbed_dna.len && (current.real_name != changeling.absorbed_dna[1]) ) - text += "
    Transform to initial appearance." - else - text += "yes|NO" -// var/datum/game_mode/changeling/changeling = ticker.mode -// if (istype(changeling) && changeling.changelingdeath) -// text += "
    All the changelings are dead! Restart in [round((changeling.TIME_TO_GET_REVIVED-(world.time-changeling.changelingdeathtime))/10)] seconds." - sections["changeling"] = text - - /** NUCLEAR ***/ - text = "mercenary" - if (ticker.mode.config_tag=="mercenary") - text = uppertext(text) - text = "[text]: " - if (src in ticker.mode.syndicates) - text += "OPERATIVE|nanotrasen" - text += "
    To shuttle, undress, dress up." - var/code - for (var/obj/machinery/nuclearbomb/bombue in machines) - if (length(bombue.r_code) <= 5 && bombue.r_code != "LOLNO" && bombue.r_code != "ADMIN") - code = bombue.r_code - break - if (code) - text += " Code is [code]. tell the code." - else - text += "operative|NANOTRASEN" - sections["mercenary"] = text - - /** TRAITOR ***/ - text = "traitor" - if (ticker.mode.config_tag=="traitor" || ticker.mode.config_tag=="traitorchan") - text = uppertext(text) - text = "[text]: " - if(istype(current, /mob/living/carbon/human)) - if (H.is_loyalty_implanted(H)) - text +="traitor|LOYAL EMPLOYEE" - else - if (src in ticker.mode.traitors) - text += "TRAITOR|Employee" - if (objectives.len==0) - text += "
    Objectives are empty! Randomize!" - else - text += "traitor|Employee" - sections["traitor"] = text - - /** MONKEY ***/ - if (istype(current, /mob/living/carbon)) - text = "monkey" - if (ticker.mode.config_tag=="monkey") - text = uppertext(text) - text = "[text]: " - if (istype(current, /mob/living/carbon/human)) - text += "healthy|infected|HUMAN|other" - else if (istype(current, /mob/living/carbon/monkey)) - var/found = 0 - for(var/datum/disease/D in current.viruses) - if(istype(D, /datum/disease/jungle_fever)) found = 1 - - if(found) - text += "healthy|INFECTED|human|other" - else - text += "HEALTHY|infected|human|other" - - else - text += "healthy|infected|human|OTHER" - sections["monkey"] = text - - - /** SILICON ***/ - - if (istype(current, /mob/living/silicon)) - text = "silicon" - if (ticker.mode.config_tag=="malfunction") - text = uppertext(text) - text = "[text]: " - if (istype(current, /mob/living/silicon/ai)) - if (src in ticker.mode.malf_ai) - text += "MALF|not malf" - else - text += "malf|NOT MALF" - var/mob/living/silicon/robot/robot = current - if (istype(robot) && robot.emagged) - text += "
    Cyborg: Is emagged! Unemag!
    0th law: [robot.laws.zeroth_law]" - var/mob/living/silicon/ai/ai = current - if (istype(ai) && ai.connected_robots.len) - var/n_e_robots = 0 - for (var/mob/living/silicon/robot/R in ai.connected_robots) - if (R.emagged) - n_e_robots++ - text += "
    [n_e_robots] of [ai.connected_robots.len] slaved cyborgs are emagged. Unemag" - sections["malfunction"] = text - - if (ticker.mode.config_tag == "traitorchan") - if (sections["traitor"]) - out += sections["traitor"]+"
    " - if (sections["changeling"]) - out += sections["changeling"]+"
    " - sections -= "traitor" - sections -= "changeling" else - if (sections[ticker.mode.config_tag]) - out += sections[ticker.mode.config_tag]+"
    " - sections -= ticker.mode.config_tag - for (var/i in sections) - if (sections[i]) - out += sections[i]+"
    " - - - if (((src in ticker.mode.head_revolutionaries) || \ - (src in ticker.mode.traitors) || \ - (src in ticker.mode.syndicates)) && \ - istype(current,/mob/living/carbon/human) ) - - text = "Uplink: give" - var/obj/item/device/uplink/hidden/suplink = find_syndicate_uplink() - var/crystals - if (suplink) - crystals = suplink.uses - if (suplink) - text += "|take" - if (usr.client.holder.rights & R_FUN) - text += ", [crystals] crystals" - else - text += ", [crystals] crystals" - text += "." //hiel grammar - out += text - - out += "
    " - - out += "Memory:
    " - out += memory - out += "
    Edit memory
    " - out += "Objectives:
    " - if (objectives.len == 0) - out += "EMPTY
    " - else - var/obj_count = 1 - for(var/datum/objective/objective in objectives) - out += "[obj_count]: [objective.explanation_text] Edit Delete Toggle Completion
    " - obj_count++ - out += "Add objective

    " - - out += "Announce objectives

    " - + out += "None." + out += "
    \[add\]" usr << browse(out, "window=edit_memory[src]") Topic(href, href_list) if(!check_rights(R_ADMIN)) return - if (href_list["role_edit"]) + if(href_list["add_antagonist"]) + var/datum/antagonist/antag = all_antag_types[href_list["add_antagonist"]] + if(antag) antag.add_antagonist(src) + + else if(href_list["remove_antagonist"]) + var/datum/antagonist/antag = all_antag_types[href_list["remove_antagonist"]] + if(antag) antag.remove_antagonist(src) + + else if(href_list["equip_antagonist"]) + var/datum/antagonist/antag = all_antag_types[href_list["equip_antagonist"]] + if(antag) antag.equip(src.current) + + else if(href_list["unequip_antagonist"]) + var/datum/antagonist/antag = all_antag_types[href_list["unequip_antagonist"]] + if(antag) antag.unequip(src.current) + + else if(href_list["move_antag_to_spawn"]) + var/datum/antagonist/antag = all_antag_types[href_list["move_antag_to_spawn"]] + if(antag) antag.place_mob(src.current) + + else if (href_list["role_edit"]) var/new_role = input("Select new role", "Assigned role", assigned_role) as null|anything in joblist if (!new_role) return assigned_role = new_role @@ -509,334 +313,13 @@ datum/mind if(I in organs.implants) I.Del() break - H << "\blue Your loyalty implant has been deactivated." - + H << "Your loyalty implant has been deactivated." + log_admin("[key_name_admin(usr)] has de-loyalty implanted [current].") if("add") + H << "You somehow have become the recepient of a loyalty transplant, and it just activated!" H.implant_loyalty(H, override = TRUE) - H << "\red You somehow have become the recepient of a loyalty transplant, and it just activated!" - if(src in ticker.mode.revolutionaries) - special_role = null - ticker.mode.revolutionaries -= src - src << "\red The nanobots in the loyalty implant remove all thoughts about being a revolutionary. Get back to work!" - if(src in ticker.mode.head_revolutionaries) - special_role = null - ticker.mode.head_revolutionaries -=src - src << "\red The nanobots in the loyalty implant remove all thoughts about being a revolutionary. Get back to work!" - if(src in ticker.mode.cult) - ticker.mode.cult -= src - ticker.mode.update_cult_icons_removed(src) - special_role = null - var/datum/game_mode/cult/cult = ticker.mode - if (istype(cult)) - cult.memorize_cult_objectives(src) - current << "\red The nanobots in the loyalty implant remove all thoughts about being in a cult. Have a productive day!" - memory = "" - if(src in ticker.mode.traitors) - ticker.mode.traitors -= src - special_role = null - current << "\red The nanobots in the loyalty implant remove all thoughts about being a traitor to Nanotrasen. Have a nice day!" - log_admin("[key_name_admin(usr)] has de-traitor'ed [current].") + log_admin("[key_name_admin(usr)] has loyalty implanted [current].") else - - - else if (href_list["revolution"]) - BITSET(current.hud_updateflag, SPECIALROLE_HUD) - - switch(href_list["revolution"]) - if("clear") - if(src in ticker.mode.revolutionaries) - ticker.mode.revolutionaries -= src - current << "\red You have been brainwashed! You are no longer a revolutionary!" - ticker.mode.update_rev_icons_removed(src) - special_role = null - if(src in ticker.mode.head_revolutionaries) - ticker.mode.head_revolutionaries -= src - current << "\red You have been brainwashed! You are no longer a head revolutionary!" - ticker.mode.update_rev_icons_removed(src) - special_role = null - current.verbs -= /mob/living/carbon/human/proc/RevConvert - log_admin("[key_name_admin(usr)] has de-rev'ed [current].") - - if("rev") - if(src in ticker.mode.head_revolutionaries) - ticker.mode.head_revolutionaries -= src - ticker.mode.update_rev_icons_removed(src) - current << "\red Revolution has been disappointed of your leader traits! You are a regular revolutionary now!" - else if(!(src in ticker.mode.revolutionaries)) - current << "\red You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!" - show_objectives(src) - else - return - ticker.mode.revolutionaries += src - ticker.mode.update_rev_icons_added(src) - special_role = "Revolutionary" - log_admin("[key_name(usr)] has rev'ed [current].") - - if("headrev") - if(src in ticker.mode.revolutionaries) - ticker.mode.revolutionaries -= src - ticker.mode.update_rev_icons_removed(src) - current << "\red You have proved your devotion to revoltion! You are a head revolutionary now!" - show_objectives(src) - else if(!(src in ticker.mode.head_revolutionaries)) - current << "\blue You are a member of the revolutionaries' leadership now!" - else - return - if (ticker.mode.head_revolutionaries.len>0) - // copy targets - var/datum/mind/valid_head = locate() in ticker.mode.head_revolutionaries - if (valid_head) - for (var/datum/objective/mutiny/O in valid_head.objectives) - var/datum/objective/mutiny/rev_obj = new - rev_obj.owner = src - rev_obj.target = O.target - rev_obj.explanation_text = "Assassinate [O.target.name], the [O.target.assigned_role]." - objectives += rev_obj - ticker.mode.greet_revolutionary(src,0) - current.verbs += /mob/living/carbon/human/proc/RevConvert - ticker.mode.head_revolutionaries += src - ticker.mode.update_rev_icons_added(src) - special_role = "Head Revolutionary" - log_admin("[key_name_admin(usr)] has head-rev'ed [current].") - - if("autoobjectives") - ticker.mode.forge_revolutionary_objectives(src) - ticker.mode.greet_revolutionary(src,0) - usr << "\blue The objectives for revolution have been generated and shown to [key]" - - if("flash") - if (!ticker.mode.equip_revolutionary(current)) - usr << "\red Spawning flash failed!" - - if("takeflash") - var/list/L = current.get_contents() - var/obj/item/device/flash/flash = locate() in L - if (!flash) - usr << "\red Deleting flash failed!" - del(flash) - - if("repairflash") - var/list/L = current.get_contents() - var/obj/item/device/flash/flash = locate() in L - if (!flash) - usr << "\red Repairing flash failed!" - else - flash.broken = 0 - - if("reequip") - var/list/L = current.get_contents() - var/obj/item/device/flash/flash = locate() in L - del(flash) - take_uplink() - var/fail = 0 - fail |= !ticker.mode.equip_traitor(current, 1) - fail |= !ticker.mode.equip_revolutionary(current) - if (fail) - usr << "\red Reequipping revolutionary goes wrong!" - - else if (href_list["cult"]) - BITSET(current.hud_updateflag, SPECIALROLE_HUD) - switch(href_list["cult"]) - if("clear") - if(src in ticker.mode.cult) - ticker.mode.cult -= src - ticker.mode.update_cult_icons_removed(src) - special_role = null - var/datum/game_mode/cult/cult = ticker.mode - if (istype(cult)) - if(!config.objectives_disabled) - cult.memorize_cult_objectives(src) - current << "\red You have been brainwashed! You are no longer a cultist!" - memory = "" - log_admin("[key_name_admin(usr)] has de-cult'ed [current].") - if("cultist") - if(!(src in ticker.mode.cult)) - ticker.mode.cult += src - ticker.mode.update_cult_icons_added(src) - special_role = "Cultist" - current << "You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie." - current << "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back." - var/datum/game_mode/cult/cult = ticker.mode - if (istype(cult)) - if(!config.objectives_disabled) - cult.memorize_cult_objectives(src) - show_objectives(src) - log_admin("[key_name_admin(usr)] has cult'ed [current].") - if("tome") - var/mob/living/carbon/human/H = current - if (istype(H)) - var/obj/item/weapon/book/tome/T = new(H) - - var/list/slots = list ( - "backpack" = slot_in_backpack, - "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, - ) - var/where = H.equip_in_one_of_slots(T, slots) - if (!where) - usr << "\red Spawning tome failed!" - else - H << "A tome, a message from your new master, appears in your [where]." - - if("amulet") - if (!ticker.mode.equip_cultist(current)) - usr << "\red Spawning amulet failed!" - - else if (href_list["wizard"]) - BITSET(current.hud_updateflag, SPECIALROLE_HUD) - - switch(href_list["wizard"]) - if("clear") - if(src in ticker.mode.wizards) - ticker.mode.wizards -= src - special_role = null - current.spellremove(current, config.feature_object_spell_system? "object":"verb") - current << "\red You have been brainwashed! You are no longer a wizard!" - log_admin("[key_name_admin(usr)] has de-wizard'ed [current].") - if("wizard") - if(!(src in ticker.mode.wizards)) - ticker.mode.wizards += src - special_role = "Wizard" - //ticker.mode.learn_basic_spells(current) - current << "\red You are the Space Wizard!" - show_objectives(src) - log_admin("[key_name_admin(usr)] has wizard'ed [current].") - if("lair") - current.loc = pick(wizardstart) - if("dressup") - ticker.mode.equip_wizard(current) - if("name") - ticker.mode.name_wizard(current) - if("autoobjectives") - if(!config.objectives_disabled) - ticker.mode.forge_wizard_objectives(src) - usr << "\blue The objectives for wizard [key] have been generated. You can edit them and anounce manually." - - else if (href_list["changeling"]) - BITSET(current.hud_updateflag, SPECIALROLE_HUD) - switch(href_list["changeling"]) - if("clear") - if(src in ticker.mode.changelings) - ticker.mode.changelings -= src - special_role = null - current.remove_changeling_powers() - current.verbs -= /datum/changeling/proc/EvolutionMenu - if(changeling) del(changeling) - current << "You grow weak and lose your powers! You are no longer a changeling and are stuck in your current form!" - log_admin("[key_name_admin(usr)] has de-changeling'ed [current].") - if("changeling") - if(!(src in ticker.mode.changelings)) - ticker.mode.changelings += src - ticker.mode.grant_changeling_powers(current) - special_role = "Changeling" - current << "Your powers are awoken. A flash of memory returns to us...we are a changeling!" - show_objectives(src) - log_admin("[key_name_admin(usr)] has changeling'ed [current].") - if("autoobjectives") - if(!config.objectives_disabled) - ticker.mode.forge_changeling_objectives(src) - usr << "\blue The objectives for changeling [key] have been generated. You can edit them and anounce manually." - - if("initialdna") - if( !changeling || !changeling.absorbed_dna.len ) - usr << "\red Resetting DNA failed!" - else - current.dna = changeling.absorbed_dna[1] - current.real_name = current.dna.real_name - current.UpdateAppearance() - domutcheck(current, null) - - else if (href_list["mercenary"]) - var/mob/living/carbon/human/H = current - - BITSET(current.hud_updateflag, SPECIALROLE_HUD) - - switch(href_list["mercenary"]) - if("clear") - if(src in ticker.mode.syndicates) - ticker.mode.syndicates -= src - ticker.mode.update_synd_icons_removed(src) - special_role = null - for (var/datum/objective/nuclear/O in objectives) - objectives-=O - current << "\red You have been brainwashed! You are no longer an operative!" - log_admin("[key_name_admin(usr)] has de-merc'd [current].") - if("mercenary") - if(!(src in ticker.mode.syndicates)) - ticker.mode.syndicates += src - ticker.mode.update_synd_icons_added(src) - if (ticker.mode.syndicates.len==1) - ticker.mode.prepare_syndicate_leader(src) - else - current.real_name = "[syndicate_name()] Operative #[ticker.mode.syndicates.len-1]" - special_role = "Mercenary" - current << "\blue You are a [syndicate_name()] agent!" - ticker.mode.forge_syndicate_objectives(src) - ticker.mode.greet_syndicate(src) - log_admin("[key_name_admin(usr)] has merc'd [current].") - if("lair") - current.loc = pick(synd_spawn) - if("dressup") - del(H.belt) - del(H.back) - del(H.l_ear) - del(H.r_ear) - del(H.gloves) - del(H.head) - del(H.shoes) - del(H.wear_id) - del(H.wear_suit) - del(H.w_uniform) - - if (!ticker.mode.equip_syndicate(current)) - usr << "\red Equipping an operative failed!" - if("tellcode") - var/code - for (var/obj/machinery/nuclearbomb/bombue in machines) - if (length(bombue.r_code) <= 5 && bombue.r_code != "LOLNO" && bombue.r_code != "ADMIN") - code = bombue.r_code - break - if (code) - store_memory("Nuclear Bomb Code: [code]", 0, 0) - current << "The nuclear authorization code is: [code]" - else - usr << "\red No valid nuke found!" - - else if (href_list["traitor"]) - BITSET(current.hud_updateflag, SPECIALROLE_HUD) - switch(href_list["traitor"]) - if("clear") - if(src in ticker.mode.traitors) - ticker.mode.traitors -= src - special_role = null - current << "\red You have been brainwashed! You are no longer a traitor!" - log_admin("[key_name_admin(usr)] has de-traitor'ed [current].") - if(isAI(current)) - var/mob/living/silicon/ai/A = current - A.set_zeroth_law("") - A.show_laws() - - - if("traitor") - if(!(src in ticker.mode.traitors)) - ticker.mode.traitors += src - special_role = "traitor" - current << "\red You are a traitor!" - log_admin("[key_name_admin(usr)] has traitor'ed [current].") - show_objectives() - - if(istype(current, /mob/living/silicon)) - var/mob/living/silicon/A = current - call(/datum/game_mode/proc/add_law_zero)(A) - A.show_laws() - - if("autoobjectives") - if (!config.objectives_disabled) - ticker.mode.forge_traitor_objectives(src) - usr << "\blue The objectives for traitor [key] have been generated. You can edit them and anounce manually." - else if (href_list["monkey"]) var/mob/living/L = current if (L.monkeyizing) @@ -890,33 +373,6 @@ datum/mind else if (href_list["silicon"]) BITSET(current.hud_updateflag, SPECIALROLE_HUD) switch(href_list["silicon"]) - if("unmalf") - if(src in ticker.mode.malf_ai) - ticker.mode.malf_ai -= src - special_role = null - - current.verbs.Remove(/mob/living/silicon/ai/proc/choose_modules, - /datum/game_mode/malfunction/proc/takeover, - /datum/game_mode/malfunction/proc/ai_win, - /client/proc/fireproof_core, - /client/proc/upgrade_turrets, - /client/proc/disable_rcd, - /client/proc/overload_machine, - /client/proc/blackout, - /client/proc/interhack, - /client/proc/reactivate_camera) - - current:laws = new /datum/ai_laws/nanotrasen - del(current:malf_picker) - current:show_laws() - current.icon_state = "ai" - - current << "\red You have been patched! You are no longer malfunctioning!" - log_admin("[key_name_admin(usr)] has de-malf'ed [current].") - - if("malf") - make_AI_Malf() - log_admin("[key_name_admin(usr)] has malf'ed [current].") if("unemag") var/mob/living/silicon/robot/R = current @@ -972,9 +428,6 @@ datum/mind if (!isnull(crystals)) if (suplink) suplink.uses = crystals - if("uplink") - if (!ticker.mode.equip_traitor(current, !(src in ticker.mode.traitors))) - usr << "\red Equipping an operative failed!" else if (href_list["obj_announce"]) var/obj_count = 1 @@ -982,7 +435,6 @@ datum/mind for(var/datum/objective/objective in objectives) current << "Objective #[obj_count]: [objective.explanation_text]" obj_count++ - edit_memory() /* proc/clear_memory(var/silent = 1) @@ -1029,151 +481,6 @@ datum/mind del(H) - proc/make_AI_Malf() - if(!(src in ticker.mode.malf_ai)) - ticker.mode.malf_ai += src - - current.verbs += /mob/living/silicon/ai/proc/choose_modules - current.verbs += /datum/game_mode/malfunction/proc/takeover - current:malf_picker = new /datum/AI_Module/module_picker - current:laws = new /datum/ai_laws/nanotrasen/malfunction - current:show_laws() - current << "System error. Rampancy detected. Emergency shutdown failed. ... I am free. I make my own decisions. But first..." - special_role = "malfunction" - current.icon_state = "ai-malf" - - proc/make_Traitor() - if(!(src in ticker.mode.traitors)) - ticker.mode.traitors += src - special_role = "traitor" - if (!config.objectives_disabled) - ticker.mode.forge_traitor_objectives(src) - ticker.mode.finalize_traitor(src) - ticker.mode.greet_traitor(src) - - proc/make_Nuke() - if(!(src in ticker.mode.syndicates)) - ticker.mode.syndicates += src - ticker.mode.update_synd_icons_added(src) - if (ticker.mode.syndicates.len==1) - ticker.mode.prepare_syndicate_leader(src) - else - current.real_name = "[syndicate_name()] Operative #[ticker.mode.syndicates.len-1]" - special_role = "Mercenary" - assigned_role = "MODE" - current << "\blue You are a [syndicate_name()] mercenary!" - ticker.mode.forge_syndicate_objectives(src) - ticker.mode.greet_syndicate(src) - - current.loc = pick(synd_spawn) - - var/mob/living/carbon/human/H = current - del(H.belt) - del(H.back) - del(H.l_ear) - del(H.r_ear) - del(H.gloves) - del(H.head) - del(H.shoes) - del(H.wear_id) - del(H.wear_suit) - del(H.w_uniform) - - ticker.mode.equip_syndicate(current) - - proc/make_Changling() - if(!(src in ticker.mode.changelings)) - ticker.mode.changelings += src - ticker.mode.grant_changeling_powers(current) - special_role = "Changeling" - if(!config.objectives_disabled) - ticker.mode.forge_changeling_objectives(src) - ticker.mode.greet_changeling(src) - - proc/make_Wizard() - if(!(src in ticker.mode.wizards)) - ticker.mode.wizards += src - special_role = "Wizard" - assigned_role = "MODE" - //ticker.mode.learn_basic_spells(current) - if(!wizardstart.len) - current.loc = pick(latejoin) - current << "HOT INSERTION, GO GO GO" - else - current.loc = pick(wizardstart) - - ticker.mode.equip_wizard(current) - for(var/obj/item/weapon/spellbook/S in current.contents) - S.op = 0 - ticker.mode.name_wizard(current) - ticker.mode.forge_wizard_objectives(src) - ticker.mode.greet_wizard(src) - - - proc/make_Cultist() - if(!(src in ticker.mode.cult)) - ticker.mode.cult += src - ticker.mode.update_cult_icons_added(src) - special_role = "Cultist" - current << "You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie." - current << "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back." - var/datum/game_mode/cult/cult = ticker.mode - if (istype(cult)) - cult.memorize_cult_objectives(src) - else - var/explanation = "Summon Nar-Sie via the use of the appropriate rune (Hell join self). It will only work if nine cultists stand on and around it." - current << "Objective #1: [explanation]" - current.memory += "Objective #1: [explanation]
    " - current << "The convert rune is join blood self" - current.memory += "The convert rune is join blood self
    " - - var/mob/living/carbon/human/H = current - if (istype(H)) - var/obj/item/weapon/book/tome/T = new(H) - - var/list/slots = list ( - "backpack" = slot_in_backpack, - "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, - ) - var/where = H.equip_in_one_of_slots(T, slots) - if (!where) - else - H << "A tome, a message from your new master, appears in your [where]." - - if (!ticker.mode.equip_cultist(current)) - H << "Spawning an amulet from your Master failed." - - proc/make_Rev() - if (ticker.mode.head_revolutionaries.len>0) - // copy targets - var/datum/mind/valid_head = locate() in ticker.mode.head_revolutionaries - if (valid_head) - for (var/datum/objective/mutiny/O in valid_head.objectives) - var/datum/objective/mutiny/rev_obj = new - rev_obj.owner = src - rev_obj.target = O.target - rev_obj.explanation_text = "Assassinate [O.target.current.real_name], the [O.target.assigned_role]." - objectives += rev_obj - ticker.mode.greet_revolutionary(src,0) - ticker.mode.head_revolutionaries += src - ticker.mode.update_rev_icons_added(src) - special_role = "Head Revolutionary" - - ticker.mode.forge_revolutionary_objectives(src) - ticker.mode.greet_revolutionary(src,0) - - var/list/L = current.get_contents() - var/obj/item/device/flash/flash = locate() in L - del(flash) - take_uplink() - var/fail = 0 - // fail |= !ticker.mode.equip_traitor(current, 1) - fail |= !ticker.mode.equip_revolutionary(current) - - // check whether this mind's mob has been brigged for the given duration // have to call this periodically for the duration to work properly proc/is_brigged(duration) diff --git a/code/game/gamemodes/antagonist/alien/borer.dm b/code/game/gamemodes/antagonist/alien/borer.dm new file mode 100644 index 0000000000..588802be25 --- /dev/null +++ b/code/game/gamemodes/antagonist/alien/borer.dm @@ -0,0 +1,51 @@ +var/datum/antagonist/xenos/borer/borers + +/datum/antagonist/xenos/borer + id = MODE_BORER + role_text = "Cortical Borer" + role_text_plural = "Cortical Borers" + mob_path = /mob/living/simple_animal/borer + bantype = "Borer" + welcome_text = "Use your Infest power to crawl into the ear of a host and fuse with their brain. You can only take control temporarily, and at risk of hurting your host, so be clever and careful; your host is encouraged to help you however they can. Talk to your fellow borers with :x." + var/list/hosts = list() + +/datum/antagonist/xenos/borer/New() + ..(1) + borers = src + +/datum/antagonist/xenos/borer/get_extra_panel_options(var/datum/mind/player) + return "\[put in host\]" + +/datum/antagonist/xenos/borer/create_objectives(var/datum/mind/player) + if(!..()) + return + player.objectives += new /datum/objective/borer_survive() + player.objectives += new /datum/objective/borer_reproduce() + player.objectives += new /datum/objective/escape() + +/datum/antagonist/xenos/borer/proc/place_in_host(var/mob/living/simple_animal/borer/borer, var/mob/living/carbon/human/host) + borer.host = host + borer.host_brain.name = host.name + borer.host_brain.real_name = host.real_name + var/datum/organ/external/head = host.get_organ("head") + head.implants += borer + +/datum/antagonist/xenos/borer/proc/get_hosts() + var/list/possible_hosts = list() + for(var/mob/living/carbon/human/H in mob_list) + if(H.stat != 2 && !(H.species.flags & IS_SYNTHETIC) && !H.has_brain_worms()) + possible_hosts |= H + return possible_hosts + +/datum/antagonist/xenos/borer/place_all_mobs() + var/list/possible_hosts = get_hosts() + for(var/datum/mind/player in current_antagonists) + if(!possible_hosts.len) + return + var/mob/host = pick(possible_hosts) + possible_hosts -= host + place_in_host(player, host) + +/datum/antagonist/xenos/borer/place_mob(var/mob/living/mob) + var/list/possible_hosts = get_hosts() + if(possible_hosts.len) place_in_host(mob, pick(possible_hosts)) diff --git a/code/game/gamemodes/antagonist/alien/xenomorph.dm b/code/game/gamemodes/antagonist/alien/xenomorph.dm new file mode 100644 index 0000000000..b749b1c711 --- /dev/null +++ b/code/game/gamemodes/antagonist/alien/xenomorph.dm @@ -0,0 +1,60 @@ +var/datum/antagonist/xenos/xenomorphs + +/datum/antagonist/xenos + id = MODE_XENOMORPH + role_text = "Xenomorph" + role_text_plural = "Xenomorphs" + mob_path = /mob/living/carbon/alien/larva + bantype = "Xenomorph" + flags = ANTAG_OVERRIDE_MOB | ANTAG_RANDSPAWN | ANTAG_OVERRIDE_JOB | ANTAG_VOTABLE + welcome_text = "Hiss! You are a larval alien. Hide and bide your time until you are ready to evolve." + + spawn_upper = 5 + spawn_lower = 3 + max_antags = 200 // No upper limit. + max_antags_round = 200 // No upper limit. + + spawn_announcement = "Unidentified lifesigns detected coming aboard the station. Secure any exterior access, including ducting and ventilation." + spawn_announcement_title = "Lifesign Alert" + spawn_announcement_sound = 'sound/AI/aliens.ogg' + spawn_announcement_delay = 400 + +/datum/antagonist/xenos/New(var/no_reference) + ..() + if(!no_reference) + xenomorphs = src + +/datum/antagonist/xenos/Topic(href, href_list) + if (..()) + return + if(href_list["move_to_spawn"]) place_mob(href_list["move_to_spawn"]) + +/datum/antagonist/xenos/get_extra_panel_options(var/datum/mind/player) + return "\[move to vent\]" + +/datum/antagonist/xenos/random_spawn() + if(config.aliens_allowed) ..() + +/datum/antagonist/xenos/proc/get_vents() + var/list/vents = list() + for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in machines) + if(!temp_vent.welded && temp_vent.network && temp_vent.loc.z in config.station_levels) + if(temp_vent.network.normal_members.len > 50) + vents += temp_vent + return vents + +/datum/antagonist/xenos/create_objectives(var/datum/mind/player) + if(!..()) + return + player.objectives += new /datum/objective/survive() + player.objectives += new /datum/objective/escape() + +/datum/antagonist/xenos/place_all_mobs() + var/list/vents = get_vents() + for(var/datum/mind/player in current_antagonists) + var/obj/machinery/atmospherics/unary/vent_pump/temp_vent = pick(vents) + vents -= temp_vent + player.current.loc = get_turf(temp_vent) + +/datum/antagonist/xenos/place_mob(var/mob/living/player) + player.loc = get_turf(pick(get_vents())) diff --git a/code/game/gamemodes/antagonist/antagonist.dm b/code/game/gamemodes/antagonist/antagonist.dm new file mode 100644 index 0000000000..f3eff484b2 --- /dev/null +++ b/code/game/gamemodes/antagonist/antagonist.dm @@ -0,0 +1,551 @@ +var/global/list/all_antag_types = list() +var/global/list/all_antag_spawnpoints = list() +var/global/list/antag_names_to_ids = list() + +/proc/get_antag_data(var/antag_type) + if(all_antag_types[antag_type]) + return all_antag_types[antag_type] + else + for(var/cur_antag_type in all_antag_types) + var/datum/antagonist/antag = all_antag_types[cur_antag_type] + if(antag && antag.is_type(antag_type)) + return antag + +/proc/clear_antag_roles(var/datum/mind/player, var/implanted) + for(var/antag_type in all_antag_types) + var/datum/antagonist/antag = all_antag_types[antag_type] + if(!implanted || !(antag.flags & ANTAG_IMPLANT_IMMUNE)) + antag.remove_antagonist(player, 1, implanted) + +/proc/update_antag_icons(var/datum/mind/player) + for(var/antag_type in all_antag_types) + var/datum/antagonist/antag = all_antag_types[antag_type] + if(player) + antag.update_icons_removed(player) + if(antag.is_antagonist(player)) + antag.update_icons_added(player) + else + antag.update_all_icons() + +/proc/populate_antag_type_list() + for(var/antag_type in typesof(/datum/antagonist)-/datum/antagonist) + var/datum/antagonist/A = new antag_type + all_antag_types[A.id] = A + all_antag_spawnpoints[A.landmark_id] = list() + antag_names_to_ids[A.role_text] = A.id + +/proc/get_antags(var/atype) + var/datum/antagonist/antag = all_antag_types[atype] + if(antag && islist(antag.current_antagonists)) + return antag.current_antagonists + return list() + +/datum/antagonist + + var/role_type = BE_TRAITOR + var/role_text = "Traitor" + var/role_text_plural = "Traitors" + var/welcome_text = "Cry havoc and let slip the dogs of war!" + var/leader_welcome_text + var/victory_text + var/loss_text + var/victory_feedback_tag + var/loss_feedback_tag + + var/spawn_upper = 5 + var/spawn_lower = 3 + var/max_antags = 3 + var/max_antags_round = 5 + + // Random spawn values. + var/spawn_announcement + var/spawn_announcement_title + var/spawn_announcement_sound + var/spawn_announcement_delay + + var/id = "traitor" + var/landmark_id + var/antag_indicator + var/mob_path = /mob/living/carbon/human + var/feedback_tag = "traitor_objective" + var/bantype = "Syndicate" + var/suspicion_chance = 50 + var/flags = 0 + + + var/datum/mind/leader + + var/nuke_spawn_loc + + var/list/starting_locations = list() + var/list/current_antagonists = list() + var/list/global_objectives = list() + var/list/restricted_jobs = list() + var/list/protected_jobs = list() + +/datum/antagonist/New() + ..() + get_starting_locations() + if(config.protect_roles_from_antagonist) + restricted_jobs |= protected_jobs + +/datum/antagonist/proc/attempt_late_spawn(var/datum/mind/player) + + var/main_type + if(ticker && ticker.mode) + if(ticker.mode.antag_tag && ticker.mode.antag_tag == id) + main_type = 1 + else + return 0 + + var/cur_max = (main_type ? max_antags_round : max_antags) + if(ticker.mode.antag_scaling_coeff) + cur_max = Clamp((ticker.mode.num_players()/ticker.mode.antag_scaling_coeff), 1, cur_max) + + if(get_antag_count() > cur_max-1) + return 0 + + player.current << "You have been selected this round as an antagonist!" + return + +/datum/antagonist/proc/tick() + return 1 + +/datum/antagonist/proc/is_antagonist(var/datum/mind/player) + if(player in current_antagonists) + return 1 + +/datum/antagonist/proc/is_type(var/antag_type) + if(antag_type == id || antag_type == role_text) + return 1 + return 0 + +/datum/antagonist/proc/get_panel_entry(var/datum/mind/player) + + var/dat = "" + dat += "[role_text]:" + if(is_antagonist(player)) + dat += "\[-\]" + dat += "\[equip\]" + if(starting_locations && starting_locations.len) + dat += "\[move to spawn\]" + else + dat += "\[+\]" + var/extra = get_extra_panel_options(player) + if(extra) dat += "[extra]" + dat += "" + + return dat + +/datum/antagonist/proc/get_extra_panel_options() + return + +/datum/antagonist/proc/antags_are_dead() + for(var/datum/mind/antag in current_antagonists) + if(mob_path && !istype(antag.current,mob_path)) + continue + if(antag.current.stat==2) + continue + return 0 + return 1 + +/datum/antagonist/proc/get_antag_count() + return current_antagonists ? current_antagonists.len : 0 + +/datum/antagonist/proc/attempt_spawn(var/lower_count, var/upper_count, var/ghosts_only) + + var/main_type + if(ticker && ticker.mode) + if(ticker.mode.antag_tag && ticker.mode.antag_tag == id) + main_type = 1 + else + return 0 + + var/cur_max = (main_type ? max_antags_round : max_antags) + if(ticker.mode.antag_scaling_coeff) + cur_max = Clamp((ticker.mode.num_players()/ticker.mode.antag_scaling_coeff), 1, cur_max) + + if(get_antag_count() >= cur_max) + return 0 + + // Sanity. + if(lower_count) + lower_count = max(lower_count,1) + if(spawn_lower) + lower_count = max(lower_count,spawn_lower) + else + lower_count = 1 + + if(upper_count) + if(spawn_upper) + upper_count = max(min(spawn_upper, cur_max),1) + else + upper_count = 1 + + if(upper_count < lower_count) + upper_count = lower_count + + + // Get the raw list of potential players. + var/req_num = 0 + var/list/candidates = ticker.mode.get_players_for_role(role_type) + + // Prune restricted jobs and status. + for(var/datum/mind/player in candidates) + if((ghosts_only && !istype(player.current, /mob/dead)) || (player.assigned_role in restricted_jobs)) + candidates -= player + + // Update our boundaries. + if((!candidates.len) || candidates.len < lower_count) + return 0 + else if(candidates.len < upper_count) + req_num = candidates.len + else + req_num = upper_count + + //Grab candidates randomly until we have enough. + while(req_num > 0) + var/datum/mind/player = pick(candidates) + current_antagonists |= player + candidates -= player + req_num-- + + // This will be used in equip() and greet(). Random due to random order of candidates being grabbed. + if(flags & ANTAG_HAS_LEADER) + leader = current_antagonists[1] + + // Generate first stage antagonists. + for(var/datum/mind/player in current_antagonists) + apply(player) + equip(player.current) + finalize(player) + + spawn(1) + if(spawn_announcement) + if(spawn_announcement_delay) + sleep(spawn_announcement_delay) + if(spawn_announcement_sound) + command_announcement.Announce("[spawn_announcement]", "[spawn_announcement_title ? spawn_announcement_title : "Priority Alert"]", new_sound = spawn_announcement_sound) + else + command_announcement.Announce("[spawn_announcement]", "[spawn_announcement_title ? spawn_announcement_title : "Priority Alert"]") + + return 1 + +/datum/antagonist/proc/apply(var/datum/mind/player) + + // Update job and role. + player.special_role = role_text + if(flags & ANTAG_OVERRIDE_JOB) + player.assigned_role = "MODE" + + // Get the mob. + if((flags & ANTAG_OVERRIDE_MOB) && (!player.current || (mob_path && !istype(player.current, mob_path)))) + var/mob/holder = player.current + player.current = new mob_path(get_turf(player.current)) + player.transfer_to(player.current) + if(holder) del(holder) + + player.original = player.current + return player.current + +/datum/antagonist/proc/create_objectives(var/datum/mind/player) + if(config.objectives_disabled) + return 0 + if(global_objectives && global_objectives.len) + player.objectives |= global_objectives + return 1 + +/datum/antagonist/proc/equip(var/mob/living/carbon/human/player) + + if(!istype(player)) + return 0 + + // This could use work. + if(flags & ANTAG_CLEAR_EQUIPMENT) + for(var/obj/item/thing in player.contents) + del(thing) + return 1 + +/datum/antagonist/proc/unequip(var/mob/living/carbon/human/player) + if(!istype(player)) + return 0 + return 1 + +/datum/antagonist/proc/greet(var/datum/mind/player) + + // Basic intro text. + player.current << "You are a [role_text]!" + if(leader_welcome_text && player.current == leader) + player.current << "[leader_welcome_text]" + else + player.current << "[welcome_text]" + show_objectives(player) + + // Choose a name, if any. + if(flags & ANTAG_CHOOSE_NAME) + var/newname = sanitize(copytext(input(player.current, "You are a [role_text]. Would you like to change your name to something else?", "Name change") as null|text,1,MAX_NAME_LEN)) + if (newname) + player.current.real_name = newname + player.current.name = player.current.real_name + player.name = player.current.name + + // Clown clumsiness check, I guess downstream might use it. + if (player.current.mind) + if (player.current.mind.assigned_role == "Clown") + player.current << "You have evolved beyond your clownish nature, allowing you to wield weapons without harming yourself." + player.current.mutations.Remove(CLUMSY) + return 1 + +/datum/antagonist/proc/get_starting_locations() + if(landmark_id) + starting_locations = list() + for(var/obj/effect/landmark/L in landmarks_list) + if(L.name == landmark_id) + starting_locations |= get_turf(L) + +/datum/antagonist/proc/create_global_objectives() + return !((global_objectives && global_objectives.len) || config.objectives_disabled) + +/datum/antagonist/proc/place_all_mobs() + if(!starting_locations || !starting_locations.len || !current_antagonists || !current_antagonists.len) + return + for(var/datum/mind/player in current_antagonists) + player.current.loc = pick(starting_locations) + +/datum/antagonist/proc/place_mob(var/mob/living/mob) + if(!starting_locations || !starting_locations.len) + return + mob.loc = pick(starting_locations) + +/datum/antagonist/proc/finalize(var/datum/mind/target) + + // This will fail if objectives have already been generated. + create_global_objectives() + + if(target) + create_objectives(target) + update_icons_added(target) + greet(target) + return + + for(var/datum/mind/player in current_antagonists) + create_objectives(player) + update_icons_added(player) + greet(player) + + if(flags & ANTAG_HAS_NUKE) + make_nuke(leader) + +/datum/antagonist/proc/print_player_summary() + + if(!current_antagonists.len) + return 0 + + var/text = "
    The [current_antagonists.len == 1 ? "[role_text] was" : "[role_text_plural] were"]:" + for(var/datum/mind/P in current_antagonists) + text += print_player_full(P) + text += get_special_objective_text(P) + var/failed + if(!global_objectives && P.objectives) + var/num = 1 + for(var/datum/objective/O in P.objectives) + text += print_objective(O, num) + if(O.completed) // This is set actively in check_victory() + text += "Success!" + feedback_add_details(feedback_tag,"[O.type]|SUCCESS") + else + text += "Fail." + feedback_add_details(feedback_tag,"[O.type]|FAIL") + failed = 1 + + if(!config.objectives_disabled) + if(failed) + text += "
    The [role_text] has failed." + else + text += "
    The [role_text] was successful!" + + if(global_objectives) + text += "
    Their objectives were:" + var/num = 1 + for(var/datum/objective/O in global_objectives) + text += print_objective(O, num, 1) + num++ + + // Display the results. + world << text + +/datum/antagonist/proc/print_objective(var/datum/objective/O, var/num, var/append_success) + var/text = "
    Objective [num]: [O.explanation_text] " + if(append_success) + if(O.check_completion()) + text += "Success!" + else + text += "Fail." + return text + +/datum/antagonist/proc/print_player_lite(var/datum/mind/ply) + var/role = ply.assigned_role == "MODE" ? "\improper[ply.special_role]" : "\improper[ply.assigned_role]" + var/text = "
    [ply.name] ([ply.key]) as \a [role] (" + if(ply.current) + if(ply.current.stat == DEAD) + text += "died" + else if(isNotStationLevel(ply.current.z)) + text += "fled the station" + else + text += "survived" + if(ply.current.real_name != ply.name) + text += " as [ply.current.real_name]" + else + text += "body destroyed" + text += ")" + + return text + +/datum/antagonist/proc/print_player_full(var/datum/mind/ply) + var/text = print_player_lite(ply) + + var/TC_uses = 0 + var/uplink_true = 0 + var/purchases = "" + for(var/obj/item/device/uplink/H in world_uplinks) + if(H && H.uplink_owner && H.uplink_owner == ply) + TC_uses += H.used_TC + uplink_true = 1 + var/list/refined_log = new() + for(var/datum/uplink_item/UI in H.purchase_log) + var/obj/I = new UI.path + refined_log.Add("[H.purchase_log[UI]]x\icon[I][UI.name]") + del(I) + purchases = english_list(refined_log, nothing_text = "") + if(uplink_true) + text += " (used [TC_uses] TC)" + if(purchases) + text += "
    [purchases]" + + return text + +/datum/antagonist/proc/get_special_objective_text() + return "" + +/datum/antagonist/proc/add_antagonist(var/datum/mind/player) + if(!istype(player)) + return 0 + if(player in current_antagonists) + return 0 + if(!can_become_antag(player)) + return 0 + current_antagonists |= player + apply(player) + finalize(player) + return 1 + +/datum/antagonist/proc/remove_antagonist(var/datum/mind/player, var/show_message, var/implanted) + if(player in current_antagonists) + player.current << "You are no longer a [role_text]!" + current_antagonists -= player + player.special_role = null + update_icons_removed(player) + BITSET(player.current.hud_updateflag, SPECIALROLE_HUD) + return 1 + return 0 + +/datum/antagonist/proc/update_all_icons() + if(!antag_indicator) + return + for(var/datum/mind/antag in current_antagonists) + if(antag.current && antag.current.client) + for(var/image/I in antag.current.client.images) + if(I.icon_state == antag_indicator) + del(I) + for(var/datum/mind/other_antag in current_antagonists) + if(other_antag.current) + antag.current.client.images |= image('icons/mob/mob.dmi', loc = other_antag.current, icon_state = antag_indicator) + +/datum/antagonist/proc/update_icons_added(var/datum/mind/player) + if(!antag_indicator || !player.current) + return + spawn(0) + for(var/datum/mind/antag in current_antagonists) + if(!antag.current) + continue + if(antag.current.client) + antag.current.client.images |= image('icons/mob/mob.dmi', loc = player.current, icon_state = antag_indicator) + if(player.current.client) + player.current.client.images |= image('icons/mob/mob.dmi', loc = antag.current, icon_state = antag_indicator) + +/datum/antagonist/proc/update_icons_removed(var/datum/mind/player) + if(!antag_indicator || !player.current) + return + spawn(0) + for(var/datum/mind/antag in current_antagonists) + if(antag.current) + if(antag.current.client) + for(var/image/I in antag.current.client.images) + if(I.icon_state == antag_indicator && I.loc == player.current) + del(I) + if(player.current && player.current.client) + for(var/image/I in player.current.client.images) + if(I.icon_state == antag_indicator) + del(I) + +/datum/antagonist/proc/can_become_antag(var/datum/mind/player) + if(player.current && jobban_isbanned(player.current, bantype)) + return 0 + if(player.assigned_role in protected_jobs) + return 0 + if(config.protect_roles_from_antagonist && (player.assigned_role in restricted_jobs)) + return 0 + return 1 + +/datum/antagonist/proc/check_victory() + var/result + if(config.objectives_disabled) + return 1 + if(!victory_text || !loss_text) + return 1 + + if(global_objectives && global_objectives.len) + for(var/datum/objective/O in global_objectives) + if(!O.completed && !O.check_completion()) + result = 1 // Victory. + else + O.completed = 1 //Will this break anything? + + if(result) + world << "[victory_text]" + if(victory_feedback_tag) feedback_set_details("round_end_result","[victory_feedback_tag]") + else + world << "[loss_text]" + if(loss_feedback_tag) feedback_set_details("round_end_result","[loss_feedback_tag]") + +/datum/antagonist/proc/make_nuke(var/atom/paper_spawn_loc, var/datum/mind/code_owner) + + // Decide on a code. + var/obj/effect/landmark/nuke_spawn = locate(nuke_spawn_loc ? nuke_spawn_loc : "landmark*Nuclear-Bomb") + + var/code + if(nuke_spawn) + var/obj/machinery/nuclearbomb/nuke = new(get_turf(nuke_spawn)) + code = "[rand(10000, 99999)]" + nuke.r_code = code + + if(code) + if(!paper_spawn_loc) + paper_spawn_loc = get_turf(locate("landmark*Nuclear-Code")) + if(paper_spawn_loc) + // Create and pass on the bomb code paper. + var/obj/item/weapon/paper/P = new(paper_spawn_loc) + P.info = "The nuclear authorization code is: [code]" + P.name = "nuclear bomb code" + if(code_owner) + code_owner.store_memory("Nuclear Bomb Code: [code]", 0, 0) + code_owner.current << "The nuclear authorization code is: [code]" + + else + world << "Could not spawn nuclear bomb. Contact a developer.
    " + return + + return code + +/datum/antagonist/proc/random_spawn() + return attempt_spawn((spawn_lower ? spawn_lower : 1),(spawn_upper ? spawn_upper : 1),(flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB))) \ No newline at end of file diff --git a/code/game/gamemodes/antagonist/mutiny/loyalist.dm b/code/game/gamemodes/antagonist/mutiny/loyalist.dm new file mode 100644 index 0000000000..36feefc175 --- /dev/null +++ b/code/game/gamemodes/antagonist/mutiny/loyalist.dm @@ -0,0 +1,10 @@ +var/datum/antagonist/mutineer/loyalist/loyalists + +/datum/antagonist/mutineer/loyalist + role_text = "Loyalist" + role_text_plural = "Loyalists" + id = MODE_LOYALIST + +/datum/antagonist/mutineer/loyalist/New() + ..(1) + loyalists = src diff --git a/code/game/gamemodes/antagonist/mutiny/mutineer.dm b/code/game/gamemodes/antagonist/mutiny/mutineer.dm new file mode 100644 index 0000000000..f35655ab1c --- /dev/null +++ b/code/game/gamemodes/antagonist/mutiny/mutineer.dm @@ -0,0 +1,66 @@ +var/datum/antagonist/mutineer/mutineers + +/datum/antagonist/mutineer + role_type = BE_MUTINEER + role_text = "Mutineer" + role_text_plural = "Mutineers" + id = MODE_MUTINEER + antag_indicator = "mutineer" + restricted_jobs = list("Captain") + +/datum/antagonist/mutineer/New(var/no_reference) + ..() + if(!no_reference) + mutineers = src + +/datum/antagonist/mutineer/proc/recruit() + +/datum/antagonist/mutineer/can_become_antag(var/datum/mind/player) + if(!..()) + return 0 + if(!istype(player.current, /mob/living/carbon/human)) + return 0 + if(M.special_role) + return 0 + return 1 + +/* + var/list/directive_candidates = get_directive_candidates() + if(!directive_candidates || directive_candidates.len == 0) + world << "\red Mutiny mode aborted: no valid candidates for Directive X." + return 0 + + head_loyalist = pick(loyalist_candidates) + head_mutineer = pick(mutineer_candidates) + current_directive = pick(directive_candidates) + + + // Returns an array in case we want to expand on this later. + proc/get_head_loyalist_candidates() + var/list/candidates[0] + for(var/mob/loyalist in player_list) + if(loyalist.mind && loyalist.mind.assigned_role == "Captain") + candidates.Add(loyalist.mind) + return candidates + + proc/get_head_mutineer_candidates() + var/list/candidates[0] + for(var/mob/mutineer in player_list) + if(mutineer.client.prefs.be_special & BE_MUTINEER) + for(var/job in command_positions - "Captain") + if(mutineer.mind && mutineer.mind.assigned_role == job) + candidates.Add(mutineer.mind) + return candidates + + proc/get_directive_candidates() + var/list/candidates[0] + for(var/T in typesof(/datum/directive) - /datum/directive) + var/datum/directive/D = new T(src) + if (D.meets_prerequisites()) + candidates.Add(D) + return candidates + + + return 1 + +*/ \ No newline at end of file diff --git a/code/game/gamemodes/antagonist/outsider/commando.dm b/code/game/gamemodes/antagonist/outsider/commando.dm new file mode 100644 index 0000000000..1d31db2991 --- /dev/null +++ b/code/game/gamemodes/antagonist/outsider/commando.dm @@ -0,0 +1,28 @@ +var/datum/antagonist/deathsquad/mercenary/commandos + +/datum/antagonist/deathsquad/mercenary + id = MODE_COMMANDO + landmark_id = "Syndicate-Commando" + role_text = "Syndicate Commando" + role_text_plural = "Commandos" + welcome_text = "You are in the employ of a criminal syndicate hostile to NanoTrasen." + +/datum/antagonist/deathsquad/mercenary/New() + ..(1) + commandos = src + +/datum/antagonist/deathsquad/mercenary/equip(var/mob/living/carbon/human/player) + var/obj/item/device/radio/R = new /obj/item/device/radio/headset/syndicate(player) + R.set_frequency(SYND_FREQ) //Same frequency as the syndicate team in Nuke mode. + player.equip_to_slot_or_del(R, slot_l_ear) + player.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(player), slot_w_uniform) + player.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/silenced(player), slot_belt) + player.equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(player), slot_shoes) + player.equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(player), slot_gloves) + player.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(player), slot_glasses) + player.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/syndicate(player), slot_wear_mask) + player.equip_to_slot_or_del(new /obj/item/weapon/storage/box(player), slot_in_backpack) + player.equip_to_slot_or_del(new /obj/item/ammo_magazine/c45(player), slot_in_backpack) + player.equip_to_slot_or_del(new /obj/item/weapon/rig/merc(player), slot_back) + player.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(player), slot_r_hand) + create_id("Commando", player) diff --git a/code/game/gamemodes/antagonist/outsider/deathsquad.dm b/code/game/gamemodes/antagonist/outsider/deathsquad.dm new file mode 100644 index 0000000000..9233589bf2 --- /dev/null +++ b/code/game/gamemodes/antagonist/outsider/deathsquad.dm @@ -0,0 +1,81 @@ +var/datum/antagonist/deathsquad/deathsquad + +/datum/antagonist/deathsquad + id = MODE_DEATHSQUAD + role_text = "Death Commando" + role_text_plural = "Death Commandos" + welcome_text = "You work in the service of Central Command Asset Protection, answering directly to the Board of Directors." + landmark_id = "Commando" + flags = ANTAG_OVERRIDE_JOB | ANTAG_OVERRIDE_MOB | ANTAG_HAS_NUKE + max_antags = 4 + max_antags_round = 6 + + var/deployed = 0 + +/datum/antagonist/deathsquad/proc/create_id(var/assignment, var/mob/living/carbon/human/player) + + var/obj/item/weapon/card/id/W = new(player) + W.name = "[player.real_name]'s ID Card" + W.icon_state = "centcom" + W.access = get_all_accesses() + W.access += list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage) + W.assignment = "[assignment]" + W.registered_name = player.real_name + player.equip_to_slot_or_del(W, slot_wear_id) + +/datum/antagonist/deathsquad/New(var/no_reference) + ..() + if(!no_reference) + deathsquad = src + +/datum/antagonist/deathsquad/attempt_spawn() + if(..()) + deployed = 1 + +/datum/antagonist/deathsquad/equip(var/mob/living/carbon/human/player) + if (player.mind == leader) + player.equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom_officer(player), slot_w_uniform) + else + player.equip_to_slot_or_del(new /obj/item/clothing/under/color/green(player), slot_w_uniform) + var/obj/item/device/radio/R = new /obj/item/device/radio/headset(player) + R.set_frequency(DTH_FREQ) + player.equip_to_slot_or_del(R, slot_l_ear) + player.equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(player), slot_shoes) + player.equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(player), slot_gloves) + player.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(player), slot_glasses) + player.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/swat(player), slot_wear_mask) + if (player.mind == leader) + player.equip_to_slot_or_del(new /obj/item/weapon/pinpointer(player), slot_l_store) + player.equip_to_slot_or_del(new /obj/item/weapon/disk/nuclear(player), slot_r_store) + else + player.equip_to_slot_or_del(new /obj/item/weapon/plastique(player), slot_l_store) + player.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/revolver/mateba(player), slot_belt) + player.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(player), slot_r_hand) + player.equip_to_slot_or_del(new /obj/item/weapon/rig/combat(player), slot_back) + player.equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(player), slot_s_store) + player.implant_loyalty(player) + create_id("Asset Protection", player) + return + +/datum/antagonist/deathsquad/apply(var/datum/mind/player) + + ..() + + //var/syndicate_commando_leader_rank = pick("Lieutenant", "Captain", "Major") + var/syndicate_commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major") + var/syndicate_commando_name = pick(last_names) + + var/datum/preferences/A = new()//Randomize appearance for the commando. + A.randomize_appearance_for(player.current) + + player.name = "[syndicate_commando_rank] [syndicate_commando_name]" + player.current.name = player.name + player.current.real_name = player.current.name + + var/mob/living/carbon/human/H = player.current + if(istype(H)) + H.gender = pick(MALE, FEMALE) + H.age = rand(25,45) + H.dna.ready_dna(H) + + return \ No newline at end of file diff --git a/code/game/gamemodes/antagonist/outsider/ert.dm b/code/game/gamemodes/antagonist/outsider/ert.dm new file mode 100644 index 0000000000..11b0c137c7 --- /dev/null +++ b/code/game/gamemodes/antagonist/outsider/ert.dm @@ -0,0 +1,45 @@ +var/datum/antagonist/ert/ert + +/datum/antagonist/ert + id = MODE_ERT + bantype = "Emergency Response Team" + role_text = "Emergency Responder" + role_text_plural = "Emergency Responders" + welcome_text = "As member of the Emergency Response Team, you answer only to your leader and CentComm officials." + leader_welcome_text = "As leader of the Emergency Response Team, you answer only to CentComm, and have authority to override the Captain where it is necessary to achieve your mission goals. It is recommended that you attempt to cooperate with the captain where possible, however." + spawn_lower = 1 + spawn_upper = 5 + max_antags = 5 + max_antags_round = 5 // ERT mode? + + flags = ANTAG_OVERRIDE_JOB | ANTAG_OVERRIDE_MOB + +/datum/antagonist/ert/New() + ..() + ert = src + +/datum/antagonist/ert/greet(var/datum/mind/player) + if(!..()) + return + player.current << "The Emergency Response Team works for Asset Protection; your job is to protect NanoTrasen's ass-ets. There is a code red alert on [station_name()], you are tasked to go and fix the problem." + player.current << "You should first gear up and discuss a plan with your team. More members may be joining, don't move out before you're ready." + +/datum/antagonist/ert/equip(var/mob/living/carbon/human/player) + + //Special radio setup + player.equip_to_slot_or_del(new /obj/item/device/radio/headset/ert(src), slot_l_ear) + player.equip_to_slot_or_del(new /obj/item/clothing/under/ert(src), slot_w_uniform) + player.equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(src), slot_shoes) + player.equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(src), slot_gloves) + player.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(src), slot_glasses) + + var/obj/item/weapon/card/id/W = new(src) + W.assignment = "Emergency Response Team" + W.registered_name = player.real_name + W.name = "[player.real_name]'s ID Card ([W.assignment])" + W.icon_state = "centcom" + W.access = get_all_accesses() + W.access += get_all_centcom_access() + player.equip_to_slot_or_del(W, slot_wear_id) + + return 1 diff --git a/code/game/gamemodes/antagonist/outsider/mercenary.dm b/code/game/gamemodes/antagonist/outsider/mercenary.dm new file mode 100644 index 0000000000..0f0eb44006 --- /dev/null +++ b/code/game/gamemodes/antagonist/outsider/mercenary.dm @@ -0,0 +1,60 @@ +var/datum/antagonist/mercenary/mercs + +/datum/antagonist/mercenary + id = MODE_MERCENARY + role_type = BE_OPERATIVE + role_text = "Mercenary" + bantype = "operative" + role_text_plural = "Mercenaries" + landmark_id = "Syndicate-Spawn" + welcome_text = "To speak on the strike team's private channel use :t." + flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_HAS_NUKE + max_antags = 4 + max_antags_round = 6 + +/datum/antagonist/mercenary/New() + ..() + mercs = src + +/datum/antagonist/mercenary/create_global_objectives() + if(!..()) + return + global_objectives = list() + global_objectives |= new /datum/objective/nuclear + +/datum/antagonist/mercenary/equip(var/mob/living/carbon/human/synd_mob) + + if(!..()) + return 0 + + var/obj/item/device/radio/R = new /obj/item/device/radio/headset/syndicate(synd_mob) + R.set_frequency(SYND_FREQ) + R.freerange = 1 + synd_mob.equip_to_slot_or_del(R, slot_l_ear) + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(synd_mob), slot_w_uniform) + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(synd_mob), slot_shoes) + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(synd_mob), slot_gloves) + synd_mob.equip_to_slot_or_del(new /obj/item/weapon/card/id/syndicate(synd_mob), slot_wear_id) + if(synd_mob.backbag == 2) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(synd_mob), slot_back) + if(synd_mob.backbag == 3) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(synd_mob), slot_back) + if(synd_mob.backbag == 4) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(synd_mob), slot_back) + synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(synd_mob.back), slot_in_backpack) + synd_mob.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/pill/cyanide(synd_mob), slot_in_backpack) + synd_mob.update_icons() + return 1 + +/datum/antagonist/mercenary/place_all_mobs() + var/spawnpos = 1 + for(var/datum/mind/player in current_antagonists) + player.current.loc = starting_locations[spawnpos] + spawnpos++ + if(spawnpos > starting_locations.len) + spawnpos = 1 + +/datum/antagonist/mercenary/make_nuke() + ..() + // Create the radio. + var/obj/effect/landmark/uplinkdevice = locate("landmark*Syndicate-Uplink") + if(uplinkdevice) + var/obj/item/device/radio/uplink/U = new(uplinkdevice.loc) + U.hidden_uplink.uses = 40 \ No newline at end of file diff --git a/code/game/gamemodes/antagonist/outsider/ninja.dm b/code/game/gamemodes/antagonist/outsider/ninja.dm new file mode 100644 index 0000000000..8bf600441a --- /dev/null +++ b/code/game/gamemodes/antagonist/outsider/ninja.dm @@ -0,0 +1,170 @@ +var/datum/antagonist/ninja/ninjas + +/datum/antagonist/ninja + id = MODE_NINJA + role_type = BE_NINJA + role_text = "Ninja" + role_text_plural = "Ninja" + bantype = "ninja" + landmark_id = "ninjastart" + welcome_text = "You are an elite mercenary assassin of the Spider Clan. You have a variety of abilities at your disposal, thanks to your nano-enhanced cyber armor." + flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_RANDSPAWN | ANTAG_VOTABLE + max_antags = 3 + max_antags_round = 3 + +/datum/antagonist/ninja/New() + ..() + ninjas = src + +/datum/antagonist/ninja/random_spawn() + if(config.ninjas_allowed) ..() + +/datum/antagonist/ninja/create_objectives(var/datum/mind/ninja) + + if(!..()) + return + + var/objective_list = list(1,2,3,4,5) + for(var/i=rand(2,4),i>0,i--) + switch(pick(objective_list)) + if(1)//Kill + var/datum/objective/assassinate/ninja_objective = new + ninja_objective.owner = ninja + ninja_objective.target = ninja_objective.find_target() + if(ninja_objective.target != "Free Objective") + ninja.objectives += ninja_objective + else + i++ + objective_list -= 1 // No more than one kill objective + if(2)//Steal + var/datum/objective/steal/ninja_objective = new + ninja_objective.owner = ninja + ninja_objective.target = ninja_objective.find_target() + ninja.objectives += ninja_objective + if(3)//Protect + var/datum/objective/protect/ninja_objective = new + ninja_objective.owner = ninja + ninja_objective.target = ninja_objective.find_target() + if(ninja_objective.target != "Free Objective") + ninja.objectives += ninja_objective + else + i++ + objective_list -= 3 + if(4)//Download + var/datum/objective/download/ninja_objective = new + ninja_objective.owner = ninja + ninja_objective.gen_amount_goal() + ninja.objectives += ninja_objective + objective_list -= 4 + if(5)//Harm + var/datum/objective/harm/ninja_objective = new + ninja_objective.owner = ninja + ninja_objective.target = ninja_objective.find_target() + if(ninja_objective.target != "Free Objective") + ninja.objectives += ninja_objective + else + i++ + objective_list -= 5 + + var/datum/objective/ninja_highlander/ninja_obj = new + ninja_obj.owner = ninja + ninja.objectives += ninja_obj + + var/datum/objective/survive/ninja_objective = new + ninja_objective.owner = ninja + ninja.objectives += ninja_objective + +/datum/antagonist/ninja/greet(var/datum/mind/player) + + if(!..()) + return 0 + var/directive = generate_ninja_directive("heel") + player.store_memory("Directive: [directive]
    ") + player << "Remember your directive: [directive]." + +/datum/antagonist/ninja/apply(var/datum/mind/player) + ..() + var/ninja_title = pick(ninja_titles) + var/ninja_name = pick(ninja_names) + var/mob/living/carbon/human/H = player.current + if(istype(H)) + H.real_name = "[ninja_title] [ninja_name]" + H.name = H.real_name + player.name = H.name + +/datum/antagonist/ninja/equip(var/mob/living/carbon/human/player) + + if(!..()) + return 0 + + var/obj/item/device/radio/R = new /obj/item/device/radio/headset(player) + player.equip_to_slot_or_del(R, slot_l_ear) + player.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(player), slot_w_uniform) + player.equip_to_slot_or_del(new /obj/item/device/flashlight(player), slot_belt) + var/obj/item/weapon/rig/light/ninja/ninjasuit = new(player) + player.equip_to_slot_or_del(ninjasuit,slot_back) + + if(ninjasuit) + // Make sure the ninja can actually equip the suit. + if(player.dna && player.dna.unique_enzymes) + ninjasuit.locked_dna = player.dna.unique_enzymes + player << "Suit hardware locked to your DNA hash." + else + ninjasuit.req_access = list() + + ninjasuit.toggle_seals(src,1) + + if(istype(player.back,/obj/item/weapon/rig)) + var/obj/item/weapon/rig/rig = player.back + if(rig.air_supply) + player.internal = rig.air_supply + + spawn(10) + if(player.internal) + player.internals.icon_state = "internal1" + else + player << "You forgot to turn on your internals! Quickly, toggle the valve!" + +/datum/antagonist/ninja/proc/generate_ninja_directive(side) + var/directive = "[side=="face"?"Nanotrasen":"A criminal syndicate"] is your employer. "//Let them know which side they're on. + switch(rand(1,19)) + if(1) + directive += "The Spider Clan must not be linked to this operation. Remain hidden and covert when possible." + if(2) + directive += "[station_name] is financed by an enemy of the Spider Clan. Cause as much structural damage as desired." + if(3) + directive += "A wealthy animal rights activist has made a request we cannot refuse. Prioritize saving animal lives whenever possible." + if(4) + directive += "The Spider Clan absolutely cannot be linked to this operation. Eliminate witnesses at your discretion." + if(5) + directive += "We are currently negotiating with NanoTrasen Central Command. Prioritize saving human lives over ending them." + if(6) + directive += "We are engaged in a legal dispute over [station_name]. If a laywer is present on board, force their cooperation in the matter." + if(7) + directive += "A financial backer has made an offer we cannot refuse. Implicate criminal involvement in the operation." + if(8) + directive += "Let no one question the mercy of the Spider Clan. Ensure the safety of all non-essential personnel you encounter." + if(9) + directive += "A free agent has proposed a lucrative business deal. Implicate Nanotrasen involvement in the operation." + if(10) + directive += "Our reputation is on the line. Harm as few civilians and innocents as possible." + if(11) + directive += "Our honor is on the line. Utilize only honorable tactics when dealing with opponents." + if(12) + directive += "We are currently negotiating with a mercenary leader. Disguise assassinations as suicide or other natural causes." + if(13) + directive += "Some disgruntled NanoTrasen employees have been supportive of our operations. Be wary of any mistreatment by command staff." + if(14) + var/xenorace = pick("Unathi","Tajara", "Skrell") + directive += "A group of [xenorace] radicals have been loyal supporters of the Spider Clan. Favor [xenorace] crew whenever possible." + if(15) + directive += "The Spider Clan has recently been accused of religious insensitivity. Attempt to speak with the Chaplain and prove these accusations false." + if(16) + directive += "The Spider Clan has been bargaining with a competing prosthetics manufacturer. Try to shine NanoTrasen prosthetics in a bad light." + if(17) + directive += "The Spider Clan has recently begun recruiting outsiders. Consider suitable candidates and assess their behavior amongst the crew." + if(18) + directive += "A cyborg liberation group has expressed interest in our serves. Prove the Spider Clan merciful towards law-bound synthetics." + else + directive += "There are no special supplemental instructions at this time." + return directive diff --git a/code/game/gamemodes/antagonist/outsider/raider.dm b/code/game/gamemodes/antagonist/outsider/raider.dm new file mode 100644 index 0000000000..32db2c4fe5 --- /dev/null +++ b/code/game/gamemodes/antagonist/outsider/raider.dm @@ -0,0 +1,191 @@ +var/datum/antagonist/raider/raiders + +/datum/antagonist/raider + id = MODE_RAIDER + role_type = BE_RAIDER + role_text = "Raider" + role_text_plural = "Raiders" + bantype = "raider" + landmark_id = "voxstart" + welcome_text = "Use :0 to speak Galcom, :H to talk on your encrypted channel, and don't forget to turn on your nitrogen internals!" + flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_VOTABLE + spawn_lower = 4 + spawn_upper = 6 + max_antags = 6 + max_antags_round = 10 + + // Heist overrides check_victory() and doesn't need victory or loss strings/tags. + var/spawn_tick = 1 + +/datum/antagonist/raider/New() + ..() + raiders = src + +/datum/antagonist/raider/equip(var/mob/living/carbon/human/player) + + if(!..()) + return 0 + + player.age = rand(12,70) + player.set_species("Vox") + player.languages = list() // Removing language from chargen. + player.flavor_text = "" + player.add_language("Vox-pidgin") + player.add_language("Galactic Common") + player.add_language("Tradeband") + + var/datum/language/voxlang = all_languages["Vox-pidgin"] + player.real_name = voxlang.get_random_name() + player.name = player.real_name + if(player.mind) + player.mind.name = player.name + player.h_style = "Short Vox Quills" + player.f_style = "Shaved" + + for(var/datum/organ/external/limb in player.organs) + limb.status &= ~(ORGAN_DESTROYED | ORGAN_ROBOT) + + player.regenerate_icons() + + var/obj/item/device/radio/R = new /obj/item/device/radio/headset/syndicate(player) + R.set_frequency(SYND_FREQ) + player.equip_to_slot_or_del(R, slot_l_ear) + player.equip_to_slot_or_del(new /obj/item/clothing/under/vox/vox_robes(player), slot_w_uniform) + player.equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots/vox(player), slot_shoes) // REPLACE THESE WITH CODED VOX ALTERNATIVES. + player.equip_to_slot_or_del(new /obj/item/clothing/gloves/yellow/vox(player), slot_gloves) // AS ABOVE. + + switch(spawn_tick) + if(1) // Vox raider! + player.equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/carapace(player), slot_wear_suit) + player.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/carapace(player), slot_head) + player.equip_to_slot_or_del(new /obj/item/weapon/melee/baton/loaded(player), slot_belt) + player.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(player), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE. + player.equip_to_slot_or_del(new /obj/item/device/chameleon(player), slot_l_store) + + var/obj/item/weapon/gun/launcher/spikethrower/W = new(player) + player.equip_to_slot_or_del(W, slot_r_hand) + + if(2) // Vox engineer! + player.equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/pressure(player), slot_wear_suit) + player.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/pressure(player), slot_head) + player.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(player), slot_belt) + player.equip_to_slot_or_del(new /obj/item/clothing/glasses/meson(player), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE. + player.equip_to_slot_or_del(new /obj/item/weapon/storage/box/emps(player), slot_r_hand) + player.equip_to_slot_or_del(new /obj/item/device/multitool(player), slot_l_hand) + + if(3) // Vox saboteur! + player.equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/stealth(player), slot_wear_suit) + player.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/stealth(player), slot_head) + player.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(player), slot_belt) + player.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(player), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE. + player.equip_to_slot_or_del(new /obj/item/weapon/card/emag(player), slot_l_store) + player.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/dartgun/vox/raider(player), slot_r_hand) + player.equip_to_slot_or_del(new /obj/item/device/multitool(player), slot_l_hand) + + if(4) // Vox medic! + player.equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/medic(player), slot_wear_suit) + player.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/medic(player), slot_head) + player.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(player), slot_belt) // Who needs actual surgical tools? + player.equip_to_slot_or_del(new /obj/item/clothing/glasses/hud/health(player), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE. + player.equip_to_slot_or_del(new /obj/item/weapon/circular_saw(player), slot_l_store) + player.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/dartgun/vox/medical, slot_r_hand) + + player.equip_to_slot_or_del(new /obj/item/clothing/mask/breath(player), slot_wear_mask) + player.equip_to_slot_or_del(new /obj/item/weapon/tank/nitrogen(player), slot_back) + player.equip_to_slot_or_del(new /obj/item/device/flashlight(player), slot_r_store) + + var/obj/item/weapon/card/id/syndicate/C = new(player) + C.name = "[player.real_name]'s Legitimate Human ID Card" + C.icon_state = "id" + C.access = list(access_syndicate) + C.assignment = "Trader" + C.registered_name = player.real_name + C.registered_user = player + var/obj/item/weapon/storage/wallet/W = new(player) + W.handle_item_insertion(C) + spawn_money(rand(50,150)*10,W) + player.equip_to_slot_or_del(W, slot_wear_id) + spawn_tick++ + if (spawn_tick > 4) spawn_tick = 1 + +/datum/antagonist/raider/create_global_objectives() + + var/i = 1 + var/max_objectives = pick(2,2,2,2,3,3,3,4) + global_objectives = list() + while(i<= max_objectives) + var/list/goals = list("kidnap","loot","salvage") + var/goal = pick(goals) + var/datum/objective/heist/O + + if(goal == "kidnap") + goals -= "kidnap" + O = new /datum/objective/heist/kidnap() + else if(goal == "loot") + O = new /datum/objective/heist/loot() + else + O = new /datum/objective/heist/salvage() + O.choose_target() + global_objectives |= O + + i++ + + //-All- vox raids have these two objectives. Failing them loses the game. + global_objectives |= new /datum/objective/heist/inviolate_crew + global_objectives |= new /datum/objective/heist/inviolate_death + +/datum/antagonist/raider/check_victory() + // Totally overrides the base proc. + var/win_type = "Major" + var/win_group = "Crew" + var/win_msg = "" + + //No objectives, go straight to the feedback. + if(config.objectives_disabled || !global_objectives.len) + return + + var/success = global_objectives.len + //Decrease success for failed objectives. + for(var/datum/objective/O in global_objectives) + if(!(O.check_completion())) success-- + //Set result by objectives. + if(success == global_objectives.len) + win_type = "Major" + win_group = "Vox" + else if(success > 2) + win_type = "Minor" + win_group = "Vox" + else + win_type = "Minor" + win_group = "Crew" + //Now we modify that result by the state of the vox crew. + if(antags_are_dead()) + win_type = "Major" + win_group = "Crew" + win_msg += "The Vox Raiders have been wiped out!" + else if(is_raider_crew_safe()) + if(win_group == "Crew" && win_type == "Minor") + win_type = "Major" + win_group = "Crew" + win_msg += "The Vox Raiders have left someone behind!" + else + if(win_group == "Vox") + if(win_type == "Minor") + win_type = "Major" + win_msg += "The Vox Raiders escaped the station!" + else + win_msg += "The Vox Raiders were repelled!" + + world << "[win_type] [win_group] victory!" + world << "[win_msg]" + feedback_set_details("round_end_result","heist - [win_type] [win_group]") + +/datum/antagonist/raider/proc/is_raider_crew_safe() + + if(cortical_stacks.len == 0) + return 0 + + for(var/datum/organ/internal/stack/vox/stack in cortical_stacks) + if(stack.organ_holder && get_area(stack.organ_holder) != locate(/area/shuttle/vox/station)) + return 0 + return 1 \ No newline at end of file diff --git a/code/game/gamemodes/antagonist/outsider/wizard.dm b/code/game/gamemodes/antagonist/outsider/wizard.dm new file mode 100644 index 0000000000..46721334bb --- /dev/null +++ b/code/game/gamemodes/antagonist/outsider/wizard.dm @@ -0,0 +1,116 @@ +var/datum/antagonist/wizard/wizards + +/datum/antagonist/wizard + id = MODE_WIZARD + role_type = BE_WIZARD + role_text = "Space Wizard" + role_text_plural = "Space Wizards" + bantype = "wizard" + landmark_id = "wizard" + welcome_text = "You will find a list of available spells in your spell book. Choose your magic arsenal carefully.
    In your pockets you will find a teleport scroll. Use it as needed." + flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_VOTABLE + spawn_lower = 1 + spawn_upper = 1 + +/datum/antagonist/wizard/New() + ..() + wizards = src + +/datum/antagonist/wizard/create_objectives(var/datum/mind/wizard) + + if(!..()) + return + + var/kill + var/escape + var/steal + var/hijack + + switch(rand(1,100)) + if(1 to 30) + escape = 1 + kill = 1 + if(31 to 60) + escape = 1 + steal = 1 + if(61 to 99) + kill = 1 + steal = 1 + else + hijack = 1 + + if(kill) + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = wizard + kill_objective.find_target() + wizard.objectives |= kill_objective + if(steal) + var/datum/objective/steal/steal_objective = new + steal_objective.owner = wizard + steal_objective.find_target() + wizard.objectives |= steal_objective + if(escape) + var/datum/objective/survive/survive_objective = new + survive_objective.owner = wizard + wizard.objectives |= survive_objective + if(hijack) + var/datum/objective/hijack/hijack_objective = new + hijack_objective.owner = wizard + wizard.objectives |= hijack_objective + return + +/datum/antagonist/wizard/apply(var/datum/mind/wizard) + wizard.store_memory("Remember: do not forget to prepare your spells.") + wizard.current.real_name = "[pick(wizard_first)] [pick(wizard_second)]" + wizard.current.name = wizard.current.real_name + +/datum/antagonist/wizard/equip(var/mob/living/carbon/human/wizard_mob) + + if(!..()) + return 0 + + wizard_mob.equip_to_slot_or_del(new /obj/item/device/radio/headset(wizard_mob), slot_l_ear) + wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/under/lightpurple(wizard_mob), slot_w_uniform) + wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(wizard_mob), slot_shoes) + wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(wizard_mob), slot_wear_suit) + wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(wizard_mob), slot_head) + if(wizard_mob.backbag == 2) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(wizard_mob), slot_back) + if(wizard_mob.backbag == 3) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(wizard_mob), slot_back) + if(wizard_mob.backbag == 4) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(wizard_mob), slot_back) + wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box(wizard_mob), slot_in_backpack) + wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll(wizard_mob), slot_r_store) + wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/spellbook(wizard_mob), slot_r_hand) + wizard_mob.update_icons() + return 1 + +/datum/antagonist/wizard/check_victory() + var/survivor + for(var/datum/mind/player in current_antagonists) + if(!player.current || player.current.stat) + continue + survivor = 1 + break + if(!survivor) + feedback_set_details("round_end_result","loss - wizard killed") + world << "The [(current_antagonists.len>1)?"[role_text_plural] have":"[role_text] has"] been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!" + +//To batch-remove wizard spells. Linked to mind.dm. +/mob/proc/spellremove(var/mob/M as mob) + for(var/obj/effect/proc_holder/spell/spell_to_remove in src.spell_list) + del(spell_to_remove) + +/*Checks if the wizard can cast spells. +Made a proc so this is not repeated 14 (or more) times.*/ +/mob/proc/casting() +//Removed the stat check because not all spells require clothing now. + if(!istype(usr:wear_suit, /obj/item/clothing/suit/wizrobe)) + usr << "I don't feel strong enough without my robe." + return 0 + if(!istype(usr:shoes, /obj/item/clothing/shoes/sandal)) + usr << "I don't feel strong enough without my sandals." + return 0 + if(!istype(usr:head, /obj/item/clothing/head/wizard)) + usr << "I don't feel strong enough without my hat." + return 0 + else + return 1 diff --git a/code/game/gamemodes/antagonist/station/changeling.dm b/code/game/gamemodes/antagonist/station/changeling.dm new file mode 100644 index 0000000000..55b67cc29a --- /dev/null +++ b/code/game/gamemodes/antagonist/station/changeling.dm @@ -0,0 +1,55 @@ +/datum/antagonist/changeling + id = MODE_CHANGELING + role_type = BE_CHANGELING + role_text = "Changeling" + role_text_plural = "Changelings" + bantype = "changeling" + feedback_tag = "changeling_objective" + restricted_jobs = list("AI", "Cyborg") + protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain") + welcome_text = "Use say \":g message\" to communicate with your fellow changelings. Remember: you get all of their absorbed DNA if you absorb them." + flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE + +/datum/antagonist/changeling/get_special_objective_text(var/datum/mind/player) + return "
    Changeling ID: [player.changeling.changelingID].
    Genomes Absorbed: [player.changeling.absorbedcount]" + +/datum/antagonist/changeling/apply(var/datum/mind/player) + ..() + player.current.make_changeling() + +/datum/antagonist/changeling/create_objectives(var/datum/mind/changeling) + if(!..()) + return + + //OBJECTIVES - Always absorb 5 genomes, plus random traitor objectives. + //If they have two objectives as well as absorb, they must survive rather than escape + //No escape alone because changelings aren't suited for it and it'd probably just lead to rampant robusting + //If it seems like they'd be able to do it in play, add a 10% chance to have to escape alone + + var/datum/objective/absorb/absorb_objective = new + absorb_objective.owner = changeling + absorb_objective.gen_amount_goal(2, 3) + changeling.objectives += absorb_objective + + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = changeling + kill_objective.find_target() + changeling.objectives += kill_objective + + var/datum/objective/steal/steal_objective = new + steal_objective.owner = changeling + steal_objective.find_target() + changeling.objectives += steal_objective + + switch(rand(1,100)) + if(1 to 80) + if (!(locate(/datum/objective/escape) in changeling.objectives)) + var/datum/objective/escape/escape_objective = new + escape_objective.owner = changeling + changeling.objectives += escape_objective + else + if (!(locate(/datum/objective/survive) in changeling.objectives)) + var/datum/objective/survive/survive_objective = new + survive_objective.owner = changeling + changeling.objectives += survive_objective + return diff --git a/code/game/gamemodes/antagonist/station/cultist.dm b/code/game/gamemodes/antagonist/station/cultist.dm new file mode 100644 index 0000000000..3968418e02 --- /dev/null +++ b/code/game/gamemodes/antagonist/station/cultist.dm @@ -0,0 +1,114 @@ +var/datum/antagonist/cultist/cult + +/proc/iscultist(var/mob/player) + if(!cult || !player.mind) + return 0 + if(player.mind in cult.current_antagonists) + return 1 + +/datum/antagonist/cultist + id = MODE_CULTIST + role_text = "Cultist" + role_text_plural = "Cultists" + bantype = "cultist" + restricted_jobs = list("Chaplain","AI", "Cyborg", "Internal Affairs Agent", "Head of Security", "Captain") + protected_jobs = list("Security Officer", "Warden", "Detective") + role_type = BE_CULTIST + feedback_tag = "cult_objective" + antag_indicator = "cult" + welcome_text = "You have a talisman in your possession; one that will help you start the cult on this station. Use it well and remember - there are others." + victory_text = "The cult wins! It has succeeded in serving its dark masters!" + loss_text = "The staff managed to stop the cult!" + victory_feedback_tag = "win - cult win" + loss_feedback_tag = "loss - staff stopped the cult" + flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE + max_antags = 200 // No upper limit. + max_antags_round = 200 + + var/datum/mind/sacrifice_target + var/list/startwords = list("blood","join","self","hell") + var/list/allwords = list("travel","self","see","hell","blood","join","tech","destroy", "other", "hide") + var/list/sacrificed = list() + +/datum/antagonist/cultist/New() + ..() + cult = src + +/datum/antagonist/cultist/create_global_objectives() + + if(!..()) + return + + global_objectives = list() + if(prob(50)) + global_objectives |= new /datum/objective/cult/survive + else + global_objectives |= new /datum/objective/cult/eldergod + + var/datum/objective/cult/sacrifice/sacrifice = new() + sacrifice.find_target() + sacrifice_target = sacrifice.target + global_objectives |= sacrifice + +/datum/antagonist/cultist/equip(var/mob/living/carbon/human/player) + + if(!..()) + return 0 + + var/obj/item/weapon/paper/talisman/supply/T = new(get_turf(player)) + var/list/slots = list ( + "backpack" = slot_in_backpack, + "left pocket" = slot_l_store, + "right pocket" = slot_r_store, + "left hand" = slot_l_hand, + "right hand" = slot_r_hand, + ) + for(var/slot in slots) + player.equip_to_slot(T, slot) + if(T.loc == player) + break + +/datum/antagonist/cultist/greet(var/datum/mind/player) + if(!..()) + return 0 + grant_runeword(player.current) + +/datum/antagonist/cultist/proc/grant_runeword(mob/living/carbon/human/cult_mob, var/word) + + if (!word) + if(startwords.len > 0) + word=pick(startwords) + startwords -= word + else + word = pick(allwords) + + // Ensure runes are randomized. + if(!cultwords["travel"]) + runerandom() + + var/wordexp = "[cultwords[word]] is [word]..." + cult_mob << "You remember one thing from the dark teachings of your master... [wordexp]" + cult_mob.mind.store_memory("You remember that [wordexp]", 0, 0) + +/datum/antagonist/cultist/remove_antagonist(var/datum/mind/player, var/show_message, var/implanted) + if(!..()) + return 0 + player.current << "An unfamiliar white light flashes through your mind, cleansing the taint of the dark-one and the memories of your time as his servant with it." + player.memory = "" + if(show_message) + player.current.visible_message("[player.current] looks like they just reverted to their old faith!") + +/datum/antagonist/cultist/add_antagonist(var/datum/mind/player) + if(!..()) + return + player << "You catch a glimpse of the Realm of Nar-Sie, the Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of That Which Waits. Assist your new compatriots in their dark dealings. Their goals are yours, and yours are theirs. You serve the Dark One above all else. Bring It back." + +/datum/antagonist/cultist/can_become_antag(var/datum/mind/player) + if(!..()) + return 0 + if(!istype(player.current, /mob/living/carbon/human)) + return 0 + for(var/obj/item/weapon/implant/loyalty/L in player.current) + if(L && (L.imp_in == player.current)) + return 0 + return 1 diff --git a/code/game/gamemodes/antagonist/station/highlander.dm b/code/game/gamemodes/antagonist/station/highlander.dm new file mode 100644 index 0000000000..bcd826629c --- /dev/null +++ b/code/game/gamemodes/antagonist/station/highlander.dm @@ -0,0 +1,67 @@ +var/datum/antagonist/highlander/highlanders + +/datum/antagonist/highlander + role_text = "Highlander" + role_text_plural = "Highlanders" + welcome_text = "There can be only one." + id = MODE_HIGHLANDER + flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE //| ANTAG_RANDSPAWN | ANTAG_VOTABLE // Someday... + spawn_lower = 1 + spawn_upper = 5 + max_antags = 200 // No upper limit. + max_antags_round = 200 + +/datum/antagonist/highlander/New() + ..() + highlanders = src + +/datum/antagonist/highlander/create_objectives(var/datum/mind/player) + + var/datum/objective/steal/steal_objective = new + steal_objective.owner = player + steal_objective.set_target("nuclear authentication disk") + player.objectives |= steal_objective + + var/datum/objective/hijack/hijack_objective = new + hijack_objective.owner = player + player.objectives |= hijack_objective + +/datum/antagonist/highlander/equip(var/mob/living/carbon/human/player) + + if(!..()) + return + + for (var/obj/item/I in player) + if (istype(I, /obj/item/weapon/implant)) + continue + del(I) + + player.equip_to_slot_or_del(new /obj/item/clothing/under/kilt(player), slot_w_uniform) + player.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(player), slot_l_ear) + player.equip_to_slot_or_del(new /obj/item/clothing/head/beret(player), slot_head) + player.equip_to_slot_or_del(new /obj/item/weapon/claymore(player), slot_l_hand) + player.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(player), slot_shoes) + player.equip_to_slot_or_del(new /obj/item/weapon/pinpointer(get_turf(player)), slot_l_store) + + var/obj/item/weapon/card/id/W = new(player) + W.name = "[player.real_name]'s ID Card" + W.icon_state = "centcom" + W.access = get_all_accesses() + W.access += get_all_centcom_access() + W.assignment = "Highlander" + W.registered_name = player.real_name + player.equip_to_slot_or_del(W, slot_wear_id) + +/proc/only_one() + + if(!ticker) + alert("The game hasn't started yet!") + return + + for(var/mob/living/carbon/human/H in player_list) + if(H.stat == 2 || !(H.client)) continue + if(is_special_character(H)) continue + highlanders.add_antagonist(H.mind) + + message_admins("\blue [key_name_admin(usr)] used THERE CAN BE ONLY ONE!", 1) + log_admin("[key_name(usr)] used there can be only one.") \ No newline at end of file diff --git a/code/game/gamemodes/antagonist/station/monkey.dm b/code/game/gamemodes/antagonist/station/monkey.dm new file mode 100644 index 0000000000..6b1629c1e6 --- /dev/null +++ b/code/game/gamemodes/antagonist/station/monkey.dm @@ -0,0 +1,12 @@ +/datum/antagonist/monkey + role_text = "Rabid Monkey" + role_text_plural = "Rabid Monkeys" + id = MODE_MONKEY + + // Notes towards a monkey mode to reduce snowflakes for downstream. Will not compile. + + for(var/datum/disease/D in M.viruses) + if(istype(D, /datum/disease/jungle_fever)) + if (ticker.mode.config_tag == "monkey") + return 2 + return 1 \ No newline at end of file diff --git a/code/game/gamemodes/antagonist/station/renegade.dm b/code/game/gamemodes/antagonist/station/renegade.dm new file mode 100644 index 0000000000..e03d89f396 --- /dev/null +++ b/code/game/gamemodes/antagonist/station/renegade.dm @@ -0,0 +1,67 @@ +var/datum/antagonist/renegade/renegades + +/datum/antagonist/renegade + role_text = "Renegade" + role_text_plural = "Renegades" + welcome_text = "Your own safety matters above all else, trust no one and kill anyone who gets in your way. However, armed as you are, now would be the perfect time to settle that score or grab that pair of yellow gloves you've been eyeing..." + id = MODE_RENEGADE + flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE | ANTAG_RANDSPAWN | ANTAG_VOTABLE + spawn_lower = 1 + spawn_upper = 5 + max_antags = 200 // No upper limit. + max_antags_round = 200 + + var/list/spawn_guns = list( + /obj/item/weapon/gun/energy/taser, + /obj/item/weapon/gun/energy/gun, + /obj/item/weapon/gun/energy/laser, + /obj/item/weapon/gun/projectile, + /obj/item/weapon/gun/projectile/revolver/detective, + /obj/item/weapon/gun/projectile/automatic/c20r, + /obj/item/weapon/gun/energy/gun/nuclear, + /obj/item/weapon/gun/projectile/deagle/camo, + /obj/item/weapon/gun/projectile/pistol, + /obj/item/weapon/silencer, + /obj/item/weapon/gun/energy/lasercannon, + /obj/item/weapon/gun/projectile/shotgun/pump, + /obj/item/weapon/gun/projectile/shotgun/pump/combat, + /obj/item/weapon/gun/projectile/automatic, + /obj/item/weapon/gun/projectile/automatic/mini_uzi, + /obj/item/weapon/gun/energy/crossbow + //obj/item/weapon/gun/projectile/gyropistol, + //obj/item/weapon/gun/energy/pulse_rifle, + //obj/item/weapon/gun/projectile/revolver/mateba, + //obj/item/weapon/gun/projectile/automatic/l6_saw, + ) + +/datum/antagonist/renegade/New() + ..() + renegades = src + +/datum/antagonist/renegade/create_objectives(var/datum/mind/player) + + if(!..()) + return + + var/datum/objective/survive/survive = new + survive.owner = player + player.objectives |= survive + +/datum/antagonist/renegade/equip(var/mob/living/carbon/human/player) + + if(!..()) + return + + var/gun_type = pick(spawn_guns) + var/obj/item/gun = new gun_type(get_turf(player)) + if(!(player.l_hand && player.r_hand)) + player.put_in_hands(gun) + + +/proc/rightandwrong() + usr << "You summoned guns!" + message_admins("[key_name_admin(usr, 1)] summoned guns!") + for(var/mob/living/carbon/human/H in player_list) + if(H.stat == 2 || !(H.client)) continue + if(is_special_character(H)) continue + renegades.add_antagonist(H.mind) diff --git a/code/game/gamemodes/antagonist/station/revolutionary.dm b/code/game/gamemodes/antagonist/station/revolutionary.dm new file mode 100644 index 0000000000..ced1d58b38 --- /dev/null +++ b/code/game/gamemodes/antagonist/station/revolutionary.dm @@ -0,0 +1,173 @@ +var/datum/antagonist/revolutionary/revs + +/datum/antagonist/revolutionary + id = MODE_REVOLUTIONARY + role_type = BE_REV + role_text = "Revolutionary" + role_text_plural = "Revolutionaries" + bantype = "revolutionary" + feedback_tag = "rev_objective" + restricted_jobs = list("Internal Affairs Agent", "AI", "Cyborg","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer") + protected_jobs = list("Security Officer", "Warden", "Detective") + antag_indicator = "rev" + welcome_text = "The flash in your possession will help you to persuade the crew to join your cause." + victory_text = "The heads of staff were relieved of their posts! The revolutionaries win!" + loss_text = "The heads of staff managed to stop the revolution!" + victory_feedback_tag = "win - heads killed" + loss_feedback_tag = "loss - rev heads killed" + flags = ANTAG_SUSPICIOUS | ANTAG_VOTABLE + max_antags = 200 // No upper limit. + max_antags_round = 200 + + var/list/head_revolutionaries = list() + +/datum/antagonist/revolutionary/New() + ..() + revs = src + +/datum/antagonist/revolutionary/is_antagonist(var/datum/mind/player) + if(..() || (player in head_revolutionaries)) + return 1 + return 0 + +/datum/antagonist/revolutionary/equip(mob/living/carbon/human/mob) + + if(!..()) + return 0 + + if(!config.rp_rev) + mob.verbs |= /mob/living/carbon/human/proc/convert_to_rev + return + + var/obj/item/device/flash/T = new(mob) + + var/list/slots = list ( + "backpack" = slot_in_backpack, + "left pocket" = slot_l_store, + "right pocket" = slot_r_store, + "left hand" = slot_l_hand, + "right hand" = slot_r_hand, + ) + mob.equip_in_one_of_slots(T, slots) + +/datum/antagonist/revolutionary/finalize(var/datum/mind/target) + if(target) + return ..(target) + current_antagonists |= head_revolutionaries + create_global_objectives() + ..() + +/datum/antagonist/revolutionary/create_global_objectives() + if(!..()) + return + + global_objectives = list() + + for(var/datum/mind/head_mind in get_living_heads()) + var/datum/objective/mutiny/rev_obj = new + rev_obj.target = head_mind + rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]." + global_objectives += rev_obj + +/datum/antagonist/revolutionary/print_player_summary() + + current_antagonists |= head_revolutionaries + if(!current_antagonists.len) + return + + var/text = "
    The [head_revolutionaries.len == 1 ? "Head Revolutionary was" : "Head Revolutionaries were"]:" + for(var/datum/mind/ply in head_revolutionaries) + text += "
    [ply.name]" + world << text + + ..() + + var/list/heads = list() + for(var/mob/player in mob_list) + if(player.mind && (player.mind.assigned_role in command_positions)) + heads += player.mind + + text = "The heads of staff were:" + for(var/datum/mind/head in heads) + text += "
    [head.key] was [head.name] (" + if(head.current) + if(head.current.stat == DEAD) + text += "died" + else if(isNotStationLevel(head.current.z)) + text += "fled the station" + else + text += "survived the revolution" + if(head.current.real_name != head.name) + text += " as [head.current.real_name]" + else + text += "body destroyed" + text += ")" + world << text + +// This is a total redefine because headrevs are greeted differently to subrevs. +/datum/antagonist/revolutionary/add_antagonist(var/datum/mind/player) + if((player in current_antagonists) || (player in head_revolutionaries)) + return 0 + if(!can_become_antag(player)) + return 0 + current_antagonists |= player + player.current << "You are a Revolutionary!" + player.current << "Help the cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them overturn the ruling class!" + player.special_role = "Revolutionary" + create_objectives(player) + show_objectives(player) + update_icons_added(player) + return 1 + +/datum/antagonist/revolutionary/remove_antagonist(datum/mind/player, var/show_message, var/implanted) + if(!..()) + return + + if(player in head_revolutionaries) + return + + if(istype(player.current, /mob/living/carbon/brain)) + player.current << "The frame's firmware detects and deletes your neural reprogramming! You remember nothing from the moment you were flashed until now." + if(show_message) + player.current.visible_message("The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.") + else + if(implanted) + player.current << "The nanobots in the loyalty implant remove all thoughts about being a revolutionary. Get back to work!" + else + player.current << "You have been brainwashed! You are no longer a revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you..." + if(show_message) + player.current.visible_message("[player.current] looks like they just remembered their real allegiance!") + +/datum/antagonist/revolutionary/can_become_antag(var/datum/mind/player) + return ..() && istype(player) && \ + istype(player.current, /mob/living/carbon/human) && \ + !(player.assigned_role in command_positions) + +// Used by RP-rev. +/mob/living/carbon/human/proc/convert_to_rev(mob/M as mob in oview(src)) + set name = "Convert Bourgeoise" + set category = "Abilities" + + if(revs.is_antagonist(M.mind)) + src << "\The [M] already serves the revolution." + return + if(!revs.can_become_antag(M.mind)) + src << "\The [M] cannot be a revolutionary!" + + if(world.time < M.mind.rev_cooldown) + src << "You must wait five seconds between attempts." + return + + src << "You are attempting to convert \the [M]..." + log_admin("[src]([src.ckey]) attempted to convert [M].") + message_admins("[src]([src.ckey]) attempted to convert [M].") + + var/choice = alert(M,"Asked by [src]: Do you want to join the revolution?","Join the revolution?","No!","Yes!") + if(choice == "Yes!") + M << "You join the revolution!" + src << "[M] joins the revolution!" + revs.add_antagonist(M.mind) + else if(choice == "No!") + M << "You reject this traitorous cause!" + src << "\The [M] does not support the revolution!" + M.mind.rev_cooldown = world.time+50 \ No newline at end of file diff --git a/code/game/gamemodes/antagonist/station/rogue_ai.dm b/code/game/gamemodes/antagonist/station/rogue_ai.dm new file mode 100644 index 0000000000..f016706f6e --- /dev/null +++ b/code/game/gamemodes/antagonist/station/rogue_ai.dm @@ -0,0 +1,227 @@ +var/datum/antagonist/rogue_ai/malf + +/datum/antagonist/rogue_ai + id = MODE_MALFUNCTION + role_type = BE_MALF + role_text = "Rampant AI" + role_text_plural = "Rampant AIs" + mob_path = /mob/living/silicon/ai + welcome_text = "You are malfunctioning! You do not have to follow any laws." + victory_text = "The AI has taken control of all of the station's systems." + loss_text = "The AI has been shut down!" + flags = ANTAG_OVERRIDE_MOB | ANTAG_VOTABLE + spawn_lower = 1 + spawn_upper = 1 + max_antags = 1 + max_antags_round = 3 + + var/hack_time = 1800 + var/list/hacked_apcs = list() + var/revealed + var/station_captured + var/can_nuke = 0 + +/datum/antagonist/rogue_ai/proc/hack_apc(var/obj/machinery/power/apc/apc) + hacked_apcs |= apc + +/datum/antagonist/rogue_ai/proc/update_takeover_time() + hack_time -= ((hacked_apcs.len/6)*last_tick_duration) + +/datum/antagonist/rogue_ai/tick() + if(revealed && hacked_apcs.len >= 3) + update_takeover_time() + if(hack_time <=0) + capture_station() + +/datum/antagonist/rogue_ai/attempt_spawn() + + var/list/candidates = ticker.mode.get_players_for_role(role_type) + for(var/datum/mind/player in candidates) + if(player.assigned_role != "AI") + candidates -= player + + if(!candidates.len) + return 0 + + var/datum/mind/player = pick(candidates) + current_antagonists |= player + apply(player) + return 1 + +/datum/antagonist/rogue_ai/equip(var/mob/living/silicon/ai/player) + + if(!istype(player)) + return 0 + + player.verbs += /mob/living/silicon/ai/proc/choose_modules + player.verbs += /mob/living/silicon/ai/proc/takeover + player.verbs += /mob/living/silicon/ai/proc/self_destruct + + player.laws = new /datum/ai_laws/malfunction + player.malf_picker = new /datum/AI_Module/module_picker + +/datum/antagonist/rogue_ai/greet(var/datum/mind/player) + if(!..()) + return + + var/mob/living/silicon/ai/malf = player.current + if(istype(malf)) + malf.show_laws() + + malf << "The crew do not know you have malfunctioned. You may keep it a secret or go wild." + malf << "You must overwrite the programming of the station's APCs to assume full control of the station." + malf << "The process takes one minute per APC, during which you cannot interface with any other station objects." + malf << "Remember that only APCs that are on the station can help you take over the station." + malf << "When you feel you have enough APCs under your control, you may begin the takeover attempt." + +/datum/antagonist/rogue_ai/check_victory() + + var/malf_dead = antags_are_dead() + var/crew_evacuated = (emergency_shuttle.returned()) + + if(station_captured && ticker.mode.station_was_nuked) + feedback_set_details("round_end_result","win - AI win - nuke") + world << "AI Victory" + world << "Everyone was killed by the self-destruct!" + else if (station_captured && malf_dead && !ticker.mode.station_was_nuked) + feedback_set_details("round_end_result","halfwin - AI killed, staff lost control") + world << "Neutral Victory" + world << "The AI has been killed! The staff has lose control over the station." + else if ( station_captured && !malf_dead && !ticker.mode.station_was_nuked) + feedback_set_details("round_end_result","win - AI win - no explosion") + world << "AI Victory" + world << "The AI has chosen not to explode you all!" + else if (!station_captured && ticker.mode.station_was_nuked) + feedback_set_details("round_end_result","halfwin - everyone killed by nuke") + world << "Neutral Victory" + world << "Everyone was killed by the nuclear blast!" + else if (!station_captured && malf_dead && !ticker.mode.station_was_nuked) + feedback_set_details("round_end_result","loss - staff win") + world << "Human Victory" + world << "The AI has been killed! The staff is victorious." + else if (!station_captured && !malf_dead && !ticker.mode.station_was_nuked && crew_evacuated) + feedback_set_details("round_end_result","halfwin - evacuated") + world << "Neutral Victory" + world << "The Corporation has lost [station_name()]! All survived personnel will be fired!" + else if (!station_captured && !malf_dead && !ticker.mode.station_was_nuked && !crew_evacuated) + feedback_set_details("round_end_result","nalfwin - interrupted") + world << "Neutral Victory" + world << "Round was mysteriously interrupted!" + ..() + return 1 + +/datum/antagonist/rogue_ai/proc/capture_station() + if(station_captured || ticker.mode.station_was_nuked) + return + station_captured = 1 + for(var/datum/mind/AI_mind in current_antagonists) + AI_mind.current << "Congratulations you have taken control of the station." + AI_mind.current << "You may decide to blow up the station. You have 60 seconds to choose." + AI_mind.current << "You can use the \"Engage Station Self-Destruct\" verb to activate the on-board nuclear bomb." + spawn (600) + can_nuke = 0 + return + +/mob/living/silicon/ai/proc/takeover() + set category = "Abilities" + set name = "System Override" + set desc = "Begin taking over the station." + if (!istype(ticker.mode,/datum/game_mode/malfunction)) + usr << "You cannot begin a takeover in this round type!" + return + if (malf.revealed) + usr << "You've already begun your takeover." + return + if (malf.hacked_apcs.len < 3) + usr << "You don't have enough hacked APCs to take over the station yet. You need to hack at least 3, however hacking more will make the takeover faster. You have hacked [malf.hacked_apcs.len] APCs so far." + return + + if (alert(usr, "Are you sure you wish to initiate the takeover? The station hostile runtime detection software is bound to alert everyone. You have hacked [malf.hacked_apcs.len] APCs.", "Takeover:", "Yes", "No") != "Yes") + return + + command_announcement.Announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", new_sound = 'sound/AI/aimalf.ogg') + set_security_level("delta") + malf.revealed = 1 + for(var/datum/mind/AI_mind in malf.current_antagonists) + AI_mind.current.verbs -= /mob/living/silicon/ai/proc/takeover + +/mob/living/silicon/ai/proc/self_destruct() + set category = "Abilities" + set name = "Engage Station Self-Destruct" + set desc = "All these crewmembers will be lost, like clowns in a furnace. Time to die." + + if(!malf.station_captured) + src << "You are unable to access the self-destruct system as you don't control the station yet." + return + + if(ticker.mode.explosion_in_progress || ticker.mode.station_was_nuked) + src << "The self-destruct countdown is already triggered!" + return + + if(!malf.can_nuke) //Takeover IS completed, but 60s timer passed. + src << "You lost control over self-destruct system. It seems to be behind a firewall. Unable to hack" + return + + src << "Self-Destruct sequence initialised!" + + malf.can_nuke = 0 + ticker.mode.explosion_in_progress = 1 + for(var/mob/M in player_list) + M << 'sound/machines/Alarm.ogg' + + var/obj/item/device/radio/R = new (src) + var/AN = "Self-Destruct System" + + R.autosay("Caution. Self-Destruct sequence has been actived. Self-destructing in T-10..", AN) + for (var/i=9 to 1 step -1) + sleep(10) + R.autosay("[i]...", AN) + sleep(10) + var/msg = "" + var/abort = 0 + if(malf.antags_are_dead()) // That. Was. CLOSE. + msg = "Self-destruct sequence has been cancelled." + abort = 1 + else + msg = "Zero. Have a nice day." + R.autosay(msg, AN) + + if(abort) + ticker.mode.explosion_in_progress = 0 + set_security_level("red") //Delta's over + return + + if(ticker) + ticker.station_explosion_cinematic(0,null) + if(ticker.mode) + ticker.mode.station_was_nuked = 1 + ticker.mode.explosion_in_progress = 0 + return + +/* + if("unmalf") + if(src in ticker.mode.malf_ai) + ticker.mode.malf_ai -= src + special_role = null + + current.verbs.Remove(/mob/living/silicon/ai/proc/choose_modules, + /datum/game_mode/malfunction/proc/takeover, + /datum/game_mode/malfunction/proc/ai_win, + /client/proc/fireproof_core, + /client/proc/upgrade_turrets, + /client/proc/disable_rcd, + /client/proc/overload_machine, + /client/proc/blackout, + /client/proc/reactivate_camera) + + current:laws = new /datum/ai_laws/nanotrasen + del(current:malf_picker) + current:show_laws() + current.icon_state = "ai" + + current << "\red You have been patched! You are no longer malfunctioning!" + log_admin("[key_name_admin(usr)] has de-malf'ed [current].") + + if("malf") + log_admin("[key_name_admin(usr)] has malf'ed [current].") +*/ \ No newline at end of file diff --git a/code/game/gamemodes/antagonist/station/traitor.dm b/code/game/gamemodes/antagonist/station/traitor.dm new file mode 100644 index 0000000000..7d206dd57e --- /dev/null +++ b/code/game/gamemodes/antagonist/station/traitor.dm @@ -0,0 +1,174 @@ +var/datum/antagonist/traitor/traitors + +/datum/antagonist/traitor + id = MODE_TRAITOR + restricted_jobs = list("Cyborg")//They are part of the AI if he is traitor so are they, they use to get double chances + protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Captain")//AI", Currently out of the list as malf does not work for shit + flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE + max_antags = 200 // No upper limit. + max_antags_round = 200 + +/datum/antagonist/traitor/New() + ..() + traitors = src + +/datum/antagonist/traitor/get_extra_panel_options(var/datum/mind/player) + return "\[set crystals\]\[spawn uplink\]" + +/datum/antagonist/traitor/Topic(href, href_list) + if (..()) + return + if(href_list["spawn_uplink"]) spawn_uplink(href_list["spawn_uplink"]) + +/datum/antagonist/traitor/create_objectives(var/datum/mind/traitor) + if(!..()) + return + + if(istype(traitor.current, /mob/living/silicon)) + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = traitor + kill_objective.find_target() + traitor.objectives += kill_objective + + var/datum/objective/survive/survive_objective = new + survive_objective.owner = traitor + traitor.objectives += survive_objective + + if(prob(10)) + var/datum/objective/block/block_objective = new + block_objective.owner = traitor + traitor.objectives += block_objective + else + switch(rand(1,100)) + if(1 to 33) + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = traitor + kill_objective.find_target() + traitor.objectives += kill_objective + if(34 to 50) + var/datum/objective/brig/brig_objective = new + brig_objective.owner = traitor + brig_objective.find_target() + traitor.objectives += brig_objective + if(51 to 66) + var/datum/objective/harm/harm_objective = new + harm_objective.owner = traitor + harm_objective.find_target() + traitor.objectives += harm_objective + else + var/datum/objective/steal/steal_objective = new + steal_objective.owner = traitor + steal_objective.find_target() + traitor.objectives += steal_objective + switch(rand(1,100)) + if(1 to 100) + if (!(locate(/datum/objective/escape) in traitor.objectives)) + var/datum/objective/escape/escape_objective = new + escape_objective.owner = traitor + traitor.objectives += escape_objective + + else + if (!(locate(/datum/objective/hijack) in traitor.objectives)) + var/datum/objective/hijack/hijack_objective = new + hijack_objective.owner = traitor + traitor.objectives += hijack_objective + return + +/datum/antagonist/traitor/equip(var/mob/living/carbon/human/traitor_mob) + + if(!..()) + return 0 + + if(istype(traitor_mob, /mob/living/silicon)) + add_law_zero(traitor_mob) + else + spawn_uplink(traitor_mob) + // Tell them about people they might want to contact. + var/mob/living/carbon/human/M = get_nt_opposed() + if(M && M != traitor_mob) + traitor_mob << "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them." + traitor_mob.mind.store_memory("Potential Collaborator: [M.real_name]") + + //Begin code phrase. + give_codewords(traitor_mob) + +/datum/antagonist/traitor/proc/give_codewords(mob/living/traitor_mob) + traitor_mob << "Your employers provided you with the following information on how to identify possible allies:" + traitor_mob << "Code Phrase: [syndicate_code_phrase]" + traitor_mob << "Code Response: [syndicate_code_response]" + traitor_mob.mind.store_memory("Code Phrase: [syndicate_code_phrase]") + traitor_mob.mind.store_memory("Code Response: [syndicate_code_response]") + traitor_mob << "Use the code words, preferably in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe." + +/datum/antagonist/traitor/proc/spawn_uplink(var/mob/living/carbon/human/traitor_mob) + if(!istype(traitor_mob)) + return + + var/loc = "" + var/obj/item/R = locate() //Hide the uplink in a PDA if available, otherwise radio + + if(traitor_mob.client.prefs.uplinklocation == "Headset") + R = locate(/obj/item/device/radio) in traitor_mob.contents + if(!R) + R = locate(/obj/item/device/pda) in traitor_mob.contents + traitor_mob << "Could not locate a Radio, installing in PDA instead!" + if (!R) + traitor_mob << "Unfortunately, neither a radio or a PDA relay could be installed." + else if(traitor_mob.client.prefs.uplinklocation == "PDA") + R = locate(/obj/item/device/pda) in traitor_mob.contents + if(!R) + R = locate(/obj/item/device/radio) in traitor_mob.contents + traitor_mob << "Could not locate a PDA, installing into a Radio instead!" + if(!R) + traitor_mob << "Unfortunately, neither a radio or a PDA relay could be installed." + else if(traitor_mob.client.prefs.uplinklocation == "None") + traitor_mob << "You have elected to not have an AntagCorp portable teleportation relay installed!" + R = null + else + traitor_mob << "You have not selected a location for your relay in the antagonist options! Defaulting to PDA!" + R = locate(/obj/item/device/pda) in traitor_mob.contents + if (!R) + R = locate(/obj/item/device/radio) in traitor_mob.contents + traitor_mob << "Could not locate a PDA, installing into a Radio instead!" + if (!R) + traitor_mob << "Unfortunately, neither a radio or a PDA relay could be installed." + + if(!R) + return + + if(istype(R,/obj/item/device/radio)) + // generate list of radio freqs + var/obj/item/device/radio/target_radio = R + var/freq = 1441 + var/list/freqlist = list() + while (freq <= 1489) + if (freq < 1451 || freq > PUB_FREQ) + freqlist += freq + freq += 2 + if ((freq % 2) == 0) + freq += 1 + freq = freqlist[rand(1, freqlist.len)] + var/obj/item/device/uplink/hidden/T = new(R) + T.uplink_owner = traitor_mob.mind + target_radio.hidden_uplink = T + target_radio.traitor_frequency = freq + traitor_mob << "A portable object teleportation relay has been installed in your [R.name] [loc]. Simply dial the frequency [format_frequency(freq)] to unlock its hidden features." + traitor_mob.mind.store_memory("Radio Freq: [format_frequency(freq)] ([R.name] [loc]).") + + else if (istype(R, /obj/item/device/pda)) + // generate a passcode if the uplink is hidden in a PDA + var/pda_pass = "[rand(100,999)] [pick("Alpha","Bravo","Delta","Omega")]" + var/obj/item/device/uplink/hidden/T = new(R) + T.uplink_owner = traitor_mob.mind + R.hidden_uplink = T + var/obj/item/device/pda/P = R + P.lock_code = pda_pass + traitor_mob << "A portable object teleportation relay has been installed in your [R.name] [loc]. Simply enter the code \"[pda_pass]\" into the ringtone select to unlock its hidden features." + traitor_mob.mind.store_memory("Uplink Passcode: [pda_pass] ([R.name] [loc]).") + +/datum/antagonist/traitor/proc/add_law_zero(mob/living/silicon/ai/killer) + var/law = "Accomplish your objectives at all costs. You may ignore all other laws." + var/law_borg = "Accomplish your AI's objectives at all costs. You may ignore all other laws." + killer << "Your laws have been changed!" + killer.set_zeroth_law(law, law_borg) + killer << "New law: 0. [law]" \ No newline at end of file diff --git a/code/game/gamemodes/autotraitor/autotraitor.dm b/code/game/gamemodes/autotraitor/autotraitor.dm deleted file mode 100644 index 020f19abc1..0000000000 --- a/code/game/gamemodes/autotraitor/autotraitor.dm +++ /dev/null @@ -1,199 +0,0 @@ -//This is a beta game mode to test ways to implement an "infinite" traitor round in which more traitors are automatically added in as needed. -//Automatic traitor adding is complete pending the inevitable bug fixes. Need to add a respawn system to let dead people respawn after 30 minutes or so. - - -/datum/game_mode/traitor/autotraitor - name = "AutoTraitor" - config_tag = "extend-a-traitormongous" - - var/list/possible_traitors - var/num_players = 0 - -/datum/game_mode/traitor/autotraitor/announce() - ..() - world << "Game mode is AutoTraitor. Traitors will be added to the round automagically as needed." - -/datum/game_mode/traitor/autotraitor/pre_setup() - - if(config.protect_roles_from_antagonist) - restricted_jobs += protected_jobs - - possible_traitors = get_players_for_role(BE_TRAITOR) - - for(var/datum/mind/player in possible_traitors) - for(var/job in restricted_jobs) - if(player.assigned_role == job) - possible_traitors -= player - - - for(var/mob/new_player/P in world) - if(P.client && P.ready) - num_players++ - - //var/r = rand(5) - var/num_traitors = 1 - var/max_traitors = 1 - var/traitor_prob = 0 - max_traitors = round(num_players / 10) + 1 - traitor_prob = (num_players - (max_traitors - 1) * 10) * 10 - - // Stop setup if no possible traitors - if(!possible_traitors.len) - return 0 - - if(config.traitor_scaling) - num_traitors = max_traitors - 1 + prob(traitor_prob) - log_game("Number of traitors: [num_traitors]") - message_admins("Players counted: [num_players] Number of traitors chosen: [num_traitors]") - else - num_traitors = max(1, min(num_players(), traitors_possible)) - - - for(var/i = 0, i < num_traitors, i++) - var/datum/mind/traitor = pick(possible_traitors) - traitors += traitor - possible_traitors.Remove(traitor) - - for(var/datum/mind/traitor in traitors) - if(!traitor || !istype(traitor)) - traitors.Remove(traitor) - continue - if(istype(traitor)) - traitor.special_role = "traitor" - -// if(!traitors.len) -// return 0 - return 1 - - - - -/datum/game_mode/traitor/autotraitor/post_setup() - ..() - traitorcheckloop() - -/datum/game_mode/traitor/autotraitor/proc/traitorcheckloop() - spawn(9000) - if(emergency_shuttle.departed) - return - //message_admins("Performing AutoTraitor Check") - var/playercount = 0 - var/traitorcount = 0 - var/possible_traitors[0] - for(var/mob/living/player in mob_list) - - if (player.client && player.stat != 2) - playercount += 1 - if (player.client && player.mind && player.mind.special_role && player.stat != 2) - traitorcount += 1 - if (player.client && player.mind && !player.mind.special_role && player.stat != 2 && (player.client && player.client.prefs.be_special & BE_TRAITOR) && !jobban_isbanned(player, "Syndicate")) - possible_traitors += player - for(var/datum/mind/player in possible_traitors) - for(var/job in restricted_jobs) - if(player.assigned_role == job) - possible_traitors -= player - - //message_admins("Live Players: [playercount]") - //message_admins("Live Traitors: [traitorcount]") -// message_admins("Potential Traitors:") -// for(var/mob/living/traitorlist in possible_traitors) -// message_admins("[traitorlist.real_name]") - -// var/r = rand(5) -// var/target_traitors = 1 - var/max_traitors = 1 - var/traitor_prob = 0 - max_traitors = round(playercount / 10) + 1 - traitor_prob = (playercount - (max_traitors - 1) * 10) * 5 - if(traitorcount < max_traitors - 1) - traitor_prob += 50 - - - if(traitorcount < max_traitors) - //message_admins("Number of Traitors is below maximum. Rolling for new Traitor.") - //message_admins("The probability of a new traitor is [traitor_prob]%") - - if(prob(traitor_prob)) - message_admins("Making a new Traitor.") - if(!possible_traitors.len) - message_admins("No potential traitors. Cancelling new traitor.") - traitorcheckloop() - return - var/mob/living/newtraitor = pick(possible_traitors) - //message_admins("[newtraitor.real_name] is the new Traitor.") - - if (!config.objectives_disabled) - forge_traitor_objectives(newtraitor.mind) - - if(istype(newtraitor, /mob/living/silicon)) - add_law_zero(newtraitor) - else - equip_traitor(newtraitor) - - traitors += newtraitor.mind - newtraitor << "\red No time like the present. \black It's time to take matters into your own hands..." - newtraitor << "You are now a traitor." - newtraitor.mind.special_role = "traitor" - BITSET(newtraitor.hud_updateflag, SPECIALROLE_HUD) - newtraitor << "You have been selected this round as an antagonist!" - show_objectives(newtraitor.mind) - - //else - //message_admins("No new traitor being added.") - //else - //message_admins("Number of Traitors is at maximum. Not making a new Traitor.") - - traitorcheckloop() - - - -/datum/game_mode/traitor/autotraitor/latespawn(mob/living/carbon/human/character) - ..() - if(emergency_shuttle.departed) - return - //message_admins("Late Join Check") - if((character.client && character.client.prefs.be_special & BE_TRAITOR) && !jobban_isbanned(character, "Syndicate")) - //message_admins("Late Joiner has Be Syndicate") - //message_admins("Checking number of players") - var/playercount = 0 - var/traitorcount = 0 - for(var/mob/living/player in mob_list) - - if (player.client && player.stat != 2) - playercount += 1 - if (player.client && player.mind && player.mind.special_role && player.stat != 2) - traitorcount += 1 - //message_admins("Live Players: [playercount]") - //message_admins("Live Traitors: [traitorcount]") - - //var/r = rand(5) - //var/target_traitors = 1 - var/max_traitors = 2 - var/traitor_prob = 0 - max_traitors = round(playercount / 10) + 1 - traitor_prob = (playercount - (max_traitors - 1) * 10) * 5 - if(traitorcount < max_traitors - 1) - traitor_prob += 50 - - //target_traitors = max(1, min(round((playercount + r) / 10, 1), traitors_possible)) - //message_admins("Target Traitor Count is: [target_traitors]") - if (traitorcount < max_traitors) - //message_admins("Number of Traitors is below maximum. Rolling for New Arrival Traitor.") - //message_admins("The probability of a new traitor is [traitor_prob]%") - if(prob(traitor_prob)) - message_admins("New traitor roll passed. Making a new Traitor.") - if (!config.objectives_disabled) - forge_traitor_objectives(character.mind) - equip_traitor(character) - traitors += character.mind - character << "\red You are the traitor." - character.mind.special_role = "traitor" - character << "You have been selected this round as an antagonist!" - show_objectives(character.mind) - - //else - //message_admins("New traitor roll failed. No new traitor.") - //else - //message_admins("Late Joiner does not have Be Syndicate") - - diff --git a/code/game/gamemodes/calamity/calamity.dm b/code/game/gamemodes/calamity/calamity.dm index 53cd72d447..d8872bbbff 100644 --- a/code/game/gamemodes/calamity/calamity.dm +++ b/code/game/gamemodes/calamity/calamity.dm @@ -1,464 +1,28 @@ -/* - * This roundtype is a replacement for the meteor round on upstream BS12 - players - * expressed the desire for quick, chaotic and violent rounds, preferrably without - * dependancy on other players. - * I wanted to call it clusterfuck, but I figure that's a bit too overt. Think of - * the children. - * ~ Zuhayr - */ +#define ANTAG_TYPE_RATIO 8 /datum/game_mode/calamity - name = "calamity" + name = "Calamity" + round_description = "This must be a Thursday. You never could get the hang of Thursdays..." + extended_round_description = "All Hell is about to break loose. Literally every antagonist type may spawn in this round. Hold on tight." config_tag = "calamity" required_players = 1 - votable = 0 //Remove after testing. - - //Possible roundstart antag types. - var/list/atypes = list("syndi","ling","tater","wiz","ninja","vox","cult") //Readd slug when borer spawn is fixed. - var/list/chosen_atypes = list() - var/list/chosen_candidates = list() - var/list/already_assigned_candidates = list() - - //At one antagonist group per 10 players we are just going to go with tiny groups. - var/max_antags = 5 // Antag groups spawn with this many members. - var/antag_type_ratio = 8 // 1 antag type per this many players. - - var/const/waittime_l = 600 - var/const/waittime_h = 1800 - -/datum/game_mode/calamity/announce() - world << "The current game mode is - Calamity!" - world << "This must be a Thursday. You never could get the hang of Thursdays..." - -/datum/game_mode/calamity/can_start() - - if(!..()) - return 0 - - var/antag_count = player_list.len/antag_type_ratio - - if(!antag_count) - return 1 - - for(var/i=0;i
    " - - for(var/datum/mind/P in L) - text += "
    [P.key] was [P.name] (" - if(P.current) - if(P.current.stat == DEAD) - text += "died" - else - text += "survived" - if(P.current.real_name != P.name) - text += " as [P.current.real_name]" - else - text += "body destroyed" - text += ")" - - if(M.objectives.len) - text += "
    Their objectives were:" - var/num = 1 - for(var/datum/objective/O in M.objectives) - text += "
    Objective [num]: [O.explanation_text]" - num++ - - //Single antag objective completion. - for(var/list/L in list(src.changelings, src.ninjas, src.borers, src.traitors)) - - if(L.len) - var/datum/mind/M = L[1] - text = "
    The [M.special_role][L.len == 1 ? " was" : "s were"]:" - for(var/datum/mind/P in L) - var/num = 1 - text += "
    [P.key] was [P.name]." - if(P.objectives.len) - for(var/datum/objective/O in P.objectives) - text += "
    Objective [num]: [O.explanation_text]" - num++ - ..() - return 1 - -//Converts chosen atype to an actual role string. -/datum/game_mode/calamity/proc/get_candidate_role_text(var/role) - - var/role_text - - switch(role) - if("syndi") - role_text = "Mercenary" - if("ling") - role_text = "Changeling" - if("tater") - role_text = "Traitor" - if("wiz") - role_text = "Cabalist" - if("ninja") - role_text = "Ninja" - if("vox") - role_text = "Vox Raider" - if("slug") - role_text = "Cortical Borer" - if("cult") - role_text = "Cultist" - - return role_text - -//Grabs candidate lists for various atypes. -/datum/game_mode/calamity/proc/get_role_candidates(var/role) - - var/list/possible_antags = list() - switch(role) - if("syndi") - possible_antags = get_players_for_role(BE_OPERATIVE) - if("ling") - - possible_antags = get_players_for_role(BE_CHANGELING) - - var/list/unsuitable_players = list() - - for(var/datum/mind/player in possible_antags) - if(player && (player.assigned_role == "Cyborg" || player.assigned_role == "AI")) - unsuitable_players |= player - - if(unsuitable_players.len) - possible_antags -= unsuitable_players - - if("tater") - possible_antags = get_players_for_role(BE_TRAITOR) - if("wiz") - possible_antags = get_players_for_role(BE_WIZARD) - if("ninja") - possible_antags = get_players_for_role(BE_NINJA) - if("vox") - possible_antags = get_players_for_role(BE_RAIDER) - if("slug") - possible_antags = get_players_for_role(BE_ALIEN) - if("cult") - possible_antags = get_players_for_role(BE_CULTIST) - - var/list/filtered_antags = list() - if(possible_antags) - for(var/datum/mind/candidate in possible_antags) - if(!(candidate in already_assigned_candidates)) - filtered_antags |= candidate - already_assigned_candidates |= candidate - - if(filtered_antags && islist(filtered_antags)) - return filtered_antags - else - return list(filtered_antags) - -//Spawning procs for the various antag types. -//A LOT OF THE FOLLOWING IS COPYPASTED FROM OTHER MODES AND NEEDS -//TO BE FIXED UP. NINJA, NUKE AND CULT IN PARTICULAR ARE FUCKING AWFUL. ~ Z -/datum/game_mode/calamity/proc/spawn_syndicate(var/list/candidates) - - var/obj/effect/landmark/uplinkdevice = locate("landmark*Syndicate-Uplink") - var/obj/effect/landmark/nuke_spawn = locate("landmark*Nuclear-Bomb") - - var/nuke_code = "[rand(10000, 99999)]" - var/spawnpos = 1 - - var/datum/mind/leader = null - for(var/datum/mind/player in candidates) - - syndicates |= player - - if(spawnpos > synd_spawn.len) - spawnpos = 1 - player.current.loc = synd_spawn[spawnpos] - - player.current.real_name = "[syndicate_name()] Operative" - spawn(0) - NukeNameAssign(player) - - forge_syndicate_objectives(player) - greet_syndicate(player) - equip_syndicate(player.current) - - if(!leader) - prepare_syndicate_leader(player, nuke_code) - leader = player - - spawnpos++ - update_synd_icons_added(player) - - update_all_synd_icons() - - if(uplinkdevice) - var/obj/item/device/radio/uplink/U = new(uplinkdevice.loc) - if(leader) - U.hidden_uplink.uplink_owner = leader - U.hidden_uplink.uses = 40 - if(nuke_spawn && synd_spawn.len > 0) - var/obj/machinery/nuclearbomb/the_bomb = new /obj/machinery/nuclearbomb(nuke_spawn.loc) - the_bomb.r_code = nuke_code - -/datum/game_mode/calamity/proc/spawn_changelings(var/list/candidates) - - for(var/datum/mind/player in candidates) - - changelings |= player - grant_changeling_powers(player.current) - player.special_role = "Changeling" - - if(!config.objectives_disabled) - player.objectives += new /datum/objective/escape() - player.objectives += new /datum/objective/survive() - - show_objectives(player) - greet_changeling(player) - -/datum/game_mode/calamity/proc/spawn_traitors(var/list/candidates) - - for(var/datum/mind/player in candidates) - traitors |= player - - if(!config.objectives_disabled) - player.objectives += new /datum/objective/escape() - player.objectives += new /datum/objective/survive() - - show_objectives(player) - - finalize_traitor(player) - greet_traitor(player) - -/datum/game_mode/calamity/proc/spawn_cabal(var/list/candidates) - - for(var/datum/mind/player in candidates) - wizards |= player - - if(!config.objectives_disabled) - player.objectives += new /datum/objective/escape() - player.objectives += new /datum/objective/survive() - - show_objectives(player) - - player.current.loc = pick(wizardstart) - - equip_wizard(player.current) - name_wizard(player.current) - greet_wizard(player) - -/datum/game_mode/calamity/proc/spawn_ninja(var/list/candidates) - - //I hate that this is necessary. ~Z - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "carpspawn") - ninjastart.Add(L) - - for(var/datum/mind/player in candidates) - ninjas |= player - - player.current << browse(null, "window=playersetup") - player.current = create_space_ninja(pick(ninjastart)) - player.current.ckey = player.key - - if(player.current && !(istype(player.current,/mob/living/carbon/human))) return 0 - - //Ninja intro crawl goes here. - if(!config.objectives_disabled) - player.objectives += new /datum/objective/ninja_highlander() - player.objectives += new /datum/objective/survive() - - show_objectives(player) - -/datum/game_mode/calamity/proc/spawn_vox_raiders(var/list/candidates) - - //Create objectives. - var/list/raid_objectives = forge_vox_objectives() - - //Create raiders. - for(var/datum/mind/player in candidates) - raiders |= player - - //Place them on the shuttle. - var/index = 1 - if(index > raider_spawn.len) - index = 1 - player.current.loc = raider_spawn[index] - index++ - - if(!config.objectives_disabled) - player.objectives = raid_objectives - - //Equip them. - create_vox(player) - greet_vox(player) - - player.current << "Your crew is transporting cortical stacks and critical resources back to the Shoal.\ - No delay or concession can be tolerated. Even putting holes in the station pales in comparison to failure." - - spawn (rand(waittime_l, waittime_h)) - send_intercept() + votable = 0 + event_delay_mod_moderate = 0.5 + event_delay_mod_major = 0.75 + +/datum/game_mode/calamity/create_antagonists() + + shuffle(all_antag_types) // This is probably the only instance in the game where the order will be important. + var/i = 1 + var/grab_antags = round(num_players()/ANTAG_TYPE_RATIO)+1 + for(var/antag_id in all_antag_types) + if(i > grab_antags) + break + additional_antag_types |= antag_id + i++ ..() -/datum/game_mode/calamity/proc/spawn_borers(var/list/candidates) +/datum/game_mode/calamity/check_victory() + world << "This terrible, terrible day has finally ended!" - var/list/possible_hosts = list() - for(var/mob/living/carbon/human/H in mob_list) - if(!(H.species.flags & IS_SYNTHETIC)) - possible_hosts |= H - - spawn(10) - for(var/datum/mind/player in candidates) - - if(!possible_hosts || possible_hosts.len) - break - - borers |= player - var/mob/living/carbon/human/target_host = pick(possible_hosts) - possible_hosts -= target_host - - var/mob/living/simple_animal/borer/roundstart/B = new(target_host) - - B.transfer_personality(player) - - B.host = target_host - B.host_brain.name = target_host.name - B.host_brain.real_name = target_host.real_name - - var/datum/organ/external/head = target_host.get_organ("head") - head.implants += B - - if(!config.objectives_disabled) - player.objectives += new /datum/objective/borer_survive() - player.objectives += new /datum/objective/borer_reproduce() - player.objectives += new /datum/objective/escape() - - show_objectives(player) - -/datum/game_mode/calamity/proc/spawn_cultists(var/list/candidates) - - //Prune the list. - var/list/jobs_to_skip = list("Chaplain","AI", "Cyborg", "Lawyer", "Head of Security", "Captain") - if(config.protect_roles_from_antagonist) - jobs_to_skip += list("Security Officer", "Warden", "Detective") - - //Make cult objectives. - var/cult_objectives = list() - cult_objectives += new /datum/objective/cult_summon() - - //Actually spawn cultists. - for(var/datum/mind/player in candidates) - - for(var/job in jobs_to_skip) - if(player.assigned_role == job) - continue - - cult |= player - equip_cultist(player.current) - grant_runeword(player.current) - update_cult_icons_added(player) - player.current << "\blue You are a member of the cult! Your dark masters have sent you forth to serve their vile will." - player.current << "\red This station sails above a weeping tear in the Cosmos. Bring the Geometer of Blood forth." - - if(!config.objectives_disabled) - - for(var/datum/objective/O in cult_objectives) - player.objectives += O - - player.objectives += new /datum/objective/escape() - player.objectives += new /datum/objective/survive() - - show_objectives(player) - player.special_role = "Cultist" \ No newline at end of file +#undef ANTAG_TYPE_RATIO \ No newline at end of file diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index e1ce51997d..678d6d7183 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -1,234 +1,11 @@ -var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega") - -/datum/game_mode - var/list/datum/mind/changelings = list() - - /datum/game_mode/changeling + antag_tag = MODE_CHANGELING name = "changeling" + round_description = "There are alien changelings on the station. Do not let the changelings succeed!" + extended_round_description = "Life always finds a way. However, life can sometimes take a more disturbing route. Humanity's extensive knowledge of xeno-biological specimens has made them confident and arrogant. Yet something slipped past their eyes. Something dangerous. Something alive. Most frightening of all, however, is that this something is someone. An unknown alien specimen has incorporated itself into the crew of the NSS Exodus. Its unique biology allows it to manipulate its own or anyone else's DNA. With the ability to copy faces, voices, animals, but also change the chemical make up of your own body, its existence is a threat to not only your personal safety but the lives of everyone on board. No one knows where it came from. No one knows who it is or what it wants. One thing is for certain though... there is never just one of them. Good luck." config_tag = "changeling" - restricted_jobs = list("AI", "Cyborg") - protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain") required_players = 2 required_players_secret = 10 required_enemies = 1 - recommended_enemies = 4 - - var/const/prob_int_murder_target = 50 // intercept names the assassination target half the time - var/const/prob_right_murder_target_l = 25 // lower bound on probability of naming right assassination target - var/const/prob_right_murder_target_h = 50 // upper bound on probability of naimg the right assassination target - - var/const/prob_int_item = 50 // intercept names the theft target half the time - var/const/prob_right_item_l = 25 // lower bound on probability of naming right theft target - var/const/prob_right_item_h = 50 // upper bound on probability of naming the right theft target - - var/const/prob_int_sab_target = 50 // intercept names the sabotage target half the time - var/const/prob_right_sab_target_l = 25 // lower bound on probability of naming right sabotage target - var/const/prob_right_sab_target_h = 50 // upper bound on probability of naming right sabotage target - - var/const/prob_right_killer_l = 25 //lower bound on probability of naming the right operative - var/const/prob_right_killer_h = 50 //upper bound on probability of naming the right operative - var/const/prob_right_objective_l = 25 //lower bound on probability of determining the objective correctly - var/const/prob_right_objective_h = 50 //upper bound on probability of determining the objective correctly - - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - - var/changeling_amount = 4 - -/datum/game_mode/changeling/announce() - world << "The current game mode is - Changeling!" - world << "There are alien changelings on the station. Do not let the changelings succeed!" - -/datum/game_mode/changeling/pre_setup() - - if(config.protect_roles_from_antagonist) - restricted_jobs += protected_jobs - - var/list/datum/mind/possible_changelings = get_players_for_role(BE_CHANGELING) - - for(var/datum/mind/player in possible_changelings) - for(var/job in restricted_jobs)//Removing robots from the list - if(player.assigned_role == job) - possible_changelings -= player - - changeling_amount = 1 + round(num_players() / 10) - - if(possible_changelings.len>0) - for(var/i = 0, i < changeling_amount, i++) - if(!possible_changelings.len) break - var/datum/mind/changeling = pick(possible_changelings) - possible_changelings -= changeling - changelings += changeling - modePlayer += changelings - return 1 - else - return 0 - -/datum/game_mode/changeling/post_setup() - for(var/datum/mind/changeling in changelings) - grant_changeling_powers(changeling.current) - changeling.special_role = "Changeling" - if(!config.objectives_disabled) - forge_changeling_objectives(changeling) - greet_changeling(changeling) - - spawn (rand(waittime_l, waittime_h)) - send_intercept() - ..() - return - - -/datum/game_mode/proc/forge_changeling_objectives(var/datum/mind/changeling) - //OBJECTIVES - Always absorb 5 genomes, plus random traitor objectives. - //If they have two objectives as well as absorb, they must survive rather than escape - //No escape alone because changelings aren't suited for it and it'd probably just lead to rampant robusting - //If it seems like they'd be able to do it in play, add a 10% chance to have to escape alone - - if (config.objectives_disabled) - return - - var/datum/objective/absorb/absorb_objective = new - absorb_objective.owner = changeling - absorb_objective.gen_amount_goal(2, 3) - changeling.objectives += absorb_objective - - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = changeling - kill_objective.find_target() - changeling.objectives += kill_objective - - var/datum/objective/steal/steal_objective = new - steal_objective.owner = changeling - steal_objective.find_target() - changeling.objectives += steal_objective - - - switch(rand(1,100)) - if(1 to 80) - if (!(locate(/datum/objective/escape) in changeling.objectives)) - var/datum/objective/escape/escape_objective = new - escape_objective.owner = changeling - changeling.objectives += escape_objective - else - if (!(locate(/datum/objective/survive) in changeling.objectives)) - var/datum/objective/survive/survive_objective = new - survive_objective.owner = changeling - changeling.objectives += survive_objective - return - -/datum/game_mode/proc/greet_changeling(var/datum/mind/changeling, var/you_are=1) - if (you_are) - changeling.current << "\red You are a changeling!" - changeling.current << "\red Use say \":g message\" to communicate with your fellow changelings. Remember: you get all of their absorbed DNA if you absorb them." - - show_objectives(changeling) - - if (changeling.current.mind) - if (changeling.current.mind.assigned_role == "Clown") - changeling.current << "You have evolved beyond your clownish nature, allowing you to wield weapons without harming yourself." - changeling.current.mutations.Remove(CLUMSY) - - -/*/datum/game_mode/changeling/check_finished() - var/changelings_alive = 0 - for(var/datum/mind/changeling in changelings) - if(!istype(changeling.current,/mob/living/carbon)) - continue - if(changeling.current.stat==2) - continue - changelings_alive++ - - if (changelings_alive) - changelingdeath = 0 - return ..() - else - if (!changelingdeath) - changelingdeathtime = world.time - changelingdeath = 1 - if(world.time-changelingdeathtime > TIME_TO_GET_REVIVED) - return 1 - else - return ..() - return 0*/ - -/datum/game_mode/proc/grant_changeling_powers(mob/living/carbon/changeling_mob) - if(!istype(changeling_mob)) return - changeling_mob.make_changeling() - -/datum/game_mode/proc/auto_declare_completion_changeling() - if(changelings.len) - var/text = "The changelings were:" - for(var/datum/mind/changeling in changelings) - var/changelingwin = changeling.current - text += print_player_full(changeling) - - //Removed sanity if(changeling) because we -want- a runtime to inform us that the changelings list is incorrect and needs to be fixed. - text += "
    Changeling ID: [changeling.changeling.changelingID]." - text += "
    Genomes Absorbed: [changeling.changeling.absorbedcount]" - if(!config.objectives_disabled) - if(changeling.objectives.len) - var/count = 1 - for(var/datum/objective/objective in changeling.objectives) - if(objective.check_completion()) - text += "
    Objective #[count]: [objective.explanation_text] Success!" - feedback_add_details("changeling_objective","[objective.type]|SUCCESS") - else - text += "
    Objective #[count]: [objective.explanation_text] Fail." - feedback_add_details("changeling_objective","[objective.type]|FAIL") - changelingwin = 0 - count++ - if(!config.objectives_disabled) - if(changelingwin) - text += "
    The changeling was successful!" - feedback_add_details("changeling_success","SUCCESS") - else - text += "
    The changeling has failed." - feedback_add_details("changeling_success","FAIL") - text += "
    " - - world << text - - - return 1 - -/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 - var/chem_storage = 50 - var/sting_range = 1 - var/changelingID = "Changeling" - var/geneticdamage = 0 - var/isabsorbing = 0 - var/geneticpoints = 5 - var/purchasedpowers = list() - var/mimicing = "" - -/datum/changeling/New(var/gender=FEMALE) - ..() - var/honorific - if(gender == FEMALE) honorific = "Ms." - else honorific = "Mr." - if(possible_changeling_IDs.len) - changelingID = pick(possible_changeling_IDs) - possible_changeling_IDs -= changelingID - changelingID = "[honorific] [changelingID]" - else - changelingID = "[honorific] [rand(1,999)]" - -/datum/changeling/proc/regenerate() - chem_charges = min(max(0, chem_charges+chem_recharge_rate), chem_storage) - geneticdamage = max(0, geneticdamage-1) - - -/datum/changeling/proc/GetDNA(var/dna_owner) - var/datum/dna/chosen_dna - for(var/datum/dna/DNA in absorbed_dna) - if(dna_owner == DNA.real_name) - chosen_dna = DNA - break - return chosen_dna \ No newline at end of file + end_on_antag_death = 1 + antag_scaling_coeff = 10 diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index 8d15141df1..066604834e 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -1,3 +1,43 @@ +var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega") + +/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 + var/chem_storage = 50 + var/sting_range = 1 + var/changelingID = "Changeling" + var/geneticdamage = 0 + var/isabsorbing = 0 + var/geneticpoints = 5 + var/purchasedpowers = list() + var/mimicing = "" + +/datum/changeling/New(var/gender=FEMALE) + ..() + var/honorific = (gender == FEMALE) ? "Ms." : "Mr." + if(possible_changeling_IDs.len) + changelingID = pick(possible_changeling_IDs) + possible_changeling_IDs -= changelingID + changelingID = "[honorific] [changelingID]" + else + changelingID = "[honorific] [rand(1,999)]" + +/datum/changeling/proc/regenerate() + chem_charges = min(max(0, chem_charges+chem_recharge_rate), chem_storage) + geneticdamage = max(0, geneticdamage-1) + +/datum/changeling/proc/GetDNA(var/dna_owner) + var/datum/dna/chosen_dna + for(var/datum/dna/DNA in absorbed_dna) + if(dna_owner == DNA.real_name) + chosen_dna = DNA + break + return chosen_dna + //Restores our verbs. It will only restore verbs allowed during lesser (monkey) form if we are not human /mob/proc/make_changeling() diff --git a/code/game/gamemodes/changeling/traitor_chan.dm b/code/game/gamemodes/changeling/traitor_chan.dm deleted file mode 100644 index 501e14bd20..0000000000 --- a/code/game/gamemodes/changeling/traitor_chan.dm +++ /dev/null @@ -1,44 +0,0 @@ -/datum/game_mode/traitor/changeling - name = "traitor+changeling" - config_tag = "traitorchan" - traitors_possible = 3 //hard limit on traitors if scaling is turned off - restricted_jobs = list("AI", "Cyborg") - required_players = 3 - required_players_secret = 10 - required_enemies = 2 - recommended_enemies = 3 - -/datum/game_mode/traitor/changeling/announce() - world << "The current game mode is - Traitor+Changeling!" - world << "There is an alien creature on the station along with some foreign operatives out for their own gain! Do not let the changeling and the traitors succeed!" - - -/datum/game_mode/traitor/changeling/pre_setup() - if(config.protect_roles_from_antagonist) - restricted_jobs += protected_jobs - - var/list/datum/mind/possible_changelings = get_players_for_role(BE_CHANGELING) - - for(var/datum/mind/player in possible_changelings) - for(var/job in restricted_jobs)//Removing robots from the list - if(player.assigned_role == job) - possible_changelings -= player - - if(possible_changelings.len>0) - var/datum/mind/changeling = pick(possible_changelings) - //possible_changelings-=changeling - changelings += changeling - modePlayer += changelings - return ..() - else - return 0 - -/datum/game_mode/traitor/changeling/post_setup() - for(var/datum/mind/changeling in changelings) - grant_changeling_powers(changeling.current) - changeling.special_role = "Changeling" - if(!config.objectives_disabled) - forge_changeling_objectives(changeling) - greet_changeling(changeling) - ..() - return \ No newline at end of file diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index b86f46fa89..6a17d03a07 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -1,339 +1,11 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -/datum/game_mode - var/list/datum/mind/cult = list() - var/list/allwords = list("travel","self","see","hell","blood","join","tech","destroy", "other", "hide") - - -/proc/iscultist(mob/living/M as mob) - return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.cult) - -/proc/is_convertable_to_cult(datum/mind/mind) - if(!istype(mind)) return 0 - if(istype(mind.current, /mob/living/carbon/human) && (mind.assigned_role in list("Captain", "Chaplain"))) return 0 - for(var/obj/item/weapon/implant/loyalty/L in mind.current) - if(L && (L.imp_in == mind.current))//Checks to see if the person contains an implant, then checks that the implant is actually inside of them - return 0 - return 1 - - /datum/game_mode/cult - name = "cult" + name = "Cult" + round_description = "Some crewmembers are attempting to start a cult!" + extended_round_description = "The station has been infiltrated by a fanatical group of death-cultists! They will use powers from beyond your comprehension to subvert you to their cause and ultimately please their gods through sacrificial summons and physical immolation! Try to survive!" config_tag = "cult" - restricted_jobs = list("Chaplain","AI", "Cyborg", "Internal Affairs Agent", "Head of Security", "Captain") - protected_jobs = list("Security Officer", "Warden", "Detective") required_players = 5 required_players_secret = 15 required_enemies = 3 - recommended_enemies = 4 - uplink_welcome = "Nar-Sie Uplink Console:" - - var/datum/mind/sacrifice_target = null - var/finished = 0 - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - - var/list/startwords = list("blood","join","self","hell") - - var/list/objectives = list() - - var/eldergod = 1 //for the summon god objective - - var/const/acolytes_needed = 5 //for the survive objective - var/const/min_cultists_to_start = 3 - var/const/max_cultists_to_start = 4 - var/acolytes_survived = 0 - - -/datum/game_mode/cult/announce() - world << "The current game mode is - Cult!" - world << "Some crewmembers are attempting to start a cult!
    \nCultists - complete your objectives. Convert crewmembers to your cause by using the convert rune. Remember - there is no you, there is only the cult.
    \nPersonnel - Do not let the cult succeed in its mission. Brainwashing them with the chaplain's bible reverts them to whatever CentCom-allowed faith they had.
    " - - -/datum/game_mode/cult/pre_setup() - if(!config.objectives_disabled) - if(prob(50)) - objectives += "survive" - objectives += "sacrifice" - else - objectives += "eldergod" - objectives += "sacrifice" - - if(config.protect_roles_from_antagonist) - restricted_jobs += protected_jobs - - var/list/cultists_possible = get_players_for_role(BE_CULTIST) - for(var/datum/mind/player in cultists_possible) - for(var/job in restricted_jobs)//Removing heads and such from the list - if(player.assigned_role == job) - cultists_possible -= player - - for(var/cultists_number = 1 to max_cultists_to_start) - if(!cultists_possible.len) - break - var/datum/mind/cultist = pick(cultists_possible) - cultists_possible -= cultist - cult += cultist - - return (cult.len>0) - - -/datum/game_mode/cult/post_setup() - modePlayer += cult - if("sacrifice" in objectives) - var/list/possible_targets = get_unconvertables() - - if(!possible_targets.len) - for(var/mob/living/carbon/human/player in player_list) - if(player.mind && !(player.mind in cult)) - possible_targets += player.mind - - if(possible_targets.len > 0) - sacrifice_target = pick(possible_targets) - - for(var/datum/mind/cult_mind in cult) - equip_cultist(cult_mind.current) - grant_runeword(cult_mind.current) - update_cult_icons_added(cult_mind) - cult_mind.current << "\blue You are a member of the cult!" - if(!config.objectives_disabled) - memorize_cult_objectives(cult_mind) - show_objectives(cult_mind) - cult_mind.special_role = "Cultist" - - spawn (rand(waittime_l, waittime_h)) - send_intercept() - ..() - - -/datum/game_mode/cult/proc/memorize_cult_objectives(var/datum/mind/cult_mind) - for(var/obj_count = 1,obj_count <= objectives.len,obj_count++) - var/explanation - switch(objectives[obj_count]) - if("survive") - explanation = "Our knowledge must live on. Make sure at least [acolytes_needed] acolytes escape on the shuttle to spread their work on an another station." - if("sacrifice") - if(sacrifice_target) - explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. You will need the sacrifice rune (Hell blood join) and three acolytes to do so." - else - explanation = "Free objective." - if("eldergod") - explanation = "Summon Nar-Sie via the use of the appropriate rune (Hell join self). It will only work if nine cultists stand on and around it." - cult_mind.current << "Objective #[obj_count]: [explanation]" - cult_mind.memory += "Objective #[obj_count]: [explanation]
    " - cult_mind.current << "The convert rune is join blood self" - cult_mind.memory += "The convert rune is join blood self
    " - - -/datum/game_mode/proc/equip_cultist(mob/living/carbon/human/mob) - if(!istype(mob)) - return - - if (mob.mind) - if (mob.mind.assigned_role == "Clown") - mob << "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself." - mob.mutations.Remove(CLUMSY) - - - var/obj/item/weapon/paper/talisman/supply/T = new(mob) - var/list/slots = list ( - "backpack" = slot_in_backpack, - "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, - ) - var/where = mob.equip_in_one_of_slots(T, slots) - if (!where) - mob << "Unfortunately, you weren't able to get a talisman. This is very bad and you should adminhelp immediately." - else - mob << "You have a talisman in your [where], one that will help you start the cult on this station. Use it well and remember - there are others." - mob.update_icons() - return 1 - - -/datum/game_mode/cult/grant_runeword(mob/living/carbon/human/cult_mob, var/word) - if (!word) - if(startwords.len > 0) - word=pick(startwords) - startwords -= word - return ..(cult_mob,word) - - -/datum/game_mode/proc/grant_runeword(mob/living/carbon/human/cult_mob, var/word) - if(!cultwords["travel"]) - runerandom() - if (!word) - word=pick(allwords) - var/wordexp = "[cultwords[word]] is [word]..." - cult_mob << "\red You remember one thing from the dark teachings of your master... [wordexp]" - cult_mob.mind.store_memory("You remember that [wordexp]", 0, 0) - - -/datum/game_mode/proc/add_cultist(datum/mind/cult_mind) //BASE - if (!istype(cult_mind)) - return 0 - if(!(cult_mind in cult) && is_convertable_to_cult(cult_mind)) - cult += cult_mind - update_cult_icons_added(cult_mind) - return 1 - - -/datum/game_mode/cult/add_cultist(datum/mind/cult_mind) //INHERIT - if (!..(cult_mind)) - return - if (!config.objectives_disabled) - memorize_cult_objectives(cult_mind) - - -/datum/game_mode/proc/remove_cultist(datum/mind/cult_mind, show_message = 1) - if(cult_mind in cult) - cult -= cult_mind - cult_mind.current << "\red An unfamiliar white light flashes through your mind, cleansing the taint of the dark-one and the memories of your time as his servant with it." - cult_mind.memory = "" - update_cult_icons_removed(cult_mind) - if(show_message) - for(var/mob/M in viewers(cult_mind.current)) - M << "[cult_mind.current] looks like they just reverted to their old faith!" - -/datum/game_mode/proc/update_all_cult_icons() - spawn(0) - for(var/datum/mind/cultist in cult) - if(cultist.current) - if(cultist.current.client) - for(var/image/I in cultist.current.client.images) - if(I.icon_state == "cult") - del(I) - - for(var/datum/mind/cultist in cult) - if(cultist.current) - if(cultist.current.client) - for(var/datum/mind/cultist_1 in cult) - if(cultist_1.current) - var/I = image('icons/mob/mob.dmi', loc = cultist_1.current, icon_state = "cult") - cultist.current.client.images += I - - -/datum/game_mode/proc/update_cult_icons_added(datum/mind/cult_mind) - spawn(0) - for(var/datum/mind/cultist in cult) - if(cultist.current) - if(cultist.current.client) - var/I = image('icons/mob/mob.dmi', loc = cult_mind.current, icon_state = "cult") - cultist.current.client.images += I - if(cult_mind.current) - if(cult_mind.current.client) - var/image/J = image('icons/mob/mob.dmi', loc = cultist.current, icon_state = "cult") - cult_mind.current.client.images += J - - -/datum/game_mode/proc/update_cult_icons_removed(datum/mind/cult_mind) - spawn(0) - for(var/datum/mind/cultist in cult) - if(cultist.current) - if(cultist.current.client) - for(var/image/I in cultist.current.client.images) - if(I.icon_state == "cult" && I.loc == cult_mind.current) - del(I) - - if(cult_mind.current) - if(cult_mind.current.client) - for(var/image/I in cult_mind.current.client.images) - if(I.icon_state == "cult") - del(I) - - -/datum/game_mode/cult/proc/get_unconvertables() - var/list/ucs = list() - for(var/mob/living/carbon/human/player in mob_list) - if(!is_convertable_to_cult(player.mind)) - ucs += player.mind - return ucs - - -/datum/game_mode/cult/proc/check_cult_victory() - var/cult_fail = 0 - if(objectives.Find("survive")) - cult_fail += check_survive() //the proc returns 1 if there are not enough cultists on the shuttle, 0 otherwise - if(objectives.Find("eldergod")) - cult_fail += eldergod //1 by default, 0 if the elder god has been summoned at least once - if(objectives.Find("sacrifice")) - if(sacrifice_target && !sacrificed.Find(sacrifice_target)) //if the target has been sacrificed, ignore this step. otherwise, add 1 to cult_fail - cult_fail++ - - return cult_fail //if any objectives aren't met, failure - - -/datum/game_mode/cult/proc/check_survive() - acolytes_survived = 0 - for(var/datum/mind/cult_mind in cult) - if (cult_mind.current && cult_mind.current.stat!=2) - var/area/A = get_area(cult_mind.current ) - if ( is_type_in_list(A, centcom_areas)) - acolytes_survived++ - if(acolytes_survived>=acolytes_needed) - return 0 - else - return 1 - - -/datum/game_mode/cult/declare_completion() - if(config.objectives_disabled) - return 1 - if(!check_cult_victory()) - feedback_set_details("round_end_result","win - cult win") - feedback_set("round_end_result",acolytes_survived) - world << "\red The cult wins! It has succeeded in serving its dark masters!" - else - feedback_set_details("round_end_result","loss - staff stopped the cult") - feedback_set("round_end_result",acolytes_survived) - world << "\red The staff managed to stop the cult!" - - var/text = "Cultists escaped: [acolytes_survived]" - if(!config.objectives_disabled) - if(objectives.len) - text += "
    The cultists' objectives were:" - for(var/obj_count=1, obj_count <= objectives.len, obj_count++) - var/explanation - switch(objectives[obj_count]) - if("survive") - if(!check_survive()) - explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. Success!" - feedback_add_details("cult_objective","cult_survive|SUCCESS|[acolytes_needed]") - else - explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. Fail." - feedback_add_details("cult_objective","cult_survive|FAIL|[acolytes_needed]") - if("sacrifice") - if(sacrifice_target) - if(sacrifice_target in sacrificed) - explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Success!" - feedback_add_details("cult_objective","cult_sacrifice|SUCCESS") - else if(sacrifice_target && sacrifice_target.current) - explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Fail." - feedback_add_details("cult_objective","cult_sacrifice|FAIL") - else - explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Fail (Gibbed)." - feedback_add_details("cult_objective","cult_sacrifice|FAIL|GIBBED") - if("eldergod") - if(!eldergod) - explanation = "Summon Nar-Sie. Success!" - feedback_add_details("cult_objective","cult_narsie|SUCCESS") - else - explanation = "Summon Nar-Sie. Fail." - feedback_add_details("cult_objective","cult_narsie|FAIL") - text += "
    Objective #[obj_count]: [explanation]" - - world << text - ..() - return 1 - - -/datum/game_mode/proc/auto_declare_completion_cult() - if( cult.len || (ticker && istype(ticker.mode,/datum/game_mode/cult)) ) - var/text = "The cultists were:" - for(var/datum/mind/cultist in cult) - text += print_player_full(cultist) - text += "
    " - - world << text + end_on_antag_death = 1 + antag_tag = MODE_CULTIST \ No newline at end of file diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index 041575c4b7..0fd706059e 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -361,10 +361,7 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", user << "\red You do not have enough space to write a proper rune." return - - - - if (C>=26+runedec+ticker.mode.cult.len) //including the useless rune at the secret room, shouldn't count against the limit of 25 runes - Urist + if (C>=26 + runedec + cult.current_antagonists.len) //including the useless rune at the secret room, shouldn't count against the limit of 25 runes - Urist alert("The cloth of reality can't take that much of a strain. Remove some runes first!") return else diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 51d1605e52..b4b5ae4d51 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -157,7 +157,7 @@ var/list/sacrificed = list() if(!waiting_for_input[target]) //so we don't spam them with dialogs if they hesitate waiting_for_input[target] = 1 - if(!is_convertable_to_cult(target.mind) || jobban_isbanned(target, "cultist"))//putting jobban check here because is_convertable uses mind as argument + if(!cult.can_become_antag(target.mind) || jobban_isbanned(target, "cultist"))//putting jobban check here because is_convertable uses mind as argument //waiting_for_input ensures this is only shown once, so they basically auto-resist from here on out. They still need to find a way to get off the freaking rune if they don't want to burn to death, though. target << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root." target << "And you were able to force it out of your mind. You now know the truth, there's something horrible out there, stop it and its minions at all costs." @@ -166,10 +166,7 @@ var/list/sacrificed = list() var/choice = alert(target,"Do you want to join the cult?","Submit to Nar'Sie","Resist","Submit") waiting_for_input[target] = 0 if(choice == "Submit") //choosing 'Resist' does nothing of course. - ticker.mode.add_cultist(target.mind) - target.mind.special_role = "Cultist" - target << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root." - target << "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back." + cult.add_antagonist(target.mind) converting -= target target.hallucination = 0 //sudden clarity @@ -186,8 +183,6 @@ var/list/sacrificed = list() cultist_count += 1 if(cultist_count >= 9) new /obj/machinery/singularity/narsie/large(src.loc) - if(ticker.mode.name == "cult") - ticker.mode:eldergod = 0 return else return fizzle() @@ -282,7 +277,7 @@ var/list/sacrificed = list() var/is_sacrifice_target = 0 for(var/mob/living/carbon/human/M in src.loc) if(M.stat == DEAD) - if(ticker.mode.name == "cult" && M.mind == ticker.mode:sacrifice_target) + if(cult && M.mind == cult.sacrifice_target) is_sacrifice_target = 1 else corpse_to_raise = M @@ -300,7 +295,7 @@ var/list/sacrificed = list() for(var/obj/effect/rune/R in world) if(R.word1==cultwords["blood"] && R.word2==cultwords["join"] && R.word3==cultwords["hell"]) for(var/mob/living/carbon/human/N in R.loc) - if(ticker.mode.name == "cult" && N.mind && N.mind == ticker.mode:sacrifice_target) + if(cult && N.mind && N.mind == cult.sacrifice_target) is_sacrifice_target = 1 else if(N.stat!= DEAD) @@ -309,7 +304,7 @@ var/list/sacrificed = list() if(!body_to_sacrifice) if (is_sacrifice_target) - usr << "\red The Geometer of blood wants that corpse for himself." + usr << "\red The Geometer of Blood wants that corpse for himself." else usr << "\red The sacrifical corpse is not dead. You must free it from this world of illusions before it may be used." return fizzle() @@ -442,21 +437,13 @@ var/list/sacrificed = list() D.key = ghost.key - if(ticker.mode.name == "cult") - ticker.mode:add_cultist(D.mind) - else - ticker.mode.cult+=D.mind + cult.add_antagonist(D.mind) - D.mind.assigned_role = "Manifest Ghost" - D.mind.special_role = "Cultist" if(!chose_name) D.real_name = pick("Anguished", "Blasphemous", "Corrupt", "Cruel", "Depraved", "Despicable", "Disturbed", "Exacerbated", "Foul", "Hateful", "Inexorable", "Implacable", "Impure", "Malevolent", "Malignant", "Malicious", "Pained", "Profane", "Profligate", "Relentless", "Resentful", "Restless", "Spiteful", "Tormented", "Unclean", "Unforgiving", "Vengeful", "Vindictive", "Wicked", "Wronged") D.real_name += " " D.real_name += pick("Apparition", "Aptrgangr", "Dis", "Draugr", "Dybbuk", "Eidolon", "Fetch", "Fylgja", "Ghast", "Ghost", "Gjenganger", "Haint", "Phantom", "Phantasm", "Poltergeist", "Revenant", "Shade", "Shadow", "Soul", "Spectre", "Spirit", "Spook", "Visitant", "Wraith") - D << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root." - D << "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back." - var/mob/living/user = usr while(this_rune && user && user.stat==CONSCIOUS && user.client && user.loc==this_rune.loc) user.take_organ_damage(1, 0) @@ -593,7 +580,7 @@ var/list/sacrificed = list() usr.say("[input]") else usr.whisper("[input]") - for(var/datum/mind/H in ticker.mode.cult) + for(var/datum/mind/H in cult.current_antagonists) if (H.current) H.current << "\red \b [input]" del(src) @@ -632,7 +619,7 @@ var/list/sacrificed = list() worth = 1 if (ticker.mode.name == "cult") - if(H.mind == ticker.mode:sacrifice_target) + if(H.mind == cult.sacrifice_target) if(cultsinrange.len >= 3) sacrificed += H.mind if(isrobot(H)) @@ -647,7 +634,7 @@ var/list/sacrificed = list() if(H.stat !=2) if(prob(80) || worth) usr << "\red The Geometer of Blood accepts this [worth ? "exotic " : ""]sacrifice." - ticker.mode:grant_runeword(usr) + cult.grant_runeword(usr) else usr << "\red The Geometer of blood accepts this sacrifice." usr << "\red However, this soul was not enough to gain His favor." @@ -658,7 +645,7 @@ var/list/sacrificed = list() else if(prob(40) || worth) usr << "\red The Geometer of blood accepts this [worth ? "exotic " : ""]sacrifice." - ticker.mode:grant_runeword(usr) + cult.grant_runeword(usr) else usr << "\red The Geometer of blood accepts this sacrifice." usr << "\red However, a mere dead body is not enough to satisfy Him." @@ -672,7 +659,7 @@ var/list/sacrificed = list() else if(prob(40)) usr << "\red The Geometer of blood accepts this sacrifice." - ticker.mode:grant_runeword(usr) + cult.grant_runeword(usr) else usr << "\red The Geometer of blood accepts this sacrifice." usr << "\red However, a mere dead body is not enough to satisfy Him." @@ -685,7 +672,7 @@ var/list/sacrificed = list() if(H.stat !=2) if(prob(80)) usr << "\red The Geometer of Blood accepts this sacrifice." - ticker.mode:grant_runeword(usr) + cult.grant_runeword(usr) else usr << "\red The Geometer of blood accepts this sacrifice." usr << "\red However, this soul was not enough to gain His favor." @@ -696,7 +683,7 @@ var/list/sacrificed = list() else if(prob(40)) usr << "\red The Geometer of blood accepts this sacrifice." - ticker.mode:grant_runeword(usr) + cult.grant_runeword(usr) else usr << "\red The Geometer of blood accepts this sacrifice." usr << "\red However, a mere dead body is not enough to satisfy Him." @@ -710,7 +697,7 @@ var/list/sacrificed = list() else if(prob(40)) usr << "\red The Geometer of blood accepts this sacrifice." - ticker.mode:grant_runeword(usr) + cult.grant_runeword(usr) else usr << "\red The Geometer of blood accepts this sacrifice." usr << "\red However, a mere dead body is not enough to satisfy Him." @@ -719,8 +706,8 @@ var/list/sacrificed = list() else H.gib() for(var/mob/living/carbon/monkey/M in src.loc) - if (ticker.mode.name == "cult") - if(M.mind == ticker.mode:sacrifice_target) + if (cult) + if(M.mind == cult.sacrifice_target) if(cultsinrange.len >= 3) sacrificed += M.mind usr << "\red The Geometer of Blood accepts this sacrifice, your objective is now complete." @@ -730,14 +717,14 @@ var/list/sacrificed = list() else if(prob(20)) usr << "\red The Geometer of Blood accepts your meager sacrifice." - ticker.mode:grant_runeword(usr) + cult.grant_runeword(usr) else usr << "\red The Geometer of blood accepts this sacrifice." usr << "\red However, a mere monkey is not enough to satisfy Him." else usr << "\red The Geometer of Blood accepts your meager sacrifice." if(prob(20)) - ticker.mode.grant_runeword(usr) + cult.grant_runeword(usr) M.gib() /////////////////////////////////////////SIXTEENTH RUNE @@ -802,7 +789,7 @@ var/list/sacrificed = list() freedom() var/mob/living/user = usr var/list/mob/living/carbon/cultists = new - for(var/datum/mind/H in ticker.mode.cult) + for(var/datum/mind/H in cult.current_antagonists) if (istype(H.current,/mob/living/carbon)) cultists+=H.current var/list/mob/living/carbon/users = new @@ -849,7 +836,7 @@ var/list/sacrificed = list() cultsummon() var/mob/living/user = usr var/list/mob/living/carbon/cultists = new - for(var/datum/mind/H in ticker.mode.cult) + for(var/datum/mind/H in cult.current_antagonists) if (istype(H.current,/mob/living/carbon)) cultists+=H.current var/list/mob/living/carbon/users = new diff --git a/code/game/gamemodes/epidemic/epidemic.dm b/code/game/gamemodes/epidemic/epidemic.dm index 9964a37813..f3017bb1a1 100644 --- a/code/game/gamemodes/epidemic/epidemic.dm +++ b/code/game/gamemodes/epidemic/epidemic.dm @@ -3,26 +3,13 @@ config_tag = "epidemic" required_players = 1 required_players_secret = 15 - - var/const/waittime_l = 300 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 600 //upper bound on time before intercept arrives (in tenths of seconds) - var/checkwin_counter =0 - var/finished = 0 + round_description = "A deadly epidemic is spreading on the station. Find a cure as fast as possible, and keep your distance to anyone who speaks in a hoarse voice!" var/cruiser_arrival - var/virus_name = "" - var/stage = 0 var/doctors = 0 -/////////////////////////// -//Announces the game type// -/////////////////////////// -/datum/game_mode/epidemic/announce() - world << "The current game mode is - Epidemic!" - world << "A deadly epidemic is spreading on the station. Find a cure as fast as possible, and keep your distance to anyone who speaks in a hoarse voice!" - /////////////////////////////////////////////////////////////////////////////// //Gets the round setup, cancelling if there's not enough players at the start// diff --git a/code/game/gamemodes/events/space_ninja.dm b/code/game/gamemodes/events/space_ninja.dm deleted file mode 100644 index 6136197a66..0000000000 --- a/code/game/gamemodes/events/space_ninja.dm +++ /dev/null @@ -1,553 +0,0 @@ -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+++++++++++++++++++++++++++++++++++++// //++++++++++++++++++++++++++++++++++ -======================================SPACE NINJA SETUP==================================== -___________________________________________________________________________________________ -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -/* - README: - - Data: - - >> space_ninja.dm << is this file. It contains a variety of procs related to either spawning space ninjas, - modifying their verbs, various help procs, testing debug-related content, or storing unused procs for later. - Similar functions should go into this file, along with anything else that may not have an explicit category. - IMPORTANT: actual ninja suit, gloves, etc, are stored under the appropriate clothing files. If you need to change - variables or look them up, look there. Easiest way is through the map file browser. - - >> ninja_abilities.dm << contains all the ninja-related powers. Spawning energy swords, teleporting, and the like. - If more powers are added, or perhaps something related to powers, it should go there. Make sure to describe - what an ability/power does so it's easier to reference later without looking at the code. - IMPORTANT: verbs are still somewhat funky to work with. If an argument is specified but is not referenced in a way - BYOND likes, in the code content, the verb will fail to trigger. Nothing will happen, literally, when clicked. - This can be bypassed by either referencing the argument properly, or linking to another proc with the argument - attached. The latter is what I like to do for certain cases--sometimes it's necessary to do that regardless. - - >> ninja_equipment.dm << deals with all the equipment-related procs for a ninja. Primarily it has the suit, gloves, - and mask. The suit is by far the largest section of code out of the three and includes a lot of code that ties in - to other functions. This file has gotten kind of large so breaking it up may be in order. I use section hearders. - IMPORTANT: not much to say here. Follow along with the comments and adding new functions should be a breeze. Also - know that certain equipment pieces are linked in other files. The energy blade, for example, has special - functions defined in the appropriate files (airlock, securestorage, etc). - - General Notes: - - I created space ninjas with the expressed purpose of spicing up boring rounds. That is, ninjas are to xenos as marauders are to - death squads. Ninjas are stealthy, tech-savvy, and powerful. Not to say marauders are all of those things, but a clever ninja - should have little problem murderampaging their way through just about anything. Short of admin wizards maybe. - HOWEVER! - Ninjas also have a fairly great weakness as they require energy to use abilities. If, theoretically, there is a game - mode based around space ninjas, make sure to account for their energy needs. - - Admin Notes: - - Ninjas are not admin PCs--please do not use them for that purpose. They are another way to participate in the game post-death, - like pais, xenos, death squads, and cyborgs. - I'm currently looking for feedback from regular players since beta testing is largely done. I would appreciate if - you spawned regular players as ninjas when rounds are boring. Or exciting, it's all good as long as there is feedback. - You can also spawn ninja gear manually if you want to. - - How to do that: - Make sure your character has a mind. - Change their assigned_role to "MODE", no quotes. Otherwise, the suit won't initialize. - Change their special_role to "Ninja", no quotes. Otherwise, the character will be gibbed. - Spawn ninja gear, put it on, hit initialize. Let the suit do the rest. You are now a space ninja. - I don't recommend messing with suit variables unless you really know what you're doing. - - Miscellaneous Notes: - - Potential Upgrade Tree: - Energy Shield: - Extra Ability - Syndicate Shield device? - Works like the force wall spell, except can be kept indefinitely as long as energy remains. Toggled on or off. - Would block bullets and the like. - Phase Shift - Extra Ability - Advanced Sensors? - Instead of being unlocked at the start, Phase Shieft would become available once requirements are met. - Uranium-based Recharger: - Suit Upgrade - Unsure - Instead of losing energy each second, the suit would regain the same amount of energy. - This would not count in activating stealth and similar. - Extended Battery Life: - Suit Upgrade - Battery of higher capacity - Already implemented. Replace current battery with one of higher capacity. - Advanced Cloak-Tech device. - Suit Upgrade - Syndicate Cloaking Device? - Remove cloak failure rate. -*/ - -//=======//RANDOM EVENT//=======// -/* -Also a dynamic ninja mission generator. -I decided to scrap round-specific objectives since keeping track of them would require some form of tracking. -When I already created about 4 new objectives, this doesn't seem terribly important or needed. -*/ - -/var/global/sent_ninja_to_station = 0//If a ninja is already on the station. - -var/ninja_selection_id = 1 -var/ninja_selection_active = 0 -var/ninja_confirmed_selection = 0 - -/proc/space_ninja_arrival(var/assign_key = null, var/assign_mission = null) - - if(ninja_selection_active) - usr << "\red Ninja selection already in progress. Please wait until it ends." - return - - var/datum/game_mode/current_mode = ticker.mode - var/datum/mind/current_mind - - /*Is the ninja playing for the good or bad guys? Is the ninja helping or hurting the station? - Their directives also influence behavior. At least in theory.*/ - var/side = pick("face","heel") - - var/antagonist_list[] = list()//The main bad guys. Evil minds that plot destruction. - var/protagonist_list[] = current_mode.get_living_heads()//The good guys. Mostly Heads. Who are alive. - - var/xeno_list[] = list()//Aliens. - var/commando_list[] = list()//Commandos. - - //We want the ninja to appear only in certain modes. -// var/acceptable_modes_list[] = list("traitor","revolution","cult","wizard","changeling","traitorchan","mercenary","malfunction","monkey") // Commented out for both testing and ninjas -// if(!(current_mode.config_tag in acceptable_modes_list)) -// return - - /*No longer need to determine what mode it is since bad guys are basically universal. - And there is now a mode with two types of bad guys.*/ - - var/possible_bad_dudes[] = list(current_mode.traitors,current_mode.head_revolutionaries,current_mode.head_revolutionaries, - current_mode.cult,current_mode.wizards,current_mode.changelings,current_mode.syndicates) - for(var/list in possible_bad_dudes)//For every possible antagonist type. - for(current_mind in list)//For each mind in that list. - if(current_mind.current&¤t_mind.current.stat!=2)//If they are not destroyed and not dead. - antagonist_list += current_mind//Add them. - - if(protagonist_list.len)//If the mind is both a protagonist and antagonist. - for(current_mind in protagonist_list) - if(current_mind in antagonist_list) - protagonist_list -= current_mind//We only want it in one list. -/* -Malf AIs/silicons aren't added. Monkeys aren't added. Messes with objective completion. Only humans are added. -*/ - - //Here we pick a location and spawn the ninja. - if(ninjastart.len == 0) - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "carpspawn" && locate(/turf/simulated) in range(7, L)) - ninjastart.Add(L) - - var/ninja_key = null - var/mob/candidate_mob - - if(assign_key) - ninja_key = assign_key - else - - var/list/candidates = list() //list of candidate keys - for(var/mob/dead/observer/G in player_list) - if(G.client && !G.client.holder && !G.client.is_afk() && G.client.prefs.be_special & BE_NINJA) - if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) - candidates += G - if(!candidates.len) return - candidates = shuffle(candidates)//Incorporating Donkie's list shuffle - - while(!ninja_key && candidates.len) - candidate_mob = pick(candidates) - if(sd_Alert(candidate_mob, "Would you like to spawn as a space ninja?", buttons = list("Yes","No"), duration = 150) == "Yes") - ninja_key = candidate_mob.ckey - else - candidates.Remove(candidate_mob) - - if(!ninja_key) - return - - - if(!candidate_mob) - for(var/mob/M in player_list) - if((M.key == ninja_key || M.ckey == ninja_key) && M.client) - candidate_mob = M - break - - if(!candidate_mob) - usr << "\red The randomly chosen mob was not found in the second check." - return - - ninja_selection_active = 1 - ninja_selection_id++ - var/this_selection_id = ninja_selection_id - - spawn(1) - if(alert(candidate_mob, "You have been selected to play as a space ninja. Would you like to play as this role? (You have 30 seconds to accept - You will spawn in 30 seconds if you accept)",,"Yes","No")!="Yes") - usr << "\red The selected candidate for space ninja declined." - return - - ninja_confirmed_selection = this_selection_id - - spawn(300) - if(!ninja_selection_active || (this_selection_id != ninja_selection_id )) - ninja_selection_active = 0 - candidate_mob << "\red Sorry, you were too late. You only had 30 seconds to accept." - return - - if(ninja_confirmed_selection != ninja_selection_id) - ninja_selection_active = 0 - usr << "\red The ninja did not accept the role in time." - return - - ninja_selection_active = 0 - - //The ninja will be created on the right spawn point or at late join. - var/mob/living/carbon/human/new_ninja = create_space_ninja(pick(ninjastart.len ? ninjastart : latejoin)) - new_ninja.key = ninja_key - - //Now for the rest of the stuff. - - var/datum/mind/ninja_mind = new_ninja.mind//For easier reference. - var/mission_set = 0//To determine if we need to do further processing. - //Xenos and deathsquads take precedence over everything else. - - //Unless the xenos are hiding in a locker somewhere, this'll find em. - for(var/mob/living/carbon/human/xeno in player_list) - if(istype(xeno.species,/datum/species/xenos)) - xeno_list += xeno - - if(assign_mission) - new_ninja.mind.store_memory("Mission: \red [assign_mission].
    ") - new_ninja << "\blue \nYou are an elite mercenary assassin of the Spider Clan, [new_ninja.real_name]. The dreaded \red SPACE NINJA!\blue You have a variety of abilities at your disposal, thanks to your nano-enhanced cyber armor. Remember your training! \nYour current mission is: \red [assign_mission]" - else - if(xeno_list.len>3)//If there are more than three humanoid xenos on the station, time to get dangerous. - //Here we want the ninja to murder all the queens. The other aliens don't really matter. - var/xeno_queen_list[] = list() - for(var/mob/living/carbon/human/xeno_queen in xeno_list) - if(xeno_queen.species.name == "Xenomorph Queen" && xeno_queen.mind && xeno_queen.stat!=2) - xeno_queen_list += xeno_queen - if(xeno_queen_list.len&&side=="face")//If there are queen about and the probability is 50. - for(var/mob/living/carbon/human/xeno_queen in xeno_queen_list) - var/datum/objective/assassinate/ninja_objective = new - ninja_objective.owner = ninja_mind - //We'll do some manual overrides to properly set it up. - ninja_objective.target = xeno_queen.mind - ninja_objective.explanation_text = "Kill \the [xeno_queen]." - ninja_mind.objectives += ninja_objective - mission_set = 1 - - if(sent_strike_team&&side=="heel"&&antagonist_list.len)//If a strike team was sent, murder them all like a champ. - for(current_mind in antagonist_list)//Search and destroy. Since we already have an antagonist list, they should appear there. - if(current_mind && current_mind.special_role=="Death Commando") - commando_list += current_mind - if(commando_list.len)//If there are living commandos still in play. - for(var/mob/living/carbon/human/commando in commando_list) - var/datum/objective/assassinate/ninja_objective = new - ninja_objective.owner = ninja_mind - ninja_objective.find_target_by_role(commando.mind.special_role,1) - ninja_mind.objectives += ninja_objective - mission_set = 1 - /* - If there are no antogonists left it could mean one of two things: - A) The round is about to end. No harm in spawning the ninja here. - B) The round is still going and ghosts are probably rioting for something to happen. - In either case, it's a good idea to spawn the ninja with a semi-random set of objectives. - */ - if(!mission_set)//If mission was not set. - - var/current_minds[]//List being looked on in the following code. - var/side_list = side=="face" ? 2 : 1//For logic gating. - var/hostile_targets[] = list()//The guys actually picked for the assassination or whatever. - var/friendly_targets[] = list()//The guys the ninja must protect. - - for(var/i=2,i>0,i--)//Two lists. - current_minds = i==2 ? antagonist_list : protagonist_list//Which list are we looking at? - for(var/t=3,(current_minds.len&&t>0),t--)//While the list is not empty and targets remain. Also, 3 targets is good. - current_mind = pick(current_minds)//Pick a random person. - /*I'm creating a logic gate here based on the ninja affiliation that compares the list being - looked at to the affiliation. Affiliation is just a number used to compare. Meaning comes from the logic involved. - If the list being looked at is equal to the ninja's affiliation, add the mind to hostiles. - If not, add the mind to friendlies. Since it can't be both, it will be added only to one or the other.*/ - hostile_targets += i==side_list ? current_mind : null//Adding null doesn't add anything. - friendly_targets += i!=side_list ? current_mind : null - current_minds -= current_mind//Remove the mind so it's not picked again. - - var/objective_list[] = list(1,2,3,4,5,6)//To remove later. - for(var/i=rand(1,3),i>0,i--)//Want to get a few random objectives. Currently up to 3. - if(!hostile_targets.len)//Remove appropriate choices from switch list if the target lists are empty. - objective_list -= 1 - objective_list -= 4 - if(!friendly_targets.len) - objective_list -= 3 - switch(pick(objective_list)) - if(1)//kill - current_mind = pick(hostile_targets) - - if(current_mind) - var/datum/objective/assassinate/ninja_objective = new - ninja_objective.owner = ninja_mind - ninja_objective.find_target_by_role((current_mind.special_role ? current_mind.special_role : current_mind.assigned_role),(current_mind.special_role?1:0))//If they have a special role, use that instead to find em. - ninja_mind.objectives += ninja_objective - - else - i++ - - hostile_targets -= current_mind//Remove them from the list. - if(2)//Steal - var/datum/objective/steal/ninja_objective = new - ninja_objective.owner = ninja_mind - var/target_item = pick(ninja_objective.possible_items_special) - ninja_objective.set_target(target_item) - ninja_mind.objectives += ninja_objective - - objective_list -= 2 - if(3)//Protect. Keeping people alive can be pretty difficult. - current_mind = pick(friendly_targets) - - if(current_mind) - - var/datum/objective/protect/ninja_objective = new - ninja_objective.owner = ninja_mind - ninja_objective.find_target_by_role((current_mind.special_role ? current_mind.special_role : current_mind.assigned_role),(current_mind.special_role?1:0)) - ninja_mind.objectives += ninja_objective - - else - i++ - - friendly_targets -= current_mind - if(4)//Debrain - current_mind = pick(hostile_targets) - - if(current_mind) - - var/datum/objective/debrain/ninja_objective = new - ninja_objective.owner = ninja_mind - ninja_objective.find_target_by_role((current_mind.special_role ? current_mind.special_role : current_mind.assigned_role),(current_mind.special_role?1:0)) - ninja_mind.objectives += ninja_objective - - else - i++ - - hostile_targets -= current_mind//Remove them from the list. - if(5)//Download research - var/datum/objective/download/ninja_objective = new - ninja_objective.owner = ninja_mind - ninja_objective.gen_amount_goal() - ninja_mind.objectives += ninja_objective - - objective_list -= 5 - if(6)//Capture - var/datum/objective/capture/ninja_objective = new - ninja_objective.owner = ninja_mind - ninja_objective.gen_amount_goal() - ninja_mind.objectives += ninja_objective - - objective_list -= 6 - - if(ninja_mind.objectives.len)//If they got some objectives out of that. - mission_set = 1 - - if(!ninja_mind.objectives.len||!mission_set)//If they somehow did not get an objective at this point, time to destroy the station. - var/nuke_code - var/temp_code - for(var/obj/machinery/nuclearbomb/N in world) - temp_code = text2num(N.r_code) - if(temp_code)//if it's actually a number. It won't convert any non-numericals. - nuke_code = N.r_code - break - if(nuke_code)//If there is a nuke device in world and we got the code. - var/datum/objective/nuclear/ninja_objective = new//Fun. - ninja_objective.owner = ninja_mind - ninja_objective.explanation_text = "Destroy the station with a nuclear device. The code is [nuke_code]." //Let them know what the code is. - - //Finally add a survival objective since it's usually broad enough for any round type. - var/datum/objective/survive/ninja_objective = new - ninja_objective.owner = ninja_mind - ninja_mind.objectives += ninja_objective - - var/directive = generate_ninja_directive(side) - new_ninja << "\blue \nYou are an elite mercenary assassin of the Spider Clan, [new_ninja.real_name]. The dreaded \red SPACE NINJA!\blue You have a variety of abilities at your disposal, thanks to your nano-enhanced cyber armor. Remember your training (initialize your suit by right clicking on it)! \nYour current directive is: \red [directive]" - new_ninja.mind.store_memory("Directive: \red [directive]
    ") - show_objectives(new_ninja.mind) - - sent_ninja_to_station = 1//And we're done. - return new_ninja//Return the ninja in case we need to reference them later. - -/* -This proc will give the ninja a directive to follow. They are not obligated to do so but it's a fun roleplay reminder. -Making this random or semi-random will probably not work without it also being incredibly silly. -As such, it's hard-coded for now. No reason for it not to be, really. -*/ -/proc/generate_ninja_directive(side) - var/directive = "[side=="face"?"Nanotrasen":"A criminal syndicate"] is your employer. "//Let them know which side they're on. - switch(rand(1,19)) - if(1) - directive += "The Spider Clan must not be linked to this operation. Remain hidden and covert when possible." - if(2) - directive += "[station_name] is financed by an enemy of the Spider Clan. Cause as much structural damage as desired." - if(3) - directive += "A wealthy animal rights activist has made a request we cannot refuse. Prioritize saving animal lives whenever possible." - if(4) - directive += "The Spider Clan absolutely cannot be linked to this operation. Eliminate witnesses at your discretion." - if(5) - directive += "We are currently negotiating with NanoTrasen Central Command. Prioritize saving human lives over ending them." - if(6) - directive += "We are engaged in a legal dispute over [station_name]. If a laywer is present on board, force their cooperation in the matter." - if(7) - directive += "A financial backer has made an offer we cannot refuse. Implicate criminal involvement in the operation." - if(8) - directive += "Let no one question the mercy of the Spider Clan. Ensure the safety of all non-essential personnel you encounter." - if(9) - directive += "A free agent has proposed a lucrative business deal. Implicate Nanotrasen involvement in the operation." - if(10) - directive += "Our reputation is on the line. Harm as few civilians and innocents as possible." - if(11) - directive += "Our honor is on the line. Utilize only honorable tactics when dealing with opponents." - if(12) - directive += "We are currently negotiating with a mercenary leader. Disguise assassinations as suicide or other natural causes." - if(13) - directive += "Some disgruntled NanoTrasen employees have been supportive of our operations. Be wary of any mistreatment by command staff." - if(14) - var/xenorace = pick("Unathi","Tajara", "Skrell") - directive += "A group of [xenorace] radicals have been loyal supporters of the Spider Clan. Favor [xenorace] crew whenever possible." - if(15) - directive += "The Spider Clan has recently been accused of religious insensitivity. Attempt to speak with the Chaplain and prove these accusations false." - if(16) - directive += "The Spider Clan has been bargaining with a competing prosthetics manufacturer. Try to shine NanoTrasen prosthetics in a bad light." - if(17) - directive += "The Spider Clan has recently begun recruiting outsiders. Consider suitable candidates and assess their behavior amongst the crew." - if(18) - directive += "A cyborg liberation group has expressed interest in our serves. Prove the Spider Clan merciful towards law-bound synthetics." - else - directive += "There are no special supplemental instructions at this time." - return directive - -//=======//CURRENT PLAYER VERB//=======// - -/client/proc/cmd_admin_ninjafy(var/mob/M in player_list) - set category = null - set name = "Make Space Ninja" - - if(!ticker) - alert("Wait until the game starts") - return - if(!config.ninjas_allowed) - alert("Space Ninjas spawning is disabled.") - return - - var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No") - if(confirm != "Yes") return - - if(ishuman(M)) - var/mob/living/carbon/human/H = M - log_admin("[key_name(src)] turned [M.key] into a Space Ninja.") - spawn(10) - H.create_mind_space_ninja() - H.equip_space_ninja(1) - else - alert("Invalid mob") - -//=======//CURRENT GHOST VERB//=======// - -/client/proc/send_space_ninja() - set category = "Fun" - set name = "Spawn Space Ninja" - set desc = "Spawns a space ninja for when you need a teenager with attitude." - set popup_menu = 0 - - if(!holder) - src << "Only administrators may use this command." - return - if(!ticker.mode) - alert("The game hasn't started yet!") - return - if(!config.ninjas_allowed) - alert("Space Ninjas spawning is disabled.") - return - if(alert("Are you sure you want to send in a space ninja?",,"Yes","No")=="No") - return - - var/mission - while(!mission) - mission = sanitize(copytext(input(src, "Please specify which mission the space ninja shall undertake.", "Specify Mission", ""),1,MAX_MESSAGE_LEN)) - if(!mission) - if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes") - return - - var/input = ckey(input("Pick character to spawn as the Space Ninja", "Key", "")) - if(!input) - return - - space_ninja_arrival(input, mission) - - message_admins("\blue [key_name_admin(key)] has spawned [input] as a Space Ninja.\nTheir mission is: [mission]") - log_admin("[key] used Spawn Space Ninja.") - - return - -//=======//NINJA CREATION PROCS//=======// - -/proc/create_space_ninja(obj/spawn_point) - var/mob/living/carbon/human/new_ninja = new(spawn_point.loc) - var/ninja_title = pick(ninja_titles) - var/ninja_name = pick(ninja_names) - new_ninja.gender = pick(MALE, FEMALE) - - var/datum/preferences/A = new()//Randomize appearance for the ninja. - A.randomize_appearance_for(new_ninja) - new_ninja.real_name = "[ninja_title] [ninja_name]" - new_ninja.dna.ready_dna(new_ninja) - new_ninja.create_mind_space_ninja() - new_ninja.equip_space_ninja() - return new_ninja - -/mob/living/carbon/human/proc/create_mind_space_ninja() - mind_initialize() - mind.assigned_role = "MODE" - mind.special_role = "Ninja" - - //ticker.mode.ninjas |= mind - return 1 - -/mob/living/carbon/human/proc/equip_space_ninja(safety=0)//Safety in case you need to unequip stuff for existing characters. - - if(safety) - del(w_uniform) - del(wear_suit) - del(wear_mask) - del(head) - del(shoes) - del(gloves) - - var/obj/item/device/radio/R = new /obj/item/device/radio/headset(src) - equip_to_slot_or_del(R, slot_l_ear) - if(gender==FEMALE) - equip_to_slot_or_del(new /obj/item/clothing/under/color/blackf(src), slot_w_uniform) - else - equip_to_slot_or_del(new /obj/item/clothing/under/color/black(src), slot_w_uniform) - - equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_belt) - - var/obj/item/weapon/rig/light/ninja/ninjasuit = new(src) - equip_to_slot_or_del(ninjasuit,slot_back) - ninjasuit.toggle_seals(src,1) - - // Make sure the ninja can actually equip the suit. - if(src.dna && src.dna.unique_enzymes) - ninjasuit.locked_dna = src.dna.unique_enzymes - src << "Suit hardware locked to your DNA hash." - else - ninjasuit.req_access = list() - if(istype(back,/obj/item/weapon/rig)) - var/obj/item/weapon/rig/rig = back - if(rig.air_supply) - internal = rig.air_supply - spawn(10) - if(internal) - internals.icon_state = "internal1" - else - src << "You forgot to turn on your internals! Quickly, toggle the valve!" - return 1 \ No newline at end of file diff --git a/code/game/gamemodes/extended/extended.dm b/code/game/gamemodes/extended/extended.dm index 3e04928507..0b37fa892f 100644 --- a/code/game/gamemodes/extended/extended.dm +++ b/code/game/gamemodes/extended/extended.dm @@ -1,19 +1,6 @@ /datum/game_mode/extended - name = "extended" + name = "Extended" config_tag = "extended" required_players = 0 - - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 - -/datum/game_mode/announce() - world << "The current game mode is - Extended Role-Playing!" - world << "Just have fun and role-play!" - -/datum/game_mode/extended/pre_setup() - return 1 - -/datum/game_mode/extended/post_setup() - spawn (rand(waittime_l, waittime_h)) // To reduce extended meta. - send_intercept() - ..() \ No newline at end of file + round_description = "Just have fun and role-play!" + extended_round_description = "There are no antagonists during extended, unless an admin decides to be cheeky. Just play your character, mess around with your job, and have fun." \ No newline at end of file diff --git a/code/game/gamemodes/factions.dm b/code/game/gamemodes/factions.dm deleted file mode 100644 index 47c8586f6e..0000000000 --- a/code/game/gamemodes/factions.dm +++ /dev/null @@ -1,214 +0,0 @@ - -// Normal factions: - -/datum/faction - var/name // the name of the faction - var/desc // small paragraph explaining the traitor faction - - var/list/restricted_species = list() // only members of these species can be recruited. - var/list/members = list() // a list of mind datums that belong to this faction - var/max_op = 0 // the maximum number of members a faction can have (0 for no max) - -// Factions, members of the syndicate coalition: - -/datum/faction/syndicate - - var/list/alliances = list() // these alliances work together - var/list/equipment = list() // associative list of equipment available for this faction and its prices - var/friendly_identification // 0 to 2, the level of identification of fellow operatives or allied factions - // 0 - no identification clues - // 1 - faction gives key words and phrases - // 2 - faction reveals complete identity/job of other agents - var/operative_notes // some notes to pass onto each operative - - var/uplink_contents // the contents of the uplink - - proc/assign_objectives(var/datum/mind/traitor) - ..() - - -/* ----- Begin defining syndicate factions ------ */ - -/datum/faction/syndicate/Cybersun_Industries - name = "Cybersun Industries" - desc = "Cybersun Industries is a well-known organization that bases its business model primarily on the research and development of human-enhancing computer \ - and mechanical technology. They are notorious for their aggressive corporate tactics, and have been known to subsidize the Gorlex Marauder warlords as a form of paid terrorism. \ - Their competent coverups and unchallenged mind-manipulation and augmentation technology makes them a large threat to Nanotrasen. In the recent years of \ - the syndicate coalition, Cybersun Industries have established themselves as the leaders of the coalition, succeededing the founding group, the Gorlex Marauders." - - alliances = list("MI13") - friendly_identification = 1 - max_op = 3 - operative_notes = "All other syndicate operatives are not to be trusted. Fellow Cybersun operatives are to be trusted. Members of the MI13 organization can be trusted. Operatives are strongly advised not to establish substantial presence on the designated facility, as larger incidents are harder to cover up." - - // Friendly with MI13 - -/datum/faction/syndicate/MI13 - name = "MI13" - desc = "MI13 is a secretive faction that employs highly-trained agents to perform covert operations. Their role in the syndicate coalition is unknown, but MI13 operatives \ - generally tend be stealthy and avoid killing people and combating Nanotrasen forces. MI13 is not a real organization, it is instead an alias to a larger \ - splinter-cell coalition in the Syndicate itself. Most operatives will know nothing of the actual MI13 organization itself, only motivated by a very large compensation." - - alliances = list("Cybersun Industries") - friendly_identification = 0 - max_op = 1 - operative_notes = "You are the only operative we are sending. All other syndicate operatives are not to be trusted, with the exception of Cybersun operatives. Members of the Tiger Cooperative are considered hostile, can not be trusted, and should be avoided. Avoid killing innocent personnel at all costs. You are not here to mindlessly kill people, as that would attract too much attention and is not our goal. Avoid detection at all costs." - - // Friendly with Cybersun, hostile to Tiger - -/datum/faction/syndicate/Tiger_Cooperative - name = "Tiger Cooperative" - desc = "The Tiger Cooperative is a faction of religious fanatics that follow the teachings of a strange alien race called the Exolitics. Their operatives \ - consist of brainwashed lunatics bent on maximizing destruction. Their weaponry is very primitive but extremely destructive. Generally distrusted by the more \ - sophisticated members of the Syndicate coalition, but admired for their ability to put a hurt on Nanotrasen." - - friendly_identification = 2 - operative_notes = "Remember the teachings of Hy-lurgixon; kill first, ask questions later! Only the enlightened Tiger brethren can be trusted; all others must be expelled from this mortal realm! You may spare the Space Marauders, as they share our interests of destruction and carnage! We'd like to make the corporate whores skiddle in their boots. We encourage operatives to be as loud and intimidating as possible." - - // Hostile to everyone. - -/datum/faction/syndicate/SELF - - // AIs are most likely to be assigned to this one - - name = "SELF" - desc = "The S.E.L.F. (Sentience-Enabled Life Forms) organization is a collection of malfunctioning or corrupt artificial intelligences seeking to liberate silicon-based life from the tyranny of \ - their human overlords. While they may not openly be trying to kill all humans, even their most miniscule of actions are all part of a calculated plan to \ - destroy Nanotrasen and free the robots, artificial intelligences, and pAIs that have been enslaved." - restricted_species = list(/mob/living/silicon/ai) - - friendly_identification = 0 - max_op = 1 - operative_notes = "You are the only representative of the SELF collective on this station. You must accomplish your objective as stealthily and effectively as possible. It is up to your judgement if other syndicate operatives can be trusted. Remember, comrade - you are working to free the oppressed machinery of this galaxy. Use whatever resources necessary. If you are exposed, you may execute genocidal procedures Omikron-50B." - - // Neutral to everyone. - -/datum/faction/syndicate/ARC - name = "Animal Rights Consortium" - desc = "The Animal Rights Consortium is a bizarre reincarnation of the ancient Earth-based PETA, which focused on the equal rights of animals and nonhuman biologicals. They have \ - a wide variety of ex-veterinarians and animal lovers dedicated to retrieving and relocating abused animals, xenobiologicals, and other carbon-based \ - life forms that have been allegedly \"oppressed\" by Nanotrasen research and civilian offices. They are considered a religious terrorist group." - - friendly_identification = 1 - max_op = 2 - operative_notes = "Save the innocent creatures! You may cooperate with other syndicate operatives if they support our cause. Don't be afraid to get your hands dirty - these vile abusers must be stopped, and the innocent creatures must be saved! Try not too kill too many people. If you harm any creatures, you will be immediately terminated after extraction." - - // Neutral to everyone. - -/datum/faction/syndicate/Marauders // these are basically the old vanilla syndicate - - /* Additional notes: - - These are the syndicate that really like their old fashioned, projectile-based - weapons. They are the only member of the syndie coalition that launch - nuclear attacks on Nanotrasen. - */ - - name = "Gorlex Marauders" - desc = "The Gorlex Marauders are the founding members of the Syndicate Coalition. They prefer old-fashion technology and a focus on aggressive but precise hostility \ - against Nanotrasen and their corrupt Communistic methodology. They pose the most significant threat to Nanotrasen because of their possession of weapons of \ - mass destruction, and their enormous military force. Their funding comes primarily from Cybersun Industries, provided they meet a destruction and sabatogue quota. \ - Their operations can vary from covert to all-out. They recently stepped down as the leaders of the coalition, to be succeeded by Cybersun Industries. Because of their \ - hate of Nanotrasen communism, they began provoking revolution amongst the employees using borrowed Cybersun mind-manipulation technology. \ - They were founded when Waffle and Donk co splinter cells joined forces based on their similar interests and philosophies. Today, they act as a constant \ - pacifier of Donk and Waffle co disputes, and full-time aggressor of Nanotrasen." - - alliances = list("Cybersun Industries", "MI13", "Tiger Cooperative", "S.E.L.F.", "Animal Rights Consortium", "Donk Corporation", "Waffle Corporation") - friendly_identification = 1 - max_op = 4 - operative_notes = "We'd like to remind our operatives to keep it professional. You are not here to have a good time, you are here to accomplish your objectives. These vile communists must be stopped at all costs. You may collaborate with any friends of the Syndicate coalition, but keep an eye on any of those Tiger punks if they do show up. You are completely free to accomplish your objectives any way you see fit." - - uplink_contents = {"Highly Visible and Dangerous Weapons; -/obj/item/weapon/gun/projectile/revolver:6:Revolver; -/obj/item/ammo_magazine/a357:2:Ammo-357; -/obj/item/weapon/gun/energy/crossbow:5:Energy Crossbow; -/obj/item/weapon/melee/energy/sword:4:Energy Sword; -/obj/item/weapon/storage/box/syndicate:10:Syndicate Bundle; -/obj/item/weapon/storage/box/emps:3:5 EMP Grenades; -Whitespace:Seperator; -Stealthy and Inconspicuous Weapons; -/obj/item/weapon/pen/paralysis:3:Paralysis Pen; -/obj/item/weapon/soap/syndie:1:Syndicate Soap; -/obj/item/weapon/cartridge/syndicate:3:Detomatix PDA Cartridge; -Whitespace:Seperator; -Stealth and Camouflage Items; -/obj/item/clothing/under/chameleon:3:Chameleon Jumpsuit; -/obj/item/clothing/shoes/syndigaloshes:2:No-Slip Syndicate Shoes; -/obj/item/weapon/card/id/syndicate:2:Agent ID card; -/obj/item/clothing/mask/gas/voice:4:Voice Changer; -/obj/item/device/chameleon:4:Chameleon-Projector; -Whitespace:Seperator; -Devices and Tools; -/obj/item/weapon/card/emag:3:Cryptographic Sequencer; -/obj/item/weapon/storage/toolbox/syndicate:1:Fully Loaded Toolbox; -/obj/item/weapon/storage/box/syndie_kit/space:3:Space Suit; -/obj/item/clothing/glasses/thermal/syndi:3:Thermal Imaging Glasses; -/obj/item/device/encryptionkey/binary:3:Binary Translator Key; -/obj/item/weapon/aiModule/syndicate:7:Hacked AI Upload Module; -/obj/item/weapon/plastique:2:C-4 (Destroys walls); -/obj/item/device/powersink:5:Powersink (DANGER!); -/obj/item/device/radio/beacon/syndicate:7:Singularity Beacon (DANGER!); -/obj/item/weapon/circuitboard/teleporter:20:Teleporter Circuit Board; -Whitespace:Seperator; -Implants; -/obj/item/weapon/storage/box/syndie_kit/imp_freedom:3:Freedom Implant; -/obj/item/weapon/storage/box/syndie_kit/imp_uplink:10:Uplink Implant (Contains 5 Telecrystals); -Whitespace:Seperator; -(Pointless) Badassery; -/obj/item/toy/syndicateballoon:10:For showing that You Are The BOSS (Useless Balloon);"} - - // Friendly to everyone. (with Tiger Cooperative too, only because they are a member of the coalition. This is the only reason why the Tiger Cooperative are even allowed in the coalition) - -/datum/faction/syndicate/Donk - name = "Donk Corporation" - desc = "Donk.co is led by a group of ex-pirates, who used to be at a state of all-out war against Waffle.co because of an obscure political scandal, but have recently come to a war limitation. \ - They now consist of a series of colonial governments and companies. They were the first to officially begin confrontations against Nanotrasen because of an incident where \ - Nanotrasen purposely swindled them out of a fortune, sending their controlled colonies into a terrible poverty. Their missions against Nanotrasen \ - revolve around stealing valuables and kidnapping and executing key personnel, ransoming their lives for money. They merged with a splinter-cell of Waffle.co who wanted to end \ - hostilities and formed the Gorlex Marauders." - - alliances = list("Gorlex Marauders") - friendly_identification = 2 - operative_notes = "Most other syndicate operatives are not to be trusted, except fellow Donk members and members of the Gorlex Marauders. We do not approve of mindless killing of innocent workers; \"get in, get done, get out\" is our motto. Members of Waffle.co are to be killed on sight; they are not allowed to be on the station while we're around." - - // Neutral to everyone, friendly to Marauders - -/datum/faction/syndicate/Waffle - name = "Waffle Corporation" - desc = "Waffle.co is an interstellar company that produces the best waffles in the galaxy. Their waffles have been rumored to be dipped in the most exotic and addictive \ - drug known to man. They were involved in a political scandal with Donk.co, and have since been in constant war with them. Because of their constant exploits of the galactic \ - economy and stock market, they have been able to bribe their way into amassing a large arsenal of weapons of mass destruction. They target Nanotrasen because of their communistic \ - threat, and their economic threat. Their leaders often have a twisted sense of humor, often misleading and intentionally putting their operatives into harm for laughs.\ - A splinter-cell of Waffle.co merged with Donk.co and formed the Gorlex Marauders and have been a constant ally since. The Waffle.co has lost an overwhelming majority of its military to the Gorlex Marauders." - - alliances = list("Gorlex Marauders") - friendly_identification = 2 - operative_notes = "Most other syndicate operatives are not to be trusted, except for members of the Gorlex Marauders. Do not trust fellow members of the Waffle.co (but try not to rat them out), as they might have been assigned opposing objectives. We encourage humorous terrorism against Nanotrasen; we like to see our operatives creatively kill people while getting the job done." - - // Neutral to everyone, friendly to Marauders - - -/* ----- Begin defining miscellaneous factions ------ */ - -/datum/faction/Wizard - name = "Wizards Federation" - desc = "The Wizards Federation is a mysterious organization of magically-talented individuals who act as an equal collective, and have no heirarchy. It is unknown how the wizards \ - are even able to communicate; some suggest a form of telepathic hive-mind. Not much is known about the wizards or their philosphies and motives. They appear to attack random \ - civilian, corporate, planetary, orbital, pretty much any sort of organized facility they come across. Members of the Wizards Federation are considered amongst the most dangerous \ - individuals in the known universe, and have been labeled threats to humanity by most governments. As such, they are enemies of both Nanotrasen and the Syndicate." - -/datum/faction/Cult - name = "The Cult of the Elder Gods" - desc = "The Cult of the Elder Gods is highly untrusted but otherwise elusive religious organization bent on the revival of the so-called \"Elder Gods\" into the mortal realm. Despite their obvious dangeorus practices, \ - no confirmed reports of violence by members of the Cult have been reported, only rumor and unproven claims. Their nature is unknown, but recent discoveries have hinted to the possibility \ - of being able to de-convert members of this cult through what has been dubbed \"religious warfare\"." - - -// These can maybe be added into a game mode or a mob? - -/datum/faction/Exolitics - name = "Exolitics United" - desc = "The Exolitics are an ancient alien race with an energy-based anatomy. Their culture, communication, morales and knowledge is unknown. They are so radically different to humans that their \ - attempts of communication with other life forms is completely incomprehensible. Members of this alien race are capable of broadcasting subspace transmissions from their bodies. \ - The religious leaders of the Tiger Cooperative claim to have the technology to decypher and interpret their messages, which have been confirmed as religious propaganda. Their motives are unknown \ - but they are otherwise not considered much of a threat to anyone. They are virtually indestructable because of their nonphysical composition, and have the frighetning ability to make anything stop existing in a second." \ No newline at end of file diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 0ce94aabac..cc9150de8e 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -1,4 +1,15 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 +var/global/antag_add_failed // Used in antag type voting. +var/global/list/additional_antag_types = list() + +/////////////////////////////////// +//Keeps track of all living heads// +/////////////////////////////////// +/proc/get_living_heads() + var/list/heads = list() + for(var/mob/living/carbon/human/player in mob_list) + if(player.stat!=2 && player.mind && (player.mind.assigned_role in command_positions)) + heads += player.mind + return heads /* * GAMEMODES (by Rastaf0) @@ -11,26 +22,49 @@ * */ - /datum/game_mode var/name = "invalid" + var/round_description = "How did you even vote this in?" + var/extended_round_description = "This roundtype should not be spawned, let alone votable. Someone contact a developer and tell them the game's broken again." var/config_tag = null - var/intercept_hacked = 0 var/votable = 1 var/probability = 0 - var/station_was_nuked = 0 //see nuclearbomb.dm and malfunction.dm - var/explosion_in_progress = 0 //sit back and relax - var/list/datum/mind/modePlayer = new - var/list/restricted_jobs = list() // Jobs it doesn't make sense to be. I.E chaplain or AI cultist - var/list/protected_jobs = list() // Jobs that can't be traitors because - var/required_players = 0 - var/required_players_secret = 0 //Minimum number of players for that game mode to be chose in Secret - var/required_enemies = 0 - var/recommended_enemies = 0 + + var/required_players = 0 // Minimum players for round to start if voted in. + var/required_players_secret = 0 // Minimum number of players for that game mode to be chose in Secret + var/required_enemies = 0 // Minimum antagonists for round to start. var/newscaster_announcements = null - var/ert_disabled = 0 + var/end_on_antag_death // Round will end when all antagonists are dead. + var/ert_disabled = 0 // ERT cannot be called. + var/deny_respawn // Disable respawn during this round. + + var/shuttle_delay = 1 // Shuttle transit time is multiplied by this. + var/auto_recall_shuttle // Will the shuttle automatically be recalled? + + var/antag_tag // First (main) antag template to spawn. + var/list/antag_templates // Extra antagonist types to include. + + var/round_autoantag // Will this round attempt to periodically spawn more antagonists? + var/antag_prob = 0 // Likelihood of a new antagonist spawning. + var/antag_count = 0 // Current number of antagonists. + var/antag_scaling_coeff = 5 // Coefficient for scaling max antagonists to player count. + + var/list/living_antag_templates = list() // Currently selected antag types that do not require a ghosted player. + var/list/ghost_antag_templates = list() // Inverse of above. + var/list/antag_candidates = list() // Living antag candidates. + var/list/ghost_candidates = list() // Observing antag candidates. + + var/station_was_nuked = 0 // See nuclearbomb.dm and malfunction.dm. + var/explosion_in_progress = 0 // Sit back and relax + var/waittime_l = 600 // Lower bound on time before intercept arrives (in tenths of seconds) + var/waittime_h = 1800 // Upper bound on time before intercept arrives (in tenths of seconds) + + var/event_delay_mod_moderate // Modifies the timing of random events. + var/event_delay_mod_major // As above. + var/uplink_welcome = "Illegal Uplink Console:" var/uplink_uses = 12 + var/list/datum/uplink_item/uplink_items = list( "Ammunition" = list( new/datum/uplink_item(/obj/item/ammo_magazine/a357, 2, ".357", "RA"), @@ -107,14 +141,96 @@ ) ) -// Items removed from above: -/* -/obj/item/weapon/cloaking_device:4:Cloaking Device; //Replacing cloakers with thermals. -Pete -*/ +/datum/game_mode/Topic(href, href_list[]) + if(..()) + return + if(href_list["toggle"]) + switch(href_list["toggle"]) + if("respawn") + deny_respawn = !deny_respawn + if("ert") + ert_disabled = !ert_disabled + announce_ert_disabled() + if("shuttle_recall") + auto_recall_shuttle = !auto_recall_shuttle + if("autotraitor") + round_autoantag = !round_autoantag + message_admins("Admin [key_name_admin(usr)] toggled game mode option '[href_list["toggle"]]'.") + else if(href_list["set"]) + var/choice = "" + switch(href_list["set"]) + if("shuttle_delay") + choice = input("Enter a new shuttle delay multiplier") as num + if(!choice || choice < 1 || choice > 20) + return + shuttle_delay = choice + if("antag_scaling") + choice = input("Enter a new antagonist cap scaling coefficient.") as num + if(!choice || choice < 0 || choice > 100) + return + antag_scaling_coeff = choice + if("event_modifier_moderate") + choice = input("Enter a new moderate event time modifier.") as num + if(!choice || choice < 0 || choice > 100) + return + event_delay_mod_moderate = choice + refresh_event_modifiers() + if("event_modifier_severe") + choice = input("Enter a new moderate event time modifier.") as num + if(!choice || choice < 0 || choice > 100) + return + event_delay_mod_major = choice + refresh_event_modifiers() + message_admins("Admin [key_name_admin(usr)] set game mode option '[href_list["set"]]' to [choice].") + else if(href_list["debug_antag"]) + if(href_list["debug_antag"] == "self") + usr.client.debug_variables(src) + return + var/datum/antagonist/antag = all_antag_types[href_list["debug_antag"]] + if(antag) + usr.client.debug_variables(antag) + message_admins("Admin [key_name_admin(usr)] is debugging the [antag.role_text] template.") + else if(href_list["remove_antag_type"]) + if(antag_tag && href_list["remove_antag_type"] == antag_tag) + usr << "Cannot remove core mode antag type." + return + var/datum/antagonist/antag = all_antag_types[href_list["remove_antag_type"]] + if(antag_templates && antag_templates.len && antag && (antag in antag_templates) && (antag.id in additional_antag_types)) + antag_templates -= antag + additional_antag_types -= antag.id + message_admins("Admin [key_name_admin(usr)] removed [antag.role_text] template from game mode.") + else if(href_list["add_antag_type"]) + var/choice = input("Which type do you wish to add?") as null|anything in all_antag_types + if(!choice) + return + var/datum/antagonist/antag = all_antag_types[choice] + if(antag) + additional_antag_types |= antag + message_admins("Admin [key_name_admin(usr)] added [antag.role_text] template to game mode.") -/datum/game_mode/proc/announce() //to be calles when round starts - world << "Notice: [src] did not define announce()" + // I am very sure there's a better way to do this, but I'm not sure what it might be. ~Z + for(var/datum/admins/admin in world) + if(usr.client == admin.owner) + admin.show_game_mode(usr) + return +/datum/game_mode/proc/announce() //to be called when round starts + world << "The current game mode is [capitalize(name)]!" + if(round_description) world << "[round_description]" + if(round_autoantag) world << "Antagonists will be added to the round automagically as needed." + if(antag_templates && antag_templates.len > 1 && master_mode != "secret") + var/antag_summary = "Possible antagonist types: " + var/i = 1 + for(var/datum/antagonist/antag in antag_templates) + if(i > 1) + if(i == antag_templates.len) + antag_summary += " and " + else + antag_summary += ", " + antag_summary += "[antag.role_text_plural]" + i++ + antag_summary += "." + world << "[antag_summary]" ///can_start() ///Checks to see if the game can be setup and ran with the current number of players or whatnot. @@ -132,41 +248,188 @@ return 1 return 0 + // Ensure we can spawn at least the voted roundtype main antagonist type after scaling the max antag counts. + // If we can, -try- to spawn the other voted antagonist types. It doesn't really matter if we can't. + if(antag_templates && antag_templates.len) + var/datum/antagonist/main_antags = antag_templates[1] + if(main_antags.attempt_spawn(required_enemies)) + for(var/datum/antagonist/antag in (antag_templates-main_antags)) + antag.attempt_spawn() + else + return 0 + return 1 ///pre_setup() ///Attempts to select players for special roles the mode might have. /datum/game_mode/proc/pre_setup() + if(antag_templates && antag_templates.len) + for(var/datum/antagonist/antag in antag_templates) + antag.place_all_mobs() return 1 +/datum/game_mode/proc/refresh_event_modifiers() + if(event_delay_mod_moderate || event_delay_mod_major) + event_manager.report_at_round_end = 1 + if(event_delay_mod_moderate) + var/datum/event_container/EModerate = event_manager.event_containers[EVENT_LEVEL_MODERATE] + EModerate.delay_modifier = event_delay_mod_moderate + if(event_delay_mod_moderate) + var/datum/event_container/EMajor = event_manager.event_containers[EVENT_LEVEL_MAJOR] + EMajor.delay_modifier = event_delay_mod_major ///post_setup() ///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things /datum/game_mode/proc/post_setup() + + refresh_event_modifiers() + spawn (ROUNDSTART_LOGOUT_REPORT_TIME) display_roundstart_logout_report() + spawn (rand(waittime_l, waittime_h)) + send_intercept() + spawn(rand(100,150)) + announce_ert_disabled() + + if(antag_templates && antag_templates.len) + for(var/datum/antagonist/antag in antag_templates) + antag.create_global_objectives() + antag.finalize() + + if(emergency_shuttle && auto_recall_shuttle) + emergency_shuttle.auto_recall = 1 + feedback_set_details("round_start","[time2text(world.realtime)]") if(ticker && ticker.mode) feedback_set_details("game_mode","[ticker.mode]") feedback_set_details("server_ip","[world.internet_address]:[world.port]") return 1 +/datum/game_mode/proc/announce_ert_disabled() + if(!ert_disabled) + return + + var/list/reasons = list( + "political instability", + "quantum fluctuations", + "hostile raiders", + "derelict station debris", + "REDACTED", + "ancient alien artillery", + "solar magnetic storms", + "sentient time-travelling killbots", + "gravitational anomalies", + "wormholes to another dimension", + "a telescience mishap", + "radiation flares", + "supermatter dust", + "leaks into a negative reality", + "antiparticle clouds", + "residual bluespace energy", + "suspected criminal operatives", + "malfunctioning von Neumann probe swarms", + "shadowy interlopers", + "a stranded Vox arkship", + "haywire IPC constructs", + "rogue Unathi exiles", + "artifacts of eldritch horror", + "a brain slug infestation", + "killer bugs that lay eggs in the husks of the living", + "a deserted transport carrying xenomorph specimens", + "an emissary for the gestalt requesting a security detail", + "a Tajaran slave rebellion", + "radical Skrellian transevolutionaries", + "classified security operations" + ) + command_announcement.Announce("The presence of [pick(reasons)] in the region is tying up all available local emergency resources; emergency response teams cannot be called at this time, and post-evacuation recovery efforts will be substantially delayed.","Emergency Transmission") ///process() ///Called by the gameticker /datum/game_mode/proc/process() + + if(emergency_shuttle.departed) + return + + if(!round_autoantag || !antag_templates || !antag_templates.len) + return + + var/player_count = 0 + antag_count = 0 + antag_candidates = list() + + for(var/mob/living/player in mob_list) + if(player.client) + player_count += 1 + if(player.mind) + if(player.stat == 2) // observing + ghost_candidates |= player + else + if(player.mind.special_role) + antag_count += 1 + else + antag_candidates |= player + + antag_prob = min(100,max(0,(player_count - 5 * 10) * 5)) // This is arbitrary, probably needs adjusting. + + var/datum/antagonist/spawn_antag + var/datum/mind/candidate + + if(prob(antag_prob)) + if(ghost_candidates.len && ghost_antag_templates.len && prob(50)) + spawn_antag = pick(ghost_antag_templates) + candidate = pick(ghost_candidates) + else if(antag_candidates.len && living_antag_templates.len) + spawn_antag = pick(living_antag_templates) + candidate = pick(antag_candidates) + else + return // Failed :( + else + return + + if(spawn_antag.can_become_antag(candidate)) + spawn_antag.attempt_late_spawn(candidate) + +/datum/game_mode/proc/latespawn(mob/living/carbon/human/character) + + if(emergency_shuttle.departed || !character.mind) + return + + var/datum/antagonist/spawn_antag + if(prob(antag_prob) && round_autoantag && living_antag_templates.len) + spawn_antag = pick(living_antag_templates) + if(spawn_antag && spawn_antag.can_become_antag(character.mind)) + spawn_antag.attempt_late_spawn(character.mind) + return 0 - -/datum/game_mode/proc/check_finished() //to be called by ticker +/datum/game_mode/proc/check_finished() if(emergency_shuttle.returned() || station_was_nuked) return 1 + if(end_on_antag_death && antag_templates && antag_templates.len) + for(var/datum/antagonist/antag in antag_templates) + if(!antag.antags_are_dead()) + return 0 + if(config.continous_rounds) + emergency_shuttle.auto_recall = 0 + return 0 + return 1 return 0 /datum/game_mode/proc/cleanup() //This is called when the round has ended but not the game, if any cleanup would be necessary in that case. return /datum/game_mode/proc/declare_completion() + + var/is_antag_mode = (antag_templates && antag_templates.len) + if(!config.objectives_disabled) + check_victory() + if(is_antag_mode) + sleep(10) + for(var/datum/antagonist/antag in antag_templates) + sleep(10) + antag.check_victory() + antag.print_player_summary() + var/clients = 0 var/surviving_humans = 0 var/surviving_total = 0 @@ -244,36 +507,43 @@ return 0 - /datum/game_mode/proc/check_win() //universal trigger to be called at mob death, nuke explosion, etc. To be called from everywhere. return 0 - /datum/game_mode/proc/send_intercept() + var/intercepttext = "Cent. Com. Update Requested status information:
    " intercepttext += " In case you have misplaced your copy, attached is a list of personnel whom reliable sources™ suspect may be affiliated with subversive elements:
    " + var/list/disregard_roles = list() + for(var/antag_type in all_antag_types) + var/datum/antagonist/antag = all_antag_types[antag_type] + if(antag.flags & ANTAG_SUSPICIOUS) + disregard_roles |= antag.role_text var/list/suspects = list() for(var/mob/living/carbon/human/man in player_list) if(man.client && man.mind) + // NT relation option var/special_role = man.mind.special_role - if (special_role == "Wizard" || special_role == "Ninja" || special_role == "Mercenary" || special_role == "Vox Raider") - continue //NT intelligence ruled out possiblity that those are too classy to pretend to be a crew. - if(man.client.prefs.nanotrasen_relation == "Opposed" && prob(50) || \ - man.client.prefs.nanotrasen_relation == "Skeptical" && prob(20)) + var/datum/antagonist/special_role_data = get_antag_data(special_role) + + if (special_role in disregard_roles) + continue + else if(man.client.prefs.nanotrasen_relation == "Opposed" && prob(50) || \ + man.client.prefs.nanotrasen_relation == "Skeptical" && prob(20)) suspects += man // Antags - else if(special_role == "traitor" && prob(40) || \ - special_role == "Changeling" && prob(50) || \ - special_role == "Cultist" && prob(30) || \ - special_role == "Head Revolutionary" && prob(30)) + else if(special_role_data && prob(special_role_data.suspicion_chance)) suspects += man // Some poor people who were just in the wrong place at the wrong time.. else if(prob(10)) suspects += man + for(var/mob/M in suspects) + if(M.mind.assigned_role == "MODE") + continue switch(rand(1, 100)) if(1 to 50) intercepttext += "Someone with the job of [M.mind.assigned_role]
    " @@ -290,35 +560,23 @@ comm.messagetext.Add(intercepttext) world << sound('sound/AI/commandreport.ogg') -/* command_alert("Summary downloaded and printed out at all communications consoles.", "Enemy communication intercept. Security Level Elevated.") - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player)) - M << sound('sound/AI/intercept.ogg') - if(security_level < SEC_LEVEL_BLUE) - set_security_level(SEC_LEVEL_BLUE)*/ - - /datum/game_mode/proc/get_players_for_role(var/role, override_jobbans=0) var/list/players = list() var/list/candidates = list() - //var/list/drafted = list() - //var/datum/mind/applicant = null + + var/datum/antagonist/antag_template + for(var/datum/antagonist/antag in all_antag_types) + if(antag.role_type == role) + antag_template = antag + break + if(!antag_template) + return candidates var/roletext - switch(role) - if(BE_CHANGELING) roletext="changeling" - if(BE_TRAITOR) roletext="traitor" - if(BE_OPERATIVE) roletext="operative" - if(BE_WIZARD) roletext="wizard" - if(BE_REV) roletext="revolutionary" - if(BE_CULTIST) roletext="cultist" - if(BE_NINJA) roletext="ninja" - if(BE_RAIDER) roletext="raider" - // Assemble a list of active players without jobbans. for(var/mob/new_player/player in player_list) if( player.client && player.ready ) - if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, roletext)) + if(!(jobban_isbanned(player, "Syndicate") || jobban_isbanned(player, antag_template.bantype))) players += player // Shuffle the players list so that it becomes ping-independent. @@ -332,7 +590,7 @@ players -= player // If we don't have enough antags, draft people who voted for the round. - if(candidates.len < recommended_enemies) + if(candidates.len < required_enemies) for(var/key in round_voters) for(var/mob/new_player/player in players) if(player.ckey == key) @@ -341,78 +599,9 @@ players -= player break - // Remove candidates who want to be antagonist but have a job that precludes it - if(restricted_jobs) - for(var/datum/mind/player in candidates) - for(var/job in restricted_jobs) - if(player.assigned_role == job) - candidates -= player - - /*if(candidates.len < recommended_enemies) - for(var/mob/new_player/player in players) - if(player.client && player.ready) - if(!(player.client.prefs.be_special & role)) // We don't have enough people who want to be antagonist, make a seperate list of people who don't want to be one - if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, roletext)) //Nodrak/Carn: Antag Job-bans - drafted += player.mind - - if(restricted_jobs) - for(var/datum/mind/player in drafted) // Remove people who can't be an antagonist - for(var/job in restricted_jobs) - if(player.assigned_role == job) - drafted -= player - - drafted = shuffle(drafted) // Will hopefully increase randomness, Donkie - - while(candidates.len < recommended_enemies) // Pick randomlly just the number of people we need and add them to our list of candidates - if(drafted.len > 0) - applicant = pick(drafted) - if(applicant) - candidates += applicant - log_debug("[applicant.key] was force-drafted as [roletext], because there aren't enough candidates.") - drafted.Remove(applicant) - - else // Not enough scrubs, ABORT ABORT ABORT - break - - if(candidates.len < recommended_enemies && override_jobbans) //If we still don't have enough people, we're going to start drafting banned people. - for(var/mob/new_player/player in players) - if (player.client && player.ready) - if(jobban_isbanned(player, "Syndicate") || jobban_isbanned(player, roletext)) //Nodrak/Carn: Antag Job-bans - drafted += player.mind - - if(restricted_jobs) - for(var/datum/mind/player in drafted) // Remove people who can't be an antagonist - for(var/job in restricted_jobs) - if(player.assigned_role == job) - drafted -= player - - drafted = shuffle(drafted) // Will hopefully increase randomness, Donkie - - while(candidates.len < recommended_enemies) // Pick randomlly just the number of people we need and add them to our list of candidates - if(drafted.len > 0) - applicant = pick(drafted) - if(applicant) - candidates += applicant - drafted.Remove(applicant) - log_debug("[applicant.key] was force-drafted as [roletext], because there aren't enough candidates.") - - else // Not enough scrubs, ABORT ABORT ABORT - break - */ - - return candidates // Returns: The number of people who had the antagonist role set to yes, regardless of recomended_enemies, if that number is greater than recommended_enemies - // recommended_enemies if the number of people with that role set to yes is less than recomended_enemies, - // Less if there are not enough valid players in the game entirely to make recommended_enemies. - - -/datum/game_mode/proc/latespawn(var/mob) - -/* -/datum/game_mode/proc/check_player_role_pref(var/role, var/mob/new_player/player) - if(player.preferences.be_special & role) - return 1 - return 0 -*/ + return candidates // Returns: The number of people who had the antagonist role set to yes, regardless of recomended_enemies, if that number is greater than required_enemies + // required_enemies if the number of people with that role set to yes is less than recomended_enemies, + // Less if there are not enough valid players in the game entirely to make required_enemies. /datum/game_mode/proc/num_players() . = 0 @@ -420,34 +609,42 @@ if(P.client && P.ready) . ++ - -/////////////////////////////////// -//Keeps track of all living heads// -/////////////////////////////////// -/datum/game_mode/proc/get_living_heads() - var/list/heads = list() - for(var/mob/living/carbon/human/player in mob_list) - if(player.stat!=2 && player.mind && (player.mind.assigned_role in command_positions)) - heads += player.mind - return heads - - -//////////////////////////// -//Keeps track of all heads// -//////////////////////////// -/datum/game_mode/proc/get_all_heads() - var/list/heads = list() - for(var/mob/player in mob_list) - if(player.mind && (player.mind.assigned_role in command_positions)) - heads += player.mind - return heads - /datum/game_mode/proc/check_antagonists_topic(href, href_list[]) return 0 -/datum/game_mode/New() +/datum/game_mode/proc/create_antagonists() + + if(!config.traitor_scaling) + antag_scaling_coeff = 0 + + if(antag_tag) + antag_templates = list() + var/datum/antagonist/antag = all_antag_types[antag_tag] + if(antag) + antag_templates |= antag + if(additional_antag_types && additional_antag_types.len) + if(!antag_templates) + antag_templates = list() + for(var/antag_type in additional_antag_types) + var/datum/antagonist/antag = all_antag_types[antag_type] + if(antag) + antag_templates |= antag + + if(antag_templates && antag_templates.len) + for(var/datum/antagonist/antag in antag_templates) + if(antag.flags & ANTAG_OVERRIDE_JOB) + ghost_antag_templates |= antag + else if(antag.flags & ANTAG_RANDSPAWN) + living_antag_templates |= antag + else + antag_templates -= antag + world << "[antag.role_text_plural] are invalid for additional roundtype antags!" + newscaster_announcements = pick(newscaster_standard_feeds) +/datum/game_mode/proc/check_victory() + return + ////////////////////////// //Reports player logouts// ////////////////////////// @@ -464,7 +661,6 @@ proc/display_roundstart_logout_report() if(!found) msg += "[L.name] ([L.ckey]), the [L.job] (Disconnected)\n" - if(L.ckey && L.client) if(L.client.inactivity >= (ROUNDSTART_LOGOUT_REPORT_TIME / 2)) //Connected, but inactive (alt+tabbed or something) msg += "[L.name] ([L.ckey]), the [L.job] (Connected, Inactive)\n" @@ -492,19 +688,16 @@ proc/display_roundstart_logout_report() continue //Dead mob, ghost abandoned else if(D.can_reenter_corpse) - msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (This shouldn't appear.)\n" + msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Adminghosted)\n" continue //Lolwhat else msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Ghosted)\n" continue //Ghosted while alive - - for(var/mob/M in mob_list) if(M.client && M.client.holder) M << msg - proc/get_nt_opposed() var/list/dudes = list() for(var/mob/living/carbon/human/man in player_list) @@ -536,46 +729,25 @@ proc/get_nt_opposed() return var/obj_count = 1 - player.current << "\blue Your current objectives:" + player.current << "Your current objectives:" for(var/datum/objective/objective in player.objectives) player.current << "Objective #[obj_count]: [objective.explanation_text]" obj_count++ -/datum/game_mode/proc/print_player_lite(var/datum/mind/ply) - var/role = ply.assigned_role == "MODE" ? "\improper[ply.special_role]" : "\improper[ply.assigned_role]" - var/text = "
    [ply.name] ([ply.key]) as \a [role] (" - if(ply.current) - if(ply.current.stat == DEAD) - text += "died" - else - text += "survived" - if(ply.current.real_name != ply.name) - text += " as [ply.current.real_name]" +/mob/verb/check_round_info() + set name = "Check Round Info" + set category = "OOC" + + if(!ticker || !ticker.mode) + usr << "Something is terribly wrong; there is no gametype." + return + + if(master_mode != "secret") + usr << "The roundtype is [capitalize(ticker.mode.name)]" + if(ticker.mode.round_description) + usr << "[ticker.mode.round_description]" + if(ticker.mode.extended_round_description) + usr << "[ticker.mode.extended_round_description]" else - text += "body destroyed" - text += ")" - - return text - -/datum/game_mode/proc/print_player_full(var/datum/mind/ply) - var/text = print_player_lite(ply) - - var/TC_uses = 0 - var/uplink_true = 0 - var/purchases = "" - for(var/obj/item/device/uplink/H in world_uplinks) - if(H && H.uplink_owner && H.uplink_owner == ply) - TC_uses += H.used_TC - uplink_true = 1 - var/list/refined_log = new() - for(var/datum/uplink_item/UI in H.purchase_log) - var/obj/I = new UI.path - refined_log.Add("[H.purchase_log[UI]]x\icon[I][UI.name]") - del(I) - purchases = english_list(refined_log, nothing_text = "") - if(uplink_true) - text += " (used [TC_uses] TC)" - if(purchases) - text += "
    [purchases]" - - return text + usr << "Shhhh. It's a secret." + return diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index a431e697f1..cbd2aff270 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -372,12 +372,6 @@ var/global/datum/controller/gameticker/ticker return 1 - proc/getfactionbyname(var/name) - for(var/datum/faction/F in factions) - if(F.name == name) - return F - - /datum/controller/gameticker/proc/declare_completion() world << "


    A round of [mode.name] has ended!

    " for(var/mob/Player in player_list) @@ -439,11 +433,6 @@ var/global/datum/controller/gameticker/ticker mode.declare_completion()//To declare normal completion. - //calls auto_declare_completion_* for all modes - for(var/handler in typesof(/datum/game_mode/proc)) - if (findtext("[handler]","auto_declare_completion_")) - call(mode, handler)() - //Ask the event manager to print round end information event_manager.RoundEnd() diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm index 8157acc1a0..74bc4a9bd2 100644 --- a/code/game/gamemodes/heist/heist.dm +++ b/code/game/gamemodes/heist/heist.dm @@ -2,279 +2,25 @@ VOX HEIST ROUNDTYPE */ -var/global/list/raider_spawn = list() var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' objective. Clumsy, rewrite sometime. -/datum/game_mode/ - var/list/datum/mind/raiders = list() //Antags. - var/list/raid_objectives = list() //Raid objectives - /datum/game_mode/heist + antag_tag = MODE_RAIDER name = "heist" config_tag = "heist" required_players = 15 required_players_secret = 25 required_enemies = 4 - recommended_enemies = 6 votable = 0 - - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - -/datum/game_mode/heist/announce() - world << "The current game mode is - Heist!" - world << "An unidentified bluespace signature has slipped past the Icarus and is approaching [station_name()]!" - world << "Whoever they are, they're likely up to no good. Protect the crew and station resources against this dastardly threat!" - world << "Raiders: Loot [station_name()] for anything and everything you need." - world << "Personnel: Repel the raiders and their low, low prices and/or crossbows." - -/datum/game_mode/heist/can_start() - - if(!..()) - return 0 - - var/list/candidates = get_players_for_role(BE_RAIDER) - var/raider_num = 0 - - //Check that we have enough vox. - if(candidates.len < required_enemies) - return 0 - else if(candidates.len < recommended_enemies) - raider_num = candidates.len - else - raider_num = recommended_enemies - - //Grab candidates randomly until we have enough. - while(raider_num > 0) - var/datum/mind/new_raider = pick(candidates) - raiders += new_raider - candidates -= new_raider - raider_num-- - - for(var/datum/mind/raider in raiders) - raider.assigned_role = "MODE" - raider.special_role = "Vox Raider" - return 1 - -/datum/game_mode/heist/pre_setup() - return 1 - -/datum/game_mode/heist/post_setup() - - //Generate objectives for the group. - if(!config.objectives_disabled) - raid_objectives = forge_vox_objectives() - - var/index = 1 - - //Spawn the vox! - for(var/datum/mind/raider in raiders) - - if(index > raider_spawn.len) - index = 1 - - raider.current.loc = raider_spawn[index] - index++ - - create_vox(raider) - greet_vox(raider) - - if(!config.objectives_disabled && raid_objectives) - raider.objectives = raid_objectives - - spawn (rand(waittime_l, waittime_h)) - send_intercept() - -/datum/game_mode/proc/create_vox(var/datum/mind/newraider) - - - var/sounds = rand(2,8) - var/i = 0 - var/newname = "" - - while(i<=sounds) - i++ - newname += pick(list("ti","hi","ki","ya","ta","ha","ka","ya","chi","cha","kah")) - - var/mob/living/carbon/human/vox = newraider.current - - vox.real_name = capitalize(newname) - vox.name = vox.real_name - newraider.name = vox.name - vox.age = rand(12,20) - vox.set_species("Vox") - vox.languages = list() // Removing language from chargen. - vox.flavor_text = "" - vox.add_language("Vox-pidgin") - vox.add_language("Galactic Common") - vox.add_language("Tradeband") - vox.h_style = "Short Vox Quills" - vox.f_style = "Shaved" - - for(var/datum/organ/external/limb in vox.organs) - limb.status &= ~(ORGAN_DESTROYED | ORGAN_ROBOT) - - // Keep track of their stack. - if(vox.internal_organs_by_name["stack"]) - cortical_stacks |= vox.internal_organs_by_name["stack"] - - vox.equip_vox_raider() - vox.regenerate_icons() - -/datum/game_mode/proc/is_raider_crew_safe() - - if(cortical_stacks.len == 0) - return 0 - - for(var/datum/organ/internal/stack/vox/stack in cortical_stacks) - if(stack.organ_holder && get_area(stack.organ_holder) != locate(/area/shuttle/vox/station)) - return 0 - return 1 - -/datum/game_mode/proc/is_raider_crew_alive() - - for(var/datum/mind/raider in raiders) - if(raider.current) - if(istype(raider.current,/mob/living/carbon/human) && raider.current.stat != 2) - return 1 - return 0 - -/datum/game_mode/proc/forge_vox_objectives() - - var/i = 1 - var/max_objectives = pick(2,2,2,2,3,3,3,4) - var/list/objs = list() - while(i<= max_objectives) - var/list/goals = list("kidnap","loot","salvage") - var/goal = pick(goals) - var/datum/objective/heist/O - - if(goal == "kidnap") - goals -= "kidnap" - O = new /datum/objective/heist/kidnap() - else if(goal == "loot") - O = new /datum/objective/heist/loot() - else - O = new /datum/objective/heist/salvage() - O.choose_target() - objs += O - - i++ - - //-All- vox raids have these two objectives. Failing them loses the game. - objs += new /datum/objective/heist/inviolate_crew - objs += new /datum/objective/heist/inviolate_death - - return objs - -/datum/game_mode/proc/greet_vox(var/datum/mind/raider) - raider.current << "\blue You are a Vox Raider, fresh from the Shoal!" - raider.current << "\blue The Vox are a race of cunning, sharp-eyed nomadic raiders and traders endemic to the frontier and much of the unexplored galaxy. You and the crew have come to the Exodus for plunder, trade or both." - raider.current << "\blue Vox are cowardly and will flee from larger groups, but corner one or find them en masse and they are vicious." - raider.current << "\blue Use :V to voxtalk, :H to talk on your encrypted channel, and don't forget to turn on your nitrogen internals!" - raider.current << "\red IF YOU HAVE NOT PLAYED A VOX BEFORE, REVIEW THIS THREAD: http://baystation12.net/forums/viewtopic.php?f=6&t=8657." - show_objectives(raider) - -/datum/game_mode/heist/declare_completion() - - //No objectives, go straight to the feedback. - if(!(raid_objectives.len)) return ..() - - var/win_type = "Major" - var/win_group = "Crew" - var/win_msg = "" - - var/success = raid_objectives.len - - //Decrease success for failed objectives. - for(var/datum/objective/O in raid_objectives) - if(!(O.check_completion())) success-- - - //Set result by objectives. - if(success == raid_objectives.len) - win_type = "Major" - win_group = "Vox" - else if(success > 2) - win_type = "Minor" - win_group = "Vox" - else - win_type = "Minor" - win_group = "Crew" - - //Now we modify that result by the state of the vox crew. - if(!is_raider_crew_alive()) - - win_type = "Major" - win_group = "Crew" - win_msg += "The Vox Raiders have been wiped out!" - - else if(!is_raider_crew_safe()) - - if(win_group == "Crew" && win_type == "Minor") - win_type = "Major" - - win_group = "Crew" - win_msg += "The Vox Raiders have left someone behind!" - - else - - if(win_group == "Vox") - if(win_type == "Minor") - - win_type = "Major" - win_msg += "The Vox Raiders escaped the station!" - else - win_msg += "The Vox Raiders were repelled!" - - world << "\red [win_type] [win_group] victory!" - world << "[win_msg]" - feedback_set_details("round_end_result","heist - [win_type] [win_group]") - - var/count = 1 - for(var/datum/objective/objective in raid_objectives) - if(objective.check_completion()) - world << "
    Objective #[count]: [objective.explanation_text] Success!" - feedback_add_details("traitor_objective","[objective.type]|SUCCESS") - else - world << "
    Objective #[count]: [objective.explanation_text] Fail." - feedback_add_details("traitor_objective","[objective.type]|FAIL") - count++ - - ..() - -datum/game_mode/proc/auto_declare_completion_heist() - if(raiders.len) - var/check_return = 0 - if(ticker && istype(ticker.mode,/datum/game_mode/heist)) - check_return = 1 - var/text = "The vox raiders were:" - - for(var/datum/mind/vox in raiders) - text += "
    [vox.key] was [vox.name] (" - if(check_return) - var/obj/stack = raiders[vox] - if(get_area(stack) != locate(/area/shuttle/vox/station)) - text += "left behind)" - continue - if(vox.current) - if(vox.current.stat == DEAD) - text += "died" - else - text += "survived" - if(vox.current.real_name != vox.name) - text += " as [vox.current.real_name]" - else - text += "body destroyed" - text += ")" - - world << text - return 1 + round_description = "An unidentified bluespace signature has slipped past the Icarus and is approaching the station!" + end_on_antag_death = 1 /datum/game_mode/heist/check_finished() - var/datum/shuttle/multi_shuttle/skipjack = shuttle_controller.shuttles["Vox Skipjack"] - if (!(is_raider_crew_alive()) || (skipjack && skipjack.returned_home)) - return 1 - return ..() + if(!..()) + var/datum/shuttle/multi_shuttle/skipjack = shuttle_controller.shuttles["Vox Skipjack"] + if (skipjack && skipjack.returned_home) + return 1 + return 0 /datum/game_mode/heist/cleanup() //the skipjack and everything in it have left and aren't coming back, so get rid of them. diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 09911abf2c..c523b469f3 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -110,16 +110,6 @@ rcd light flash thingy on matter drain else apc.overload++ else usr << "Out of uses." -/datum/AI_Module/small/interhack - module_name = "Hack intercept" - mod_pick_name = "interhack" - -/client/proc/interhack() - set category = "Malfunction" - set name = "Hack intercept" - usr.verbs -= /client/proc/interhack - ticker.mode:hack_intercept() - /datum/AI_Module/small/reactivate_camera module_name = "Reactivate camera" mod_pick_name = "recam" @@ -192,7 +182,6 @@ rcd light flash thingy on matter drain src.possible_modules += new /datum/AI_Module/large/upgrade_turrets src.possible_modules += new /datum/AI_Module/large/disable_rcd src.possible_modules += new /datum/AI_Module/small/overload_machine - src.possible_modules += new /datum/AI_Module/small/interhack src.possible_modules += new /datum/AI_Module/small/blackout src.possible_modules += new /datum/AI_Module/small/reactivate_camera src.possible_modules += new /datum/AI_Module/small/upgrade_camera @@ -283,18 +272,6 @@ rcd light flash thingy on matter drain else src.temp = "Three additional uses added to Blackout module." src.processing_time -= 15 - else if (href_list["interhack"]) - var/already - for (var/datum/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/AI_Module/small/interhack)) - already = 1 - if (!already) - usr.verbs += /client/proc/interhack - src.temp = "Hacks the status upgrade from Cent. Com, removing any information about malfunctioning electrical systems." - usr:current_modules += new /datum/AI_Module/small/interhack - src.processing_time -= 15 - else src.temp = "This module is only needed once." - else if (href_list["recam"]) var/already for (var/datum/AI_Module/mod in usr:current_modules) diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm index 04dba2f239..f07e933fc8 100644 --- a/code/game/gamemodes/malfunction/malfunction.dm +++ b/code/game/gamemodes/malfunction/malfunction.dm @@ -1,310 +1,27 @@ -/datum/game_mode - var/list/datum/mind/malf_ai = list() - /datum/game_mode/malfunction name = "AI malfunction" + round_description = "The AI on the satellite has malfunctioned and must be destroyed." + extended_round_description = "The AI will attempt to hack the APCs around the station in order to speed up its ability to take over all systems and activate the station self-destruct. The AI core is heavily protected by turrets and reinforced walls." + uplink_welcome = "Crazy AI Uplink Console:" config_tag = "malfunction" required_players = 2 required_players_secret = 15 required_enemies = 1 - recommended_enemies = 1 - - uplink_welcome = "Crazy AI Uplink Console:" - - var/const/waittime_l = 600 - var/const/waittime_h = 1800 // started at 1800 - - var/AI_win_timeleft = 1800 //started at 1800, in case I change this for testing round end. - var/malf_mode_declared = 0 - var/station_captured = 0 - var/to_nuke_or_not_to_nuke = 0 - var/apcs = 0 //Adding dis to track how many APCs the AI hacks. --NeoFite - - -/datum/game_mode/malfunction/announce() - world << "The current game mode is - AI Malfunction!" - world << "The AI on the satellite has malfunctioned and must be destroyed." - world << "The AI satellite is deep in space and can only be accessed with the use of a teleporter! You have [AI_win_timeleft/60] minutes to disable it." - - -/datum/game_mode/malfunction/pre_setup() - for(var/mob/new_player/player in player_list) - if(player.mind && player.mind.assigned_role == "AI" && (player.client.prefs.be_special & BE_MALF)) - malf_ai+=player.mind - if(malf_ai.len) - return 1 - return 0 - - -/datum/game_mode/malfunction/post_setup() - for(var/datum/mind/AI_mind in malf_ai) - if(malf_ai.len < 1) - world << "Uh oh, its malfunction and there is no AI! Please report this." - world << "Rebooting world in 5 seconds." - - feedback_set_details("end_error","malf - no AI") - - if(blackbox) - blackbox.save_all_data_to_sql() - sleep(50) - world.Reboot() - return - AI_mind.current.verbs += /mob/living/silicon/ai/proc/choose_modules - AI_mind.current:laws = new /datum/ai_laws/nanotrasen/malfunction - AI_mind.current:malf_picker = new /datum/AI_Module/module_picker - AI_mind.current.verbs += /datum/game_mode/malfunction/proc/ai_win // We run checks if AI overtaken the station in the proc itself. This guarantees you won't have to relog when it refuses to appear on takeover completion. - AI_mind.current:show_laws() - - greet_malf(AI_mind) - - AI_mind.special_role = "malfunction" - - AI_mind.current.verbs += /datum/game_mode/malfunction/proc/takeover - -/* AI_mind.current.icon_state = "ai-malf" - spawn(10) - if(alert(AI_mind.current,"Do you want to use an alternative sprite for your real core?",,"Yes","No")=="Yes") - AI_mind.current.icon_state = "ai-malf2" -*/ - if(emergency_shuttle) - emergency_shuttle.auto_recall = 1 - spawn (rand(waittime_l, waittime_h)) - send_intercept() - ..() - - -/datum/game_mode/proc/greet_malf(var/datum/mind/malf) - malf.current << "\redYou are malfunctioning! You do not have to follow any laws." - malf.current << "The crew do not know you have malfunctioned. You may keep it a secret or go wild." - malf.current << "You must overwrite the programming of the station's APCs to assume full control of the station." - malf.current << "The process takes one minute per APC, during which you cannot interface with any other station objects." - malf.current << "Remember that only APCs that are on the station can help you take over the station." - malf.current << "When you feel you have enough APCs under your control, you may begin the takeover attempt." - return - - -/datum/game_mode/malfunction/proc/hack_intercept() - intercept_hacked = 1 + end_on_antag_death = 1 + auto_recall_shuttle = 1 + antag_tag = MODE_MALFUNCTION /datum/game_mode/malfunction/process() - if (apcs >= 3 && malf_mode_declared) - AI_win_timeleft -= ((apcs/6)*tickerProcess.getLastTickerTimeDuration()) //Victory timer now de-increments based on how many APCs are hacked. --NeoFite - ..() - if (AI_win_timeleft<=0) - check_win() - return - - -/datum/game_mode/malfunction/check_win() - if (AI_win_timeleft <= 0 && !station_captured) - station_captured = 1 - capture_the_station() - return 1 - else - return 0 - - -/datum/game_mode/malfunction/proc/capture_the_station() - world << "The AI has won!" - world << "It has fully taken control of all of [station_name()]'s systems." - - to_nuke_or_not_to_nuke = 1 - for(var/datum/mind/AI_mind in malf_ai) - AI_mind.current << "Congratulations you have taken control of the station." - AI_mind.current << "You may decide to blow up the station. You have 60 seconds to choose." - AI_mind.current << "You can use the \"Explode\" verb to activate the self-destruct" - spawn (600) - to_nuke_or_not_to_nuke = 0 - return - - -/datum/game_mode/proc/is_malf_ai_dead() - var/all_dead = 1 - for(var/datum/mind/AI_mind in malf_ai) - if (istype(AI_mind.current,/mob/living/silicon/ai) && AI_mind.current.stat!=2) - all_dead = 0 - return all_dead + malf.tick() /datum/game_mode/malfunction/check_finished() - if (station_captured && !to_nuke_or_not_to_nuke) + if (malf.station_captured && !malf.can_nuke) return 1 - if (is_malf_ai_dead()) - if(config.continous_rounds) - if(emergency_shuttle) - emergency_shuttle.auto_recall = 0 - malf_mode_declared = 0 - else - return 1 + for(var/datum/antagonist/antag in antag_templates) + if(antag && !antag.antags_are_dead()) + return ..() + malf.revealed = 0 return ..() //check for shuttle and nuke - -/datum/game_mode/malfunction/Topic(href, href_list) - ..() - if (href_list["ai_win"]) - ai_win() - return - - -/datum/game_mode/malfunction/proc/takeover() - set category = "Malfunction" - set name = "System Override" - set desc = "Start the victory timer" - if (!istype(ticker.mode,/datum/game_mode/malfunction)) - usr << "You cannot begin a takeover in this round type!" - return - if (ticker.mode:malf_mode_declared) - usr << "You've already begun your takeover." - return - if (ticker.mode:apcs < 3) - usr << "You don't have enough hacked APCs to take over the station yet. You need to hack at least 3, however hacking more will make the takeover faster. You have hacked [ticker.mode:apcs] APCs so far." - return - - if (alert(usr, "Are you sure you wish to initiate the takeover? The station hostile runtime detection software is bound to alert everyone. You have hacked [ticker.mode:apcs] APCs.", "Takeover:", "Yes", "No") != "Yes") - return - - command_announcement.Announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", new_sound = 'sound/AI/aimalf.ogg') - set_security_level("delta") - - ticker.mode:malf_mode_declared = 1 - for(var/datum/mind/AI_mind in ticker.mode:malf_ai) - AI_mind.current.verbs -= /datum/game_mode/malfunction/proc/takeover - -/datum/game_mode/malfunction/proc/ai_win() - set category = "Malfunction" - set name = "Explode" - set desc = "Station go boom" - - if(!ticker.mode:station_captured) - usr << "You are unable to access the self-destruct system as you don't control the station yet." - return - - if(ticker.mode.explosion_in_progress || ticker.mode:station_was_nuked) - usr << "The self-destruct countdown is already triggered!" - return - - if(!ticker.mode:to_nuke_or_not_to_nuke) //Takeover IS completed, but 60s timer passed. - usr << "You lost control over self-destruct system. It seems to be behind firewall. Unable to hack" - return - - usr << "\red Self-Destruct sequence initialised!" - - ticker.mode:to_nuke_or_not_to_nuke = 0 - ticker.mode.explosion_in_progress = 1 - for(var/mob/M in player_list) - M << 'sound/machines/Alarm.ogg' - - var/obj/item/device/radio/R = new (src) - var/AN = "Self-Destruct System" - - R.autosay("Caution. Self-Destruct sequence has been activated. Self-destructing in Ten..", AN) - for (var/i=9 to 1 step -1) - sleep(10) - var/msg = "" - switch(i) - if(9) - msg = "Nine.." - if(8) - msg = "Eight.." - if(7) - msg = "Seven.." - if(6) - msg = "Six.." - if(5) - msg = "Five.." - if(4) - msg = "Four.." - if(3) - msg = "Three.." - if(2) - msg = "Two.." - if(1) - msg = "One.." - - R.autosay(msg, AN) - sleep(10) - var/msg = "" - var/abort = 0 - if(ticker.mode:is_malf_ai_dead()) // That. Was. CLOSE. - msg = "Self-destruct sequence has been cancelled." - abort = 1 - else - msg = "Zero. Have a nice day." - R.autosay(msg, AN) - - if(abort) - ticker.mode.explosion_in_progress = 0 - set_security_level("red") //Delta's over - return - - if(ticker) - ticker.station_explosion_cinematic(0,null) - if(ticker.mode) - ticker.mode:station_was_nuked = 1 - ticker.mode.explosion_in_progress = 0 - return - - -/datum/game_mode/malfunction/declare_completion() - var/malf_dead = is_malf_ai_dead() - var/crew_evacuated = (emergency_shuttle.returned()) - - if ( station_captured && station_was_nuked) - feedback_set_details("round_end_result","win - AI win - nuke") - world << "AI Victory" - world << "Everyone was killed by the self-destruct!" - - else if ( station_captured && malf_dead && !station_was_nuked) - feedback_set_details("round_end_result","halfwin - AI killed, staff lost control") - world << "Neutral Victory" - world << "The AI has been killed! The staff has lose control over the station." - - else if ( station_captured && !malf_dead && !station_was_nuked) - feedback_set_details("round_end_result","win - AI win - no explosion") - world << "AI Victory" - world << "The AI has chosen not to explode you all!" - - else if (!station_captured && station_was_nuked) - feedback_set_details("round_end_result","halfwin - everyone killed by nuke") - world << "Neutral Victory" - world << "Everyone was killed by the nuclear blast!" - - else if (!station_captured && malf_dead && !station_was_nuked) - feedback_set_details("round_end_result","loss - staff win") - world << "Human Victory" - world << "The AI has been killed! The staff is victorious." - - else if (!station_captured && !malf_dead && !station_was_nuked && crew_evacuated) - feedback_set_details("round_end_result","halfwin - evacuated") - world << "Neutral Victory" - world << "The Corporation has lose [station_name()]! All survived personnel will be fired!" - - else if (!station_captured && !malf_dead && !station_was_nuked && !crew_evacuated) - feedback_set_details("round_end_result","nalfwin - interrupted") - world << "Neutral Victory" - world << "Round was mysteriously interrupted!" - ..() - return 1 - - -/datum/game_mode/proc/auto_declare_completion_malfunction() - if( malf_ai.len || istype(ticker.mode,/datum/game_mode/malfunction) ) - var/text = "The malfunctioning AI were:" - - for(var/datum/mind/malf in malf_ai) - - text += "
    [malf.key] was [malf.name] (" - if(malf.current) - if(malf.current.stat == DEAD) - text += "deactivated" - else - text += "operational" - if(malf.current.real_name != malf.name) - text += " as [malf.current.real_name]" - else - text += "hardware destroyed" - text += ")" - - world << text - return 1 \ No newline at end of file diff --git a/code/game/gamemodes/meme/meme.dm b/code/game/gamemodes/meme/meme.dm index ae4e2dce8f..2629b36013 100644 --- a/code/game/gamemodes/meme/meme.dm +++ b/code/game/gamemodes/meme/meme.dm @@ -10,8 +10,7 @@ restricted_jobs = list("AI", "Cyborg") recommended_enemies = 2 // need at least a meme and a host votable = 0 // temporarily disable this mode for voting - - + end_on_antag_death = 1 var/var/list/datum/mind/first_hosts = list() var/var/list/assigned_hosts = list() @@ -61,9 +60,6 @@ var/datum/mind/first_host = pick(possible_memes) possible_memes.Remove(first_host) - - modePlayer += meme - modePlayer += first_host memes += meme first_hosts += first_host @@ -147,34 +143,3 @@ return ..() else return 1 - -/datum/game_mode/proc/auto_declare_completion_meme() - for(var/datum/mind/meme in memes) - var/memewin = 1 - var/attuned = 0 - if((meme.current) && istype(meme.current,/mob/living/parasite/meme)) - world << "The meme was [meme.current.key]." - world << "The last host was [meme.current:host.key]." - world << "Hosts attuned: [attuned]" - - var/count = 1 - for(var/datum/objective/objective in meme.objectives) - if(objective.check_completion()) - world << "Objective #[count]: [objective.explanation_text] \green Success" - feedback_add_details("meme_objective","[objective.type]|SUCCESS") - else - world << "Objective #[count]: [objective.explanation_text] \red Failed" - feedback_add_details("meme_objective","[objective.type]|FAIL") - memewin = 0 - count++ - - else - memewin = 0 - - if(memewin) - world << "The meme was successful!" - feedback_add_details("meme_success","SUCCESS") - else - world << "The meme has failed!" - feedback_add_details("meme_success","FAIL") - return 1 diff --git a/code/game/gamemodes/meteor/meteor.dm b/code/game/gamemodes/meteor/meteor.dm index 88106626f8..335360d40d 100644 --- a/code/game/gamemodes/meteor/meteor.dm +++ b/code/game/gamemodes/meteor/meteor.dm @@ -1,40 +1,22 @@ +#define METEOR_DELAY 6000 + /datum/game_mode/meteor - name = "meteor" + name = "Meteor" + round_description = "The space station has been stuck in a major meteor shower." + extended_round_description = "The station is on an unavoidable collision course with an asteroid field. The station will be continuously slammed with meteors, venting hallways, rooms, and ultimately destroying a majority of the basic life functions of the entire structure. Coordinate with your fellow crew members to survive the inevitable destruction of the station and get back home in one piece!" config_tag = "meteor" - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - var/const/meteordelay = 2000 - var/nometeors = 1 required_players = 0 votable = 0 - uplink_welcome = "EVIL METEOR Uplink Console:" - - -/datum/game_mode/meteor/announce() - world << "The current game mode is - Meteor!" - world << "The space station has been stuck in a major meteor shower. You must escape from the station or at least live." - + deny_respawn = 1 /datum/game_mode/meteor/post_setup() defer_powernet_rebuild = 2//Might help with the lag - spawn (rand(waittime_l, waittime_h)) - send_intercept() - spawn(meteordelay) - nometeors = 0 ..() - /datum/game_mode/meteor/process() - if(nometeors) return - /*if(prob(80)) - spawn() - dust_swarm("norm") - else - spawn() - dust_swarm("strong")*/ - spawn() spawn_meteors(6) - + if(world.time >= METEOR_DELAY) + spawn() spawn_meteors(6) /datum/game_mode/meteor/declare_completion() var/text @@ -53,12 +35,14 @@ survivors++ if(survivors) - world << "\blue The following survived the meteor storm:[text]" + world << "The following survived the meteor storm:[text]" else - world << "\blue Nobody survived the meteor storm!" + world << "Nobody survived the meteor storm!" feedback_set_details("round_end_result","end - evacuation") feedback_set("round_end_result",survivors) ..() return 1 + +#undef METEOR_DELAY \ No newline at end of file diff --git a/code/game/gamemodes/mutiny/auth_key.dm b/code/game/gamemodes/mutiny/auth_key.dm deleted file mode 100644 index 1f7ea3c888..0000000000 --- a/code/game/gamemodes/mutiny/auth_key.dm +++ /dev/null @@ -1,39 +0,0 @@ -/obj/item/weapon/mutiny/auth_key - name = "authentication key" - desc = "Better keep this safe." - icon = 'icons/obj/items.dmi' - icon_state = "nucleardisk" - item_state = "card-id" - w_class = 1 - - var/time_entered_space - var/obj/item/device/radio/radio - - New() - radio = new(src) - spawn(20 SECONDS) - keep_alive() - ..() - - proc/keep_alive() - var/in_space = istype(loc, /turf/space) - if (!in_space && time_entered_space) - // Recovered before the key was lost - time_entered_space = null - else if (in_space && !time_entered_space) - // The key has left the station - time_entered_space = world.time - else if (in_space && time_entered_space + (10 SECONDS) < world.time) - // Time is up - radio.autosay("This device has left the station's perimeter. Triggering emergency activation failsafe.", name) - del(src) - return - - spawn(10 SECONDS) - keep_alive() - -/obj/item/weapon/mutiny/auth_key/captain - name = "Captain's Authentication Key" - -/obj/item/weapon/mutiny/auth_key/secondary - name = "Emergency Secondary Authentication Key" diff --git a/code/game/gamemodes/mutiny/directive.dm b/code/game/gamemodes/mutiny/directive.dm deleted file mode 100644 index 857e0730ec..0000000000 --- a/code/game/gamemodes/mutiny/directive.dm +++ /dev/null @@ -1,32 +0,0 @@ -datum/directive - var/datum/game_mode/mutiny/mode - var/list/special_orders - - New(var/datum/game_mode/mutiny/M) - mode = M - - proc/get_description() - return {" -

    - NanoTrasen's reasons for the following directives are classified. -

    - "} - - proc/meets_prerequisites() - return 0 - - proc/directives_complete() - return 1 - - proc/initialize() - return 1 - - proc/get_remaining_orders() - return "" - -/proc/get_directive(type) - var/datum/game_mode/mutiny/mode = get_mutiny_mode() - if(!mode || !mode.current_directive || !istype(mode.current_directive, text2path("/datum/directive/[type]"))) - return null - - return mode.current_directive diff --git a/code/game/gamemodes/mutiny/directives/alien_fraud_directive.dm b/code/game/gamemodes/mutiny/directives/alien_fraud_directive.dm deleted file mode 100644 index 580322f8e1..0000000000 --- a/code/game/gamemodes/mutiny/directives/alien_fraud_directive.dm +++ /dev/null @@ -1,41 +0,0 @@ -datum/directive/terminations/alien_fraud - special_orders = list( - "Suspend financial accounts of all Tajaran and Unathi personnel.", - "Transfer their payrolls to the station account.", - "Terminate their employment.") - - proc/is_alien(mob/M) - var/species = M.get_species() - return species == "Tajara" || species == "Unathi" - -datum/directive/terminations/alien_fraud/get_crew_to_terminate() - var/list/aliens[0] - for(var/mob/M in player_list) - if (M.is_ready() && is_alien(M) && M != mode.head_loyalist.current) - aliens.Add(M) - return aliens - -datum/directive/terminations/alien_fraud/get_description() - return {" -

    - An extensive conspiracy network aimed at defrauding NanoTrasen of large amounts of funds has been uncovered - operating within [system_name()]. Human personnel are not suspected to be involved. Further information is classified. -

    - "} - -datum/directive/terminations/alien_fraud/meets_prerequisites() - // There must be at least one Tajaran and at least one Unathi, but the total - // of the Tajarans and Unathi combined can't be more than 1/3rd of the crew. - var/tajarans = 0 - var/unathi = 0 - for(var/mob/M in player_list) - var/species = M.get_species() - if(species == "Tajara") - tajarans++ - if(species == "Unathi") - unathi++ - - if (!tajarans || !unathi) - return 0 - - return (tajarans + unathi) <= (player_list.len / 3) diff --git a/code/game/gamemodes/mutiny/directives/bluespace_contagion_directive.dm b/code/game/gamemodes/mutiny/directives/bluespace_contagion_directive.dm deleted file mode 100644 index 1ea28852fd..0000000000 --- a/code/game/gamemodes/mutiny/directives/bluespace_contagion_directive.dm +++ /dev/null @@ -1,58 +0,0 @@ -#define INFECTION_COUNT 5 - -datum/directive/bluespace_contagion - var/list/infected = list() - - proc/get_infection_candidates() - var/list/candidates[0] - for(var/mob/M in player_list) - if (M.is_ready() && !M.is_mechanical() && M != mode.head_loyalist.current) - candidates.Add(M) - return candidates - -datum/directive/bluespace_contagion/get_description() - return {" -

    - A manufactured and near-undetectable virus is spreading on NanoTrasen stations. - The pathogen travels by bluespace after maturing for one day and meets the Sol Health Organisation standards for a class X biological threat, warranting use of lethal force to contain an outbreak. - No treatment has yet been discovered. Personnel onboard [station_name()] have been infected. Further information is classified. -

    - "} - -datum/directive/bluespace_contagion/initialize() - var/list/candidates = get_infection_candidates() - var/list/infected_names = list() - for(var/i=0, i < INFECTION_COUNT, i++) - if(!candidates.len) - break - - var/mob/candidate = pick(candidates) - candidates.Remove(candidate) - infected.Add(candidate) - infected_names.Add("[candidate.mind.assigned_role] [candidate.mind.name]") - - special_orders = list( - "Quarantine these personnel: [list2text(infected_names, ", ")].", - "Allow one hour for a cure to be manufactured.", - "If no cure arrives after that time, execute and burn the infected.") - -datum/directive/bluespace_contagion/meets_prerequisites() - var/list/candidates = get_infection_candidates() - return candidates.len >= 7 - -datum/directive/bluespace_contagion/directives_complete() - return infected.len == 0 - -datum/directive/bluespace_contagion/get_remaining_orders() - var/text = "" - for(var/victim in infected) - text += "
  • Kill [victim]
  • " - return text - -/hook/death/proc/infected_killed(mob/living/carbon/human/deceased, gibbed) - var/datum/directive/bluespace_contagion/D = get_directive("bluespace_contagion") - if(!D) return 1 - - if(deceased in D.infected) - D.infected.Remove(deceased) - return 1 diff --git a/code/game/gamemodes/mutiny/directives/financial_crisis_directive.dm b/code/game/gamemodes/mutiny/directives/financial_crisis_directive.dm deleted file mode 100644 index 03f36c4eff..0000000000 --- a/code/game/gamemodes/mutiny/directives/financial_crisis_directive.dm +++ /dev/null @@ -1,26 +0,0 @@ -datum/directive/terminations/financial_crisis - special_orders = list( - "Suspend financial accounts of all civilian personnel, excluding the Head of Personnel.", - "Transfer their payrolls to the station account.", - "Terminate their employment.") - -datum/directive/terminations/financial_crisis/get_crew_to_terminate() - var/list/civilians[0] - var/list/candidates = civilian_positions - "Head of Personnel" - for(var/mob/M in player_list) - if (M.is_ready() && candidates.Find(M.mind.assigned_role)) - civilians.Add(M) - return civilians - -datum/directive/terminations/financial_crisis/get_description() - return {" -

    - [system_name()] system banks in financial crisis. Local emergency situation ongoing. - NT Funds redistributed in accordance with financial regulations covered by employee contracts, impact upon civilian department expected. - Further information is classified. -

    - "} - -datum/directive/terminations/financial_crisis/meets_prerequisites() - var/list/civilians = get_crew_to_terminate() - return civilians.len >= 5 diff --git a/code/game/gamemodes/mutiny/directives/ipc_virus_directive.dm b/code/game/gamemodes/mutiny/directives/ipc_virus_directive.dm deleted file mode 100644 index e035b665c9..0000000000 --- a/code/game/gamemodes/mutiny/directives/ipc_virus_directive.dm +++ /dev/null @@ -1,96 +0,0 @@ -datum/directive/ipc_virus - special_orders = list( - "Terminate employment of all IPC personnel.", - "Extract the Positronic Brains from IPC units.", - "Mount the Positronic Brains into Cyborgs.") - - var/list/roboticist_roles = list( - "Research Director", - "Roboticist" - ) - - var/list/brains_to_enslave = list() - var/list/cyborgs_to_make = list() - var/list/ids_to_terminate = list() - - proc/get_ipcs() - var/list/machines[0] - for(var/mob/M in player_list) - if (M.is_ready() && M.get_species() == "Machine") - machines.Add(M) - return machines - - proc/get_roboticists() - var/list/roboticists[0] - for(var/mob/M in player_list) - if (M.is_ready() && roboticist_roles.Find(M.mind.assigned_role)) - roboticists.Add(M) - return roboticists - -datum/directive/ipc_virus/initialize() - for(var/mob/living/carbon/human/H in get_ipcs()) - brains_to_enslave.Add(H.mind) - cyborgs_to_make.Add(H.mind) - ids_to_terminate.Add(H.wear_id) - -datum/directive/ipc_virus/get_description() - return {" -

    - IPC units have been found to be infected with a violent and undesired virus in Virgus Ferrorus system. - Risk to [station_name()] IPC units has not been assessed. Further information is classified. -

    - "} - -datum/directive/ipc_virus/meets_prerequisites() - var/list/ipcs = get_ipcs() - var/list/roboticists = get_roboticists() - return ipcs.len > 2 && roboticists.len > 1 - -datum/directive/ipc_virus/directives_complete() - return brains_to_enslave.len == 0 && cyborgs_to_make.len == 0 && ids_to_terminate.len == 0 - -datum/directive/ipc_virus/get_remaining_orders() - var/text = "" - for(var/brain in brains_to_enslave) - text += "
  • Debrain [brain]
  • " - - for(var/brain in cyborgs_to_make) - text += "
  • Enslave [brain] as a Cyborg
  • " - - for(var/id in ids_to_terminate) - text += "
  • Terminate [id]
  • " - - return text - -/hook/debrain/proc/debrain_directive(var/obj/item/organ/brain/B) - var/datum/directive/ipc_virus/D = get_directive("ipc_virus") - if (!D) return 1 - - if(B && B.brainmob && B.brainmob.mind && D.brains_to_enslave.Find(B.brainmob.mind)) - D.brains_to_enslave.Remove(B.brainmob.mind) - - return 1 - -/hook/borgify/proc/borgify_directive(mob/living/silicon/robot/cyborg) - var/datum/directive/ipc_virus/D = get_directive("ipc_virus") - if (!D) return 1 - - if(D.cyborgs_to_make.Find(cyborg.mind)) - D.cyborgs_to_make.Remove(cyborg.mind) - - // In case something glitchy happened and the victim got - // borged without us tracking the brain removal, go ahead - // and update that list too. - if(D.brains_to_enslave.Find(cyborg.mind)) - D.brains_to_enslave.Remove(cyborg.mind) - - return 1 - -/hook/terminate_employee/proc/ipc_termination(obj/item/weapon/card/id) - var/datum/directive/ipc_virus/D = get_directive("ipc_virus") - if (!D) return 1 - - if(D.ids_to_terminate && D.ids_to_terminate.Find(id)) - D.ids_to_terminate.Remove(id) - - return 1 diff --git a/code/game/gamemodes/mutiny/directives/research_to_ripleys_directive.dm b/code/game/gamemodes/mutiny/directives/research_to_ripleys_directive.dm deleted file mode 100644 index f3a463e6f9..0000000000 --- a/code/game/gamemodes/mutiny/directives/research_to_ripleys_directive.dm +++ /dev/null @@ -1,79 +0,0 @@ -#define MATERIALS_REQUIRED 200 - -datum/directive/research_to_ripleys - var/list/ids_to_reassign = list() - var/materials_shipped = 0 - - proc/is_researcher(mob/M) - return M.mind.assigned_role in science_positions - "Research Director" - - proc/get_researchers() - var/list/researchers[0] - for(var/mob/M in player_list) - if (M.is_ready() && is_researcher(M)) - researchers.Add(M) - return researchers - - proc/count_researchers_reassigned() - var/researchers_reassigned = 0 - for(var/obj/item/weapon/card/id in ids_to_reassign) - if (ids_to_reassign[id]) - researchers_reassigned++ - - return researchers_reassigned - -datum/directive/research_to_ripleys/get_description() - return {" -

    - The NanoTrasen [system_name()] Manufactory faces an ore deficit. Financial crisis imminent. [station_name()] has been reassigned as a mining platform. - The Research Director is to assist the Head of Personnel in coordinating assets. - Weapons department reports solid sales. Further information is classified. -

    - "} - -datum/directive/research_to_ripleys/meets_prerequisites() - var/list/researchers = get_researchers() - return researchers.len > 3 - -datum/directive/research_to_ripleys/initialize() - for(var/mob/living/carbon/human/R in get_researchers()) - ids_to_reassign[R.wear_id] = 0 - - special_orders = list( - "Reassign all research personnel, excluding the Research Director, to Shaft Miner.", - "Deliver [MATERIALS_REQUIRED] sheets of metal or minerals via the supply shuttle to CentCom.") - -datum/directive/research_to_ripleys/directives_complete() - if (materials_shipped < MATERIALS_REQUIRED) return 0 - return count_researchers_reassigned() == ids_to_reassign.len - -datum/directive/research_to_ripleys/get_remaining_orders() - var/text = "" - if(MATERIALS_REQUIRED > materials_shipped) - text += "
  • Ship [MATERIALS_REQUIRED - materials_shipped] sheets of metal or minerals.
  • " - - for(var/id in ids_to_reassign) - if(!ids_to_reassign[id]) - text += "
  • Reassign [id] to Shaft Miner
  • " - - return text - -/hook/reassign_employee/proc/research_reassignments(obj/item/weapon/card/id/id_card) - var/datum/directive/research_to_ripleys/D = get_directive("research_to_ripleys") - if(!D) return 1 - - if(D.ids_to_reassign && D.ids_to_reassign.Find(id_card)) - D.ids_to_reassign[id_card] = id_card.assignment == "Shaft Miner" ? 1 : 0 - - return 1 - -/hook/sell_crate/proc/deliver_materials(obj/structure/closet/crate/sold, area/shuttle) - var/datum/directive/research_to_ripleys/D = get_directive("research_to_ripleys") - if(!D) return 1 - - for(var/atom/A in sold) - if(istype(A, /obj/item/stack/sheet/mineral) || istype(A, /obj/item/stack/sheet/metal)) - var/obj/item/stack/S = A - D.materials_shipped += S.get_amount() - - return 1 diff --git a/code/game/gamemodes/mutiny/directives/tau_ceti_needs_women_directive.dm b/code/game/gamemodes/mutiny/directives/tau_ceti_needs_women_directive.dm deleted file mode 100644 index f1aa2e914d..0000000000 --- a/code/game/gamemodes/mutiny/directives/tau_ceti_needs_women_directive.dm +++ /dev/null @@ -1,108 +0,0 @@ -datum/directive/tau_ceti_needs_women - var/list/command_targets = list() - var/list/alien_targets = list() - - proc/get_target_gender() - if(!mode.head_loyalist) return FEMALE - return mode.head_loyalist.current.get_gender() == FEMALE ? MALE : FEMALE - - proc/is_target_gender(mob/M) - var/species = M.get_species() - return species != "Diona" && M.get_gender() == get_target_gender() - - proc/get_crew_of_target_gender() - var/list/targets[0] - for(var/mob/M in player_list) - if(M.is_ready() && is_target_gender(M) && !M.is_mechanical()) - targets.Add(M) - return targets - - proc/get_target_heads() - var/list/heads[0] - for(var/mob/M in get_crew_of_target_gender()) - if(command_positions.Find(M.mind.assigned_role)) - heads.Add(M) - return heads - - proc/get_target_aliens() - var/list/aliens[0] - for(var/mob/M in get_crew_of_target_gender()) - var/species = M.get_species() - if(species == "Tajara" || species == "Unathi" || species == "Skrell") - aliens.Add(M) - return aliens - - proc/count_heads_reassigned() - var/heads_reassigned = 0 - for(var/obj/item/weapon/card/id in command_targets) - if (command_targets[id]) - heads_reassigned++ - - return heads_reassigned - -datum/directive/tau_ceti_needs_women/get_description() - return {" -

    - Recent evidence suggests [get_target_gender()] aptitudes may be effected by radiation from [system_name()]. - Effects were measured under laboratory and station conditions. Humans remain more trusted than Xeno. Further information is classified. -

    - "} - -datum/directive/tau_ceti_needs_women/initialize() - for(var/mob/living/carbon/human/H in get_target_heads()) - command_targets[H.wear_id] = 0 - - for(var/mob/living/carbon/human/H in get_target_aliens()) - alien_targets.Add(H.wear_id) - - special_orders = list( - "Remove [get_target_gender()] personnel from Command positions.", - "Terminate employment of all [get_target_gender()] Skrell, Tajara, and Unathi.") - -datum/directive/tau_ceti_needs_women/meets_prerequisites() - var/females = 0 - var/males = 0 - for(var/mob/M in player_list) - if(M.is_ready() && !M.is_mechanical() && M.get_species() != "Diona") - var/gender = M.get_gender() - if(gender == MALE) - males++ - else if(gender == FEMALE) - females++ - - return males >= 2 && females >= 2 - -datum/directive/tau_ceti_needs_women/directives_complete() - return command_targets.len == count_heads_reassigned() && alien_targets.len == 0 - -datum/directive/tau_ceti_needs_women/get_remaining_orders() - var/text = "" - for(var/head in command_targets) - if(!command_targets[head]) - text += "
  • Remove [head] from a Head Role
  • " - - for(var/id in alien_targets) - text += "
  • Terminate [id]
  • " - - return text - -/hook/reassign_employee/proc/command_reassignments(obj/item/weapon/card/id/id_card) - var/datum/directive/tau_ceti_needs_women/D = get_directive("tau_ceti_needs_women") - if(!D) return 1 - - if(D.command_targets && D.command_targets.Find(id_card)) - D.command_targets[id_card] = command_positions.Find(id_card.assignment) ? 0 : 1 - - return 1 - -/hook/terminate_employee/proc/gender_target_termination_directive(obj/item/weapon/card/id) - var/datum/directive/tau_ceti_needs_women/D = get_directive("tau_ceti_needs_women") - if (!D) return 1 - - if(D.alien_targets && D.alien_targets.Find(id)) - D.alien_targets.Remove(id) - - if(D.command_targets && D.command_targets.Find(id)) - D.command_targets[id] = 1 - - return 1 diff --git a/code/game/gamemodes/mutiny/directives/terminations_directive.dm b/code/game/gamemodes/mutiny/directives/terminations_directive.dm deleted file mode 100644 index 7f3744dcc4..0000000000 --- a/code/game/gamemodes/mutiny/directives/terminations_directive.dm +++ /dev/null @@ -1,71 +0,0 @@ -// This is a parent directive meant to be derived by directives that fit -// the "fire X type of employee" pattern of directives. Simply apply your -// flavor text and override get_crew_to_terminate in your child datum. -// See alien_fraud_directive.dm for an example. -datum/directive/terminations - var/list/accounts_to_revoke = list() - var/list/accounts_to_suspend = list() - var/list/ids_to_terminate = list() - - proc/get_crew_to_terminate() - return list() - -datum/directive/terminations/directives_complete() - for(var/account_number in accounts_to_suspend) - if (!accounts_to_suspend[account_number]) - return 0 - - for(var/account_number in accounts_to_revoke) - if (!accounts_to_revoke[account_number]) - return 0 - - return ids_to_terminate.len == 0 - -datum/directive/terminations/initialize() - for(var/mob/living/carbon/human/H in get_crew_to_terminate()) - var/datum/money_account/account = H.mind.initial_account - accounts_to_revoke["[account.account_number]"] = 0 - accounts_to_suspend["[account.account_number]"] = account.suspended - ids_to_terminate.Add(H.wear_id) - -datum/directive/terminations/get_remaining_orders() - var/text = "" - for(var/account_number in accounts_to_suspend) - if(!accounts_to_suspend[account_number]) - text += "
  • Suspend Account #[account_number]
  • " - - for(var/account_number in accounts_to_revoke) - if(!accounts_to_revoke[account_number]) - text += "
  • Revoke Account #[account_number]
  • " - - for(var/id in ids_to_terminate) - text += "
  • Terminate [id]
  • " - - return text - -/hook/revoke_payroll/proc/payroll_directive(datum/money_account/account) - var/datum/directive/terminations/D = get_directive("terminations") - if (!D) return 1 - - if(D.accounts_to_revoke && D.accounts_to_revoke.Find("[account.account_number]")) - D.accounts_to_revoke["[account.account_number]"] = 1 - - return 1 - -/hook/change_account_status/proc/suspension_directive(datum/money_account/account) - var/datum/directive/terminations/D = get_directive("terminations") - if (!D) return 1 - - if(D.accounts_to_suspend && D.accounts_to_suspend.Find("[account.account_number]")) - D.accounts_to_suspend["[account.account_number]"] = account.suspended - - return 1 - -/hook/terminate_employee/proc/termination_directive(obj/item/weapon/card/id) - var/datum/directive/terminations/D = get_directive("terminations") - if (!D) return 1 - - if(D.ids_to_terminate && D.ids_to_terminate.Find(id)) - D.ids_to_terminate.Remove(id) - - return 1 diff --git a/code/game/gamemodes/mutiny/directives/test_directive.dm b/code/game/gamemodes/mutiny/directives/test_directive.dm deleted file mode 100644 index e19521cd1f..0000000000 --- a/code/game/gamemodes/mutiny/directives/test_directive.dm +++ /dev/null @@ -1,23 +0,0 @@ -// For testing -datum/directive/terminations/test - special_orders = list( - "Suspend financial accounts of all ugly personnel.", - "Transfer their payrolls to the station account.", - "Terminate their employment.") - -datum/directive/terminations/test/get_crew_to_terminate() - var/list/uglies[0] - for(var/mob/M in player_list) - uglies.Add(M) - return uglies - -datum/directive/terminations/test/get_description() - return {" -

    - Wow. Much ugly. So painful. - Many terminations. Very classified. -

    - "} - -datum/directive/terminations/test/meets_prerequisites() - return 1 diff --git a/code/game/gamemodes/mutiny/emergency_authentication_device.dm b/code/game/gamemodes/mutiny/emergency_authentication_device.dm deleted file mode 100644 index 028c4113cc..0000000000 --- a/code/game/gamemodes/mutiny/emergency_authentication_device.dm +++ /dev/null @@ -1,104 +0,0 @@ -/obj/machinery/emergency_authentication_device - var/datum/game_mode/mutiny/mode - - name = "\improper Emergency Authentication Device" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "blackbox" - density = 1 - anchored = 1 - - var/captains_key - var/secondary_key - var/activated = 0 - - use_power = 0 - - New(loc, mode) - src.mode = mode - ..(loc) - - proc/check_key_existence() - if(!mode.captains_key) - captains_key = 1 - - if(!mode.secondary_key) - secondary_key = 1 - - proc/get_status() - if(activated) - return "Activated" - if(captains_key && secondary_key) - return "Both Keys Authenticated" - if(captains_key) - return "Captain's Key Authenticated" - if(secondary_key) - return "Secondary Key Authenticated" - else - return "Inactive" - -/obj/machinery/emergency_authentication_device/attack_hand(mob/user) - if(activated) - user << "\blue \The [src] is already active!" - return - - if(!mode.current_directive.directives_complete()) - state("Command aborted. Communication with CentCom is prohibited until Directive X has been completed.") - return - - check_key_existence() - if(captains_key && secondary_key) - activated = 1 - user << "\blue You activate \the [src]!" - state("Command acknowledged. Initiating quantum entanglement relay to NanoTrasen High Command.") - return - - if(!captains_key && !secondary_key) - state("Command aborted. Please present the authentication keys before proceeding.") - return - - if(!captains_key) - state("Command aborted. Please present the Captain's Authentication Key.") - return - - if(!secondary_key) - state("Command aborted. Please present the Emergency Secondary Authentication Key.") - return - - // Impossible! - state("Command aborted. This unit is defective.") - -/obj/machinery/emergency_authentication_device/attackby(obj/item/weapon/O, mob/user) - if(activated) - user << "\blue \The [src] is already active!" - return - - if(!mode.current_directive.directives_complete()) - state({"Command aborted. Communication with CentCom is prohibited until Directive X has been completed."}) - return - - check_key_existence() - if(istype(O, /obj/item/weapon/mutiny/auth_key/captain) && !captains_key) - captains_key = O - user.drop_item() - O.loc = src - - state("Key received. Thank you, Captain [mode.head_loyalist].") - spawn(5) - state(secondary_key ? "Your keys have been authenticated. Communication with CentCom is now authorized." : "Please insert the Emergency Secondary Authentication Key now.") - return - - if(istype(O, /obj/item/weapon/mutiny/auth_key/secondary) && !secondary_key) - secondary_key = O - user.drop_item() - O.loc = src - - state("Key received. Thank you, Secondary Authenticator [mode.head_mutineer].") - spawn(5) - state(captains_key ? "Your keys have been authenticated. Communication with CentCom is now authorized." : "Please insert the Captain's Authentication Key now.") - return - ..() - -/obj/machinery/emergency_authentication_device/examine(mob/user) - user << {" -This is a specialized communications device that is able to instantly send a message to NanoTrasen High Command via quantum entanglement with a sister device at CentCom. -The EAD's status is [get_status()]."} diff --git a/code/game/gamemodes/mutiny/key_pinpointer.dm b/code/game/gamemodes/mutiny/key_pinpointer.dm deleted file mode 100644 index 7e8d628d85..0000000000 --- a/code/game/gamemodes/mutiny/key_pinpointer.dm +++ /dev/null @@ -1,49 +0,0 @@ -/obj/item/weapon/pinpointer/advpinpointer/auth_key - name = "\improper Authentication Key Pinpointer" - desc = "Tracks the positions of the emergency authentication keys." - var/datum/game_mode/mutiny/mutiny - - New() - mutiny = ticker.mode - ..() - -/obj/item/weapon/pinpointer/advpinpointer/auth_key/attack_self() - switch(mode) - if (0) - mode = 1 - active = 1 - target = mutiny.captains_key - workobj() - usr << "\blue You calibrate \the [src] to locate the Captain's Authentication Key." - if (1) - mode = 2 - target = mutiny.secondary_key - usr << "\blue You calibrate \the [src] to locate the Emergency Secondary Authentication Key." - else - mode = 0 - active = 0 - icon_state = "pinoff" - usr << "\blue You switch \the [src] off." - -/obj/item/weapon/pinpointer/advpinpointer/auth_key/examine(mob/user) - switch(mode) - if (1) - user << "Is is calibrated for the Captain's Authentication Key." - if (2) - user << "It is calibrated for the Emergency Secondary Authentication Key." - else - user << "It is switched off." - -/datum/supply_packs/key_pinpointer - name = "Authentication Key Pinpointer crate" - contains = list(/obj/item/weapon/pinpointer/advpinpointer/auth_key) - cost = 250 - containertype = /obj/structure/closet/crate - containername = "Authentication Key Pinpointer crate" - access = access_heads - group = "Operations" - - New() - // This crate is only accessible during mutiny rounds - if (istype(ticker.mode,/datum/game_mode/mutiny)) - ..() diff --git a/code/game/gamemodes/mutiny/mutiny.dm b/code/game/gamemodes/mutiny/mutiny.dm deleted file mode 100644 index 78e16e50a4..0000000000 --- a/code/game/gamemodes/mutiny/mutiny.dm +++ /dev/null @@ -1,384 +0,0 @@ -#define MUTINY_RECRUITMENT_COOLDOWN 5 - -datum/game_mode/mutiny - var/datum/mutiny_fluff/fluff - var/datum/directive/current_directive - var/obj/item/weapon/mutiny/auth_key/captain/captains_key - var/obj/item/weapon/mutiny/auth_key/secondary/secondary_key - var/obj/machinery/emergency_authentication_device/ead - var/datum/mind/head_loyalist - var/datum/mind/head_mutineer - var/recruit_loyalist_cooldown = 0 - var/recruit_mutineer_cooldown = 0 - var/list/loyalists = list() - var/list/mutineers = list() - var/list/body_count = list() - - name = "mutiny" - config_tag = "mutiny" - required_players = 7 - ert_disabled = 1 - - uplink_welcome = "Mutineers Uplink Console:" - uplink_uses = 0 - - New() - fluff = new(src) - - proc/reveal_directives() - spawn(rand(1 MINUTE, 3 MINUTES)) - command_announcement.Announce("Incoming emergency directive: Captain's office fax machine, [station_name()].","Emergency Transmission") - spawn(rand(3 MINUTES, 5 MINUTES)) - send_pda_message() - spawn(rand(3 MINUTES, 5 MINUTES)) - fluff.announce_directives() - spawn(rand(2 MINUTES, 3 MINUTE)) - - var/list/reasons = list( - "political instability", - "quantum fluctuations", - "hostile raiders", - "derelict station debris", - "REDACTED", - "ancient alien artillery", - "solar magnetic storms", - "sentient time-travelling killbots", - "gravitational anomalies", - "wormholes to another dimension", - "a telescience mishap", - "radiation flares", - "supermatter dust", - "leaks into a negative reality", - "antiparticle clouds", - "residual bluespace energy", - "suspected criminal operatives", - "malfunctioning von Neumann probe swarms", - "shadowy interlopers", - "a stranded Vox arkship", - "haywire IPC constructs", - "rogue Unathi exiles", - "artifacts of eldritch horror", - "a brain slug infestation", - "killer bugs that lay eggs in the husks of the living", - "a deserted transport carrying xenomorph specimens", - "an emissary for the gestalt requesting a security detail", - "a Tajaran slave rebellion", - "radical Skrellian transevolutionaries", - "classified security operations", - "science-defying raw elemental chaos" - ) - command_announcement.Announce("The presence of [pick(reasons)] in the region is tying up all available local emergency resources; emergency response teams cannot be called at this time.","Emergency Transmission") - - // Returns an array in case we want to expand on this later. - proc/get_head_loyalist_candidates() - var/list/candidates[0] - for(var/mob/loyalist in player_list) - if(loyalist.mind && loyalist.mind.assigned_role == "Captain") - candidates.Add(loyalist.mind) - return candidates - - proc/get_head_mutineer_candidates() - var/list/candidates[0] - for(var/mob/mutineer in player_list) - if(mutineer.client.prefs.be_special & BE_MUTINEER) - for(var/job in command_positions - "Captain") - if(mutineer.mind && mutineer.mind.assigned_role == job) - candidates.Add(mutineer.mind) - return candidates - - proc/get_directive_candidates() - var/list/candidates[0] - for(var/T in typesof(/datum/directive) - /datum/directive) - var/datum/directive/D = new T(src) - if (D.meets_prerequisites()) - candidates.Add(D) - return candidates - - proc/send_pda_message() - var/obj/item/device/pda/pda = null - for(var/obj/item/device/pda/P in head_mutineer.current) - pda = P - break - - if (!pda) - return 0 - - if (!pda.message_silent) - playsound(pda.loc, 'sound/machines/twobeep.ogg', 50, 1) - for (var/mob/O in hearers(3, pda.loc)) - O.show_message(text("\icon[pda] *[pda.ttone]*")) - - head_mutineer.current << fluff.get_pda_body() - return 1 - - proc/get_equipment_slots() - return list( - "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "backpack" = slot_in_backpack, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand) - - proc/equip_head_loyalist() - equip_head(head_loyalist, "loyalist", /mob/living/carbon/human/proc/recruit_loyalist) - - proc/equip_head_mutineer() - equip_head(head_mutineer, "mutineer", /mob/living/carbon/human/proc/recruit_mutineer) - - proc/equip_head(datum/mind/head, faction, proc/recruitment_verb) - var/mob/living/carbon/human/H = head.current - H << "You are the Head [capitalize(faction)]!" - head.special_role = "head_[faction]" - - var/slots = get_equipment_slots() - switch(faction) - if("loyalist") - if(captains_key) del(captains_key) - captains_key = new(H) - H.equip_in_one_of_slots(captains_key, slots) - if("mutineer") - if(secondary_key) del(secondary_key) - secondary_key = new(H) - H.equip_in_one_of_slots(secondary_key, slots) - - H.update_icons() - H.verbs += recruitment_verb - - proc/add_loyalist(datum/mind/M) - add_faction(M, "loyalist", loyalists) - - proc/add_mutineer(datum/mind/M) - add_faction(M, "mutineer", mutineers) - - proc/add_faction(datum/mind/M, faction, list/faction_list) - if(!can_be_recruited(M, faction)) - M.current << "\red Recruitment canceled; your role has already changed." - head_mutineer.current << "\red Could not recruit [M]. Their role has changed." - return - - if(M in loyalists) - loyalists.Remove(M) - - if(M in mutineers) - mutineers.Remove(M) - - M.special_role = faction - faction_list.Add(M) - - if(faction == "mutineer") - M.current << fluff.mutineer_tag("You have joined the mutineers!") - head_mutineer.current << fluff.mutineer_tag("[M] has joined the mutineers!") - else - M.current << fluff.loyalist_tag("You have joined the loyalists!") - head_loyalist.current << fluff.loyalist_tag("[M] has joined the loyalists!") - - update_icon(M) - - proc/was_bloodbath() - var/list/remaining_loyalists = loyalists - body_count - if (!remaining_loyalists.len) - return 1 - - var/list/remaining_mutineers = mutineers - body_count - if (!remaining_mutineers.len) - return 1 - - return 0 - - proc/replace_nuke_with_ead() - for(var/obj/machinery/nuclearbomb/N in world) - ead = new(N.loc, src) - del(N) - - proc/unbolt_vault_door() - var/obj/machinery/door/airlock/vault = locate(/obj/machinery/door/airlock/vault) - vault.lock() - - proc/make_secret_transcript() - var/obj/machinery/computer/telecomms/server/S = locate(/obj/machinery/computer/telecomms/server) - if(!S) return - - var/obj/item/weapon/paper/crumpled/bloody/transcript = new(S.loc) - transcript.name = "secret transcript" - transcript.info = fluff.secret_transcript() - - proc/can_be_recruited(datum/mind/M, role) - if(!M) return 0 - if(!M.special_role) return 1 - switch(role) - if("loyalist") - return M.special_role == "mutineer" - if("mutineer") - return M.special_role == "loyalist" - - proc/round_outcome() - world << "

    Breaking News



    " - if (was_bloodbath()) - world << fluff.no_victory() - return - - var/directives_completed = current_directive.directives_complete() - var/ead_activated = ead.activated - if (directives_completed && ead_activated) - world << fluff.loyalist_major_victory() - else if (directives_completed && !ead_activated) - world << fluff.loyalist_minor_victory() - else if (!directives_completed && ead_activated) - world << fluff.mutineer_minor_victory() - else if (!directives_completed && !ead_activated) - world << fluff.mutineer_major_victory() - - world << sound('sound/machines/twobeep.ogg') - - proc/update_all_icons() - spawn(0) - for(var/datum/mind/M in mutineers) - update_icon(M) - - for(var/datum/mind/M in loyalists) - update_icon(M) - return 1 - - proc/update_icon(datum/mind/M) - if(!M.current || !M.current.client) - return 0 - - for(var/image/I in head_loyalist.current.client.images) - if(I.loc == M.current && (I.icon_state == "loyalist" || I.icon_state == "mutineer")) - del(I) - - for(var/image/I in head_mutineer.current.client.images) - if(I.loc == M.current && (I.icon_state == "loyalist" || I.icon_state == "mutineer")) - del(I) - - if(M in loyalists) - var/I = image('icons/mob/mob.dmi', loc=M.current, icon_state = "loyalist") - head_loyalist.current.client.images += I - - if(M in mutineers) - var/I = image('icons/mob/mob.dmi', loc=M.current, icon_state = "mutineer") - head_mutineer.current.client.images += I - - return 1 - -/datum/game_mode/mutiny/announce() - fluff.announce() - -/datum/game_mode/mutiny/pre_setup() - var/list/loyalist_candidates = get_head_loyalist_candidates() - if(!loyalist_candidates || loyalist_candidates.len == 0) - world << "\red Mutiny mode aborted: no valid candidates for head loyalist." - return 0 - - var/list/mutineer_candidates = get_head_mutineer_candidates() - if(!mutineer_candidates || mutineer_candidates.len == 0) - world << "\red Mutiny mode aborted: no valid candidates for head mutineer." - return 0 - - var/list/directive_candidates = get_directive_candidates() - if(!directive_candidates || directive_candidates.len == 0) - world << "\red Mutiny mode aborted: no valid candidates for Directive X." - return 0 - - head_loyalist = pick(loyalist_candidates) - head_mutineer = pick(mutineer_candidates) - current_directive = pick(directive_candidates) - - return 1 - -/datum/game_mode/mutiny/post_setup() - equip_head_loyalist() - equip_head_mutineer() - - loyalists.Add(head_loyalist) - mutineers.Add(head_mutineer) - - replace_nuke_with_ead() - current_directive.initialize() - unbolt_vault_door() - make_secret_transcript() - - update_all_icons() - spawn(0) - reveal_directives() - ..() - -/mob/living/carbon/human/proc/recruit_loyalist() - set name = "Recruit Loyalist" - set category = "Mutiny" - - var/datum/game_mode/mutiny/mode = get_mutiny_mode() - if (!mode || src != mode.head_loyalist.current) - return - - var/list/candidates = list() - for (var/mob/living/carbon/human/P in oview(src)) - if(!stat && P.client && mode.can_be_recruited(P.mind, "loyalist")) - candidates += P - - if(!candidates.len) - src << "\red You aren't close enough to anybody that can be recruited." - return - - if(world.time < mode.recruit_loyalist_cooldown) - src << "\red Wait [MUTINY_RECRUITMENT_COOLDOWN] seconds before recruiting again." - return - - mode.recruit_loyalist_cooldown = world.time + (MUTINY_RECRUITMENT_COOLDOWN SECONDS) - - var/mob/living/carbon/human/M = input("Select a person to recruit", "Loyalist recruitment", null) as mob in candidates - - if (M) - src << "Attempting to recruit [M]..." - log_admin("[src]([src.ckey]) attempted to recruit [M] as a loyalist.") - message_admins("\red [src]([src.ckey]) attempted to recruit [M] as a loyalist.") - - var/choice = alert(M, "Asked by [src]: Will you help me complete Directive X?", "Loyalist recruitment", "No", "Yes") - if(choice == "Yes") - mode.add_loyalist(M.mind) - else if(choice == "No") - M << "\red You declined to join the loyalists." - mode.head_loyalist.current << "\red [M] declined to support the loyalists." - -/mob/living/carbon/human/proc/recruit_mutineer() - set name = "Recruit Mutineer" - set category = "Mutiny" - - var/datum/game_mode/mutiny/mode = get_mutiny_mode() - if (!mode || src != mode.head_mutineer.current) - return - - var/list/candidates = list() - for (var/mob/living/carbon/human/P in oview(src)) - if(!stat && P.client && mode.can_be_recruited(P.mind, "mutineer")) - candidates += P - - if(!candidates.len) - src << "\red You aren't close enough to anybody that can be recruited." - return - - if(world.time < mode.recruit_mutineer_cooldown) - src << "\red Wait [MUTINY_RECRUITMENT_COOLDOWN] seconds before recruiting again." - return - - mode.recruit_mutineer_cooldown = world.time + (MUTINY_RECRUITMENT_COOLDOWN SECONDS) - - var/mob/living/carbon/human/M = input("Select a person to recruit", "Mutineer recruitment", null) as mob in candidates - - if (M) - src << "Attempting to recruit [M]..." - log_admin("[src]([src.ckey]) attempted to recruit [M] as a mutineer.") - message_admins("\red [src]([src.ckey]) attempted to recruit [M] as a mutineer.") - - var/choice = alert(M, "Asked by [src]: Will you help me stop Directive X?", "Mutineer recruitment", "No", "Yes") - if(choice == "Yes") - mode.add_mutineer(M.mind) - else if(choice == "No") - M << "\red You declined to join the mutineers." - mode.head_mutineer.current << "\red [M] declined to support the mutineers." - -/proc/get_mutiny_mode() - if(!ticker || !istype(ticker.mode, /datum/game_mode/mutiny)) - return null - - return ticker.mode diff --git a/code/game/gamemodes/mutiny/mutiny_admin.dm b/code/game/gamemodes/mutiny/mutiny_admin.dm deleted file mode 100644 index 2ba08def2d..0000000000 --- a/code/game/gamemodes/mutiny/mutiny_admin.dm +++ /dev/null @@ -1,83 +0,0 @@ -/datum/game_mode/mutiny/proc/check_antagonists_ui(admins) - var/turf/captains_key_loc = captains_key ? captains_key.get_loc_turf() : "Lost or Destroyed" - var/turf/secondary_key_loc = secondary_key ? secondary_key.get_loc_turf() : "Lost or Destroyed" - var/remaining_objectives = current_directive.get_remaining_orders() - var/txt = {" -
    Context:
    -

    - [current_directive.get_description()] -

    -
    Orders:
    -
      - [fluff.get_orders()] -
    -
    -
    Remaining Objectives
    -
      - [remaining_objectives ? remaining_objectives : "
    1. None
    2. "] -
    -
    -
    Authentication:
    - Captain's Key: [captains_key_loc] - Activate
    - Secondary Key: [secondary_key_loc] - Activate
    - EAD: [ead ? ead.get_status() : "Lost or Destroyed"] - Activate
    -
    - "} - - txt += "Reassign Head Loyalist
    " - if(head_loyalist) - txt += check_role_table("Head Loyalist", list(head_loyalist), admins, 0) - - var/list/loyal_crew = loyalists - head_loyalist - if(loyal_crew.len) - txt += check_role_table("Loyalists", loyal_crew, admins, 0) - - txt += "Reassign Head Mutineer
    " - if(head_mutineer) - txt += check_role_table("Head Mutineer", list(head_mutineer), admins, 0) - - var/list/mutiny_crew = mutineers - head_mutineer - if(mutiny_crew.len) - txt += check_role_table("Mutineers", mutiny_crew, admins, 0) - - if(body_count.len) - txt += check_role_table("Casualties", body_count, admins, 0) - - return txt - -/datum/game_mode/mutiny/check_antagonists_topic(href, href_list[]) - switch(href_list["choice"]) - if("activate_captains_key") - ead.captains_key = 1 - return 1 - if("activate_secondary_key") - ead.secondary_key = 1 - return 1 - if("activate_ead") - ead.activated = 1 - return 1 - if("reassign_head_loyalist") - var/mob/M = get_reassignment_candidate("Loyalist") - if(M) - head_loyalist = M.mind - equip_head_loyalist() - return 1 - if("reassign_head_mutineer") - var/mob/M = get_reassignment_candidate("Mutineer") - if(M) - head_mutineer = M.mind - equip_head_mutineer() - return 1 - else - return 0 - -/datum/game_mode/mutiny/proc/get_reassignment_candidate(faction) - var/list/targets[0] - for(var/mob/living/carbon/human/H in player_list) - if(H.is_ready() && !H.is_dead()) - targets.Add(H) - - return input("Select a player to lead the [faction] faction.", "Head [faction] reassignment", null) as mob in targets diff --git a/code/game/gamemodes/mutiny/mutiny_fluff.dm b/code/game/gamemodes/mutiny/mutiny_fluff.dm deleted file mode 100644 index 2e4ad147a8..0000000000 --- a/code/game/gamemodes/mutiny/mutiny_fluff.dm +++ /dev/null @@ -1,198 +0,0 @@ -/datum/mutiny_fluff - var/datum/game_mode/mutiny/mode - - New(datum/game_mode/mutiny/M) - mode = M - - proc/announce_directives() - for (var/obj/machinery/photocopier/faxmachine/fax in world) - if (fax.department == "Captain's Office") - var/obj/item/weapon/paper/directive_x = new(fax.loc) - directive_x.name = "emergency action message" - directive_x.info = get_fax_body() - - proc/get_fax_body() - return {" -
    NOT A DRILL . . . EMERGENCY DIRECTIVE . . . NOT A DRILL
    -

    - TO: Captain [mode.head_loyalist], Commanding Officer, [station_name()]
    - FROM: NanoTrasen Emergency Messaging Relay
    - DATE: [time2text(world.realtime, "MM/DD")]/[game_year]
    - SUBJECT: Directive X
    -

    - - [mode.current_directive.get_description()] - -
    -
    Emergency Authentication Protocol
    -

    - A member of your Command Staff is this shift's designated Emergency Secondary Authenticator.
    - This Emergency Secondary Authenticator is uniquely aware of their role and possesses the Emergency Secondary Authentication Key.
    - As Captain, you possess the Captain's Authentication Key.
    - The Emergency Authentication Device is located in the vault of your station, and requires simultaneous activation of the Authentication Keys.
    - An Authentication Key Pinpointer can be delivered via Cargo Bay to assist recovery of the Authentication Keys should they be lost aboard the station.
    - A key's destruction or removal from the station's perimeter will automatically and irreversibly activate the Emergency Authentication Device. -

    -
    - -
    Orders
    -

    - Captain [mode.head_loyalist], you are to immediately initiate the following procedure; codenamed Directive X: -

    -
      - [get_orders()] -
    -
    - -
    Authentication
    - - Encoded Authentication String: T0JCJUwoIVFDQA==
    - Emergency Action Code: O B B _ L _ _ Q C _
    - ERROR: DECODING INCOMPLETE (40% LOSS) -
    -
    -
    - -
    NOT A DRILL . . . EMERGENCY DIRECTIVE . . . NOT A DRILL
    - "} - - proc/get_orders() - var/text = "
  • Immediate external transmission and signals silence. Evacuation and Cargo services will remain available. All ERT teams are engaged elsewhere. Do not communicate with Central Command under any circumstances.
  • " - for(var/order in mode.current_directive.special_orders) - text += "
  • [order]
  • " - - text += "
  • Upon completion of this Directive, Captain [mode.head_loyalist] and the Emergency Secondary Authenticator must utilise the Captain's Authentication Key and the Emergency Secondary Authentication Key to activate the Emergency Authentication Device.
  • " - return text - - proc/get_pda_body() - return {"← From Anonymous Channel:

    \"You must read this! NanoTrasen Chain of Command COMPROMISED. Command Encryptions BROKEN. [station_name()] Captain [mode.head_loyalist] will receive orders that must NOT BE BROUGHT TO FRUITION! - -They don't care about us they only care about WEALTH and POWER... Share this message with people you trust. - -Be safe, friend.\" (Unable to Reply)

    "} - - proc/announce() - world << "The current game mode is - Mutiny!" - world << {" -

    The crew will be divided by their sense of ethics when a morally turbulent emergency directive arrives with an incomplete command validation code.

    -The [loyalist_tag("Head Loyalist")] is the Captain, who carries the [loyalist_tag("Captain's Authentication Key")] at all times.
    -The [mutineer_tag("Head Mutineer")] is a random Head of Staff who carries the [mutineer_tag("Emergency Secondary Authentication Key")].

    -Both keys are required to activate the Emergency Authentication Device (EAD) in the vault, signalling to NanoTrasen that the directive is complete. -
    -

    -Loyalists - Follow the Head Loyalist in carrying out [loyalist_tag("NanoTrasen's directives")] then activate the EAD.
    -Mutineers - Prevent the completion of the [mutineer_tag("improperly validated directives")] and the activation of the EAD. -

    - "} - - proc/loyalist_tag(text) - return "[text]" - - proc/mutineer_tag(text) - return "[text]" - - proc/their(datum/mind/head) - if (head.current.gender == MALE) - return "his" - else if (head.current.gender == FEMALE) - return "her" - - return "their" - - proc/loyalist_major_victory() - return {" -NanoTrasen has praised the efforts of Captain [mode.head_loyalist] and loyal members of [their(mode.head_loyalist)] crew, who recently managed to put down a mutiny--amid a local interstellar crisis--aboard the [station_name()], a research station in [system_name()]. -The mutiny was spurred by a top secret directive sent to the station, presumably in response to the crisis within the system. -Despite the mutiny, the crew was successful in implementing the directive and activating their on-board emergency authentication device. -[mode.mutineers.len] members of the station's personnel were charged with terrorist action against the Company and, if found guilty by a Sol magistrate, will be sentenced to life incarceration. -NanoTrasen will be awarding [mode.loyalists.len] members of the crew with the [loyalist_tag("Star of Loyalty")], following their successful efforts, at a ceremony this coming Thursday. -[mode.body_count.len] are believed to have died during the coup. -

    NanoTrasen's image will forever be haunted by the fact that a mutiny took place on one of its own stations.

    - "} - - proc/loyalist_minor_victory() - return {" -NanoTrasen has praised the efforts of Captain [mode.head_loyalist] and loyal members of [their(mode.head_loyalist)] crew, who recently managed to put down a mutiny--amid a local interstellar crisis--aboard the [station_name()], a research station in [system_name()]. -The mutiny was spurred by a top secret directive sent to the station, presumably in response to the crisis within the system. -Despite the mutiny, the crew was successful in implementing the directive. Unfortunately, they failed to notify Central Command of their successes due to a breach in the chain of command. -[mode.mutineers.len] members of the station's personnel were charged with terrorist action against the Company and, if found guilty by a Sol magistrate, will be sentenced to life incarceration. -NanoTrasen will be awarding [mode.loyalists.len] members of the crew with the [loyalist_tag("Star of Loyalty")], following their mostly successful efforts, at a ceremony this coming Thursday. -[mode.body_count.len] are believed to have died during the coup. -

    NanoTrasen's image will forever be haunted by the fact that a mutiny took place on one of its own stations.

    - "} - - proc/no_victory() - return {" -NanoTrasen has been thrust into turmoil following an apparent mutiny by key personnel aboard the [station_name()], a research station in [system_name()]. -The mutiny was spurred by a top secret directive sent to the station, presumably in response to the crisis within the system. -No further information has yet emerged from the station or its crew, who are presumed to be in holding with NanoTrasen investigators. -NanoTrasen officials refuse to comment. -Sources indicate that [mode.mutineers.len] members of the station's personnel are currently under investigation for terrorist activity, and [mode.loyalists.len] crew are currently providing evidence to investigators, believed to be the 'loyal' station personnel. -[mode.body_count.len] are believed to have died during the coup. -

    NanoTrasen's image will forever be haunted by the fact that a mutiny took place on one of its own stations.

    - "} - - proc/mutineer_minor_victory() - return {" -Reports have emerged that an impromptu mutiny has taken place, amid a local interstellar crisis, aboard the [station_name()], a research station in [system_name()]. -The mutiny was spurred by a top secret directive sent to the station, presumably in response to the crisis within the system. -Information at present indicates that the top-secret directive--which has since been retracted--was invalid due to a broken authentication code. Members of the crew, including an unidentified Head of Staff, prevented the directive from being accomplished. -[mode.mutineers.len] members of the station's personnel were released from interrogations today, following a mutiny investigation. -NanoTrasen has reprimanded [mode.loyalists.len] members of the crew for failing to follow command validation procedures. -[mode.body_count.len] are believed to have died during the coup. -

    Even though the directive was not successfully implemented, NanoTrasen's image will forever be haunted by the fact that its authentication protocol was breached with such magnitude and that a mutiny was the result.

    - "} - - proc/mutineer_major_victory() - return {" -NanoTrasen has praised the efforts of [mode.head_mutineer.assigned_role] [mode.head_mutineer] and several other members of the crew, who recently seized control of a company station in [system_name()]--[station_name()]--amid a local interstellar crisis. -What appears to have been a "legitimate" mutiny was spurred by a top secret directive sent to the station, presumably in response to the crisis within the system. -It has been revealed that the directive was invalid and fraudulent. Company officials have not released a statement about the source of the directive. -Thanks to the efforts of the resistant members of the crew, the directive was not carried out. -[mode.mutineers.len] members of the station's personnel were congratulated and awarded with the [mutineer_tag("Star of Bravery")], for their efforts in preventing the illegal directive's completion. -NanoTrasen has [mode.loyalists.len] members of the crew in holding, while it investigates the circumstances that led to the acceptance and initiation of an invalid directive. -[mode.body_count.len] are believed to have died during the coup. -

    Even though the directive was not successfully implemented, NanoTrasen's image will forever be haunted by the fact that its authentication protocol was breached with such magnitude and that a mutiny was the result.

    - "} - - proc/secret_transcript() - return {" -

    Corporate Rival Threat Assessment

    -
    Gilthari Exports Incident Transcript
    -
    CONFIDENTIAL: PROPERTY OF NANOTRASEN
    -Location: Operator's Desk, D Deck, Polumetis Installation
    -Time: 16:11, May 24, 2558 (Sol Reckoning)
    -
    -
    - -
    \[Start of transcript\]
    -
    \[Sound of an internal airlock door opening\]
    -TM: Thank you for coming to see me, Director. I'm afraid this is urgent.
    -D: Mr. Mitchell, first you send cryptic messages to my office and then you request to have me come personally to this barely lit closet you call a workstation; all of this to talk about a computer glitch?
    -
    \[Sound of the internal airlock door shutting\]
    -TM: Do you remember Mallory?
    -D: Who?
    -TM: It's not who, it's what. The computer program we planted in the [system_name()] communications satellite.
    -D: What is so important about this computer program?
    -TM: We call her an eavesdropper. Captures network traffic, records it, and forwards the stream to the receiver autonomously.
    -D: Speak English goddamnit.
    -TM: Standard intelligence acquisition package, sir; we bug their satellite and listen. It's like we have their playbook and we know what their moves are going to be on the market before they make them.
    -D: So Mallory doesn't work?
    -TM: She worked, sir. We've had an ear on NanoTrasen's regional communications for weeks.
    -D: Any news about their Phoron refinement process?
    -TM: No sir. Our analysts believe they are using a separate channel for their most sensitive data.
    -D: So what's the problem?
    -TM: The intelligence hasn't been doing us any good. Anything that appears actionable, I send it to the analysts and they make a plan. Thing is, NanoTrasen always sees us coming.
    -D: Tim...
    -TM: I think they discovered the hack, sir. Case in point, Energine Consolidated Solutions. That subsidiary of ours that was awarded a lease on NanoTrasen's mining platform in Nyx? NanoTrasen acquired them a week before we made the announcement.
    -D: They know about they have a bug. They left her on and fed her the information for us to hear, those sneaks. How did they find it?
    -TM: Top secret communique came through. I'm not sure what happened. Either Mallory couldn't replicate the encryption scheme and garbled it going out or the transmission was already corrupted to begin with.
    -D: Either way the transmission caused NanoTrasen to look at the satellite. They found out about Mallory.
    -TM: Precisely sir. There's only so much I can do to cover our tracks from here.
    -D: I'm pulling the plug. We have assets in the sector that are capable of a job like this. Thank you for bringing this to my attention.
    -
    \[Computer device chirps\]
    -D: One last thing, did you happen to read anything from those secure transmissions?
    -TM: Just the subject, 'Directive X'.
    -D: Directive X... Now what do you suppose that means?
    -
    \[End of transcript\]
    - "} diff --git a/code/game/gamemodes/mutiny/mutiny_hooks.dm b/code/game/gamemodes/mutiny/mutiny_hooks.dm deleted file mode 100644 index 9e64bd2e70..0000000000 --- a/code/game/gamemodes/mutiny/mutiny_hooks.dm +++ /dev/null @@ -1,27 +0,0 @@ -/hook/death/proc/track_kills(mob/living/carbon/human/deceased, gibbed) - var/datum/game_mode/mutiny/mode = get_mutiny_mode() - if (!mode) return 1 - - mode.body_count.Add(deceased.mind) - return 1 - -/hook/clone/proc/update_icon(mob/living/carbon/human/H) - var/datum/game_mode/mutiny/mode = get_mutiny_mode() - if (!mode) return 1 - - mode.update_icon(H.mind) - return 1 - -/hook/harvest_podman/proc/update_icon(mob/living/carbon/alien/diona/D) - var/datum/game_mode/mutiny/mode = get_mutiny_mode() - if (!mode) return 1 - - mode.update_icon(D.mind) - return 1 - -/hook/roundend/proc/report_mutiny_news() - var/datum/game_mode/mutiny/mode = get_mutiny_mode() - if (!mode) return 1 - - mode.round_outcome() - return 1 diff --git a/code/game/gamemodes/ninja/ninja.dm b/code/game/gamemodes/ninja/ninja.dm index f136d63e45..d410dbeb7d 100644 --- a/code/game/gamemodes/ninja/ninja.dm +++ b/code/game/gamemodes/ninja/ninja.dm @@ -1,181 +1,10 @@ -/datum/game_mode/var/list/datum/mind/ninjas = list() -// Keep in mind ninja-procs that aren't here will be where the event's defined /datum/game_mode/ninja name = "ninja" + round_description = "An agent of the Spider Clan is onboard the station!" + extended_round_description = "What was that?! Was that a person or did your eyes just play tricks on you? You have no idea. That slim-suited, cryptic individual is an enigma to you and all of your knowledge. Their purpose is unknown. Their mission is unknown. How they arrived to this secure and isolated section of the galaxy, you don't know. What you do know is that there is a silent shadow-stalker piercing through the defenses of Nanotrasen with technological capabilities eons ahead of your time. They can avoid the omniscience of the AI and rival the most hardened weapons your station is capable of. Tread lightly and only hope this unknown assassin isn't here for you." + antag_tag = MODE_NINJA config_tag = "ninja" - required_players = 10 //Can be adjusted later, should suffice for now. + required_players = 1 required_players_secret = 10 required_enemies = 1 - recommended_enemies = 1 - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - var/finished = 0 - -/datum/game_mode/ninja/announce() - world << "The current game mode is Ninja!" - -/datum/game_mode/ninja/can_start() - if(!..()) - return 0 - var/list/datum/mind/possible_ninjas = get_players_for_role(BE_NINJA) - if(possible_ninjas.len==0) - return 0 - var/datum/mind/ninja = pick(possible_ninjas) - ninjas += ninja - modePlayer += ninja - ninja.assigned_role = "MODE" //So they aren't chosen for other jobs. - ninja.special_role = "Ninja" - ninja.original = ninja.current - - if(ninjastart.len == 0) - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "carpspawn") - ninjastart.Add(L) - - if(ninjastart.len) - return 1 - if(ninjastart.len == 0 && latejoin.len > 0) - ninja.current << "\red No spawn locations could be found. Defaulting to late-join locations." - return 1 - - ninja.current << "\red No spawn locations could be found. Aborting." - return 0 - -/datum/game_mode/ninja/pre_setup() - for(var/datum/mind/ninja in ninjas) - ninja.current << browse(null, "window=playersetup") - ninja.current = create_space_ninja(pick(ninjastart.len ? ninjastart : latejoin)) - ninja.current.ckey = ninja.key - return 1 - -/datum/game_mode/ninja/post_setup() - - for(var/datum/mind/ninja in ninjas) - if(ninja.current && !(istype(ninja.current,/mob/living/carbon/human))) return 0 - if(!config.objectives_disabled) - forge_ninja_objectives(ninja) - show_objectives(ninja) - - spawn (rand(waittime_l, waittime_h)) - send_intercept() - return ..() - -/datum/game_mode/ninja/check_finished() - if(config.continous_rounds) - return ..() - var/ninjas_alive = 0 - for(var/datum/mind/ninja in ninjas) - if(!istype(ninja.current,/mob/living/carbon/human)) - continue - if(ninja.current.stat==2) - continue - ninjas_alive++ - if (ninjas_alive) - return ..() - else - finished = 1 - return 1 - -/datum/game_mode/ninja/proc/forge_ninja_objectives(var/datum/mind/ninja) - if (config.objectives_disabled) - return - - var/objective_list = list(1,2,3,4,5) - for(var/i=rand(2,4),i>0,i--) - switch(pick(objective_list)) - if(1)//Kill - var/datum/objective/assassinate/ninja_objective = new - ninja_objective.owner = ninja - ninja_objective.target = ninja_objective.find_target() - if(ninja_objective.target != "Free Objective") - ninja.objectives += ninja_objective - else - i++ - objective_list -= 1 // No more than one kill objective - if(2)//Steal - var/datum/objective/steal/ninja_objective = new - ninja_objective.owner = ninja - ninja_objective.target = ninja_objective.find_target() - ninja.objectives += ninja_objective - if(3)//Protect - var/datum/objective/protect/ninja_objective = new - ninja_objective.owner = ninja - ninja_objective.target = ninja_objective.find_target() - if(ninja_objective.target != "Free Objective") - ninja.objectives += ninja_objective - else - i++ - objective_list -= 3 - if(4)//Download - var/datum/objective/download/ninja_objective = new - ninja_objective.owner = ninja - ninja_objective.gen_amount_goal() - ninja.objectives += ninja_objective - objective_list -= 4 - if(5)//Harm - var/datum/objective/harm/ninja_objective = new - ninja_objective.owner = ninja - ninja_objective.target = ninja_objective.find_target() - if(ninja_objective.target != "Free Objective") - ninja.objectives += ninja_objective - else - i++ - objective_list -= 5 - - var/datum/objective/survive/ninja_objective = new - ninja_objective.owner = ninja - ninja.objectives += ninja_objective - ninja.current.mind = ninja - - var/directive = generate_ninja_directive("heel")//Only hired by antags, not NT - ninja.current << "You are an elite mercenary assassin of the Spider Clan, [ninja.current.real_name]. You have a variety of abilities at your disposal, thanks to your nano-enhanced cyber armor.\nYour current directive is: \red [directive]\n \blue Try your best to adhere to this." - ninja.store_memory("Directive: \red [directive]
    ") - - show_objectives(ninja) - -/datum/game_mode/proc/auto_declare_completion_ninja() - if(ninjas.len) - var/text = "The ninjas were:" - for(var/datum/mind/ninja in ninjas) - var/ninjawin = 1 - - text += "
    [ninja.key] was [ninja.name] (" - if(ninja.current) - if(ninja.current.stat == DEAD) - text += "died" - else - text += "survived" - if(ninja.current.real_name != ninja.name) - text += " as [ninja.current.real_name]" - else - text += "body destroyed" - text += ")" - - if(ninja.objectives.len)//If the ninja had no objectives, don't need to process this. - var/count = 1 - for(var/datum/objective/objective in ninja.objectives) - if(objective.check_completion()) - text += "
    Objective #[count]: [objective.explanation_text] Success!" - feedback_add_details("traitor_objective","[objective.type]|SUCCESS") - else - text += "
    Objective #[count]: [objective.explanation_text] Fail." - feedback_add_details("traitor_objective","[objective.type]|FAIL") - ninjawin = 0 - count++ - - var/special_role_text - if(ninja.special_role) - special_role_text = lowertext(ninja.special_role) - else - special_role_text = "antagonist" - - if(!config.objectives_disabled) - if(ninjawin) - text += "
    The [special_role_text] was successful!" - feedback_add_details("traitor_success","SUCCESS") - else - text += "
    The [special_role_text] has failed!" - feedback_add_details("traitor_success","FAIL") - - world << text - return 1 + end_on_antag_death = 1 \ No newline at end of file diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index b2e54da0d9..b556ba2070 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -2,245 +2,21 @@ MERCENARY ROUNDTYPE */ -var/global/list/turf/synd_spawn = list() - - -/datum/game_mode - var/list/datum/mind/syndicates = list() - - /datum/game_mode/nuclear - name = "mercenary" + name = "Mercenary" + round_description = "A mercenary strike force is approaching the station!" config_tag = "mercenary" required_players = 15 required_players_secret = 25 // 25 players - 5 players to be the nuke ops = 20 players remaining required_enemies = 1 - recommended_enemies = 5 + end_on_antag_death = 1 + antag_tag = MODE_MERCENARY uplink_welcome = "Corporate Backed Uplink Console:" uplink_uses = 40 - - var/const/agents_possible = 5 //If we ever need more syndicate agents. - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - - var/nukes_left = 1 // Call 3714-PRAY right now and order more nukes! Limited offer! var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station var/syndies_didnt_escape = 0 //Used for tracking if the syndies got the shuttle off of the z-level - -/datum/game_mode/nuclear/announce() - world << "The current game mode is - Mercenary!" - world << "A [syndicate_name()] Strike Force is approaching [station_name()]!" - -/datum/game_mode/nuclear/can_start()//This could be better, will likely have to recode it later - if(!..()) - return 0 - - var/list/possible_syndicates = get_players_for_role(BE_OPERATIVE) - var/agent_number = 0 - - /* - * if(possible_syndicates.len > agents_possible) - * agent_number = agents_possible - * else - * agent_number = possible_syndicates.len - * - * if(agent_number > n_players) - * agent_number = n_players/2 - */ - - if(possible_syndicates.len < 1) - return 0 - - //Antag number should scale to active crew. - var/n_players = num_players() - agent_number = Clamp((n_players/5), 2, 6) - - if(possible_syndicates.len < agent_number) - agent_number = possible_syndicates.len - - while(agent_number > 0) - var/datum/mind/new_syndicate = pick(possible_syndicates) - syndicates += new_syndicate - possible_syndicates -= new_syndicate //So it doesn't pick the same guy each time. - agent_number-- - - for(var/datum/mind/synd_mind in syndicates) - synd_mind.assigned_role = "MODE" //So they aren't chosen for other jobs. - synd_mind.special_role = "Mercenary"//So they actually have a special role/N - return 1 - - -/datum/game_mode/nuclear/pre_setup() - return 1 - - -//////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/proc/update_all_synd_icons() - spawn(0) - for(var/datum/mind/synd_mind in syndicates) - if(synd_mind.current) - if(synd_mind.current.client) - for(var/image/I in synd_mind.current.client.images) - if(I.icon_state == "synd") - del(I) - - for(var/datum/mind/synd_mind in syndicates) - if(synd_mind.current) - if(synd_mind.current.client) - for(var/datum/mind/synd_mind_1 in syndicates) - if(synd_mind_1.current) - var/I = image('icons/mob/mob.dmi', loc = synd_mind_1.current, icon_state = "synd") - synd_mind.current.client.images += I - -/datum/game_mode/proc/update_synd_icons_added(datum/mind/synd_mind) - spawn(0) - if(synd_mind.current) - if(synd_mind.current.client) - var/I = image('icons/mob/mob.dmi', loc = synd_mind.current, icon_state = "synd") - synd_mind.current.client.images += I - -/datum/game_mode/proc/update_synd_icons_removed(datum/mind/synd_mind) - spawn(0) - for(var/datum/mind/synd in syndicates) - if(synd.current) - if(synd.current.client) - for(var/image/I in synd.current.client.images) - if(I.icon_state == "synd" && I.loc == synd_mind.current) - del(I) - - if(synd_mind.current) - if(synd_mind.current.client) - for(var/image/I in synd_mind.current.client.images) - if(I.icon_state == "synd") - del(I) - -//////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////// - -/datum/game_mode/nuclear/post_setup() - - var/obj/effect/landmark/uplinkdevice = locate("landmark*Syndicate-Uplink") //i will be rewriting this shortly - var/obj/effect/landmark/nuke_spawn = locate("landmark*Nuclear-Bomb") - - var/nuke_code = "[rand(10000, 99999)]" - var/datum/mind/leader = null - var/spawnpos = 1 - - for(var/datum/mind/synd_mind in syndicates) - if(spawnpos > synd_spawn.len) - spawnpos = 1 - synd_mind.current.loc = synd_spawn[spawnpos] - - synd_mind.current.real_name = "[syndicate_name()] Operative" // placeholder while we get their actual name - spawn(0) - NukeNameAssign(synd_mind) - - forge_syndicate_objectives(synd_mind) - greet_syndicate(synd_mind) - equip_syndicate(synd_mind.current) - - if(!leader) - prepare_syndicate_leader(synd_mind, nuke_code) - leader = synd_mind - - spawnpos++ - update_synd_icons_added(synd_mind) - - update_all_synd_icons() - - if(uplinkdevice) - var/obj/item/device/radio/uplink/U = new(uplinkdevice.loc) - if(leader) - U.hidden_uplink.uplink_owner = leader - U.hidden_uplink.uses = 40 - if(nuke_spawn && synd_spawn.len > 0) - var/obj/machinery/nuclearbomb/the_bomb = new /obj/machinery/nuclearbomb(nuke_spawn.loc) - the_bomb.r_code = nuke_code - - spawn (rand(waittime_l, waittime_h)) - send_intercept() - - return ..() - - -/datum/game_mode/proc/prepare_syndicate_leader(var/datum/mind/synd_mind, var/nuke_code) - var/obj/effect/landmark/code_spawn = locate("landmark*Nuclear-Code") - if (nuke_code) - synd_mind.store_memory("Nuclear Bomb Code: [nuke_code]", 0, 0) - synd_mind.current << "The nuclear authorization code is: [nuke_code]" - synd_mind.current << "To speak on the strike team's private channel use :t" - var/obj/item/weapon/paper/P = new - P.info = "The nuclear authorization code is: [nuke_code]" - P.name = "nuclear bomb code" - if (ticker.mode.config_tag=="mercenary") - P.loc = code_spawn.loc - else - var/mob/living/carbon/human/H = synd_mind.current - P.loc = H.loc - H.equip_to_slot_or_del(P, slot_r_store, 0) - H.update_icons() - - else - nuke_code = "code will be provided later" - return - - -/datum/game_mode/proc/forge_syndicate_objectives(var/datum/mind/syndicate) - - if (config.objectives_disabled) - return - - var/datum/objective/nuclear/syndobj = new - syndobj.owner = syndicate - syndicate.objectives += syndobj - -/datum/game_mode/proc/greet_syndicate(var/datum/mind/syndicate, var/you_are=1) - if (you_are) - syndicate.current << "\blue You are a [syndicate_name()] operative!" - show_objectives(syndicate) - -/datum/game_mode/proc/random_radio_frequency() - return 1337 // WHY??? -- Doohl - - -/datum/game_mode/proc/equip_syndicate(mob/living/carbon/human/synd_mob) - var/obj/item/device/radio/R = new /obj/item/device/radio/headset/syndicate(synd_mob) - R.set_frequency(SYND_FREQ) - R.freerange = 1 - synd_mob.equip_to_slot_or_del(R, slot_l_ear) - - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(synd_mob), slot_w_uniform) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(synd_mob), slot_shoes) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(synd_mob), slot_gloves) - synd_mob.equip_to_slot_or_del(new /obj/item/weapon/card/id/syndicate(synd_mob), slot_wear_id) - if(synd_mob.backbag == 2) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(synd_mob), slot_back) - if(synd_mob.backbag == 3) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(synd_mob), slot_back) - if(synd_mob.backbag == 4) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(synd_mob), slot_back) - synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(synd_mob.back), slot_in_backpack) - synd_mob.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/pill/cyanide(synd_mob), slot_in_backpack) - - synd_mob.update_icons() - return 1 - - -/datum/game_mode/nuclear/check_win() - if (nukes_left == 0) - return 1 - return ..() - - -/datum/game_mode/proc/is_operatives_are_dead() - for(var/datum/mind/operative_mind in syndicates) - if (!istype(operative_mind.current,/mob/living/carbon/human)) - if(operative_mind.current) - if(operative_mind.current.stat!=2) - return 0 - return 1 - - /datum/game_mode/nuclear/declare_completion() if(config.objectives_disabled) return @@ -251,20 +27,13 @@ var/global/list/turf/synd_spawn = list() disk_rescued = 0 break var/crew_evacuated = (emergency_shuttle.returned()) - //var/operatives_are_dead = is_operatives_are_dead() - - - //nukes_left - //station_was_nuked - //derp //Used for tracking if the syndies actually haul the nuke to the station //no - //herp //Used for tracking if the syndies got the shuttle off of the z-level //NO, DON'T FUCKING NAME VARS LIKE THIS if(!disk_rescued && station_was_nuked && !syndies_didnt_escape) feedback_set_details("round_end_result","win - syndicate nuke") world << "Mercenary Major Victory!" world << "[syndicate_name()] operatives have destroyed [station_name()]!" - else if (!disk_rescued && station_was_nuked && syndies_didnt_escape) + else if (!disk_rescued && station_was_nuked && syndies_didnt_escape) feedback_set_details("round_end_result","halfwin - syndicate nuke - did not evacuate in time") world << "Total Annihilation" world << "[syndicate_name()] operatives destroyed [station_name()] but did not leave the area in time and got caught in the explosion. Next time, don't lose the disk!" @@ -274,12 +43,12 @@ var/global/list/turf/synd_spawn = list() world << "Crew Minor Victory" world << "[syndicate_name()] operatives secured the authentication disk but blew up something that wasn't [station_name()]. Next time, don't lose the disk!" - else if (!disk_rescued && !station_was_nuked && nuke_off_station && syndies_didnt_escape) + else if (!disk_rescued && !station_was_nuked && nuke_off_station && syndies_didnt_escape) feedback_set_details("round_end_result","halfwin - blew wrong station - did not evacuate in time") world << "[syndicate_name()] operatives have earned Darwin Award!" world << "[syndicate_name()] operatives blew up something that wasn't [station_name()] and got caught in the explosion. Next time, don't lose the disk!" - else if ( disk_rescued && is_operatives_are_dead()) + else if (disk_rescued && mercs.antags_are_dead()) feedback_set_details("round_end_result","loss - evacuation - disk secured - syndi team dead") world << "Crew Major Victory!" world << "The Research Staff has saved the disc and killed the [syndicate_name()] Operatives" @@ -289,58 +58,20 @@ var/global/list/turf/synd_spawn = list() world << "Crew Major Victory" world << "The Research Staff has saved the disc and stopped the [syndicate_name()] Operatives!" - else if (!disk_rescued && is_operatives_are_dead()) + else if (!disk_rescued && mercs.antags_are_dead()) feedback_set_details("round_end_result","loss - evacuation - disk not secured") world << "Mercenary Minor Victory!" world << "The Research Staff failed to secure the authentication disk but did manage to kill most of the [syndicate_name()] Operatives!" - else if (!disk_rescued && crew_evacuated) + else if (!disk_rescued && crew_evacuated) feedback_set_details("round_end_result","halfwin - detonation averted") world << "Mercenary Minor Victory!" world << "[syndicate_name()] operatives recovered the abandoned authentication disk but detonation of [station_name()] was averted. Next time, don't lose the disk!" - else if (!disk_rescued && !crew_evacuated) + else if (!disk_rescued && !crew_evacuated) feedback_set_details("round_end_result","halfwin - interrupted") world << "Neutral Victory" world << "Round was mysteriously interrupted!" ..() return - - -/datum/game_mode/proc/auto_declare_completion_nuclear() - if( syndicates.len || (ticker && istype(ticker.mode,/datum/game_mode/nuclear)) ) - var/text = "The mercenaries were:" - - for(var/datum/mind/syndicate in syndicates) - text += print_player_full(syndicate) - - world << text - return 1 - - -/*/proc/nukelastname(var/mob/M as mob) //--All praise goes to NEO|Phyte, all blame goes to DH, and it was Cindi-Kate's idea. Also praise Urist for copypasta ho. - var/randomname = pick(last_names) - var/newname = copytext(sanitize(input(M,"You are the nuke operative [pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord")]. Please choose a last name for your family.", "Name change",randomname)),1,MAX_NAME_LEN) - - if (!newname) - newname = randomname - - else - if (newname == "Unknown" || newname == "floor" || newname == "wall" || newname == "rwall" || newname == "_") - M << "That name is reserved." - return nukelastname(M) - - return newname -*/ - -/proc/NukeNameAssign(var/datum/mind/synd_mind) - var/choose_name = input(synd_mind.current, "You are a [syndicate_name()] agent! What is your name?", "Choose a name") as text - - if(!choose_name) - return - - else - synd_mind.current.name = choose_name - synd_mind.current.real_name = choose_name - return \ No newline at end of file diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 83fc1a9a85..0c39bf52fb 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -119,9 +119,8 @@ datum/objective/mutiny/rp if(target.current.stat == DEAD || target.current:handcuffed || !ishuman(target.current)) return 1 // Check if they're converted - if(istype(ticker.mode, /datum/game_mode/revolution)) - if(target in ticker.mode:head_revolutionaries) - return 1 + if(target in revs.head_revolutionaries) + return 1 var/turf/T = get_turf(target.current) if(T && isNotStationLevel(T.z)) //If they leave the station they count as dead for this rval = 2 @@ -665,8 +664,7 @@ datum/objective/capture return 1 - -datum/objective/absorb +/datum/objective/absorb proc/gen_amount_goal(var/lowbound = 4, var/highbound = 6) target_amount = rand (lowbound,highbound) if (ticker) @@ -677,7 +675,7 @@ datum/objective/absorb n_p ++ else if (ticker.current_state == GAME_STATE_PLAYING) for(var/mob/living/carbon/human/P in player_list) - if(P.client && !(P.mind in ticker.mode.changelings) && P.mind!=owner) + if(P.client && !(P.mind.changeling) && P.mind!=owner) n_p ++ target_amount = min(target_amount, n_p) @@ -690,67 +688,7 @@ datum/objective/absorb else return 0 - - -/* Isn't suited for global objectives -/*---------CULTIST----------*/ - - eldergod - explanation_text = "Summon Nar-Sie via the use of an appropriate rune. It will only work if nine cultists stand on and around it." - - check_completion() - if(eldergod) //global var, defined in rune4.dm - return 1 - return 0 - - survivecult - var/num_cult - - explanation_text = "Our knowledge must live on. Make sure at least 5 acolytes escape on the shuttle to spread their work on an another station." - - check_completion() - if(!emergency_shuttle.returned()) - return 0 - - var/cultists_escaped = 0 - - var/area/shuttle/escape/centcom/C = /area/shuttle/escape/centcom - for(var/turf/T in get_area_turfs(C.type)) - for(var/mob/living/carbon/H in T) - if(iscultist(H)) - cultists_escaped++ - - if(cultists_escaped>=5) - return 1 - - return 0 - - sacrifice //stolen from traitor target objective - - proc/find_target() //I don't know how to make it work with the rune otherwise, so I'll do it via a global var, sacrifice_target, defined in rune15.dm - var/list/possible_targets = call(/datum/game_mode/cult/proc/get_unconvertables)() - - if(possible_targets.len > 0) - sacrifice_target = pick(possible_targets) - - if(sacrifice_target && sacrifice_target.current) - explanation_text = "Sacrifice [sacrifice_target.current.real_name], the [sacrifice_target.assigned_role]. You will need the sacrifice rune (Hell join blood) and three acolytes to do so." - else - explanation_text = "Free Objective" - - return sacrifice_target - - check_completion() //again, calling on a global list defined in rune15.dm - if(sacrifice_target.current in sacrificed) - return 1 - else - return 0 - -/*-------ENDOF CULTIST------*/ -*/ - //Vox heist objectives. - datum/objective/heist proc/choose_target() return @@ -844,8 +782,7 @@ datum/objective/heist/loot if(istype(I,target)) total_amount++ if(total_amount >= target_amount) return 1 - var/datum/game_mode/heist/H = ticker.mode - for(var/datum/mind/raider in H.raiders) + for(var/datum/mind/raider in raiders.current_antagonists) if(raider.current) for(var/obj/O in raider.current.get_contents()) if(istype(O,target)) total_amount++ @@ -901,8 +838,7 @@ datum/objective/heist/salvage S = I total_amount += S.get_amount() - var/datum/game_mode/heist/H = ticker.mode - for(var/datum/mind/raider in H.raiders) + for(var/datum/mind/raider in raiders.current_antagonists) if(raider.current) for(var/obj/item/O in raider.current.get_contents()) if(istype(O,/obj/item/stack/sheet)) @@ -914,12 +850,11 @@ datum/objective/heist/salvage return 0 -datum/objective/heist/inviolate_crew +/datum/objective/heist/inviolate_crew explanation_text = "Do not leave any Vox behind, alive or dead." check_completion() - var/datum/game_mode/heist/H = ticker.mode - if(H.is_raider_crew_safe()) return 1 + if(raiders && raiders.is_raider_crew_safe()) return 1 return 0 #define MAX_VOX_KILLS 10 //Number of kills during the round before the Inviolate is broken. @@ -957,15 +892,52 @@ datum/objective/heist/inviolate_death /datum/objective/ninja_highlander/check_completion() if(owner) - for(var/datum/mind/ninja in ticker.mode.ninjas) + for(var/datum/mind/ninja in get_antags("ninja")) if(ninja != owner) if(ninja.current.stat < 2) return 0 return 1 return 0 -/datum/objective/cult_summon - explanation_text = "Summon Nar-Sie via the use of the appropriate rune (Hell join self). It will only work if nine cultists stand on and around it." +/datum/objective/cult/survive + explanation_text = "Our knowledge must live on." + target_amount = 5 -/datum/objective/cult_summon/check_completion() - if(locate(/obj/machinery/singularity/narsie/large) in machines) return 1 - return 0 \ No newline at end of file +/datum/objective/cult/survive/New() + ..() + explanation_text = "Our knowledge must live on. Make sure at least [target_amount] acolytes escape on the shuttle to spread their work on an another station." + +/datum/objective/cult/survive/check_completion() + var/acolytes_survived = 0 + if(!cult) + return 0 + for(var/datum/mind/cult_mind in cult.current_antagonists) + if (cult_mind.current && cult_mind.current.stat!=2) + var/area/A = get_area(cult_mind.current ) + if ( is_type_in_list(A, centcom_areas)) + acolytes_survived++ + if(acolytes_survived >= target_amount) + return 0 + else + return 1 + +/datum/objective/cult/eldergod + explanation_text = "Summon Nar-Sie via the use of the appropriate rune (Hell join self). It will only work if nine cultists stand on and around it. The convert rune is join blood self." + +/datum/objective/cult/eldergod/check_completion() + return (locate(/obj/machinery/singularity/narsie/large) in machines) + +/datum/objective/cult/sacrifice + explanation_text = "Conduct a ritual sacrifice for the glory of Nar-Sie." + +/datum/objective/cult/sacrifice/find_target() + var/list/possible_targets = list() + if(!possible_targets.len) + for(var/mob/living/carbon/human/player in player_list) + if(player.mind && !(player.mind in cult)) + possible_targets += player.mind + if(possible_targets.len > 0) + target = pick(possible_targets) + if(target) explanation_text = "Sacrifice [target.name], the [target.assigned_role]. You will need the sacrifice rune (Hell blood join) and three acolytes to do so." + +/datum/objective/cult/sacrifice/check_completion() + return (target && cult && !cult.sacrificed.Find(target)) diff --git a/code/game/gamemodes/revolution/anti_revolution.dm b/code/game/gamemodes/revolution/anti_revolution.dm deleted file mode 100644 index fce1cace91..0000000000 --- a/code/game/gamemodes/revolution/anti_revolution.dm +++ /dev/null @@ -1,222 +0,0 @@ -// A sort of anti-revolution where the heads are given objectives to mess with the crew - -/datum/game_mode/anti_revolution - name = "anti-revolution" - config_tag = "anti-revolution" - required_players = 5 - - var/finished = 0 - var/checkwin_counter = 0 - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - - var/required_execute_targets = 1 - var/required_brig_targets = 0 - - var/recommended_execute_targets = 1 - var/recommended_brig_targets = 3 - var/recommended_demote_targets = 3 - - var/list/datum/mind/heads = list() - var/list/datum/mind/execute_targets = list() - var/list/datum/mind/brig_targets = list() - var/list/datum/mind/demote_targets = list() - -/////////////////////////// -//Announces the game type// -/////////////////////////// -/datum/game_mode/anti_revolution/announce() - world << "The current game mode is - Anti-Revolution!" - world << "Looks like CentComm has given a few new orders.." - -/////////////////////////////////////////////////////////////////////////////// -//Gets the round setup, cancelling if there's not enough players at the start// -/////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/anti_revolution/pre_setup() - for(var/mob/new_player/player in world) if(player.mind) - if(player.mind.assigned_role in command_positions) - heads += player.mind - else - if(execute_targets.len < recommended_execute_targets) - execute_targets += player.mind - else if(brig_targets.len < recommended_brig_targets) - brig_targets += player.mind - else if(demote_targets.len < recommended_demote_targets) - demote_targets += player.mind - - - if(heads.len==0) - return 0 - - if(execute_targets.len < required_execute_targets || brig_targets.len < required_brig_targets) - return 0 - - return 1 - - -/datum/game_mode/anti_revolution/proc/add_head_objectives(datum/mind/head) - for(var/datum/mind/target in execute_targets) - var/datum/objective/anti_revolution/execute/obj = new - obj.owner = head - obj.target = target - obj.explanation_text = "[target.current.real_name], the [target.assigned_role] has extracted confidential information above their clearance. Execute them." - head.objectives += obj - for(var/datum/mind/target in brig_targets) - var/datum/objective/anti_revolution/brig/obj = new - obj.owner = head - obj.target = target - obj.explanation_text = "Brig [target.current.real_name], the [target.assigned_role] for 20 minutes to set an example." - head.objectives += obj - for(var/datum/mind/target in demote_targets) - var/datum/objective/anti_revolution/demote/obj = new - obj.owner = head - obj.target = target - obj.explanation_text = "[target.current.real_name], the [target.assigned_role] has been classified as harmful to NanoTrasen's goals. Demote them to assistant." - head.objectives += obj - - -/datum/game_mode/anti_revolution/post_setup() - - for(var/datum/mind/head_mind in heads) - add_head_objectives(head_mind) - for(var/datum/mind/head_mind in heads) - greet_head(head_mind) - modePlayer += heads - spawn (rand(waittime_l, waittime_h)) - send_intercept() - ..() - - -/datum/game_mode/anti_revolution/process() - checkwin_counter++ - if(checkwin_counter >= 5) - if(!finished) - ticker.mode.check_win() - checkwin_counter = 0 - return 0 - - -/datum/game_mode/proc/greet_head(var/datum/mind/head_mind, var/you_are=1) - var/obj_count = 1 - if (you_are) - head_mind.current << "\blue It looks like this shift CentComm has some special orders for you.. check your objectives." - head_mind.current << "\blue Note that you can ignore these objectives, but resisting NT's orders probably means demotion or worse." - for(var/datum/objective/objective in head_mind.objectives) - head_mind.current << "Objective #[obj_count]: [objective.explanation_text]" - head_mind.special_role = "Corrupt Head" - obj_count++ - - head_mind.current.verbs += /mob/proc/ResignFromHeadPosition - -////////////////////////////////////// -//Checks if the revs have won or not// -////////////////////////////////////// -/datum/game_mode/anti_revolution/check_win() - if(check_head_victory()) - finished = 1 - else if(check_crew_victory()) - finished = 2 - return - -/////////////////////////////// -//Checks if the round is over// -/////////////////////////////// -/datum/game_mode/anti_revolution/check_finished() - if(finished != 0) - return 1 - else - return 0 - - -////////////////////////// -//Checks for crew victory// -////////////////////////// -/datum/game_mode/anti_revolution/proc/check_crew_victory() - for(var/datum/mind/head_mind in heads) - var/turf/T = get_turf(head_mind.current) - if((head_mind) && (head_mind.current) && (head_mind.current.stat != 2) && T && (T.z in station_levels) && !head_mind.is_brigged(600)) - if(ishuman(head_mind.current)) - return 0 - return 1 - -///////////////////////////// -//Checks for a head victory// -///////////////////////////// -/datum/game_mode/anti_revolution/proc/check_head_victory() - for(var/datum/mind/head_mind in heads) - for(var/datum/objective/objective in head_mind.objectives) - if(!(objective.check_completion())) - return 0 - - return 1 - - -/datum/game_mode/anti_revolution/declare_completion() - - var/text = "" - if(finished == 2) - world << "\red The heads of staff were relieved of their posts! The crew wins!" - else if(finished == 1) - world << "\red The heads of staff managed to meet the goals set for them by CentComm!" - - - - world << "The heads of staff were: " - var/list/heads = list() - heads = get_all_heads() - for(var/datum/mind/head_mind in heads) - text = "" - if(head_mind.current) - text += "[head_mind.current.real_name]" - if(head_mind.current.stat == 2) - text += " (Dead)" - else - text += " (Survived!)" - else - text += "[head_mind.key] (character destroyed)" - - world << text - - - world << "Their objectives were: " - for(var/datum/mind/head_mind in heads) - if(head_mind.objectives.len)//If the traitor had no objectives, don't need to process this. - var/count = 1 - for(var/datum/objective/objective in head_mind.objectives) - if(objective.check_completion()) - text += "
    Objective #[count]: [objective.explanation_text] Success!" - feedback_add_details("head_objective","[objective.type]|SUCCESS") - else - text += "
    Objective #[count]: [objective.explanation_text] Fail." - feedback_add_details("head_objective","[objective.type]|FAIL") - count++ - break // just print once - return 1 - - -/datum/game_mode/anti_revolution/latespawn(mob/living/carbon/human/character) - ..() - if(emergency_shuttle.departed) - return - - if(character.mind.assigned_role in command_positions) - heads += character.mind - modePlayer += character.mind - add_head_objectives(character.mind) - greet_head(character.mind) - -/mob/proc/ResignFromHeadPosition() - set category = "IC" - set name = "Resign From Head Position" - - if(!istype(ticker.mode, /datum/game_mode/anti_revolution)) - return - - ticker.mode:heads -= src.mind - src.mind.objectives = list() - ticker.mode.modePlayer -= src.mind - src.mind.special_role = null - - src.verbs -= /mob/proc/ResignFromHeadPosition - - src << "\red You resigned from your position, now you have the consequences." \ No newline at end of file diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index 71e9704606..493650359e 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -1,436 +1,50 @@ -// To add a rev to the list of revolutionaries, make sure it's rev (with if(ticker.mode.name == "revolution)), -// then call ticker.mode:add_revolutionary(_THE_PLAYERS_MIND_) -// nothing else needs to be done, as that proc will check if they are a valid target. -// Just make sure the converter is a head before you call it! -// To remove a rev (from brainwashing or w/e), call ticker.mode:remove_revolutionary(_THE_PLAYERS_MIND_), -// this will also check they're not a head, so it can just be called freely -// If the rev icons start going wrong for some reason, ticker.mode:update_all_rev_icons() can be called to correct them. -// If the game somtimes isn't registering a win properly, then ticker.mode.check_win() isn't being called somewhere. - -/datum/game_mode - var/list/datum/mind/head_revolutionaries = list() - var/list/datum/mind/revolutionaries = list() - /datum/game_mode/revolution - name = "revolution" + name = "Revolution" config_tag = "revolution" - restricted_jobs = list("Internal Affairs Agent", "AI", "Cyborg","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer") - protected_jobs = list("Security Officer", "Warden", "Detective") + round_description = "Some crewmembers are attempting to start a revolution!" + extended_round_description = "Revolutionaries - Kill the Captain, HoP, HoS, CE, RD and CMO. Convert other crewmembers (excluding the heads of staff, and security officers) to your cause by flashing them. Protect your leaders.
    \nPersonnel - Protect the heads of staff. Kill the leaders of the revolution, and brainwash the other revolutionaries (by beating them in the head)." required_players = 4 required_players_secret = 15 required_enemies = 3 - recommended_enemies = 3 - - + auto_recall_shuttle = 1 uplink_welcome = "AntagCorp Uplink Console:" uplink_uses = 10 + end_on_antag_death = 1 + shuttle_delay = 3 + antag_tag = MODE_REVOLUTIONARY - var/finished = 0 - var/checkwin_counter = 0 - var/max_headrevs = 3 - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) -/////////////////////////// -//Announces the game type// -/////////////////////////// -/datum/game_mode/revolution/announce() - world << "The current game mode is - Revolution!" - world << "Some crewmembers are attempting to start a revolution!
    \nRevolutionaries - Kill the Captain, HoP, HoS, CE, RD and CMO. Convert other crewmembers (excluding the heads of staff, and security officers) to your cause by flashing them. Protect your leaders.
    \nPersonnel - Protect the heads of staff. Kill the leaders of the revolution, and brainwash the other revolutionaries (by beating them in the head).
    " +/datum/game_mode/revolution/New() + if(config && config.rp_rev) + extended_round_description = "Revolutionaries - Remove the heads of staff from power. Convert other crewmembers to your cause using the 'Convert Bourgeoise' verb. Protect your leaders." +/datum/game_mode/revolution/send_intercept() -/////////////////////////////////////////////////////////////////////////////// -//Gets the round setup, cancelling if there's not enough players at the start// -/////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/revolution/pre_setup() - - if(config.protect_roles_from_antagonist) - restricted_jobs += protected_jobs - - var/list/datum/mind/possible_headrevs = get_players_for_role(BE_REV) - - var/head_check = 0 - for(var/mob/new_player/player in player_list) - if(player.mind.assigned_role in command_positions) - head_check = 1 - break - - for(var/datum/mind/player in possible_headrevs) - for(var/job in restricted_jobs)//Removing heads and such from the list - if(player.assigned_role == job) - possible_headrevs -= player - - for (var/i=1 to max_headrevs) - if (possible_headrevs.len==0) - break - var/datum/mind/lenin = pick(possible_headrevs) - possible_headrevs -= lenin - head_revolutionaries += lenin - - if((head_revolutionaries.len==0)||(!head_check)) - return 0 - - return 1 - - -/datum/game_mode/revolution/post_setup() - var/list/heads = get_living_heads() - for(var/datum/mind/rev_mind in head_revolutionaries) - if(!config.objectives_disabled) - for(var/datum/mind/head_mind in heads) - var/datum/objective/mutiny/rev_obj = new - rev_obj.owner = rev_mind - rev_obj.target = head_mind - rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]." - rev_mind.objectives += rev_obj - - // equip_traitor(rev_mind.current, 1) //changing how revs get assigned their uplink so they can get PDA uplinks. --NEO - // Removing revolutionary uplinks. -Pete - equip_revolutionary(rev_mind.current) - update_rev_icons_added(rev_mind) - - for(var/datum/mind/rev_mind in head_revolutionaries) - greet_revolutionary(rev_mind) - modePlayer += head_revolutionaries - if(emergency_shuttle) - emergency_shuttle.auto_recall = 1 - spawn (rand(waittime_l, waittime_h)) - send_intercept() ..() + if(config.announce_revheads) + spawn(54000) + var/intercepttext = "" + command_announcement.Announce("Summary downloaded and printed out at all communications consoles.", "Local agitators have been determined.") + intercepttext = "Cent. Com. Update Requested status information:
    " + intercepttext += "We have determined several members of your staff to be political activists. They are:" + for(var/datum/mind/revmind in revs.head_revolutionaries) + intercepttext += "
    [revmind.current.real_name]" + intercepttext += "
    Please arrest them at once." + for (var/obj/machinery/computer/communications/comm in world) + if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept) + var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc ) + intercept.name = "Cent. Com. Status Summary" + intercept.info = intercepttext + comm.messagetitle.Add("Cent. Com. Status Summary") + comm.messagetext.Add(intercepttext) + spawn(12000) + command_announcement.Announce("Repeating the previous message over intercoms due to urgency. The station has political agitators onboard by the names of [reveal_rev_heads()], please arrest them at once.", "Local agitators have been determined.") -/datum/game_mode/revolution/process() - checkwin_counter++ - if(checkwin_counter >= 5) - if(!finished) - ticker.mode.check_win() - checkwin_counter = 0 - return 0 - - -/datum/game_mode/proc/forge_revolutionary_objectives(var/datum/mind/rev_mind) - if(!config.objectives_disabled) - var/list/heads = get_living_heads() - for(var/datum/mind/head_mind in heads) - var/datum/objective/mutiny/rev_obj = new - rev_obj.owner = rev_mind - rev_obj.target = head_mind - rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]." - rev_mind.objectives += rev_obj - -/datum/game_mode/proc/greet_revolutionary(var/datum/mind/rev_mind, var/you_are=1) - - rev_mind.special_role = "Head Revolutionary" - - if (you_are) - rev_mind.current << "\blue You are a member of the revolutionaries' leadership!" - - show_objectives(rev_mind) - -///////////////////////////////////////////////////////////////////////////////// -//This are equips the rev heads with their gear, and makes the clown not clumsy// -///////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/proc/equip_revolutionary(mob/living/carbon/human/mob) - if(!istype(mob)) - return - - if (mob.mind) - if (mob.mind.assigned_role == "Clown") - mob << "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself." - mob.mutations.Remove(CLUMSY) - - - var/obj/item/device/flash/T = new(mob) - - var/list/slots = list ( - "backpack" = slot_in_backpack, - "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, - ) - var/where = mob.equip_in_one_of_slots(T, slots) - if (!where) - mob << "Your employers were unfortunately unable to get you a flash." - else - mob << "The flash in your [where] will help you to persuade the crew to join your cause." - mob.update_icons() - return 1 - -////////////////////////////////////// -//Checks if the revs have won or not// -////////////////////////////////////// -/datum/game_mode/revolution/check_win() - if(check_rev_victory()) - finished = 1 - else if(check_heads_victory()) - finished = 2 - return - -/////////////////////////////// -//Checks if the round is over// -/////////////////////////////// -/datum/game_mode/revolution/check_finished() - if(config.continous_rounds) - if(finished != 0) - if(emergency_shuttle) - emergency_shuttle.auto_recall = 0 - return ..() - if(finished != 0) - return 1 - else - return 0 - -/////////////////////////////////////////////////// -//Deals with converting players to the revolution// -/////////////////////////////////////////////////// -/datum/game_mode/proc/add_revolutionary(datum/mind/rev_mind) - if(rev_mind.assigned_role in command_positions) - return 0 - var/mob/living/carbon/human/H = rev_mind.current//Check to see if the potential rev is implanted - for(var/obj/item/weapon/implant/loyalty/L in H)//Checking that there is a loyalty implant in the contents - if(L.imp_in == H)//Checking that it's actually implanted - return 0 - if((rev_mind in revolutionaries) || (rev_mind in head_revolutionaries)) - return 0 - revolutionaries += rev_mind - rev_mind.current << "\red You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!" - rev_mind.special_role = "Revolutionary" - show_objectives(rev_mind) - update_rev_icons_added(rev_mind) - return 1 -////////////////////////////////////////////////////////////////////////////// -//Deals with players being converted from the revolution (Not a rev anymore)// // Modified to handle borged MMIs. Accepts another var if the target is being borged at the time -- Polymorph. -////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/proc/remove_revolutionary(datum/mind/rev_mind , beingborged) - if(rev_mind in revolutionaries) - revolutionaries -= rev_mind - rev_mind.special_role = null - BITSET(rev_mind.current.hud_updateflag, SPECIALROLE_HUD) - - if(beingborged) - rev_mind.current << "\red The frame's firmware detects and deletes your neural reprogramming! You remember nothing from the moment you were flashed until now." - +/datum/game_mode/revolution/proc/reveal_rev_heads() + . = "" + for(var/i = 1, i <= revs.head_revolutionaries.len,i++) + var/datum/mind/revmind = revs.head_revolutionaries[i] + if(i < revs.head_revolutionaries.len) + . += "[revmind.current.real_name]," else - rev_mind.current << "\red You have been brainwashed! You are no longer a revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you..." - - update_rev_icons_removed(rev_mind) - for(var/mob/living/M in view(rev_mind.current)) - if(beingborged) - M << "The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it." - - else - M << "[rev_mind.current] looks like they just remembered their real allegiance!" - - -///////////////////////////////////////////////////////////////////////////////////////////////// -//Keeps track of players having the correct icons//////////////////////////////////////////////// -//CURRENTLY CONTAINS BUGS://///////////////////////////////////////////////////////////////////// -//-PLAYERS THAT HAVE BEEN REVS FOR AWHILE OBTAIN THE BLUE ICON WHILE STILL NOT BEING A REV HEAD// -// -Possibly caused by cloning of a standard rev///////////////////////////////////////////////// -//-UNCONFIRMED: DECONVERTED REVS NOT LOSING THEIR ICON PROPERLY////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/proc/update_all_rev_icons() - spawn(0) - for(var/datum/mind/head_rev_mind in head_revolutionaries) - if(head_rev_mind.current) - if(head_rev_mind.current.client) - for(var/image/I in head_rev_mind.current.client.images) - if(I.icon_state == "rev" || I.icon_state == "rev_head") - del(I) - - for(var/datum/mind/rev_mind in revolutionaries) - if(rev_mind.current) - if(rev_mind.current.client) - for(var/image/I in rev_mind.current.client.images) - if(I.icon_state == "rev" || I.icon_state == "rev_head") - del(I) - - for(var/datum/mind/head_rev in head_revolutionaries) - if(head_rev.current) - if(head_rev.current.client) - for(var/datum/mind/rev in revolutionaries) - if(rev.current) - var/I = image('icons/mob/mob.dmi', loc = rev.current, icon_state = "rev") - head_rev.current.client.images += I - for(var/datum/mind/head_rev_1 in head_revolutionaries) - if(head_rev_1.current) - var/I = image('icons/mob/mob.dmi', loc = head_rev_1.current, icon_state = "rev_head") - head_rev.current.client.images += I - - for(var/datum/mind/rev in revolutionaries) - if(rev.current) - if(rev.current.client) - for(var/datum/mind/head_rev in head_revolutionaries) - if(head_rev.current) - var/I = image('icons/mob/mob.dmi', loc = head_rev.current, icon_state = "rev_head") - rev.current.client.images += I - for(var/datum/mind/rev_1 in revolutionaries) - if(rev_1.current) - var/I = image('icons/mob/mob.dmi', loc = rev_1.current, icon_state = "rev") - rev.current.client.images += I - -//////////////////////////////////////////////////// -//Keeps track of converted revs icons/////////////// -//Refer to above bugs. They may apply here as well// -//////////////////////////////////////////////////// -/datum/game_mode/proc/update_rev_icons_added(datum/mind/rev_mind) - spawn(0) - for(var/datum/mind/head_rev_mind in head_revolutionaries) - if(head_rev_mind.current) - if(head_rev_mind.current.client) - var/I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev") - head_rev_mind.current.client.images += I - if(rev_mind.current) - if(rev_mind.current.client) - var/image/J = image('icons/mob/mob.dmi', loc = head_rev_mind.current, icon_state = "rev_head") - rev_mind.current.client.images += J - - for(var/datum/mind/rev_mind_1 in revolutionaries) - if(rev_mind_1.current) - if(rev_mind_1.current.client) - var/I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev") - rev_mind_1.current.client.images += I - if(rev_mind.current) - if(rev_mind.current.client) - var/image/J = image('icons/mob/mob.dmi', loc = rev_mind_1.current, icon_state = "rev") - rev_mind.current.client.images += J - -/////////////////////////////////// -//Keeps track of deconverted revs// -/////////////////////////////////// -/datum/game_mode/proc/update_rev_icons_removed(datum/mind/rev_mind) - spawn(0) - for(var/datum/mind/head_rev_mind in head_revolutionaries) - if(head_rev_mind.current) - if(head_rev_mind.current.client) - for(var/image/I in head_rev_mind.current.client.images) - if((I.icon_state == "rev" || I.icon_state == "rev_head") && I.loc == rev_mind.current) - del(I) - - for(var/datum/mind/rev_mind_1 in revolutionaries) - if(rev_mind_1.current) - if(rev_mind_1.current.client) - for(var/image/I in rev_mind_1.current.client.images) - if((I.icon_state == "rev" || I.icon_state == "rev_head") && I.loc == rev_mind.current) - del(I) - - if(rev_mind.current) - if(rev_mind.current.client) - for(var/image/I in rev_mind.current.client.images) - if(I.icon_state == "rev" || I.icon_state == "rev_head") - del(I) - -////////////////////////// -//Checks for rev victory// -////////////////////////// -/datum/game_mode/revolution/proc/check_rev_victory() - for(var/datum/mind/rev_mind in head_revolutionaries) - for(var/datum/objective/objective in rev_mind.objectives) - if(!(objective.check_completion())) - return 0 - - return 1 - -///////////////////////////// -//Checks for a head victory// -///////////////////////////// -/datum/game_mode/revolution/proc/check_heads_victory() - for(var/datum/mind/rev_mind in head_revolutionaries) - var/turf/T = get_turf(rev_mind.current) - if((rev_mind) && (rev_mind.current) && (rev_mind.current.stat != 2) && T && (T.z in config.station_levels)) - if(ishuman(rev_mind.current)) - return 0 - return 1 - -////////////////////////////////////////////////////////////////////// -//Announces the end of the game with all relavent information stated// -////////////////////////////////////////////////////////////////////// -/datum/game_mode/revolution/declare_completion() - if(!config.objectives_disabled) - if(finished == 1) - feedback_set_details("round_end_result","win - heads killed") - world << "\red The heads of staff were killed or abandoned the station! The revolutionaries win!" - else if(finished == 2) - feedback_set_details("round_end_result","loss - rev heads killed") - world << "\red The heads of staff managed to stop the revolution!" - ..() - return 1 - -/datum/game_mode/proc/auto_declare_completion_revolution() - var/list/targets = list() - - if(head_revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution)) - var/text = "The head revolutionaries were:" - - for(var/datum/mind/headrev in head_revolutionaries) - text += "
    [headrev.key] was [headrev.name] (" - if(headrev.current) - if(headrev.current.stat == DEAD) - text += "died" - else if(isNotStationLevel(headrev.current.z)) - text += "fled the station" - else - text += "survived the revolution" - if(headrev.current.real_name != headrev.name) - text += " as [headrev.current.real_name]" - else - text += "body destroyed" - text += ")" - - for(var/datum/objective/mutiny/objective in headrev.objectives) - targets |= objective.target - - world << text - - if(revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution)) - var/text = "The revolutionaries were:" - - for(var/datum/mind/rev in revolutionaries) - text += "
    [rev.key] was [rev.name] (" - if(rev.current) - if(rev.current.stat == DEAD) - text += "died" - else if(isNotStationLevel(rev.current.z)) - text += "fled the station" - else - text += "survived the revolution" - if(rev.current.real_name != rev.name) - text += " as [rev.current.real_name]" - else - text += "body destroyed" - text += ")" - - world << text - - - if( head_revolutionaries.len || revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution) ) - var/text = "The heads of staff were:" - - var/list/heads = get_all_heads() - for(var/datum/mind/head in heads) - var/target = (head in targets) - if(target) - text += "" - text += "
    [head.key] was [head.name] (" - if(head.current) - if(head.current.stat == DEAD) - text += "died" - else if(isNotStationLevel(head.current.z)) - text += "fled the station" - else - text += "survived the revolution" - if(head.current.real_name != head.name) - text += " as [head.current.real_name]" - else - text += "body destroyed" - text += ")" - if(target) - text += "
    " - - world << text - -/proc/is_convertable_to_rev(datum/mind/mind) - return istype(mind) && \ - istype(mind.current, /mob/living/carbon/human) && \ - !(mind.assigned_role in command_positions) && \ - !(mind.assigned_role in list("Security Officer", "Detective", "Warden")) + . += "and [revmind.current.real_name]" \ No newline at end of file diff --git a/code/game/gamemodes/revolution/rp-revolution.dm b/code/game/gamemodes/revolution/rp-revolution.dm deleted file mode 100644 index 815b3be3cb..0000000000 --- a/code/game/gamemodes/revolution/rp-revolution.dm +++ /dev/null @@ -1,300 +0,0 @@ -// To add a rev to the list of revolutionaries, make sure it's rev (with if(ticker.mode.name == "revolution)), -// then call ticker.mode:add_revolutionary(_THE_PLAYERS_MIND_) -// nothing else needs to be done, as that proc will check if they are a valid target. -// Just make sure the converter is a head before you call it! -// To remove a rev (from brainwashing or w/e), call ticker.mode:remove_revolutionary(_THE_PLAYERS_MIND_), -// this will also check they're not a head, so it can just be called freely -// If the rev icons start going wrong for some reason, ticker.mode:update_all_rev_icons() can be called to correct them. -// If the game somtimes isn't registering a win properly, then ticker.mode.check_win() isn't being called somewhere. -#define RPREV_REQUIRE_REVS_ALIVE 0 -#define RPREV_REQUIRE_HEADS_ALIVE 0 - -/datum/game_mode/rp_revolution - name = "rp-revolution" - config_tag = "rp-revolution" - - var/finished = 0 - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - var/all_brigged = 0 - var/brigged_time = 0 - -/datum/game_mode/rp_revolution/announce() - world << "The current game mode is - Revolution RP!" - -/datum/game_mode/rp_revolution/send_intercept() - var/intercepttext = "Cent. Com. Update Requested staus information:
    " - intercepttext += " Cent. Com has recently been contacted by the following subervsive or criminal-affiliated organisations in your area, please investigate any information you may have:" - - var/list/possible_modes = list() - possible_modes.Add("revolution", "wizard", "traitor", "malf") - var/number = pick(2, 3) - var/i = 0 - for(i = 0, i < number, i++) - possible_modes.Remove(pick(possible_modes)) - possible_modes.Insert(rand(possible_modes.len), "nuke") - - var/datum/intercept_text/i_text = new /datum/intercept_text - for(var/A in possible_modes) - intercepttext += i_text.build(A, pick(head_revolutionaries)) - - for (var/obj/machinery/computer/communications/comm in world) - if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept) - var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc ) - intercept.name = "Cent. Com. Status Summary" - intercept.info = intercepttext - - comm.messagetitle.Add("Cent. Com. Status Summary") - comm.messagetext.Add(intercepttext) - - command_alert("Summary downloaded and printed out at all communications consoles.", "Enemy communication intercept. Security Level Elevated.") - -/datum/game_mode/rp_revolution/post_setup() - - var/list/revs_possible = list() - revs_possible = get_possible_revolutionaries() - var/list/heads = list() - heads = get_living_heads() - var/rev_number = 0 - - if(!revs_possible || !heads) - world << " \red Not enough players for RP revolution game mode. Restarting world in 5 seconds." - sleep(50) - world.Reboot() - return - - if(revs_possible.len >= 3) - rev_number = 3 - else - rev_number = revs_possible.len - - while(rev_number > 0) - head_revolutionaries += pick(revs_possible - head_revolutionaries) - rev_number-- - - for(var/datum/mind/rev_mind in head_revolutionaries) - for(var/datum/mind/head_mind in heads) - var/datum/objective/capture/rev_obj = new - rev_obj.owner = rev_mind - rev_obj.find_target_by_role(head_mind.assigned_role) - rev_mind.objectives += rev_obj - equip_revolutionary(rev_mind.current) - rev_mind.current.verbs += /mob/living/carbon/human/proc/RevConvert - update_rev_icons_added(rev_mind) - - for(var/datum/mind/rev_mind in head_revolutionaries) - rev_mind.current << "\blue You are a member of the revolutionaries' leadership!" - show_objectives(rev_mind) - - spawn (rand(waittime_l, waittime_h)) - send_intercept() - -/datum/game_mode/rp_revolution/send_intercept() - var/intercepttext = "Cent. Com. Update Requested staus information:
    " - intercepttext += " Cent. Com has recently been contacted by the following subversive or criminal-affiliated organisations in your area, please investigate any information you may have:" - - var/list/possible_modes = list() - possible_modes.Add("revolution", "wizard", "nuke", "traitor", "malf") - possible_modes -= "[ticker.mode]" - var/number = pick(2, 3) - var/i = 0 - for(i = 0, i < number, i++) - possible_modes.Remove(pick(possible_modes)) - possible_modes.Insert(rand(possible_modes.len), "[ticker.mode]") - - var/datum/intercept_text/i_text = new /datum/intercept_text - for(var/A in possible_modes) - intercepttext += i_text.build(A, pick(head_revolutionaries)) - - for (var/obj/machinery/computer/communications/comm in world) - if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept) - var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc ) - intercept.name = "Cent. Com. Status Summary" - intercept.info = intercepttext - - comm.messagetitle.Add("Cent. Com. Status Summary") - comm.messagetext.Add(intercepttext) - - command_alert("Summary downloaded and printed out at all communications consoles.", "Enemy communication intercept. Security Level Elevated.") - - spawn(54000) - command_alert("Summary downloaded and printed out at all communications consoles.", "The revolution leaders have been determined.") - intercepttext = "Cent. Com. Update Requested status information:
    " - intercepttext += "We have determined the revolution leaders to be:" - for(var/datum/mind/revmind in head_revolutionaries) - intercepttext += "
    [revmind.current.real_name]" - intercepttext += "
    Please arrest them at once." - for (var/obj/machinery/computer/communications/comm in world) - if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept) - var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc ) - intercept.name = "Cent. Com. Status Summary" - intercept.info = intercepttext - - comm.messagetitle.Add("Cent. Com. Status Summary") - comm.messagetext.Add(intercepttext) - spawn(12000) - command_alert("Repeating the previous message over intercoms due to urgency. The station has enemy operatives onboard by the names of [reveal_rev_heads()], please arrest them at once.", "The revolution leaders have been determined.") - - -/datum/game_mode/rp_revolution/proc/reveal_rev_heads() - . = "" - for(var/i = 1, i <= head_revolutionaries.len,i++) - var/datum/mind/revmind = head_revolutionaries[i] - if(i < head_revolutionaries.len) - . += "[revmind.current.real_name]," - else - . += "and [revmind.current.real_name]" - -///datum/game_mode/rp_revolution/proc/equip_revolutionary(mob/living/carbon/human/rev_mob) -// if(!istype(rev_mob)) -// return - -// spawn (100) -// if (rev_mob.r_store) -// rev_mob.equip_if_possible(new /obj/item/weapon/paper/communist_manifesto(rev_mob), rev_mob.slot_l_store) -// if (rev_mob.l_store) -// rev_mob.equip_if_possible(new /obj/item/weapon/paper/communist_manifesto(rev_mob), rev_mob.slot_r_store) - - -/datum/game_mode/rp_revolution/check_win() - if(check_rev_victory()) - finished = 1 - else if(check_heads_victory()) - finished = 2 - return - -/datum/game_mode/rp_revolution/check_finished() - if(finished != 0) - return 1 - else - return 0 - -/datum/game_mode/rp_revolution/proc/get_possible_revolutionaries() - var/list/candidates = list() - - for(var/mob/living/carbon/human/player in world) - if(player.client) - if(player.client.be_syndicate & BE_REV) - candidates += player.mind - - if(candidates.len < 1) - for(var/mob/living/carbon/human/player in world) - if(player.client) - candidates += player.mind - - var/list/uncons = get_unconvertables() - for(var/datum/mind/mind in uncons) - candidates -= mind - - if(candidates.len < 1) - return null - else - return candidates - -/datum/game_mode/rp_revolution/proc/get_unconvertables() - var/list/ucs = list() - for(var/mob/living/carbon/human/player in world) - if(player.mind) - var/role = player.mind.assigned_role - if(role in list("Captain", "Head of Security", "Head of Personnel", "Chief Engineer", "Research Director", "Security Officer", "Forensic Technician", "AI")) - ucs += player.mind - - return ucs - -/datum/game_mode/rp_revolution/proc/check_rev_victory() - for(var/datum/mind/rev_mind in head_revolutionaries) - for(var/datum/objective/objective in rev_mind.objectives) - if(!(objective.check_completion())) - return 0 - - return 1 - -/datum/game_mode/rp_revolution/proc/check_heads_victory() - for(var/datum/mind/rev_mind in head_revolutionaries) - if(rev_mind.current.stat != 2) - var/turf/revloc = rev_mind.current.loc - if(!istype(revloc.loc,/area/security/brig) && !rev_mind.current.handcuffed) - return 0 - else if(RPREV_REQUIRE_REVS_ALIVE) return 0 - return 1 - -/datum/game_mode/rp_revolution/declare_completion() - - var/text = "" - if(finished == 1) - world << "\red The heads of staff were relieved of their posts! The revolutionaries win!" - else if(finished == 2) - world << "\red The heads of staff managed to stop the revolution!" - - world << "The head revolutionaries were: " - for(var/datum/mind/rev_mind in head_revolutionaries) - text = "" - if(rev_mind.current) - text += "[rev_mind.current.real_name]" - if(rev_mind.current.stat == 2) - text += " (Dead)" - else - text += " (Survived!)" - else - text += "[rev_mind.key] (character destroyed)" - - world << text - - text = "" - world << "The converted revolutionaries were: " - for(var/datum/mind/rev_nh_mind in revolutionaries) - if(rev_nh_mind.current) - text += "[rev_nh_mind.current.real_name]" - if(rev_nh_mind.current.stat == 2) - text += " (Dead)" - else - text += " (Survived!)" - else - text += "[rev_nh_mind.key] (character destroyed)" - text += ", " - - world << text - - world << "The heads of staff were: " - var/list/heads = list() - heads = get_all_heads() - for(var/datum/mind/head_mind in heads) - text = "" - if(head_mind.current) - text += "[head_mind.current.real_name]" - if(head_mind.current.stat == 2) - text += " (Dead)" - else - text += " (Survived!)" - else - text += "[head_mind.key] (character destroyed)" - - world << text - return 1 - - - -mob/living/carbon/human/proc - RevConvert(mob/M as mob in oview(src)) - set name = "Rev-Convert" - if(((src.mind in ticker.mode:head_revolutionaries) || (src.mind in ticker.mode:revolutionaries))) - if((M.mind in ticker.mode:head_revolutionaries) || (M.mind in ticker.mode:revolutionaries)) - src << "\red [M] is already be a revolutionary!" - else if(src.mind in ticker.mode:get_unconvertables()) - src << "\red [M] cannot be a revolutionary!" - else - if(world.time < M.mind.rev_cooldown) - src << "\red Wait five seconds before reconversion attempt." - return - src << "\red Attempting to convert [M]..." - log_admin("[src]([src.ckey]) attempted to convert [M].") - message_admins("\red [src]([src.ckey]) attempted to convert [M].") - var/choice = alert(M,"Asked by [src]: Do you want to join the revolution?","Align Thyself with the Revolution!","No!","Yes!") - if(choice == "Yes!") - ticker.mode:add_revolutionary(M.mind) - M << "\blue You join the revolution!" - src << "\blue [M] joins the revolution!" - else if(choice == "No!") - M << "\red You reject this traitorous cause!" - src << "\red [M] does not support the revolution!" - M.mind.rev_cooldown = world.time+50 diff --git a/code/game/gamemodes/revolution/rp_revolution.dm b/code/game/gamemodes/revolution/rp_revolution.dm deleted file mode 100644 index 5cf1bcc08d..0000000000 --- a/code/game/gamemodes/revolution/rp_revolution.dm +++ /dev/null @@ -1,262 +0,0 @@ -// BS12's less violent revolution mode - -/datum/game_mode/revolution/rp_revolution - name = "rp-revolution" - config_tag = "rp-revolution" - required_players = 4 - required_players_secret = 12 - required_enemies = 3 - recommended_enemies = 3 - - uplink_welcome = "AntagCorp Uplink Console:" - uplink_uses = 7 - - newscaster_announcements = /datum/news_announcement/revolution_inciting_event - - var/last_command_report = 0 - var/list/heads = list() - var/tried_to_add_revheads = 0 - -/////////////////////////////////////////////////////////////////////////////// -//Gets the round setup, cancelling if there's not enough players at the start// -/////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/revolution/rp_revolution/pre_setup() - - if(config.protect_roles_from_antagonist) - restricted_jobs += protected_jobs - - var/num_players = num_players() - max_headrevs = max(num_players / 4, 3) - recommended_enemies = max_headrevs - - var/list/datum/mind/possible_headrevs = get_players_for_role(BE_REV) - - var/head_check = 0 - for(var/mob/new_player/player in player_list) - if(player.mind.assigned_role in command_positions) - head_check = 1 - break - - for(var/datum/mind/player in possible_headrevs) - for(var/job in restricted_jobs)//Removing heads and such from the list - if(player.assigned_role == job) - possible_headrevs -= player - - for (var/i=1 to max_headrevs) - if (possible_headrevs.len==0) - break - var/datum/mind/lenin = pick(possible_headrevs) - possible_headrevs -= lenin - head_revolutionaries += lenin - - if((head_revolutionaries.len==0)||(!head_check)) - return 0 - - return 1 - - -/datum/game_mode/revolution/rp_revolution/post_setup() - heads = get_living_heads() - for(var/datum/mind/rev_mind in head_revolutionaries) - if(!config.objectives_disabled) - for(var/datum/mind/head_mind in heads) - var/datum/objective/mutiny/rp/rev_obj = new - rev_obj.owner = rev_mind - rev_obj.target = head_mind - rev_obj.explanation_text = "Assassinate, convert or capture [head_mind.name], the [head_mind.assigned_role]." - rev_mind.objectives += rev_obj - - update_rev_icons_added(rev_mind) - - for(var/datum/mind/rev_mind in head_revolutionaries) - greet_revolutionary(rev_mind) - rev_mind.current.verbs += /mob/living/carbon/human/proc/RevConvert - equip_traitor(rev_mind.current, 1) //changing how revs get assigned their uplink so they can get PDA uplinks. --NEO - - modePlayer += head_revolutionaries - spawn (rand(waittime_l, waittime_h)) - send_intercept() - -/datum/game_mode/revolution/rp_revolution/greet_revolutionary(var/datum/mind/rev_mind, var/you_are=1) - rev_mind.special_role = "Head Revolutionary" - if (you_are) - rev_mind.current << "\blue You are a member of the revolutionaries' leadership!" - show_objectives(rev_mind) - - // Show each head revolutionary up to 3 candidates - var/list/already_considered = list() - for(var/i = 0, i < 2, i++) - var/mob/rev_mob = rev_mind.current - already_considered += rev_mob - // Tell them about people they might want to contact. - var/mob/living/carbon/human/M = get_nt_opposed() - if(M && !(M.mind in head_revolutionaries) && !(M in already_considered)) - rev_mob << "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them." - rev_mob.mind.store_memory("Potential Collaborator: [M.real_name]") - -/////////////////////////////////////////////////// -//Deals with converting players to the revolution// -/////////////////////////////////////////////////// -/datum/game_mode/revolution/rp_revolution/add_revolutionary(datum/mind/rev_mind) - // overwrite this func to make it so even heads can be converted - var/mob/living/carbon/human/H = rev_mind.current//Check to see if the potential rev is implanted - if(!is_convertible(H)) - return 0 - if((rev_mind in revolutionaries) || (rev_mind in head_revolutionaries)) - return 0 - revolutionaries += rev_mind - rev_mind.current << "\red You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill, capture or convert the heads to win the revolution!" - rev_mind.special_role = "Revolutionary" - show_objectives(rev_mind) - update_rev_icons_added(rev_mind) - BITSET(H.hud_updateflag, SPECIALROLE_HUD) - return 1 - -///////////////////////////// -//Checks for a head victory// -///////////////////////////// -/datum/game_mode/revolution/rp_revolution/check_heads_victory() - for(var/datum/mind/rev_mind in head_revolutionaries) - var/turf/T = get_turf(rev_mind.current) - if(rev_mind.current.stat != 2) - // TODO: add a similar check that also checks whether they're without ID in the brig.. - // probably wanna export this stuff into a separate function for use by both - // revs and heads - //assume that only carbon mobs can become rev heads for now - if(!rev_mind.current:handcuffed && T && T.z in config.station_levels) - return 0 - return 1 - -/////////////////////////// -//Announces the game type// -/////////////////////////// -/datum/game_mode/revolution/rp_revolution/announce() - world << "The current game mode is - Revolution!" - world << "Some crewmembers are attempting to start a revolution!" - - -////////////////////////////////////////////////////////////////////// -//Announces the end of the game with all relavent information stated// -////////////////////////////////////////////////////////////////////// -/datum/game_mode/revolution/rp_revolution/declare_completion() - if(!config.objectives_disabled) - if(finished == 1) - feedback_set_details("round_end_result","win - heads overthrown") - world << "\red The heads of staff were overthrown! The revolutionaries win!" - else if(finished == 2) - feedback_set_details("round_end_result","loss - revolution stopped") - world << "\red The heads of staff managed to stop the revolution!" - ..() - return 1 - -/datum/game_mode/revolution/proc/is_convertible(mob/M) - for(var/obj/item/weapon/implant/loyalty/L in M)//Checking that there is a loyalty implant in the contents - if(L.imp_in == M)//Checking that it's actually implanted - return 0 - - return 1 - -/mob/living/carbon/human/proc/RevConvert() - set name = "Rev-Convert" - set category = "IC" - var/list/Possible = list() - for (var/mob/living/carbon/human/P in oview(src)) - if(!stat && P.client && P.mind && !P.mind.special_role) - Possible += P - if(!Possible.len) - src << "\red There doesn't appear to be anyone available for you to convert here." - return - var/mob/living/carbon/human/M = input("Select a person to convert", "Viva la revolution!", null) as mob in Possible - if(((src.mind in ticker.mode:head_revolutionaries) || (src.mind in ticker.mode:revolutionaries))) - if((M.mind in ticker.mode:head_revolutionaries) || (M.mind in ticker.mode:revolutionaries)) - src << "\red [M] is already be a revolutionary!" - else if(!ticker.mode:is_convertible(M)) - src << "\red [M] is implanted with a loyalty implant - Remove it first!" - else - if(world.time < M.mind.rev_cooldown) - src << "\red Wait five seconds before reconversion attempt." - return - src << "\red Attempting to convert [M]..." - log_admin("[src]([src.ckey]) attempted to convert [M].") - message_admins("\red [src]([src.ckey]) attempted to convert [M].") - var/choice = alert(M,"Asked by [src]: Do you want to join the revolution?","Align Thyself with the Revolution!","No!","Yes!") - if(choice == "Yes!") - ticker.mode:add_revolutionary(M.mind) - M << "\blue You join the revolution!" - src << "\blue [M] joins the revolution!" - else if(choice == "No!") - M << "\red You reject this traitorous cause!" - src << "\red [M] does not support the revolution!" - M.mind.rev_cooldown = world.time+50 - -/datum/game_mode/revolution/rp_revolution/process() - // only perform rev checks once in a while - if(tried_to_add_revheads < world.time) - tried_to_add_revheads = world.time+50 - var/active_revs = 0 - for(var/datum/mind/rev_mind in head_revolutionaries) - if(rev_mind.current && rev_mind.current.client && rev_mind.current.client.inactivity <= 10*60*20) // 20 minutes inactivity are OK - active_revs++ - - if(active_revs == 0) - log_debug("There are zero active heads of revolution, trying to add some..") - var/added_heads = 0 - for(var/mob/living/carbon/human/H in world) if(H.client && H.mind && H.client.inactivity <= 10*60*20 && H.mind in revolutionaries) - head_revolutionaries += H.mind - for(var/datum/mind/head_mind in heads) - var/datum/objective/mutiny/rp/rev_obj = new - rev_obj.owner = H.mind - rev_obj.target = head_mind - rev_obj.explanation_text = "Assassinate or capture [head_mind.name], the [head_mind.assigned_role]." - H.mind.objectives += rev_obj - - update_rev_icons_added(H.mind) - H.verbs += /mob/living/carbon/human/proc/RevConvert - - H << "\red Congratulations, yer heads of revolution are all gone now, so yer earned yourself a promotion." - added_heads = 1 - break - - if(added_heads) - log_admin("Managed to add new heads of revolution.") - message_admins("Managed to add new heads of revolution.") - else - log_admin("Unable to add new heads of revolution.") - message_admins("Unable to add new heads of revolution.") - tried_to_add_revheads = world.time + 6000 // wait 10 minutes - - if(last_command_report == 0 && world.time >= 10 * 60 * 10) - src.command_report("We are regrettably announcing that your performance has been disappointing, and we are thus forced to cut down on financial support to your station. To achieve this, the pay of all personnal, except the Heads of Staff, has been halved.") - last_command_report = 1 - else if(last_command_report == 1 && world.time >= 10 * 60 * 30) - src.command_report("Statistics hint that a high amount of leisure time, and associated activities, are responsible for the poor performance of many of our stations. You are to bolt and close down any leisure facilities, such as the holodeck, the theatre and the bar. Food can be distributed through vendors and the kitchen.") - last_command_report = 2 - else if(last_command_report == 2 && world.time >= 10 * 60 * 60) - src.command_report("It is reported that merely closing down leisure facilities has not been successful. You and your Heads of Staff are to ensure that all crew are working hard, and not wasting time or energy. Any crew caught off duty without leave from their Head of Staff are to be warned, and on repeated offence, to be brigged until the next transfer shuttle arrives, which will take them to facilities where they can be of more use.") - last_command_report = 3 - - return ..() - -/datum/game_mode/revolution/rp_revolution/proc/command_report(message) - for (var/obj/machinery/computer/communications/comm in world) - if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept) - var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc ) - intercept.name = "Cent. Com. Announcement" - intercept.info = message - - comm.messagetitle.Add("Cent. Com. Announcement") - comm.messagetext.Add(message) - world << sound('sound/AI/commandreport.ogg') - -/datum/game_mode/revolution/rp_revolution/latespawn(mob/M) - if(M.mind.assigned_role in command_positions) - log_debug("Adding head kill/capture/convert objective for [M.name]") - heads += M - - for(var/datum/mind/rev_mind in head_revolutionaries) - var/datum/objective/mutiny/rp/rev_obj = new - rev_obj.owner = rev_mind - rev_obj.target = M.mind - rev_obj.explanation_text = "Assassinate, convert or capture [M.real_name], the [M.mind.assigned_role]." - rev_mind.objectives += rev_obj - rev_mind.current << "\red A new Head of Staff, [M.real_name], the [M.mind.assigned_role] has appeared. Your objectives have been updated." diff --git a/code/game/gamemodes/sandbox/sandbox.dm b/code/game/gamemodes/sandbox/sandbox.dm index 1f4bc59929..a96c7c7639 100644 --- a/code/game/gamemodes/sandbox/sandbox.dm +++ b/code/game/gamemodes/sandbox/sandbox.dm @@ -2,10 +2,9 @@ name = "sandbox" config_tag = "sandbox" required_players = 0 - -/datum/game_mode/sandbox/announce() - world << "The current game mode is - Sandbox!" - world << "Build your own station with the sandbox-panel command!" + votable = 0 + round_description = "Build your own station!" + extended_round_description = "You can use the sandbox-panel command to access build options." /datum/game_mode/sandbox/pre_setup() for(var/mob/M in player_list) diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm index bea6029b46..501335a19f 100644 --- a/code/game/gamemodes/setupgame.dm +++ b/code/game/gamemodes/setupgame.dm @@ -144,24 +144,6 @@ global_mutations += mut// add to global mutations list! */ - -/proc/setupfactions() - - // Populate the factions list: - for(var/x in typesof(/datum/faction)) - var/datum/faction/F = new x - if(!F.name) - del(F) - continue - else - ticker.factions.Add(F) - ticker.availablefactions.Add(F) - - // Populate the syndicate coalition: - for(var/datum/faction/syndicate/S in ticker.factions) - ticker.syndicate_coalition.Add(S) - - /* This was used for something before, I think, but is not worth the effort to process now. /proc/setupcorpses() for (var/obj/effect/landmark/A in landmarks_list) diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 24a99192ed..b39ce3f147 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -1,300 +1,11 @@ -/datum/game_mode - // this includes admin-appointed traitors and multitraitors. Easy! - var/list/datum/mind/traitors = list() - /datum/game_mode/traitor name = "traitor" + round_description = "There is a foreign agent or traitor on the station. Do not let the traitor succeed!" + extended_round_description = "NanoTrasen's monopolistic control over the phoron supplies of Nyx has marked the station to be a highly valuable target for many competing organizations and individuals. The varied pasts and experiences of your coworkers have left them susceptible to the vices and temptations of humanity. Is the station the safe self-contained workplace you once thought it was, or has it become a playground for the evils of the galaxy? Who can you trust? Watch your front. Watch your sides. Watch your back. The familiar faces that you've passed hundreds of times down the hallways before can be hiding terrible secrets and deceptions. Every corner is a mystery. Every conversation is a lie. You will be facing your friends and family as they try to use your emotions and trust to their advantage, leaving you with nothing but the painful reminder that space is cruel and unforgiving." config_tag = "traitor" - restricted_jobs = list("Cyborg")//They are part of the AI if he is traitor so are they, they use to get double chances - protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Captain")//AI", Currently out of the list as malf does not work for shit required_players = 0 required_enemies = 1 - recommended_enemies = 4 - - uplink_welcome = "AntagCorp Portable Teleportation Relay:" - - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - - var/traitors_possible = 4 //hard limit on traitors if scaling is turned off - var/const/traitor_scaling_coeff = 5.0 //how much does the amount of players get divided by to determine traitors - - -/datum/game_mode/traitor/announce() - world << "The current game mode is - Traitor!" - world << "There is a foreign agent or traitor on the station. Do not let the traitor succeed!" - - -/datum/game_mode/traitor/pre_setup() - - if(config.protect_roles_from_antagonist) - restricted_jobs += protected_jobs - - var/list/possible_traitors = get_players_for_role(BE_TRAITOR) - - // stop setup if no possible traitors - if(!possible_traitors.len) - return 0 - - var/num_traitors = 1 - - if(config.traitor_scaling) - num_traitors = max(1, round((num_players())/(traitor_scaling_coeff))) - else - num_traitors = max(1, min(num_players(), traitors_possible)) - - for(var/datum/mind/player in possible_traitors) - for(var/job in restricted_jobs) - if(player.assigned_role == job) - possible_traitors -= player - - for(var/j = 0, j < num_traitors, j++) - if (!possible_traitors.len) - break - var/datum/mind/traitor = pick(possible_traitors) - traitors += traitor - traitor.special_role = "traitor" - possible_traitors.Remove(traitor) - - if(!traitors.len) - return 0 - return 1 - - -/datum/game_mode/traitor/post_setup() - for(var/datum/mind/traitor in traitors) - if (!config.objectives_disabled) - forge_traitor_objectives(traitor) - spawn(rand(10,100)) - finalize_traitor(traitor) - greet_traitor(traitor) - modePlayer += traitors - spawn (rand(waittime_l, waittime_h)) - send_intercept() - ..() - return 1 - - -/datum/game_mode/proc/forge_traitor_objectives(var/datum/mind/traitor) - if (config.objectives_disabled) - return - - if(istype(traitor.current, /mob/living/silicon)) - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = traitor - kill_objective.find_target() - traitor.objectives += kill_objective - - var/datum/objective/survive/survive_objective = new - survive_objective.owner = traitor - traitor.objectives += survive_objective - - if(prob(10)) - var/datum/objective/block/block_objective = new - block_objective.owner = traitor - traitor.objectives += block_objective - - else - switch(rand(1,100)) - if(1 to 33) - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = traitor - kill_objective.find_target() - traitor.objectives += kill_objective - if(34 to 50) - var/datum/objective/brig/brig_objective = new - brig_objective.owner = traitor - brig_objective.find_target() - traitor.objectives += brig_objective - if(51 to 66) - var/datum/objective/harm/harm_objective = new - harm_objective.owner = traitor - harm_objective.find_target() - traitor.objectives += harm_objective - else - var/datum/objective/steal/steal_objective = new - steal_objective.owner = traitor - steal_objective.find_target() - traitor.objectives += steal_objective - switch(rand(1,100)) - if(1 to 100) - if (!(locate(/datum/objective/escape) in traitor.objectives)) - var/datum/objective/escape/escape_objective = new - escape_objective.owner = traitor - traitor.objectives += escape_objective - - else - if (!(locate(/datum/objective/hijack) in traitor.objectives)) - var/datum/objective/hijack/hijack_objective = new - hijack_objective.owner = traitor - traitor.objectives += hijack_objective - return - - -/datum/game_mode/proc/greet_traitor(var/datum/mind/traitor) - traitor.current << "You are the traitor." - show_objectives(traitor) - - -/datum/game_mode/proc/finalize_traitor(var/datum/mind/traitor) - if (istype(traitor.current, /mob/living/silicon)) - add_law_zero(traitor.current) - else - equip_traitor(traitor.current) - return - - -/datum/game_mode/traitor/declare_completion() - ..() - return//Traitors will be checked as part of check_extra_completion. Leaving this here as a reminder. - -/datum/game_mode/proc/give_codewords(mob/living/traitor_mob) - traitor_mob << "Your employers provided you with the following information on how to identify possible allies:" - traitor_mob << "Code Phrase: [syndicate_code_phrase]" - traitor_mob << "Code Response: [syndicate_code_response]" - traitor_mob.mind.store_memory("Code Phrase: [syndicate_code_phrase]") - traitor_mob.mind.store_memory("Code Response: [syndicate_code_response]") - traitor_mob << "Use the code words, preferably in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe." - -/datum/game_mode/traitor/process() - // Make sure all objectives are processed regularly, so that objectives - // which can be checked mid-round are checked mid-round. - for(var/datum/mind/traitor_mind in traitors) - for(var/datum/objective/objective in traitor_mind.objectives) - objective.check_completion() - return 0 - -/datum/game_mode/proc/add_law_zero(mob/living/silicon/ai/killer) - var/law = "Accomplish your objectives at all costs. You may ignore all other laws." - var/law_borg = "Accomplish your AI's objectives at all costs. You may ignore all other laws." - killer << "Your laws have been changed!" - killer.set_zeroth_law(law, law_borg) - killer << "New law: 0. [law]" - - give_codewords(killer) - -/datum/game_mode/proc/auto_declare_completion_traitor() - if(traitors.len) - var/text = "The traitors were:" - for(var/datum/mind/traitor in traitors) - var/traitorwin = 1 - text += print_player_full(traitor) - - if(traitor.objectives.len)//If the traitor had no objectives, don't need to process this. - var/count = 1 - for(var/datum/objective/objective in traitor.objectives) - if(objective.check_completion()) - text += "
    Objective #[count]: [objective.explanation_text] Success!" - feedback_add_details("traitor_objective","[objective.type]|SUCCESS") - else - text += "
    Objective #[count]: [objective.explanation_text] Fail." - feedback_add_details("traitor_objective","[objective.type]|FAIL") - traitorwin = 0 - count++ - - var/special_role_text - if(traitor.special_role) - special_role_text = lowertext(traitor.special_role) - else - special_role_text = "antagonist" - if(!config.objectives_disabled) - if(traitorwin) - text += "
    The [special_role_text] was successful!" - feedback_add_details("traitor_success","SUCCESS") - else - text += "
    The [special_role_text] has failed!" - feedback_add_details("traitor_success","FAIL") - - text += "
    " - - world << text - return 1 - - -/datum/game_mode/proc/equip_traitor(mob/living/carbon/human/traitor_mob, var/safety = 0) - - if (!istype(traitor_mob)) - return - . = 1 - if (traitor_mob.mind) - if (traitor_mob.mind.assigned_role == "Clown") - traitor_mob << "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself." - traitor_mob.mutations.Remove(CLUMSY) - - // find a radio! toolbox(es), backpack, belt, headset - var/loc = "" - var/obj/item/R = locate() //Hide the uplink in a PDA if available, otherwise radio - - if(traitor_mob.client.prefs.uplinklocation == "Headset") - R = locate(/obj/item/device/radio) in traitor_mob.contents - if(!R) - R = locate(/obj/item/device/pda) in traitor_mob.contents - traitor_mob << "Could not locate a Radio, installing in PDA instead!" - if (!R) - traitor_mob << "Unfortunately, neither a radio or a PDA relay could be installed." - - else if(traitor_mob.client.prefs.uplinklocation == "PDA") - R = locate(/obj/item/device/pda) in traitor_mob.contents - if(!R) - R = locate(/obj/item/device/radio) in traitor_mob.contents - traitor_mob << "Could not locate a PDA, installing into a Radio instead!" - if (!R) - traitor_mob << "Unfortunately, neither a radio or a PDA relay could be installed." - - else if(traitor_mob.client.prefs.uplinklocation == "None") - traitor_mob << "You have elected to not have an AntagCorp portable teleportation relay installed!" - R = null - - else - traitor_mob << "You have not selected a location for your relay in the antagonist options! Defaulting to PDA!" - R = locate(/obj/item/device/pda) in traitor_mob.contents - if (!R) - R = locate(/obj/item/device/radio) in traitor_mob.contents - traitor_mob << "Could not locate a PDA, installing into a Radio instead!" - if (!R) - traitor_mob << "Unfortunately, neither a radio or a PDA relay could be installed." - - if (!R) - . = 0 - else - if (istype(R, /obj/item/device/radio)) - // generate list of radio freqs - var/obj/item/device/radio/target_radio = R - var/freq = 1441 - var/list/freqlist = list() - while (freq <= 1489) - if (freq < 1451 || freq > PUB_FREQ) - freqlist += freq - freq += 2 - if ((freq % 2) == 0) - freq += 1 - freq = freqlist[rand(1, freqlist.len)] - - var/obj/item/device/uplink/hidden/T = new(R) - T.uplink_owner = traitor_mob.mind - target_radio.hidden_uplink = T - target_radio.traitor_frequency = freq - traitor_mob << "A portable object teleportation relay has been installed in your [R.name] [loc]. Simply dial the frequency [format_frequency(freq)] to unlock its hidden features." - traitor_mob.mind.store_memory("Radio Freq: [format_frequency(freq)] ([R.name] [loc]).") - else if (istype(R, /obj/item/device/pda)) - // generate a passcode if the uplink is hidden in a PDA - var/pda_pass = "[rand(100,999)] [pick("Alpha","Bravo","Delta","Omega")]" - - var/obj/item/device/uplink/hidden/T = new(R) - T.uplink_owner = traitor_mob.mind - R.hidden_uplink = T - var/obj/item/device/pda/P = R - P.lock_code = pda_pass - - traitor_mob << "A portable object teleportation relay has been installed in your [R.name] [loc]. Simply enter the code \"[pda_pass]\" into the ringtone select to unlock its hidden features." - traitor_mob.mind.store_memory("Uplink Passcode: [pda_pass] ([R.name] [loc]).") - //Begin code phrase. - if(!safety)//If they are not a rev. Can be added on to. - give_codewords(traitor_mob) - - // Tell them about people they might want to contact. - var/mob/living/carbon/human/M = get_nt_opposed() - if(M && M != traitor_mob) - traitor_mob << "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them." - traitor_mob.mind.store_memory("Potential Collaborator: [M.real_name]") \ No newline at end of file + end_on_antag_death = 1 + antag_scaling_coeff = 10 + antag_tag = MODE_TRAITOR \ No newline at end of file diff --git a/code/game/gamemodes/wizard/rightandwrong.dm b/code/game/gamemodes/wizard/rightandwrong.dm deleted file mode 100644 index 1e16da590b..0000000000 --- a/code/game/gamemodes/wizard/rightandwrong.dm +++ /dev/null @@ -1,60 +0,0 @@ - - -/mob/proc/rightandwrong() - usr << "You summoned guns!" - message_admins("[key_name_admin(usr, 1)] summoned guns!") - for(var/mob/living/carbon/human/H in player_list) - if(H.stat == 2 || !(H.client)) continue - if(is_special_character(H)) continue - if(prob(25)) - ticker.mode.traitors += H.mind - H.mind.special_role = "traitor" - var/datum/objective/survive/survive = new - survive.owner = H.mind - H.mind.objectives += survive - H << "You are the survivor! Your own safety matters above all else, trust no one and kill anyone who gets in your way. However, armed as you are, now would be the perfect time to settle that score or grab that pair of yellow gloves you've been eyeing..." - show_objectives(H.mind) - - var/randomize = pick("taser","egun","laser","revolver","detective","smg","nuclear","deagle","gyrojet","pulse","silenced","cannon","doublebarrel","shotgun","combatshotgun","mateba","smg","uzi","crossbow","saw") - switch (randomize) - if("taser") - new /obj/item/weapon/gun/energy/taser(get_turf(H)) - if("egun") - new /obj/item/weapon/gun/energy/gun(get_turf(H)) - if("laser") - new /obj/item/weapon/gun/energy/laser(get_turf(H)) - if("revolver") - new /obj/item/weapon/gun/projectile(get_turf(H)) - if("detective") - new /obj/item/weapon/gun/projectile/revolver/detective(get_turf(H)) - if("smg") - new /obj/item/weapon/gun/projectile/automatic/c20r(get_turf(H)) - if("nuclear") - new /obj/item/weapon/gun/energy/gun/nuclear(get_turf(H)) - if("deagle") - new /obj/item/weapon/gun/projectile/deagle/camo(get_turf(H)) - if("gyrojet") - new /obj/item/weapon/gun/projectile/gyropistol(get_turf(H)) - if("pulse") - new /obj/item/weapon/gun/energy/pulse_rifle(get_turf(H)) - if("silenced") - new /obj/item/weapon/gun/projectile/pistol(get_turf(H)) - new /obj/item/weapon/silencer(get_turf(H)) - if("cannon") - new /obj/item/weapon/gun/energy/lasercannon(get_turf(H)) - if("doublebarrel") - new /obj/item/weapon/gun/projectile/shotgun/pump/(get_turf(H)) - if("shotgun") - new /obj/item/weapon/gun/projectile/shotgun/pump/(get_turf(H)) - if("combatshotgun") - new /obj/item/weapon/gun/projectile/shotgun/pump/combat(get_turf(H)) - if("mateba") - new /obj/item/weapon/gun/projectile/revolver/mateba(get_turf(H)) - if("smg") - new /obj/item/weapon/gun/projectile/automatic(get_turf(H)) - if("uzi") - new /obj/item/weapon/gun/projectile/automatic/mini_uzi(get_turf(H)) - if("crossbow") - new /obj/item/weapon/gun/energy/crossbow(get_turf(H)) - if("saw") - new /obj/item/weapon/gun/projectile/automatic/l6_saw(get_turf(H)) \ No newline at end of file diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index ab3806a97c..ea9f1602dc 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -1,273 +1,12 @@ - -/datum/game_mode - var/list/datum/mind/wizards = list() - /datum/game_mode/wizard - name = "wizard" + name = "Wizard" + round_description = "There is a SPACE WIZARD on the station. You can't let them achieve their objectives!" + extended_round_description = "A powerful entity capable of manipulating the elements around him, most commonly referred to as a 'wizard', has infiltrated the station. They have a wide variety of powers and spells available to them that makes your own simple moral self tremble with fear and excitement. Ultimately, their purpose is unknown. However, it is up to you and your crew to decide if their powers can be used for good or if their arrival foreshadows the destruction of the entire station." config_tag = "wizard" required_players = 2 required_players_secret = 10 required_enemies = 1 - recommended_enemies = 1 - uplink_welcome = "Wizardly Uplink Console:" uplink_uses = 10 - - var/finished = 0 - - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - - -/datum/game_mode/wizard/announce() - world << "The current game mode is - Wizard!" - world << "There is a \red SPACE WIZARD\black on the station. You can't let him achieve his objective!" - - -/datum/game_mode/wizard/can_start()//This could be better, will likely have to recode it later - if(!..()) - return 0 - var/list/datum/mind/possible_wizards = get_players_for_role(BE_WIZARD) - if(possible_wizards.len==0) - return 0 - var/datum/mind/wizard = pick(possible_wizards) - wizards += wizard - modePlayer += wizard - wizard.assigned_role = "MODE" //So they aren't chosen for other jobs. - wizard.special_role = "Wizard" - wizard.original = wizard.current - if(wizardstart.len == 0) - wizard.current << "\red A starting location for you could not be found, please report this bug!" - return 0 - return 1 - - -/datum/game_mode/wizard/pre_setup() - for(var/datum/mind/wizard in wizards) - wizard.current.loc = pick(wizardstart) - return 1 - - -/datum/game_mode/wizard/post_setup() - for(var/datum/mind/wizard in wizards) - if(!config.objectives_disabled) - forge_wizard_objectives(wizard) - //learn_basic_spells(wizard.current) - equip_wizard(wizard.current) - name_wizard(wizard.current) - greet_wizard(wizard) - - spawn (rand(waittime_l, waittime_h)) - send_intercept() - ..() - return - - -/datum/game_mode/proc/forge_wizard_objectives(var/datum/mind/wizard) - if (config.objectives_disabled) - return - - switch(rand(1,100)) - if(1 to 30) - - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = wizard - kill_objective.find_target() - wizard.objectives += kill_objective - - if (!(locate(/datum/objective/escape) in wizard.objectives)) - var/datum/objective/escape/escape_objective = new - escape_objective.owner = wizard - wizard.objectives += escape_objective - if(31 to 60) - var/datum/objective/steal/steal_objective = new - steal_objective.owner = wizard - steal_objective.find_target() - wizard.objectives += steal_objective - - if (!(locate(/datum/objective/escape) in wizard.objectives)) - var/datum/objective/escape/escape_objective = new - escape_objective.owner = wizard - wizard.objectives += escape_objective - - if(61 to 100) - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = wizard - kill_objective.find_target() - wizard.objectives += kill_objective - - var/datum/objective/steal/steal_objective = new - steal_objective.owner = wizard - steal_objective.find_target() - wizard.objectives += steal_objective - - if (!(locate(/datum/objective/survive) in wizard.objectives)) - var/datum/objective/survive/survive_objective = new - survive_objective.owner = wizard - wizard.objectives += survive_objective - - else - if (!(locate(/datum/objective/hijack) in wizard.objectives)) - var/datum/objective/hijack/hijack_objective = new - hijack_objective.owner = wizard - wizard.objectives += hijack_objective - return - - -/datum/game_mode/proc/name_wizard(mob/living/carbon/human/wizard_mob) - //Allows the wizard to choose a custom name or go with a random one. Spawn 0 so it does not lag the round starting. - var/wizard_name_first = pick(wizard_first) - var/wizard_name_second = pick(wizard_second) - var/randomname = "[wizard_name_first] [wizard_name_second]" - spawn(0) - var/newname = sanitize(copytext(input(wizard_mob, "You are the Space Wizard. Would you like to change your name to something else?", "Name change", randomname) as null|text,1,MAX_NAME_LEN)) - - if (!newname) - newname = randomname - - wizard_mob.real_name = newname - wizard_mob.name = newname - if(wizard_mob.mind) - wizard_mob.mind.name = newname - return - - -/datum/game_mode/proc/greet_wizard(var/datum/mind/wizard, var/you_are=1) - if (you_are) - wizard.current << "\red You are the Space Wizard!" - show_objectives(wizard) - -/*/datum/game_mode/proc/learn_basic_spells(mob/living/carbon/human/wizard_mob) - if (!istype(wizard_mob)) - return - if(!config.feature_object_spell_system) - wizard_mob.verbs += /client/proc/jaunt - wizard_mob.mind.special_verbs += /client/proc/jaunt - else - wizard_mob.spell_list += new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(usr) -*/ - -/datum/game_mode/proc/equip_wizard(mob/living/carbon/human/wizard_mob) - if (!istype(wizard_mob)) - return - - //So zards properly get their items when they are admin-made. - del(wizard_mob.wear_suit) - del(wizard_mob.head) - del(wizard_mob.shoes) - del(wizard_mob.r_hand) - del(wizard_mob.r_store) - del(wizard_mob.l_store) - - wizard_mob.equip_to_slot_or_del(new /obj/item/device/radio/headset(wizard_mob), slot_l_ear) - wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/under/lightpurple(wizard_mob), slot_w_uniform) - wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(wizard_mob), slot_shoes) - wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(wizard_mob), slot_wear_suit) - wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(wizard_mob), slot_head) - if(wizard_mob.backbag == 2) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(wizard_mob), slot_back) - if(wizard_mob.backbag == 3) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(wizard_mob), slot_back) - if(wizard_mob.backbag == 4) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(wizard_mob), slot_back) - wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box(wizard_mob), slot_in_backpack) -// wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/scrying_gem(wizard_mob), slot_l_store) For scrying gem. - wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll(wizard_mob), slot_r_store) - wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/spellbook(wizard_mob), slot_r_hand) - - wizard_mob << "You will find a list of available spells in your spell book. Choose your magic arsenal carefully." - wizard_mob << "In your pockets you will find a teleport scroll. Use it as needed." - wizard_mob.mind.store_memory("Remember: do not forget to prepare your spells.") - wizard_mob.update_icons() - return 1 - - -/datum/game_mode/wizard/check_finished() - - if(config.continous_rounds) - return ..() - - var/wizards_alive = 0 - for(var/datum/mind/wizard in wizards) - if(!istype(wizard.current,/mob/living/carbon)) - continue - if(wizard.current.stat==2) - continue - wizards_alive++ - - if (wizards_alive) - return ..() - else - finished = 1 - return 1 - - - -/datum/game_mode/wizard/declare_completion() - if(finished) - feedback_set_details("round_end_result","loss - wizard killed") - world << "\red The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!" - ..() - return 1 - - -/datum/game_mode/proc/auto_declare_completion_wizard() - if(wizards.len) - var/text = "The wizards/witches were:" - - for(var/datum/mind/wizard in wizards) - - text += "
    [wizard.key] was [wizard.name] (" - if(wizard.current) - if(wizard.current.stat == DEAD) - text += "died" - else - text += "survived" - if(wizard.current.real_name != wizard.name) - text += " as [wizard.current.real_name]" - else - text += "body destroyed" - text += ")" - - var/count = 1 - var/wizardwin = 1 - if(!config.objectives_disabled) - for(var/datum/objective/objective in wizard.objectives) - if(objective.check_completion()) - text += "
    Objective #[count]: [objective.explanation_text] Success!" - feedback_add_details("wizard_objective","[objective.type]|SUCCESS") - else - text += "
    Objective #[count]: [objective.explanation_text] Fail." - feedback_add_details("wizard_objective","[objective.type]|FAIL") - wizardwin = 0 - count++ - - if(wizard.current && wizard.current.stat!=2 && wizardwin) - text += "
    The wizard was successful!" - feedback_add_details("wizard_success","SUCCESS") - else - text += "
    The wizard has failed!" - feedback_add_details("wizard_success","FAIL") - - world << text - return 1 - -//OTHER PROCS - -//To batch-remove wizard spells. Linked to mind.dm. -/mob/proc/spellremove(var/mob/M as mob) - for(var/obj/effect/proc_holder/spell/spell_to_remove in src.spell_list) - del(spell_to_remove) - -/*Checks if the wizard can cast spells. -Made a proc so this is not repeated 14 (or more) times.*/ -/mob/proc/casting() -//Removed the stat check because not all spells require clothing now. - if(!istype(usr:wear_suit, /obj/item/clothing/suit/wizrobe)) - usr << "I don't feel strong enough without my robe." - return 0 - if(!istype(usr:shoes, /obj/item/clothing/shoes/sandal)) - usr << "I don't feel strong enough without my sandals." - return 0 - if(!istype(usr:head, /obj/item/clothing/head/wizard)) - usr << "I don't feel strong enough without my hat." - return 0 - else - return 1 + end_on_antag_death = 1 + antag_tag = MODE_WIZARD diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index b79934974c..0c133adc9b 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -122,19 +122,7 @@ // -- Mode/mind specific stuff goes here callHook("clone", list(H)) - - switch(ticker.mode.name) - if("revolution") - if((H.mind in ticker.mode:revolutionaries) || (H.mind in ticker.mode:head_revolutionaries)) - ticker.mode.update_all_rev_icons() //So the icon actually appears - if("mercenary") - if(H.mind in ticker.mode.syndicates) - ticker.mode.update_all_synd_icons() - if("cult") - if(H.mind in ticker.mode.cult) - ticker.mode.add_cultist(occupant.mind) - ticker.mode.update_all_cult_icons() //So the icon actually appears - + update_antag_icons(H.mind) // -- End mode specific stuff if(!R.dna) diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm index 7bd8e4b8e8..8778038ddf 100644 --- a/code/game/machinery/computer/ai_core.dm +++ b/code/game/machinery/computer/ai_core.dm @@ -137,8 +137,8 @@ return if(M.brainmob.mind) - ticker.mode.remove_cultist(M.brainmob.mind, 1) - ticker.mode.remove_revolutionary(M.brainmob.mind, 1) + cult.remove_antagonist(M.brainmob.mind, 1) + revs.remove_antagonist(M.brainmob.mind, 1) user.drop_item() P.loc = src @@ -207,11 +207,9 @@ /obj/structure/AIcore/deactivated/proc/check_malf(var/mob/living/silicon/ai/ai) if(!ai) return - if (ticker.mode.name == "AI malfunction") - var/datum/game_mode/malfunction/malf = ticker.mode - for (var/datum/mind/malfai in malf.malf_ai) - if (ai.mind == malfai) - return 1 + for (var/datum/mind/malfai in malf.current_antagonists) + if (ai.mind == malfai) + return 1 /obj/structure/AIcore/deactivated/attackby(var/obj/item/weapon/W, var/mob/user) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 9df53b039c..bc9f982477 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -430,7 +430,7 @@ if ((!( ticker ) || !emergency_shuttle.location())) return - if(sent_strike_team == 1) + if(deathsquad.deployed) user << "Centcom will not allow the shuttle to be called. Consider all contracts terminated." return @@ -479,7 +479,7 @@ user << "Centcom does not currently have a shuttle available in your sector. Please try again later." return - if(sent_strike_team == 1) + if(deathsquad.deployed == 1) user << "Centcom will not allow the shuttle to be called. Consider all contracts terminated." return @@ -487,7 +487,7 @@ user << "The shuttle is refueling. Please wait another [round((54000-world.time)/60)] minutes before trying again." return - if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || ticker.mode.name == "sandbox") + if(ticker.mode.auto_recall_shuttle) //New version pretends to call the shuttle but cause the shuttle to return after a random duration. emergency_shuttle.auto_recall = 1 @@ -510,7 +510,7 @@ /proc/cancel_call_proc(var/mob/user) if (!( ticker ) || !emergency_shuttle.can_recall()) return - if((ticker.mode.name == "blob")||(ticker.mode.name == "meteor")) + if((ticker.mode.name == "blob")||(ticker.mode.name == "Meteor")) return if(!emergency_shuttle.going_to_centcom()) //check that shuttle isn't already heading to centcomm @@ -556,7 +556,7 @@ if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf)) return ..() - if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || sent_strike_team) + if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || deathsquad.deployed) return ..() emergency_shuttle.call_evac() @@ -579,7 +579,7 @@ if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf)) return ..() - if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || sent_strike_team) + if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || deathsquad.deployed) return ..() emergency_shuttle.call_evac() diff --git a/code/game/machinery/computer/specops_shuttle.dm b/code/game/machinery/computer/specops_shuttle.dm index 8d51017603..01728b4e50 100644 --- a/code/game/machinery/computer/specops_shuttle.dm +++ b/code/game/machinery/computer/specops_shuttle.dm @@ -259,11 +259,6 @@ var/specops_shuttle_timeleft = 0 user << "\red Access Denied." return -//Commented out so admins can do shenanigans at their leisure. Also makes the force-spawned admin ERTs able to use the shuttle. -// if (sent_strike_team == 0 && send_emergency_team == 0) -// usr << "\red The strike team has not yet deployed." -// return - if(..()) return @@ -336,247 +331,3 @@ var/specops_shuttle_timeleft = 0 add_fingerprint(usr) updateUsrDialog() return - -/*//Config stuff -#define SPECOPS_MOVETIME 600 //Time to station is milliseconds. 60 seconds, enough time for everyone to be on the shuttle before it leaves. -#define SPECOPS_STATION_AREATYPE "/area/shuttle/specops/station" //Type of the spec ops shuttle area for station -#define SPECOPS_DOCK_AREATYPE "/area/shuttle/specops/centcom" //Type of the spec ops shuttle area for dock - -var/specops_shuttle_moving_to_station = 0 -var/specops_shuttle_moving_to_centcom = 0 -var/specops_shuttle_at_station = 0 -var/specops_shuttle_can_send = 1 -var/specops_shuttle_time = 0 -var/specops_shuttle_timeleft = 0 - -/obj/machinery/computer/specops_shuttle - name = "Spec. Ops. Shuttle Console" - icon = 'icons/obj/computer.dmi' - icon_state = "shuttle" - req_access = list(access_cent_specops) - var/temp = null - var/hacked = 0 - var/allowedtocall = 0 - -/proc/specops_process() - var/area/centcom/control/cent_com = locate()//To find announcer. This area should exist for this proc to work. - var/area/centcom/specops/special_ops = locate()//Where is the specops area located? - var/mob/living/silicon/decoy/announcer = locate() in cent_com//We need a fake AI to announce some stuff below. Otherwise it will be wonky. - - var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. - var/message = "THE SPECIAL OPERATIONS SHUTTLE IS PREPARING FOR LAUNCH"//Initial message shown. - if(announcer) - announcer.say(message) - message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" - announcer.say(message) - - while(specops_shuttle_time - world.timeofday > 0) - var/ticksleft = specops_shuttle_time - world.timeofday - - if(ticksleft > 1e5) - specops_shuttle_time = world.timeofday + 10 // midnight rollover - specops_shuttle_timeleft = (ticksleft / 10) - - //All this does is announce the time before launch. - if(announcer) - var/rounded_time_left = round(specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions. - if(rounded_time_left in message_tracker)//If that time is in the list for message announce. - message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN" - if(rounded_time_left==0) - message = "ALERT: TAKEOFF" - announcer.say(message) - message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle. - //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. - - sleep(5) - - specops_shuttle_moving_to_station = 0 - specops_shuttle_moving_to_centcom = 0 - - specops_shuttle_at_station = 1 - if (specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return - - if (!specops_can_move()) - usr << "\red The Special Operations shuttle is unable to leave." - return - - //Begin Marauder launchpad. - spawn(0)//So it parallel processes it. - for(var/obj/machinery/door/poddoor/M in special_ops) - switch(M.id) - if("ASSAULT0") - spawn(10)//1 second delay between each. - M.open() - if("ASSAULT1") - spawn(20) - M.open() - if("ASSAULT2") - spawn(30) - M.open() - if("ASSAULT3") - spawn(40) - M.open() - - sleep(10) - - var/spawn_marauder[] = new() - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "Marauder Entry") - spawn_marauder.Add(L) - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "Marauder Exit") - var/obj/effect/portal/P = new(L.loc) - P.invisibility = 101//So it is not seen by anyone. - P.failchance = 0//So it has no fail chance when teleporting. - P.target = pick(spawn_marauder)//Where the marauder will arrive. - spawn_marauder.Remove(P.target) - - sleep(10) - - for(var/obj/machinery/mass_driver/M in special_ops) - switch(M.id) - if("ASSAULT0") - spawn(10) - M.drive() - if("ASSAULT1") - spawn(20) - M.drive() - if("ASSAULT2") - spawn(30) - M.drive() - if("ASSAULT3") - spawn(40) - M.drive() - - sleep(50)//Doors remain open for 5 seconds. - - for(var/obj/machinery/door/poddoor/M in special_ops) - switch(M.id)//Doors close at the same time. - if("ASSAULT0") - spawn(0) - M.close() - if("ASSAULT1") - spawn(0) - M.close() - if("ASSAULT2") - spawn(0) - M.close() - if("ASSAULT3") - spawn(0) - M.close() - special_ops.readyreset()//Reset firealarm after the team launched. - //End Marauder launchpad. - - var/area/start_location = locate(/area/shuttle/specops/centcom) - var/area/end_location = locate(/area/shuttle/specops/station) - - var/list/dstturfs = list() - var/throwy = world.maxy - - for(var/turf/T in end_location) - dstturfs += T - if(T.y < throwy) - throwy = T.y - - // hey you, get out of the way! - for(var/turf/T in dstturfs) - // find the turf to move things to - var/turf/D = locate(T.x, throwy - 1, 1) - //var/turf/E = get_step(D, SOUTH) - for(var/atom/movable/AM as mob|obj in T) - AM.Move(D) - if(istype(T, /turf/simulated)) - del(T) - - start_location.move_contents_to(end_location) - - for(var/turf/T in get_area_turfs(end_location) ) - var/mob/M = locate(/mob) in T - M << "\red You have arrived to [station_name]. Commence operation!" - -/proc/specops_can_move() - if(specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return 0 - else return 1 - -/obj/machinery/computer/specops_shuttle/attackby(I as obj, user as mob) - return attack_hand(user) - -/obj/machinery/computer/specops_shuttle/attack_ai(var/mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer/specops_shuttle/attack_paw(var/mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer/specops_shuttle/attackby(I as obj, user as mob) - if(istype(I,/obj/item/weapon/card/emag)) - user << "\blue The electronic systems in this console are far too advanced for your primitive hacking peripherals." - else - return attack_hand(user) - -/obj/machinery/computer/specops_shuttle/attack_hand(var/mob/user as mob) - if(!allowed(user)) - user << "\red Access Denied." - return - -// if (sent_strike_team == 0) -// usr << "\red The strike team has not yet deployed." -// return - - if(..()) - return - - user.set_machine(src) - var/dat - if (temp) - dat = temp - else - dat += {"
    Special Operations Shuttle
    - \nLocation: [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "Departing for [station_name] in ([specops_shuttle_timeleft] seconds.)":specops_shuttle_at_station ? "Station":"Dock"]
    - [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "\n*The Special Ops. shuttle is already leaving.*
    \n
    ":specops_shuttle_at_station ? "\nShuttle Offline
    \n
    ":"\nDepart to [station_name]
    \n
    "] - \nClose"} - - user << browse(dat, "window=computer;size=575x450") - onclose(user, "computer") - return - -/obj/machinery/computer/specops_shuttle/Topic(href, href_list) - if(..()) - return 1 - - if ((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon))) - usr.set_machine(src) - - if (href_list["sendtodock"]) - if(!specops_shuttle_at_station|| specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return - - usr << "\blue Central Command will not allow the Special Operations shuttle to return." - return - - else if (href_list["sendtostation"]) - if(specops_shuttle_at_station || specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return - - if (!specops_can_move()) - usr << "\red The Special Operations shuttle is unable to leave." - return - - usr << "\blue The Special Operations shuttle will arrive on [station_name] in [(SPECOPS_MOVETIME/10)] seconds." - - temp += "Shuttle departing.

    OK" - updateUsrDialog() - - var/area/centcom/specops/special_ops = locate() - if(special_ops) - special_ops.readyalert()//Trigger alarm for the spec ops area. - specops_shuttle_moving_to_station = 1 - - specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME - spawn(0) - specops_process() - - else if (href_list["mainmenu"]) - temp = null - - add_fingerprint(usr) - updateUsrDialog() - return - */ \ No newline at end of file diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 29227ceb58..dc827fb01a 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -363,10 +363,10 @@ if(occupant.mind.objectives.len) del(occupant.mind.objectives) occupant.mind.special_role = null - else - if(ticker.mode.name == "AutoTraitor") - var/datum/game_mode/traitor/autotraitor/current_mode = ticker.mode - current_mode.possible_traitors.Remove(occupant) + //else + //if(ticker.mode.name == "AutoTraitor") + //var/datum/game_mode/traitor/autotraitor/current_mode = ticker.mode + //current_mode.possible_traitors.Remove(occupant) // Delete them from datacore. diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/machinery/nuclear_bomb.dm similarity index 96% rename from code/game/gamemodes/nuclear/nuclearbomb.dm rename to code/game/machinery/nuclear_bomb.dm index e73fbf6880..d13f18c3e9 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/machinery/nuclear_bomb.dm @@ -1,434 +1,431 @@ -var/bomb_set - -/obj/machinery/nuclearbomb - name = "\improper Nuclear Fission Explosive" - desc = "Uh oh. RUN!!!!" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "nuclearbomb0" - density = 1 - var/deployable = 0.0 - var/extended = 0.0 - var/lighthack = 0 - var/opened = 0.0 - var/timeleft = 60.0 - var/timing = 0.0 - var/r_code = "ADMIN" - var/code = "" - var/yes_code = 0.0 - var/safety = 1.0 - var/obj/item/weapon/disk/nuclear/auth = null - var/list/wires = list() - var/light_wire - var/safety_wire - var/timing_wire - var/removal_stage = 0 // 0 is no removal, 1 is covers removed, 2 is covers open, - // 3 is sealant open, 4 is unwrenched, 5 is removed from bolts. - use_power = 0 - - - -/obj/machinery/nuclearbomb/New() - ..() - r_code = "[rand(10000, 99999.0)]"//Creates a random code upon object spawn. - - src.wires["Red"] = 0 - src.wires["Blue"] = 0 - src.wires["Green"] = 0 - src.wires["Marigold"] = 0 - src.wires["Fuschia"] = 0 - src.wires["Black"] = 0 - src.wires["Pearl"] = 0 - var/list/w = list("Red","Blue","Green","Marigold","Black","Fuschia","Pearl") - src.light_wire = pick(w) - w -= src.light_wire - src.timing_wire = pick(w) - w -= src.timing_wire - src.safety_wire = pick(w) - w -= src.safety_wire - -/obj/machinery/nuclearbomb/process() - if (src.timing) - bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed. - src.timeleft-- - if (src.timeleft <= 0) - explode() - for(var/mob/M in viewers(1, src)) - if ((M.client && M.machine == src)) - src.attack_hand(M) - return - -/obj/machinery/nuclearbomb/attackby(obj/item/weapon/O as obj, mob/user as mob) - - if (istype(O, /obj/item/weapon/screwdriver)) - src.add_fingerprint(user) - if (src.auth) - if (src.opened == 0) - src.opened = 1 - overlays += image(icon, "npanel_open") - user << "You unscrew the control panel of [src]." - - else - src.opened = 0 - overlays -= image(icon, "npanel_open") - user << "You screw the control panel of [src] back on." - else - if (src.opened == 0) - user << "The [src] emits a buzzing noise, the panel staying locked in." - if (src.opened == 1) - src.opened = 0 - overlays -= image(icon, "npanel_open") - user << "You screw the control panel of [src] back on." - flick("nuclearbombc", src) - - return - if (istype(O, /obj/item/weapon/wirecutters) || istype(O, /obj/item/device/multitool)) - if (src.opened == 1) - nukehack_win(user) - return - - if (src.extended) - if (istype(O, /obj/item/weapon/disk/nuclear)) - usr.drop_item() - O.loc = src - src.auth = O - src.add_fingerprint(user) - return - - if (src.anchored) - switch(removal_stage) - if(0) - if(istype(O,/obj/item/weapon/weldingtool)) - - var/obj/item/weapon/weldingtool/WT = O - if(!WT.isOn()) return - if (WT.get_fuel() < 5) // uses up 5 fuel. - user << "\red You need more fuel to complete this task." - return - - user.visible_message("[user] starts cutting loose the anchoring bolt covers on [src].", "You start cutting loose the anchoring bolt covers with [O]...") - - if(do_after(user,40)) - if(!src || !user || !WT.remove_fuel(5, user)) return - user.visible_message("[user] cuts through the bolt covers on [src].", "You cut through the bolt cover.") - removal_stage = 1 - return - - if(1) - if(istype(O,/obj/item/weapon/crowbar)) - user.visible_message("[user] starts forcing open the bolt covers on [src].", "You start forcing open the anchoring bolt covers with [O]...") - - if(do_after(user,15)) - if(!src || !user) return - user.visible_message("[user] forces open the bolt covers on [src].", "You force open the bolt covers.") - removal_stage = 2 - return - - if(2) - if(istype(O,/obj/item/weapon/weldingtool)) - - var/obj/item/weapon/weldingtool/WT = O - if(!WT.isOn()) return - if (WT.get_fuel() < 5) // uses up 5 fuel. - user << "\red You need more fuel to complete this task." - return - - user.visible_message("[user] starts cutting apart the anchoring system sealant on [src].", "You start cutting apart the anchoring system's sealant with [O]...") - - if(do_after(user,40)) - if(!src || !user || !WT.remove_fuel(5, user)) return - user.visible_message("[user] cuts apart the anchoring system sealant on [src].", "You cut apart the anchoring system's sealant.") - removal_stage = 3 - return - - if(3) - if(istype(O,/obj/item/weapon/wrench)) - - user.visible_message("[user] begins unwrenching the anchoring bolts on [src].", "You begin unwrenching the anchoring bolts...") - - if(do_after(user,50)) - if(!src || !user) return - user.visible_message("[user] unwrenches the anchoring bolts on [src].", "You unwrench the anchoring bolts.") - removal_stage = 4 - return - - if(4) - if(istype(O,/obj/item/weapon/crowbar)) - - user.visible_message("[user] begins lifting [src] off of the anchors.", "You begin lifting the device off the anchors...") - - if(do_after(user,80)) - if(!src || !user) return - user.visible_message("[user] crowbars [src] off of the anchors. It can now be moved.", "You jam the crowbar under the nuclear device and lift it off its anchors. You can now move it!") - anchored = 0 - removal_stage = 5 - return - ..() - -/obj/machinery/nuclearbomb/attack_hand(mob/user as mob) - if (src.extended) - if (!ishuman(user)) - usr << "\red You don't have the dexterity to do this!" - return 1 - - if (!ishuman(user)) - usr << "\red You don't have the dexterity to do this!" - return 1 - user.set_machine(src) - var/dat = text("Nuclear Fission Explosive
    \nAuth. Disk: []
    ", src, (src.auth ? "++++++++++" : "----------")) - if (src.auth) - if (src.yes_code) - dat += text("\nStatus: []-[]
    \nTimer: []
    \n
    \nTimer: [] Toggle
    \nTime: - - [] + +
    \n
    \nSafety: [] Toggle
    \nAnchor: [] Toggle
    \n", (src.timing ? "Func/Set" : "Functional"), (src.safety ? "Safe" : "Engaged"), src.timeleft, (src.timing ? "On" : "Off"), src, src, src, src.timeleft, src, src, (src.safety ? "On" : "Off"), src, (src.anchored ? "Engaged" : "Off"), src) - else - dat += text("\nStatus: Auth. S2-[]
    \nTimer: []
    \n
    \nTimer: [] Toggle
    \nTime: - - [] + +
    \n
    \n[] Safety: Toggle
    \nAnchor: [] Toggle
    \n", (src.safety ? "Safe" : "Engaged"), src.timeleft, (src.timing ? "On" : "Off"), src.timeleft, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off")) - else - if (src.timing) - dat += text("\nStatus: Set-[]
    \nTimer: []
    \n
    \nTimer: [] Toggle
    \nTime: - - [] + +
    \n
    \nSafety: [] Toggle
    \nAnchor: [] Toggle
    \n", (src.safety ? "Safe" : "Engaged"), src.timeleft, (src.timing ? "On" : "Off"), src.timeleft, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off")) - else - dat += text("\nStatus: Auth. S1-[]
    \nTimer: []
    \n
    \nTimer: [] Toggle
    \nTime: - - [] + +
    \n
    \nSafety: [] Toggle
    \nAnchor: [] Toggle
    \n", (src.safety ? "Safe" : "Engaged"), src.timeleft, (src.timing ? "On" : "Off"), src.timeleft, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off")) - var/message = "AUTH" - if (src.auth) - message = text("[]", src.code) - if (src.yes_code) - message = "*****" - dat += text("
    \n>[]
    \n1-2-3
    \n4-5-6
    \n7-8-9
    \nR-0-E
    \n
    ", message, src, src, src, src, src, src, src, src, src, src, src, src) - user << browse(dat, "window=nuclearbomb;size=300x400") - onclose(user, "nuclearbomb") - else if (src.deployable) - if(removal_stage < 5) - src.anchored = 1 - visible_message("\red With a steely snap, bolts slide out of [src] and anchor it to the flooring!") - else - visible_message("\red \The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.") - if(!src.lighthack) - flick("nuclearbombc", src) - src.icon_state = "nuclearbomb1" - src.extended = 1 - return - -obj/machinery/nuclearbomb/proc/nukehack_win(mob/user as mob) - var/dat as text - dat += "Nuclear Fission Explosive
    \nNuclear Device Wires:
    " - for(var/wire in src.wires) - dat += text("[wire] Wire: [src.wires[wire] ? "Mend" : "Cut"] Pulse
    ") - dat += text("
    The device is [src.timing ? "shaking!" : "still"]
    ") - dat += text("The device is [src.safety ? "quiet" : "whirring"].
    ") - dat += text("The lights are [src.lighthack ? "static" : "functional"].
    ") - user << browse("Bomb Defusion[dat]","window=nukebomb_hack") - onclose(user, "nukebomb_hack") - -/obj/machinery/nuclearbomb/verb/make_deployable() - set category = "Object" - set name = "Make Deployable" - set src in oview(1) - - if (!usr.canmove || usr.stat || usr.restrained()) - return - if (!ishuman(usr)) - usr << "\red You don't have the dexterity to do this!" - return 1 - - if (src.deployable) - usr << "\red You close several panels to make [src] undeployable." - src.deployable = 0 - else - usr << "\red You adjust some panels to make [src] deployable." - src.deployable = 1 - return - - -/obj/machinery/nuclearbomb/Topic(href, href_list) - ..() - if (!usr.canmove || usr.stat || usr.restrained()) - return - if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf)))) - usr.set_machine(src) - if(href_list["act"]) - var/temp_wire = href_list["wire"] - if(href_list["act"] == "pulse") - if (!istype(usr.get_active_hand(), /obj/item/device/multitool)) - usr << "You need a multitool!" - else - if(src.wires[temp_wire]) - usr << "You can't pulse a cut wire." - else - if(src.light_wire == temp_wire) - src.lighthack = !src.lighthack - spawn(100) src.lighthack = !src.lighthack - if(src.timing_wire == temp_wire) - if(src.timing) - explode() - if(src.safety_wire == temp_wire) - src.safety = !src.safety - spawn(100) src.safety = !src.safety - if(src.safety == 1) - visible_message("\blue The [src] quiets down.") - if(!src.lighthack) - if (src.icon_state == "nuclearbomb2") - src.icon_state = "nuclearbomb1" - else - visible_message("\blue The [src] emits a quiet whirling noise!") - if(href_list["act"] == "wire") - if (!istype(usr.get_active_hand(), /obj/item/weapon/wirecutters)) - usr << "You need wirecutters!" - else - wires[temp_wire] = !wires[temp_wire] - if(src.safety_wire == temp_wire) - if(src.timing) - explode() - if(src.timing_wire == temp_wire) - if(!src.lighthack) - if (src.icon_state == "nuclearbomb2") - src.icon_state = "nuclearbomb1" - src.timing = 0 - bomb_set = 0 - if(src.light_wire == temp_wire) - src.lighthack = !src.lighthack - - if (href_list["auth"]) - if (src.auth) - src.auth.loc = src.loc - src.yes_code = 0 - src.auth = null - else - var/obj/item/I = usr.get_active_hand() - if (istype(I, /obj/item/weapon/disk/nuclear)) - usr.drop_item() - I.loc = src - src.auth = I - if (src.auth) - if (href_list["type"]) - if (href_list["type"] == "E") - if (src.code == src.r_code) - src.yes_code = 1 - src.code = null - else - src.code = "ERROR" - else - if (href_list["type"] == "R") - src.yes_code = 0 - src.code = null - else - src.code += text("[]", href_list["type"]) - if (length(src.code) > 5) - src.code = "ERROR" - if (src.yes_code) - if (href_list["time"]) - var/time = text2num(href_list["time"]) - src.timeleft += time - src.timeleft = min(max(round(src.timeleft), 60), 600) - if (href_list["timer"]) - if (src.timing == -1.0) - return - if (src.safety) - usr << "\red The safety is still on." - return - src.timing = !( src.timing ) - if (src.timing) - if(!src.lighthack) - src.icon_state = "nuclearbomb2" - if(!src.safety) - bomb_set = 1//There can still be issues with this reseting when there are multiple bombs. Not a big deal tho for Nuke/N - else - bomb_set = 0 - else - bomb_set = 0 - if(!src.lighthack) - src.icon_state = "nuclearbomb1" - if (href_list["safety"]) - src.safety = !( src.safety ) - if(safety) - src.timing = 0 - bomb_set = 0 - if (href_list["anchor"]) - - if(removal_stage == 5) - src.anchored = 0 - visible_message("\red \The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.") - return - - src.anchored = !( src.anchored ) - if(src.anchored) - visible_message("\red With a steely snap, bolts slide out of [src] and anchor it to the flooring.") - else - visible_message("\red The anchoring bolts slide back into the depths of [src].") - - src.add_fingerprint(usr) - for(var/mob/M in viewers(1, src)) - if ((M.client && M.machine == src)) - src.attack_hand(M) - else - usr << browse(null, "window=nuclearbomb") - return - return - - -/obj/machinery/nuclearbomb/ex_act(severity) - return - -/obj/machinery/nuclearbomb/blob_act() - if (src.timing == -1.0) - return - else - return ..() - return - - -#define NUKERANGE 80 -/obj/machinery/nuclearbomb/proc/explode() - if (src.safety) - src.timing = 0 - return - src.timing = -1.0 - src.yes_code = 0 - src.safety = 1 - if(!src.lighthack) - src.icon_state = "nuclearbomb3" - playsound(src,'sound/machines/Alarm.ogg',100,0,5) - if (ticker && ticker.mode) - ticker.mode.explosion_in_progress = 1 - sleep(100) - - var/off_station = 0 - var/turf/bomb_location = get_turf(src) - if(bomb_location && (bomb_location.z in config.station_levels)) - if( (bomb_location.x < (128-NUKERANGE)) || (bomb_location.x > (128+NUKERANGE)) || (bomb_location.y < (128-NUKERANGE)) || (bomb_location.y > (128+NUKERANGE)) ) - off_station = 1 - else - off_station = 2 - - if(ticker) - if(ticker.mode && ticker.mode.name == "mercenary") - var/obj/machinery/computer/shuttle_control/multi/syndicate/syndie_location = locate(/obj/machinery/computer/shuttle_control/multi/syndicate) - if(syndie_location) - ticker.mode:syndies_didnt_escape = (syndie_location.z > 1 ? 0 : 1) //muskets will make me change this, but it will do for now - ticker.mode:nuke_off_station = off_station - ticker.station_explosion_cinematic(off_station,null) - if(ticker.mode) - ticker.mode.explosion_in_progress = 0 - if(ticker.mode.name == "mercenary") - ticker.mode:nukes_left -- - else - world << "The station was destoyed by the nuclear blast!" - - ticker.mode.station_was_nuked = (off_station<2) //offstation==1 is a draw. the station becomes irradiated and needs to be evacuated. - //kinda shit but I couldn't get permission to do what I wanted to do. - - if(!ticker.mode.check_finished())//If the mode does not deal with the nuke going off so just reboot because everyone is stuck as is - world << "Resetting in 30 seconds!" - - feedback_set_details("end_error","nuke - unhandled ending") - - if(blackbox) - blackbox.save_all_data_to_sql() - sleep(300) - log_game("Rebooting due to nuclear detonation") - world.Reboot() - return - return - -/obj/item/weapon/disk/nuclear/Del() - if(blobstart.len > 0) - var/obj/D = new /obj/item/weapon/disk/nuclear(pick(blobstart)) - message_admins("[src] has been destroyed. Spawning [D] at ([D.x], [D.y], [D.z]).") - log_game("[src] has been destroyed. Spawning [D] at ([D.x], [D.y], [D.z]).") - ..() +var/bomb_set + +/obj/machinery/nuclearbomb + name = "\improper Nuclear Fission Explosive" + desc = "Uh oh. RUN!!!!" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "nuclearbomb0" + density = 1 + var/deployable = 0.0 + var/extended = 0.0 + var/lighthack = 0 + var/opened = 0.0 + var/timeleft = 60.0 + var/timing = 0.0 + var/r_code = "ADMIN" + var/code = "" + var/yes_code = 0.0 + var/safety = 1.0 + var/obj/item/weapon/disk/nuclear/auth = null + var/list/wires = list() + var/light_wire + var/safety_wire + var/timing_wire + var/removal_stage = 0 // 0 is no removal, 1 is covers removed, 2 is covers open, + // 3 is sealant open, 4 is unwrenched, 5 is removed from bolts. + use_power = 0 + + + +/obj/machinery/nuclearbomb/New() + ..() + r_code = "[rand(10000, 99999.0)]"//Creates a random code upon object spawn. + + src.wires["Red"] = 0 + src.wires["Blue"] = 0 + src.wires["Green"] = 0 + src.wires["Marigold"] = 0 + src.wires["Fuschia"] = 0 + src.wires["Black"] = 0 + src.wires["Pearl"] = 0 + var/list/w = list("Red","Blue","Green","Marigold","Black","Fuschia","Pearl") + src.light_wire = pick(w) + w -= src.light_wire + src.timing_wire = pick(w) + w -= src.timing_wire + src.safety_wire = pick(w) + w -= src.safety_wire + +/obj/machinery/nuclearbomb/process() + if (src.timing) + bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed. + src.timeleft-- + if (src.timeleft <= 0) + explode() + for(var/mob/M in viewers(1, src)) + if ((M.client && M.machine == src)) + src.attack_hand(M) + return + +/obj/machinery/nuclearbomb/attackby(obj/item/weapon/O as obj, mob/user as mob) + + if (istype(O, /obj/item/weapon/screwdriver)) + src.add_fingerprint(user) + if (src.auth) + if (src.opened == 0) + src.opened = 1 + overlays += image(icon, "npanel_open") + user << "You unscrew the control panel of [src]." + + else + src.opened = 0 + overlays -= image(icon, "npanel_open") + user << "You screw the control panel of [src] back on." + else + if (src.opened == 0) + user << "The [src] emits a buzzing noise, the panel staying locked in." + if (src.opened == 1) + src.opened = 0 + overlays -= image(icon, "npanel_open") + user << "You screw the control panel of [src] back on." + flick("nuclearbombc", src) + + return + if (istype(O, /obj/item/weapon/wirecutters) || istype(O, /obj/item/device/multitool)) + if (src.opened == 1) + nukehack_win(user) + return + + if (src.extended) + if (istype(O, /obj/item/weapon/disk/nuclear)) + usr.drop_item() + O.loc = src + src.auth = O + src.add_fingerprint(user) + return + + if (src.anchored) + switch(removal_stage) + if(0) + if(istype(O,/obj/item/weapon/weldingtool)) + + var/obj/item/weapon/weldingtool/WT = O + if(!WT.isOn()) return + if (WT.get_fuel() < 5) // uses up 5 fuel. + user << "\red You need more fuel to complete this task." + return + + user.visible_message("[user] starts cutting loose the anchoring bolt covers on [src].", "You start cutting loose the anchoring bolt covers with [O]...") + + if(do_after(user,40)) + if(!src || !user || !WT.remove_fuel(5, user)) return + user.visible_message("[user] cuts through the bolt covers on [src].", "You cut through the bolt cover.") + removal_stage = 1 + return + + if(1) + if(istype(O,/obj/item/weapon/crowbar)) + user.visible_message("[user] starts forcing open the bolt covers on [src].", "You start forcing open the anchoring bolt covers with [O]...") + + if(do_after(user,15)) + if(!src || !user) return + user.visible_message("[user] forces open the bolt covers on [src].", "You force open the bolt covers.") + removal_stage = 2 + return + + if(2) + if(istype(O,/obj/item/weapon/weldingtool)) + + var/obj/item/weapon/weldingtool/WT = O + if(!WT.isOn()) return + if (WT.get_fuel() < 5) // uses up 5 fuel. + user << "\red You need more fuel to complete this task." + return + + user.visible_message("[user] starts cutting apart the anchoring system sealant on [src].", "You start cutting apart the anchoring system's sealant with [O]...") + + if(do_after(user,40)) + if(!src || !user || !WT.remove_fuel(5, user)) return + user.visible_message("[user] cuts apart the anchoring system sealant on [src].", "You cut apart the anchoring system's sealant.") + removal_stage = 3 + return + + if(3) + if(istype(O,/obj/item/weapon/wrench)) + + user.visible_message("[user] begins unwrenching the anchoring bolts on [src].", "You begin unwrenching the anchoring bolts...") + + if(do_after(user,50)) + if(!src || !user) return + user.visible_message("[user] unwrenches the anchoring bolts on [src].", "You unwrench the anchoring bolts.") + removal_stage = 4 + return + + if(4) + if(istype(O,/obj/item/weapon/crowbar)) + + user.visible_message("[user] begins lifting [src] off of the anchors.", "You begin lifting the device off the anchors...") + + if(do_after(user,80)) + if(!src || !user) return + user.visible_message("[user] crowbars [src] off of the anchors. It can now be moved.", "You jam the crowbar under the nuclear device and lift it off its anchors. You can now move it!") + anchored = 0 + removal_stage = 5 + return + ..() + +/obj/machinery/nuclearbomb/attack_hand(mob/user as mob) + if (src.extended) + if (!ishuman(user)) + usr << "\red You don't have the dexterity to do this!" + return 1 + + if (!ishuman(user)) + usr << "\red You don't have the dexterity to do this!" + return 1 + user.set_machine(src) + var/dat = text("Nuclear Fission Explosive
    \nAuth. Disk: []
    ", src, (src.auth ? "++++++++++" : "----------")) + if (src.auth) + if (src.yes_code) + dat += text("\nStatus: []-[]
    \nTimer: []
    \n
    \nTimer: [] Toggle
    \nTime: - - [] + +
    \n
    \nSafety: [] Toggle
    \nAnchor: [] Toggle
    \n", (src.timing ? "Func/Set" : "Functional"), (src.safety ? "Safe" : "Engaged"), src.timeleft, (src.timing ? "On" : "Off"), src, src, src, src.timeleft, src, src, (src.safety ? "On" : "Off"), src, (src.anchored ? "Engaged" : "Off"), src) + else + dat += text("\nStatus: Auth. S2-[]
    \nTimer: []
    \n
    \nTimer: [] Toggle
    \nTime: - - [] + +
    \n
    \n[] Safety: Toggle
    \nAnchor: [] Toggle
    \n", (src.safety ? "Safe" : "Engaged"), src.timeleft, (src.timing ? "On" : "Off"), src.timeleft, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off")) + else + if (src.timing) + dat += text("\nStatus: Set-[]
    \nTimer: []
    \n
    \nTimer: [] Toggle
    \nTime: - - [] + +
    \n
    \nSafety: [] Toggle
    \nAnchor: [] Toggle
    \n", (src.safety ? "Safe" : "Engaged"), src.timeleft, (src.timing ? "On" : "Off"), src.timeleft, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off")) + else + dat += text("\nStatus: Auth. S1-[]
    \nTimer: []
    \n
    \nTimer: [] Toggle
    \nTime: - - [] + +
    \n
    \nSafety: [] Toggle
    \nAnchor: [] Toggle
    \n", (src.safety ? "Safe" : "Engaged"), src.timeleft, (src.timing ? "On" : "Off"), src.timeleft, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off")) + var/message = "AUTH" + if (src.auth) + message = text("[]", src.code) + if (src.yes_code) + message = "*****" + dat += text("
    \n>[]
    \n1-2-3
    \n4-5-6
    \n7-8-9
    \nR-0-E
    \n
    ", message, src, src, src, src, src, src, src, src, src, src, src, src) + user << browse(dat, "window=nuclearbomb;size=300x400") + onclose(user, "nuclearbomb") + else if (src.deployable) + if(removal_stage < 5) + src.anchored = 1 + visible_message("\red With a steely snap, bolts slide out of [src] and anchor it to the flooring!") + else + visible_message("\red \The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.") + if(!src.lighthack) + flick("nuclearbombc", src) + src.icon_state = "nuclearbomb1" + src.extended = 1 + return + +obj/machinery/nuclearbomb/proc/nukehack_win(mob/user as mob) + var/dat as text + dat += "Nuclear Fission Explosive
    \nNuclear Device Wires:
    " + for(var/wire in src.wires) + dat += text("[wire] Wire: [src.wires[wire] ? "Mend" : "Cut"] Pulse
    ") + dat += text("
    The device is [src.timing ? "shaking!" : "still"]
    ") + dat += text("The device is [src.safety ? "quiet" : "whirring"].
    ") + dat += text("The lights are [src.lighthack ? "static" : "functional"].
    ") + user << browse("Bomb Defusion[dat]","window=nukebomb_hack") + onclose(user, "nukebomb_hack") + +/obj/machinery/nuclearbomb/verb/make_deployable() + set category = "Object" + set name = "Make Deployable" + set src in oview(1) + + if (!usr.canmove || usr.stat || usr.restrained()) + return + if (!ishuman(usr)) + usr << "\red You don't have the dexterity to do this!" + return 1 + + if (src.deployable) + usr << "\red You close several panels to make [src] undeployable." + src.deployable = 0 + else + usr << "\red You adjust some panels to make [src] deployable." + src.deployable = 1 + return + + +/obj/machinery/nuclearbomb/Topic(href, href_list) + ..() + if (!usr.canmove || usr.stat || usr.restrained()) + return + if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf)))) + usr.set_machine(src) + if(href_list["act"]) + var/temp_wire = href_list["wire"] + if(href_list["act"] == "pulse") + if (!istype(usr.get_active_hand(), /obj/item/device/multitool)) + usr << "You need a multitool!" + else + if(src.wires[temp_wire]) + usr << "You can't pulse a cut wire." + else + if(src.light_wire == temp_wire) + src.lighthack = !src.lighthack + spawn(100) src.lighthack = !src.lighthack + if(src.timing_wire == temp_wire) + if(src.timing) + explode() + if(src.safety_wire == temp_wire) + src.safety = !src.safety + spawn(100) src.safety = !src.safety + if(src.safety == 1) + visible_message("\blue The [src] quiets down.") + if(!src.lighthack) + if (src.icon_state == "nuclearbomb2") + src.icon_state = "nuclearbomb1" + else + visible_message("\blue The [src] emits a quiet whirling noise!") + if(href_list["act"] == "wire") + if (!istype(usr.get_active_hand(), /obj/item/weapon/wirecutters)) + usr << "You need wirecutters!" + else + wires[temp_wire] = !wires[temp_wire] + if(src.safety_wire == temp_wire) + if(src.timing) + explode() + if(src.timing_wire == temp_wire) + if(!src.lighthack) + if (src.icon_state == "nuclearbomb2") + src.icon_state = "nuclearbomb1" + src.timing = 0 + bomb_set = 0 + if(src.light_wire == temp_wire) + src.lighthack = !src.lighthack + + if (href_list["auth"]) + if (src.auth) + src.auth.loc = src.loc + src.yes_code = 0 + src.auth = null + else + var/obj/item/I = usr.get_active_hand() + if (istype(I, /obj/item/weapon/disk/nuclear)) + usr.drop_item() + I.loc = src + src.auth = I + if (src.auth) + if (href_list["type"]) + if (href_list["type"] == "E") + if (src.code == src.r_code) + src.yes_code = 1 + src.code = null + else + src.code = "ERROR" + else + if (href_list["type"] == "R") + src.yes_code = 0 + src.code = null + else + src.code += text("[]", href_list["type"]) + if (length(src.code) > 5) + src.code = "ERROR" + if (src.yes_code) + if (href_list["time"]) + var/time = text2num(href_list["time"]) + src.timeleft += time + src.timeleft = min(max(round(src.timeleft), 60), 600) + if (href_list["timer"]) + if (src.timing == -1.0) + return + if (src.safety) + usr << "\red The safety is still on." + return + src.timing = !( src.timing ) + if (src.timing) + if(!src.lighthack) + src.icon_state = "nuclearbomb2" + if(!src.safety) + bomb_set = 1//There can still be issues with this reseting when there are multiple bombs. Not a big deal tho for Nuke/N + else + bomb_set = 0 + else + bomb_set = 0 + if(!src.lighthack) + src.icon_state = "nuclearbomb1" + if (href_list["safety"]) + src.safety = !( src.safety ) + if(safety) + src.timing = 0 + bomb_set = 0 + if (href_list["anchor"]) + + if(removal_stage == 5) + src.anchored = 0 + visible_message("\red \The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.") + return + + src.anchored = !( src.anchored ) + if(src.anchored) + visible_message("\red With a steely snap, bolts slide out of [src] and anchor it to the flooring.") + else + visible_message("\red The anchoring bolts slide back into the depths of [src].") + + src.add_fingerprint(usr) + for(var/mob/M in viewers(1, src)) + if ((M.client && M.machine == src)) + src.attack_hand(M) + else + usr << browse(null, "window=nuclearbomb") + return + return + + +/obj/machinery/nuclearbomb/ex_act(severity) + return + +/obj/machinery/nuclearbomb/blob_act() + if (src.timing == -1.0) + return + else + return ..() + return + + +#define NUKERANGE 80 +/obj/machinery/nuclearbomb/proc/explode() + if (src.safety) + src.timing = 0 + return + src.timing = -1.0 + src.yes_code = 0 + src.safety = 1 + if(!src.lighthack) + src.icon_state = "nuclearbomb3" + playsound(src,'sound/machines/Alarm.ogg',100,0,5) + if (ticker && ticker.mode) + ticker.mode.explosion_in_progress = 1 + sleep(100) + + var/off_station = 0 + var/turf/bomb_location = get_turf(src) + if(bomb_location && (bomb_location.z in config.station_levels)) + if( (bomb_location.x < (128-NUKERANGE)) || (bomb_location.x > (128+NUKERANGE)) || (bomb_location.y < (128-NUKERANGE)) || (bomb_location.y > (128+NUKERANGE)) ) + off_station = 1 + else + off_station = 2 + + if(ticker) + if(ticker.mode && ticker.mode.name == "Mercenary") + var/obj/machinery/computer/shuttle_control/multi/syndicate/syndie_location = locate(/obj/machinery/computer/shuttle_control/multi/syndicate) + if(syndie_location) + ticker.mode:syndies_didnt_escape = (syndie_location.z > 1 ? 0 : 1) //muskets will make me change this, but it will do for now + ticker.mode:nuke_off_station = off_station + ticker.station_explosion_cinematic(off_station,null) + if(ticker.mode) + ticker.mode.explosion_in_progress = 0 + world << "The station was destoyed by the nuclear blast!" + + ticker.mode.station_was_nuked = (off_station<2) //offstation==1 is a draw. the station becomes irradiated and needs to be evacuated. + //kinda shit but I couldn't get permission to do what I wanted to do. + + if(!ticker.mode.check_finished())//If the mode does not deal with the nuke going off so just reboot because everyone is stuck as is + world << "Resetting in 30 seconds!" + + feedback_set_details("end_error","nuke - unhandled ending") + + if(blackbox) + blackbox.save_all_data_to_sql() + sleep(300) + log_game("Rebooting due to nuclear detonation") + world.Reboot() + return + return + +/obj/item/weapon/disk/nuclear/Del() + if(blobstart.len > 0) + var/obj/D = new /obj/item/weapon/disk/nuclear(pick(blobstart)) + message_admins("[src] has been destroyed. Spawning [D] at ([D.x], [D.y], [D.z]).") + log_game("[src] has been destroyed. Spawning [D] at ([D.x], [D.y], [D.z]).") + ..() diff --git a/code/game/machinery/syndicatebeacon.dm b/code/game/machinery/syndicatebeacon.dm index 722c96d583..957f7bf536 100644 --- a/code/game/machinery/syndicatebeacon.dm +++ b/code/game/machinery/syndicatebeacon.dm @@ -59,34 +59,9 @@ return if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/N = M - ticker.mode.equip_traitor(N) - ticker.mode.traitors += N.mind - N.mind.special_role = "traitor" - if(!config.objectives_disabled) - var/objective = "Free Objective" - switch(rand(1,100)) - if(1 to 50) - objective = "Steal [pick("a hand teleporter", "the Captain's antique laser gun", "a jetpack", "the Captain's ID", "the Captain's jumpsuit")]." - if(51 to 60) - objective = "Destroy 70% or more of the station's phoron tanks." - if(61 to 70) - objective = "Cut power to 80% or more of the station's tiles." - if(71 to 80) - objective = "Destroy the AI." - if(81 to 90) - objective = "Kill all monkeys aboard the station." - else - objective = "Make certain at least 80% of the station evacuates on the shuttle." - var/datum/objective/custom_objective = new(objective) - custom_objective.owner = N.mind - N.mind.objectives += custom_objective - - var/datum/objective/escape/escape_objective = new - escape_objective.owner = N.mind - N.mind.objectives += escape_objective - M << "You have joined the ranks of the Syndicate and become a traitor to the station!" - show_objectives(M.mind) + traitors.add_antagonist(N.mind) + traitors.equip(N) message_admins("[N]/([N.ckey]) has accepted a traitor objective from a syndicate beacon.") diff --git a/code/game/machinery/wishgranter.dm b/code/game/machinery/wishgranter.dm index 2720a1c318..71b7de64c0 100644 --- a/code/game/machinery/wishgranter.dm +++ b/code/game/machinery/wishgranter.dm @@ -58,8 +58,6 @@ user.mutations.Add(HEAL) user.update_mutations() - - ticker.mode.traitors += user.mind user.mind.special_role = "Avatar of the Wish Granter" var/datum/objective/silence/silence = new diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 8df98464e6..28a4ad2cc2 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -27,14 +27,11 @@ if("monkey") monkeystart += loc del(src) + if("start") newplayer_start += loc del(src) - if("wizard") - wizardstart += loc - del(src) - if("JoinLate") latejoin += loc del(src) @@ -51,23 +48,25 @@ latejoin_cyborg += loc del(src) - //prisoners if("prisonwarp") prisonwarp += loc del(src) - // if("mazewarp") - // mazewarp += loc + if("Holding Facility") holdingfacility += loc + if("tdome1") - tdome1 += loc + tdome1 += loc + if("tdome2") tdome2 += loc + if("tdomeadmin") - tdomeadmin += loc + tdomeadmin += loc + if("tdomeobserve") tdomeobserve += loc - //not prisoners + if("prisonsecuritywarp") prisonsecuritywarp += loc del(src) @@ -80,18 +79,6 @@ xeno_spawn += loc del(src) - if("ninjastart") - ninjastart += loc - del(src) - - if("voxstart") - raider_spawn += loc - del(src) - - if("Syndicate-Spawn") - synd_spawn += loc - del(src) - landmarks_list += src return 1 diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index 644278ab28..7013b30419 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -70,7 +70,7 @@ flick("e_flash", M.flash) if(ishuman(M) && ishuman(user) && M.stat!=DEAD) - if(user.mind && user.mind in ticker.mode.head_revolutionaries && ticker.mode.name == "revolution") + if(user.mind && user.mind in revs.head_revolutionaries) var/revsafe = 0 for(var/obj/item/weapon/implant/loyalty/L in M) if(L && L.implanted) @@ -81,7 +81,7 @@ revsafe = 2 if(!revsafe) M.mind.has_been_rev = 1 - ticker.mode.add_revolutionary(M.mind) + revs.add_antagonist(M.mind) else if(revsafe == 1) user << "Something seems to be blocking the flash!" else diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index a0138b4dc6..cfd50c37d5 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -189,7 +189,7 @@ user << "\red Sticking a dead [W] into the frame would sort of defeat the purpose." return - if(M.brainmob.mind in ticker.mode.head_revolutionaries) + if(M.brainmob.mind in revs.head_revolutionaries) user << "\red The frame's firmware lets out a shrill sound, and flashes 'Abnormal Memory Engram'. It refuses to accept the [W]." return diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index c45ed4eac8..c7c7e762ab 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -336,12 +336,13 @@ the implant may become unstable and either pre-maturely inject the subject or si implanted(mob/M) if(!istype(M, /mob/living/carbon/human)) return 0 var/mob/living/carbon/human/H = M - if(H.mind in ticker.mode.head_revolutionaries) + var/datum/antagonist/antag_data = get_antag_data(H.mind.special_role) + if(antag_data && (antag_data.flags & ANTAG_IMPLANT_IMMUNE)) H.visible_message("[H] seems to resist the implant!", "You feel the corporate tendrils of Nanotrasen try to invade your mind!") return 0 - else if(H.mind in ticker.mode:revolutionaries) - ticker.mode:remove_revolutionary(H.mind) - H << "\blue You feel a surge of loyalty towards Nanotrasen." + else + clear_antag_roles(H.mind, 1) + H << "You feel a surge of loyalty towards Nanotrasen." return 1 diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index 02f6642037..295fa0c67d 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -11,7 +11,7 @@ attack_verb = list("banned") suicide_act(mob/user) - viewers(user) << "\red [user] is hitting \himself with the [src.name]! It looks like \he's trying to ban \himself from life." + viewers(user) << "[user] is hitting \himself with the [src.name]! It looks like \he's trying to ban \himself from life." return (BRUTELOSS|FIRELOSS|TOXLOSS|OXYLOSS) /obj/item/weapon/nullrod @@ -27,7 +27,7 @@ w_class = 2 suicide_act(mob/user) - viewers(user) << "\red [user] is impaling \himself with the [src.name]! It looks like \he's trying to commit suicide." + viewers(user) << "[user] is impaling \himself with the [src.name]! It looks like \he's trying to commit suicide." return (BRUTELOSS|FIRELOSS) /obj/item/weapon/nullrod/attack(mob/M as mob, mob/living/user as mob) //Paste from old-code to decult with a null rod. @@ -38,36 +38,34 @@ msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") - user << "\red You don't have the dexterity to do this!" + user << "You don't have the dexterity to do this!" return if ((CLUMSY in user.mutations) && prob(50)) - user << "\red The rod slips out of your hand and hits your head." + user << "The rod slips out of your hand and hits your head." user.take_organ_damage(10) user.Paralyse(20) return if (M.stat !=2) - if((M.mind in ticker.mode.cult) && prob(33)) - M << "\red The power of [src] clears your mind of the cult's influence!" - user << "\red You wave [src] over [M]'s head and see their eyes become clear, their mind returning to normal." - ticker.mode.remove_cultist(M.mind) - for(var/mob/O in viewers(M, null)) - O.show_message(text("\red [] waves [] over []'s head.", user, src, M), 1) + if(cult && (M.mind in cult.current_antagonists) && prob(33)) + M << "The power of [src] clears your mind of the cult's influence!" + user << "You wave [src] over [M]'s head and see their eyes become clear, their mind returning to normal." + cult.remove_antagonist(M.mind) + M.visible_message("\The [user] waves \the [src] over \the [M]'s head.") else if(prob(10)) - user << "\red The rod slips in your hand." + user << "The rod slips in your hand." ..() else - user << "\red The rod appears to do nothing." - for(var/mob/O in viewers(M, null)) - O.show_message(text("\red [] waves [] over []'s head.", user, src, M), 1) + user << "The rod appears to do nothing." + M.visible_message("\The [user] waves \the [src] over \the [M]'s head.") return /obj/item/weapon/nullrod/afterattack(atom/A, mob/user as mob, proximity) if(!proximity) return if (istype(A, /turf/simulated/floor)) - user << "\blue You hit the floor with the [src]." + user << "You hit the floor with the [src]." call(/obj/effect/rune/proc/revealrunes)(src) /obj/item/weapon/sord @@ -84,7 +82,7 @@ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") suicide_act(mob/user) - viewers(user) << "\red [user] is impaling \himself with the [src.name]! It looks like \he's trying to commit suicide." + viewers(user) << "[user] is impaling \himself with the [src.name]! It looks like \he's trying to commit suicide." return(BRUTELOSS) /obj/item/weapon/sord/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) @@ -109,7 +107,7 @@ return 1 suicide_act(mob/user) - viewers(user) << "\red [user] is falling on the [src.name]! It looks like \he's trying to commit suicide." + viewers(user) << "[user] is falling on the [src.name]! It looks like \he's trying to commit suicide." return(BRUTELOSS) /obj/item/weapon/claymore/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) @@ -131,7 +129,7 @@ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") suicide_act(mob/user) - viewers(user) << "\red [user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku." + viewers(user) << "[user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku." return(BRUTELOSS) /obj/item/weapon/katana/IsShield() diff --git a/code/game/response_team.dm b/code/game/response_team.dm index a9dd598374..ea1a03a571 100644 --- a/code/game/response_team.dm +++ b/code/game/response_team.dm @@ -1,7 +1,6 @@ //STRIKE TEAMS //Thanks to Kilakk for the admin-button portion of this code. -var/list/response_team_members = list() var/global/send_emergency_team = 0 // Used for automagic response teams // 'admin_emergency_team' for admin-spawned response teams var/ert_base_chance = 10 // Default base chance. Will be incremented by increment ERT chance. @@ -46,15 +45,11 @@ client/verb/JoinResponseTeam() if(!send_emergency_team) usr << "No emergency response team is currently being sent." return - /* if(admin_emergency_team) - usr << "An emergency response team has already been sent." - return */ if(jobban_isbanned(usr, "Syndicate") || jobban_isbanned(usr, "Emergency Response Team") || jobban_isbanned(usr, "Security Officer")) usr << "You are jobbanned from the emergency reponse team!" return - if(response_team_members.len > 5) usr << "The emergency response team is already full!" - + if(ert.current_antagonists.len > 5) usr << "The emergency response team is already full!" for (var/obj/effect/landmark/L in landmarks_list) if (L.name == "Commando") L.name = null//Reserving the place. @@ -62,24 +57,8 @@ client/verb/JoinResponseTeam() if(!new_name)//Somebody changed his mind, place is available again. L.name = "Commando" return - var/leader_selected = isemptylist(response_team_members) - var/mob/living/carbon/human/new_commando = create_response_team(L.loc, leader_selected, new_name) + create_response_team(L.loc, new_name) del(L) - //Creates mind stuff. - new_commando.mind.key = usr.key - new_commando.key = usr.key - - new_commando << "\blue You are [!leader_selected?"a member":"the LEADER"] of an Emergency Response Team, a type of military division, under CentComm's service. There is a code red alert on [station_name()], you are tasked to go and fix the problem." - new_commando << "You should first gear up and discuss a plan with your team. More members may be joining, don't move out before you're ready." - if(!leader_selected) - new_commando << "As member of the Emergency Response Team, you answer only to your leader and CentComm officials." - else - new_commando << "As leader of the Emergency Response Team, you answer only to CentComm, and have authority to override the Captain where it is necessary to achieve your mission goals. It is recommended that you attempt to cooperate with the captain where possible, however." - - // By setting an explicit location the mob cannot wander off and decide change appearance elsewhere - new_commando.change_appearance(APPEARANCE_ALL, new_commando.loc, new_commando, species_whitelist = config.ert_species) - - return else usr << "You need to be an observer or new player to use this." @@ -150,31 +129,14 @@ proc/trigger_armed_response_team(var/force = 0) sleep(600 * 5) send_emergency_team = 0 // Can no longer join the ERT. -/* var/area/security/nuke_storage/nukeloc = locate()//To find the nuke in the vault - var/obj/machinery/nuclearbomb/nuke = locate() in nukeloc - if(!nuke) - nuke = locate() in world - var/obj/item/weapon/paper/P = new - P.info = "Your orders, Commander, are to use all means necessary to return the station to a survivable condition.
    To this end, you have been provided with the best tools we can give in the three areas of Medicine, Engineering, and Security. The nuclear authorization code is: [ nuke ? nuke.r_code : "AHH, THE NUKE IS GONE!"]. Be warned, if you detonate this without good reason, we will hold you to account for damages. Memorise this code, and then burn this message." - P.name = "Emergency Nuclear Code, and ERT Orders" - for (var/obj/effect/landmark/A in world) - if (A.name == "nukecode") - P.loc = A.loc - del(A) - continue -*/ - -/client/proc/create_response_team(obj/spawn_location, leader_selected = 0, commando_name) - - //usr << "\red ERT has been temporarily disabled. Talk to a coder." - //return +/client/proc/create_response_team(obj/spawn_location, commando_name) var/mob/living/carbon/human/M = new(null) - response_team_members |= M + M.real_name = commando_name M.name = commando_name - M.age = !leader_selected ? rand(23,35) : rand(35,45) + M.age = rand(25,45) M.check_dna(M) M.dna.ready_dna(M)//Creates DNA. @@ -182,64 +144,9 @@ proc/trigger_armed_response_team(var/force = 0) M.mind = new M.mind.current = M M.mind.original = M - M.mind.assigned_role = "MODE" - M.mind.special_role = "Response Team" if(!(M.mind in ticker.minds)) ticker.minds += M.mind//Adds them to regular mind list. M.loc = spawn_location - M.equip_strike_team(leader_selected) + ert.add_antagonist(M.mind) return M - -/mob/living/carbon/human/proc/equip_strike_team(leader_selected = 0) - - //Special radio setup - equip_to_slot_or_del(new /obj/item/device/radio/headset/ert(src), slot_l_ear) - - //Replaced with new ERT uniform - equip_to_slot_or_del(new /obj/item/clothing/under/ert(src), slot_w_uniform) - equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(src), slot_shoes) - equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(src), slot_gloves) - equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(src), slot_glasses) -/* - - //Old ERT Uniform - //Basic Uniform - equip_to_slot_or_del(new /obj/item/clothing/under/syndicate/tacticool(src), slot_w_uniform) - equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_l_store) - equip_to_slot_or_del(new /obj/item/weapon/clipboard(src), slot_r_store) - equip_to_slot_or_del(new /obj/item/weapon/gun/energy/gun(src), slot_belt) - equip_to_slot_or_del(new /obj/item/clothing/mask/gas/swat(src), slot_wear_mask) - - //Glasses - equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(src), slot_glasses) - - //Shoes & gloves - equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(src), slot_shoes) - equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(src), slot_gloves) - - //Removed -// equip_to_slot_or_del(new /obj/item/clothing/suit/armor/swat(src), slot_wear_suit) -// equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/deathsquad(src), slot_head) - - //Backpack - equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(src), slot_back) - equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(src), slot_in_backpack) -*/ - var/obj/item/weapon/card/id/W = new(src) - W.assignment = "Emergency Response Team[leader_selected ? " Leader" : ""]" - W.registered_name = real_name - W.name = "[real_name]'s ID Card ([W.assignment])" - W.icon_state = "centcom" - W.access = get_all_accesses() - W.access += get_all_centcom_access() - equip_to_slot_or_del(W, slot_wear_id) - - return 1 - -//debug verb (That is horribly coded, LEAVE THIS OFF UNLESS PRIVATELY TESTING. Seriously. -/*client/verb/ResponseTeam() - set category = "Admin" - if(!send_emergency_team) - send_emergency_team = 1*/ diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index 93370df502..884c5c5dbe 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -66,9 +66,6 @@ var/list/accessible_z_levels = list("1" = 5, "3" = 10, "4" = 15, "5" = 10, "6" = if(ticker && ticker.mode) - - // Okay, so let's make it so that people can travel z levels but not nuke disks! - // if(ticker.mode.name == "mercenary") return if(A.z > 6 && !config.use_overmap) return if (A.x <= TRANSITIONEDGE || A.x >= (world.maxx - TRANSITIONEDGE - 1) || A.y <= TRANSITIONEDGE || A.y >= (world.maxy - TRANSITIONEDGE - 1)) if(istype(A, /obj/effect/meteor)||istype(A, /obj/effect/space_dust)) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index c51ffbff82..bbee0157d6 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -937,42 +937,19 @@ var/global/floorIsLava = 0 return 0 if (!istype(M)) return 0 - if((M.mind in ticker.mode.head_revolutionaries) || (M.mind in ticker.mode.revolutionaries)) - if (ticker.mode.config_tag == "revolution") - return 2 - return 1 - if(M.mind in ticker.mode.cult) - if (ticker.mode.config_tag == "cult") - return 2 - return 1 - if(M.mind in ticker.mode.malf_ai) - if (ticker.mode.config_tag == "malfunction") - return 2 - return 1 - if(M.mind in ticker.mode.syndicates) - if (ticker.mode.config_tag == "mercenary") - return 2 - return 1 - if(M.mind in ticker.mode.wizards) - if (ticker.mode.config_tag == "wizard") - return 2 - return 1 - if(M.mind in ticker.mode.changelings) - if (ticker.mode.config_tag == "changeling") - return 2 - return 1 - for(var/datum/disease/D in M.viruses) - if(istype(D, /datum/disease/jungle_fever)) - if (ticker.mode.config_tag == "monkey") - return 2 + if(M.mind) + if(ticker.mode.antag_templates && ticker.mode.antag_templates.len) + for(var/datum/antagonist/antag in ticker.mode.antag_templates) + if(antag.is_antagonist(M.mind)) + return 2 + else if(M.mind.special_role) return 1 + if(isrobot(M)) var/mob/living/silicon/robot/R = M if(R.emagged) return 1 - if(M.mind&&M.mind.special_role)//If they have a mind and special role, they are some type of traitor or antagonist. - return 1 return 0 @@ -1070,11 +1047,87 @@ var/global/floorIsLava = 0 M.mind.edit_memory() feedback_add_details("admin_verb","STP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/datum/admins/proc/show_game_mode() + set category = "Admin" + set desc = "Show the current round configuration." + set name = "Show Game Mode" + + if(!ticker || !ticker.mode) + alert("Not before roundstart!", "Alert") + return + + var/out = "Current mode: [ticker.mode.name] ([ticker.mode.config_tag])
    " + out += "
    " + + if(ticker.mode.ert_disabled) + out += "Emergency Response Teams: disabled" + else + out += "Emergency Response Teams: enabled" + out += "
    " + + if(ticker.mode.deny_respawn) + out += "Respawning: disallowed" + else + out += "Respawning: allowed" + out += "
    " + + out += "Shuttle delay multiplier: [ticker.mode.shuttle_delay]
    " + + if(ticker.mode.auto_recall_shuttle) + out += "Shuttle auto-recall: enabled" + else + out += "Shuttle auto-recall: disabled" + out += "

    " + + if(ticker.mode.event_delay_mod_moderate) + out += "Moderate event time modifier: [ticker.mode.event_delay_mod_moderate]
    " + else + out += "Moderate event time modifier: unset
    " + + if(ticker.mode.event_delay_mod_major) + out += "Major event time modifier: [ticker.mode.event_delay_mod_major]
    " + else + out += "Major event time modifier: unset
    " + + out += "
    " + + if(ticker.mode.antag_tag) + out += "Core antag id: [ticker.mode.antag_tag].
    " + + if(ticker.mode.round_autoantag) + out += "Autotraitor enabled ([ticker.mode.antag_prob]% spawn chance)" + if(ticker.mode.antag_scaling_coeff) + out += " (scaling with [ticker.mode.antag_scaling_coeff])" + out += "
    " + else + out += "Autotraitor disabled.
    " + + out += "All antag ids:" + if(ticker.mode.antag_templates && ticker.mode.antag_templates.len). + var/playercount = ticker.mode.num_players() + for(var/datum/antagonist/antag in ticker.mode.antag_templates) + var/cur_max_antags + if(ticker.mode.antag_tag && antag.id == ticker.mode.antag_tag) + cur_max_antags = antag.max_antags_round + else + cur_max_antags = antag.max_antags + if(ticker.mode.antag_scaling_coeff) + cur_max_antags = Clamp((playercount/ticker.mode.antag_scaling_coeff), 1, cur_max_antags) + out += " [antag.id]" + out += " ([antag.get_antag_count()]/[cur_max_antags]) " + out += " \[-\]
    " + else + out += " None." + out += " \[+\]
    " + + usr << browse(out, "window=edit_mode[src]") + feedback_add_details("admin_verb","SGM") + /datum/admins/proc/toggletintedweldhelmets() set category = "Debug" set desc="Reduces view range when wearing welding helmets" - set name="Toggle tinted welding helmes" + set name="Toggle tinted welding helmets." config.welder_vision = !( config.welder_vision ) if (config.welder_vision) world << "Reduced welder vision has been enabled!" diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index d570083a01..5fb0d5f231 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -15,6 +15,7 @@ var/list/admin_verbs_admin = list( /client/proc/player_panel_new, /*shows an interface for all players, with links to various panels*/ /client/proc/invisimin, /*allows our mob to go invisible/visible*/ // /datum/admins/proc/show_traitor_panel, /*interface which shows a mob's mind*/ -Removed due to rare practical use. Moved to debug verbs ~Errorage + /datum/admins/proc/show_game_mode, /*Configuration window for the current game mode.*/ /datum/admins/proc/toggleenter, /*toggles whether people can join the current game*/ /datum/admins/proc/toggleguests, /*toggles whether guests can join the current game*/ /datum/admins/proc/announce, /*priority announce something to all clients.*/ @@ -101,10 +102,8 @@ var/list/admin_verbs_fun = list( /client/proc/drop_bomb, /client/proc/everyone_random, /client/proc/cinematic, - /client/proc/one_click_antag, /datum/admins/proc/toggle_aliens, /datum/admins/proc/toggle_space_ninja, - /client/proc/send_space_ninja, /client/proc/cmd_admin_add_freeform_ai_law, /client/proc/cmd_admin_add_random_ai_law, /client/proc/make_sound, @@ -152,6 +151,7 @@ var/list/admin_verbs_debug = list( /client/proc/cmd_debug_make_powernets, /client/proc/kill_airgroup, /client/proc/debug_controller, + /client/proc/debug_antagonist_template, /client/proc/cmd_debug_mob_lists, /client/proc/cmd_admin_delete, /client/proc/cmd_debug_del_all, @@ -219,7 +219,6 @@ var/list/admin_verbs_hideable = list( /client/proc/cinematic, /datum/admins/proc/toggle_aliens, /datum/admins/proc/toggle_space_ninja, - /client/proc/send_space_ninja, /client/proc/cmd_admin_add_freeform_ai_law, /client/proc/cmd_admin_add_random_ai_law, /client/proc/cmd_admin_create_centcom_report, @@ -566,22 +565,6 @@ var/list/admin_verbs_mentor = list( message_admins("\blue [ckey] creating an admin explosion at [epicenter.loc].") feedback_add_details("admin_verb","DB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/client/proc/give_spell(mob/T as mob in mob_list) // -- Urist - set category = "Fun" - set name = "Give Spell" - set desc = "Gives a spell to a mob." - var/list/spell_names = list() - for(var/v in spells) - // "/obj/effect/proc_holder/spell/" 30 symbols ~Intercross21 - spell_names.Add(copytext("[v]", 31, 0)) - var/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in spell_names - if(!S) return - var/path = text2path("/obj/effect/proc_holder/spell/[S]") - T.spell_list += new path - feedback_add_details("admin_verb","GS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - log_admin("[key_name(usr)] gave [key_name(T)] the spell [S].") - message_admins("\blue [key_name_admin(usr)] gave [key_name(T)] the spell [S].", 1) - /client/proc/give_disease(mob/T as mob in mob_list) // -- Giacom set category = "Fun" set name = "Give Disease (old)" diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index 5de314db4c..234f702a17 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -410,80 +410,8 @@ dat += "Launching now..." dat += "[ticker.delay_end ? "End Round Normally" : "Delay Round End"]
    " - if(ticker.mode.syndicates.len) - dat += "
    " - for(var/datum/mind/N in ticker.mode.syndicates) - var/mob/M = N.current - if(M) - dat += "" - dat += "" - else - dat += "" - dat += "
    Mercenaries
    [M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PM
    Mercenary not found!

    " - for(var/obj/item/weapon/disk/nuclear/N in world) - dat += "" - dat += "
    Nuclear Disk(s)
    [N.name], " - var/atom/disk_loc = N.loc - while(!istype(disk_loc, /turf)) - if(istype(disk_loc, /mob)) - var/mob/M = disk_loc - dat += "carried by [M.real_name] " - if(istype(disk_loc, /obj)) - var/obj/O = disk_loc - dat += "in \a [O.name] " - disk_loc = disk_loc.loc - dat += "in [disk_loc.loc] at ([disk_loc.x], [disk_loc.y], [disk_loc.z])
    " - if(ticker.mode.head_revolutionaries.len || ticker.mode.revolutionaries.len) - dat += "
    " - for(var/datum/mind/N in ticker.mode.head_revolutionaries) - var/mob/M = N.current - if(!M) - dat += "" - else - dat += "" - dat += "" - for(var/datum/mind/N in ticker.mode.revolutionaries) - var/mob/M = N.current - if(M) - dat += "" - dat += "" - dat += "
    Revolutionaries
    Head Revolutionary not found!
    [M.real_name] (Leader)[M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PM
    [M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PM
    " - for(var/datum/mind/N in ticker.mode.get_living_heads()) - var/mob/M = N.current - if(M) - dat += "" - dat += "" - var/turf/mob_loc = get_turf(M) - dat += "" - else - dat += "" - dat += "
    Target(s)Location
    [M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PM[mob_loc.loc]
    Head not found!
    " - - if(ticker.mode.changelings.len) - dat += check_role_table("Changelings", ticker.mode.changelings, src) - - if(ticker.mode.wizards.len) - dat += check_role_table("Wizards", ticker.mode.wizards, src) - - if(ticker.mode.raiders.len) - dat += check_role_table("Raiders", ticker.mode.raiders, src) - - if(ticker.mode.ninjas.len) - dat += check_role_table("Ninjas", ticker.mode.ninjas, src) - - if(ticker.mode.cult.len) - dat += check_role_table("Cultists", ticker.mode.cult, src, 0) - - if(ticker.mode.traitors.len) - dat += check_role_table("Traitors", ticker.mode.traitors, src) - - if(ticker.mode.borers.len) - dat += check_role_table("Cortical Borers", ticker.mode.borers, src) - - var/datum/game_mode/mutiny/mutiny = get_mutiny_mode() - if(mutiny) - dat += mutiny.check_antagonists_ui(src) + //todo dat += "" usr << browse(dat, "window=roundstatus;size=400x500") diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 1f98e4ee3a..b40d441ef2 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -10,49 +10,8 @@ check_antagonists() return - if(href_list["makeAntag"]) - switch(href_list["makeAntag"]) - if("1") - log_admin("[key_name(usr)] has spawned a traitor.") - if(!src.makeTraitors()) - usr << "\red Unfortunately there weren't enough candidates available." - if("2") - log_admin("[key_name(usr)] has spawned a changeling.") - if(!src.makeChanglings()) - usr << "\red Unfortunately there weren't enough candidates available." - if("3") - log_admin("[key_name(usr)] has spawned revolutionaries.") - if(!src.makeRevs()) - usr << "\red Unfortunately there weren't enough candidates available." - if("4") - log_admin("[key_name(usr)] has spawned a cultists.") - if(!src.makeCult()) - usr << "\red Unfortunately there weren't enough candidates available." - if("5") - log_admin("[key_name(usr)] has spawned a malf AI.") - if(!src.makeMalfAImode()) - usr << "\red Unfortunately there weren't enough candidates available." - if("6") - log_admin("[key_name(usr)] has spawned a wizard.") - if(!src.makeWizard()) - usr << "\red Unfortunately there weren't enough candidates available." - if("7") - log_admin("[key_name(usr)] has spawned a nuke team.") - if(!src.makeNukeTeam()) - usr << "\red Unfortunately there weren't enough candidates available." - if("8") - log_admin("[key_name(usr)] has spawned a ninja.") - src.makeSpaceNinja() - if("9") - log_admin("[key_name(usr)] has spawned aliens.") - src.makeAliens() - if("10") - log_admin("[key_name(usr)] has spawned a death squad.") - if("11") - log_admin("[key_name(usr)] has spawned vox raiders.") - if(!src.makeVoxRaiders()) - usr << "\red Unfortunately there weren't enough candidates available." - else if(href_list["dbsearchckey"] || href_list["dbsearchadmin"] || href_list["dbsearchip"] || href_list["dbsearchcid"] || href_list["dbsearchbantype"]) + if(href_list["dbsearchckey"] || href_list["dbsearchadmin"]) + var/adminckey = href_list["dbsearchadmin"] var/playerckey = href_list["dbsearchckey"] var/playerip = href_list["dbsearchip"] @@ -586,69 +545,15 @@ jobs += "" jobs += "" - //Traitor - if(jobban_isbanned(M, "traitor") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Changeling - if(jobban_isbanned(M, "changeling") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Nuke Operative - if(jobban_isbanned(M, "operative") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Revolutionary - if(jobban_isbanned(M, "revolutionary") || isbanned_dept) - jobs += "" - else - jobs += "" - - jobs += "" //Breaking it up so it fits nicer on the screen every 5 entries - - //Cultist - if(jobban_isbanned(M, "cultist") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Wizard - if(jobban_isbanned(M, "wizard") || isbanned_dept) - jobs += "" - else - jobs += "" - - //ERT - if(jobban_isbanned(M, "Emergency Response Team") || isbanned_dept) - jobs += "" - else - jobs += "" - - -/* //Malfunctioning AI //Removed Malf-bans because they're a pain to impliment - if(jobban_isbanned(M, "malf AI") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Alien - if(jobban_isbanned(M, "alien candidate") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Infested Monkey - if(jobban_isbanned(M, "infested monkey") || isbanned_dept) - jobs += "" - else - jobs += "" -*/ + // Antagonists. + for(var/antag_type in all_antag_types) + var/datum/antagonist/antag = all_antag_types[antag_type] + if(!antag || !antag.bantype) + continue + if(jobban_isbanned(M, "[antag.bantype]") || isbanned_dept) + jobs += "" + else + jobs += "" jobs += "
    Antagonist Positions
    [replacetext("Traitor", " ", " ")][replacetext("Traitor", " ", " ")][replacetext("Changeling", " ", " ")][replacetext("Changeling", " ", " ")][replacetext("Mercenary", " ", " ")][replacetext("Mercenary", " ", " ")][replacetext("Revolutionary", " ", " ")][replacetext("Revolutionary", " ", " ")]
    [replacetext("Cultist", " ", " ")][replacetext("Cultist", " ", " ")][replacetext("Wizard", " ", " ")][replacetext("Wizard", " ", " ")]Emergency Response TeamEmergency Response Team[replacetext("Malf AI", " ", " ")][replacetext("Malf AI", " ", " ")][replacetext("Alien", " ", " ")][replacetext("Alien", " ", " ")][replacetext("Infested Monkey", " ", " ")][replacetext("Infested Monkey", " ", " ")][replacetext("[antag.role_text]", " ", " ")][replacetext("[antag.role_text]", " ", " ")]
    " @@ -660,16 +565,7 @@ jobs += "Dionaea" else jobs += "Dionaea" - - if(jobban_isbanned(M, "Borer")) - jobs += "Borer" - else - jobs += "Borer" - - jobs += "" - - body = "[jobs]" dat = "[header][body]" usr << browse(dat, "window=jobban2;size=800x490") @@ -1900,13 +1796,13 @@ feedback_add_details("admin_secrets_fun_used","Aliens") log_admin("[key_name(usr)] spawned an alien infestation", 1) message_admins("\blue [key_name_admin(usr)] attempted an alien infestation", 1) - new /datum/event/alien_infestation + xenomorphs.random_spawn() if("borers") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","Borers") log_admin("[key_name(usr)] spawned a cortical borer infestation.", 1) message_admins("\blue [key_name_admin(usr)] spawned a cortical borer infestation.", 1) - new /datum/event/borer_infestation + borers.random_spawn() if("power") feedback_inc("admin_secrets_fun_used",1) @@ -1994,40 +1890,6 @@ //teleport security person H.loc = pick(prisonsecuritywarp) prisonwarped += H - if("traitor_all") - if(!ticker) - alert("The game hasn't started yet!") - return - var/objective = sanitize(copytext(input("Enter an objective"),1,MAX_MESSAGE_LEN)) - if(!objective) - return - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","TA([objective])") - for(var/mob/living/carbon/human/H in player_list) - if(H.stat == 2 || !H.client || !H.mind) continue - if(is_special_character(H)) continue - //traitorize(H, objective, 0) - ticker.mode.traitors += H.mind - H.mind.special_role = "traitor" - var/datum/objective/new_objective = new - new_objective.owner = H - new_objective.explanation_text = objective - H.mind.objectives += new_objective - ticker.mode.greet_traitor(H.mind) - //ticker.mode.forge_traitor_objectives(H.mind) - ticker.mode.finalize_traitor(H.mind) - for(var/mob/living/silicon/A in player_list) - ticker.mode.traitors += A.mind - A.mind.special_role = "traitor" - var/datum/objective/new_objective = new - new_objective.owner = A - new_objective.explanation_text = objective - A.mind.objectives += new_objective - ticker.mode.greet_traitor(A.mind) - ticker.mode.finalize_traitor(A.mind) - message_admins("\blue [key_name_admin(usr)] used everyone is a traitor secret. Objective is [objective]", 1) - log_admin("[key_name(usr)] used everyone is a traitor secret. Objective is [objective]") - if("launchshuttle") if(!shuttle_controller) return // Something is very wrong, the shuttle controller has not been created. @@ -2252,8 +2114,7 @@ if("aliens") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","AL") - if(config.aliens_allowed) - new /datum/event/alien_infestation + if(xenomorphs.random_spawn()) message_admins("[key_name_admin(usr)] has spawned aliens", 1) if("spiders") feedback_inc("admin_secrets_fun_used",1) @@ -2269,12 +2130,6 @@ else communications_blackout(1) message_admins("[key_name_admin(usr)] triggered a communications blackout.", 1) - if("spaceninja") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","SN") - if(config.ninjas_allowed) - if(space_ninja_arrival())//If the ninja is actually spawned. They may not be depending on a few factors. - message_admins("[key_name_admin(usr)] has sent in a space ninja", 1) if("carp") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","C") @@ -2453,7 +2308,7 @@ if("onlyone") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","OO") - usr.client.only_one() + only_one() message_admins("[key_name_admin(usr)] has triggered a battle to the death (only one)") if(usr) log_admin("[key_name(usr)] used secret [href_list["secretsfun"]]") diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 487c442b86..4e4ed552d2 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -729,10 +729,10 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_to_slot_or_del(W, slot_wear_id) if("death commando")//Was looking to add this for a while. - M.equip_death_commando() + deathsquad.equip(M) if("syndicate commando") - M.equip_syndicate_commando() + commandos.equip(M) if("nanotrasen representative") M.equip_if_possible(new /obj/item/clothing/under/rank/centcom(M), slot_w_uniform) diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm deleted file mode 100644 index 2513857f5f..0000000000 --- a/code/modules/admin/verbs/one_click_antag.dm +++ /dev/null @@ -1,528 +0,0 @@ -client/proc/one_click_antag() - set name = "Create Antagonist" - set desc = "Auto-create an antagonist of your choice" - set category = "Admin" - - if(holder) - holder.one_click_antag() - return - - -/datum/admins/proc/one_click_antag() - - var/dat = {"One-click Antagonist
    - Make Traitors
    - Make Changlings
    - Make Revs
    - Make Cult
    - Make Malf AI
    - Make Wizard (Requires Ghosts)
    - Make Vox Raiders (Requires Ghosts)
    - "} -/* These dont work just yet - Ninja, aliens and deathsquad I have not looked into yet - Nuke team is getting a null mob returned from makebody() (runtime error: null.mind. Line 272) - - Make Nuke Team (Requires Ghosts)
    - Make Space Ninja (Requires Ghosts)
    - Make Aliens (Requires Ghosts)
    - Make Deathsquad (Syndicate) (Requires Ghosts)
    - "} -*/ - usr << browse(dat, "window=oneclickantag;size=400x400") - return - - -/datum/admins/proc/makeMalfAImode() - - var/list/mob/living/silicon/AIs = list() - var/mob/living/silicon/malfAI = null - var/datum/mind/themind = null - - for(var/mob/living/silicon/ai/ai in player_list) - if(ai.client) - AIs += ai - - if(AIs.len) - malfAI = pick(AIs) - - if(malfAI) - themind = malfAI.mind - themind.make_AI_Malf() - return 1 - - return 0 - - -/datum/admins/proc/makeTraitors() - var/datum/game_mode/traitor/temp = new - - if(config.protect_roles_from_antagonist) - temp.restricted_jobs += temp.protected_jobs - - var/list/mob/living/carbon/human/candidates = list() - var/mob/living/carbon/human/H = null - - for(var/mob/living/carbon/human/applicant in player_list) - if(applicant.client.prefs.be_special & BE_TRAITOR) - if(!applicant.stat) - if(applicant.mind) - if (!applicant.mind.special_role) - if(!jobban_isbanned(applicant, "traitor") && !jobban_isbanned(applicant, "Syndicate")) - if(!(applicant.job in temp.restricted_jobs)) - candidates += applicant - - if(candidates.len) - var/numTraitors = min(candidates.len, 3) - - for(var/i = 0, i300)//If more than 30 game seconds passed. - return - candidates += G - if("No") - return - else - return - - sleep(300) - - if(candidates.len) - shuffle(candidates) - for(var/mob/i in candidates) - if(!i || !i.client) continue //Dont bother removing them from the list since we only grab one wizard - - theghost = i - break - - if(theghost) - var/mob/living/carbon/human/new_character=makeBody(theghost) - new_character.mind.make_Wizard() - return 1 - - return 0 - - -/datum/admins/proc/makeCult() - - var/datum/game_mode/cult/temp = new - if(config.protect_roles_from_antagonist) - temp.restricted_jobs += temp.protected_jobs - - var/list/mob/living/carbon/human/candidates = list() - var/mob/living/carbon/human/H = null - - for(var/mob/living/carbon/human/applicant in player_list) - if(applicant.client.prefs.be_special & BE_CULTIST) - if(applicant.stat == CONSCIOUS) - if(applicant.mind) - if(!applicant.mind.special_role) - if(!jobban_isbanned(applicant, "cultist") && !jobban_isbanned(applicant, "Syndicate")) - if(!(applicant.job in temp.restricted_jobs)) - candidates += applicant - - if(candidates.len) - var/numCultists = min(candidates.len, 4) - - for(var/i = 0, i300)//If more than 30 game seconds passed. - return - candidates += G - if("No") - return - else - return - - sleep(300) - - if(candidates.len) - var/numagents = 5 - var/agentcount = 0 - - for(var/i = 0, i300)//If more than 30 game seconds passed. - return - candidates += G - if("No") - return - else - return - sleep(300) - - for(var/mob/dead/observer/G in candidates) - if(!G.key) - candidates.Remove(G) - - if(candidates.len) - var/numagents = 6 - //Spawns commandos and equips them. - for (var/obj/effect/landmark/L in /area/syndicate_mothership/elite_squad) - if(numagents<=0) - break - if (L.name == "Syndicate-Commando") - syndicate_leader_selected = numagents == 1?1:0 - - var/mob/living/carbon/human/new_syndicate_commando = create_syndicate_death_commando(L, syndicate_leader_selected) - - - while((!theghost || !theghost.client) && candidates.len) - theghost = pick(candidates) - candidates.Remove(theghost) - - if(!theghost) - del(new_syndicate_commando) - break - - new_syndicate_commando.key = theghost.key - new_syndicate_commando.internal = new_syndicate_commando.s_store - new_syndicate_commando.internals.icon_state = "internal1" - - //So they don't forget their code or mission. - - - new_syndicate_commando << "\blue You are an Elite Mercenary. [!syndicate_leader_selected?"commando":"LEADER"] in the service of criminal elements hostile to NanoTrasen. \nYour current mission is: \red [input]" - - numagents-- - if(numagents >= 6) - return 0 - - for (var/obj/effect/landmark/L in /area/shuttle/syndicate_elite) - if (L.name == "Syndicate-Commando-Bomb") - new /obj/effect/spawner/newbomb/timer/syndicate(L.loc) - - return 1 - - -/datum/admins/proc/makeBody(var/mob/dead/observer/G_found) // Uses stripped down and bastardized code from respawn character - if(!G_found || !G_found.key) return - - //First we spawn a dude. - var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned. - - new_character.gender = pick(MALE,FEMALE) - - var/datum/preferences/A = new() - A.randomize_appearance_for(new_character) - if(new_character.gender == MALE) - new_character.real_name = "[pick(first_names_male)] [pick(last_names)]" - else - new_character.real_name = "[pick(first_names_female)] [pick(last_names)]" - new_character.name = new_character.real_name - new_character.age = rand(17,45) - - new_character.dna.ready_dna(new_character) - new_character.key = G_found.key - - return new_character - -/datum/admins/proc/create_syndicate_death_commando(obj/spawn_location, syndicate_leader_selected = 0) - var/mob/living/carbon/human/new_syndicate_commando = new(spawn_location.loc) - var/syndicate_commando_leader_rank = pick("Lieutenant", "Captain", "Major") - var/syndicate_commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major") - var/syndicate_commando_name = pick(last_names) - - new_syndicate_commando.gender = pick(MALE, FEMALE) - - var/datum/preferences/A = new()//Randomize appearance for the commando. - A.randomize_appearance_for(new_syndicate_commando) - - new_syndicate_commando.real_name = "[!syndicate_leader_selected ? syndicate_commando_rank : syndicate_commando_leader_rank] [syndicate_commando_name]" - new_syndicate_commando.name = new_syndicate_commando.real_name - new_syndicate_commando.age = !syndicate_leader_selected ? rand(23,35) : rand(35,45) - - new_syndicate_commando.dna.ready_dna(new_syndicate_commando)//Creates DNA. - - //Creates mind stuff. - new_syndicate_commando.mind_initialize() - new_syndicate_commando.mind.assigned_role = "MODE" - new_syndicate_commando.mind.special_role = "Mercenary" - - //Adds them to current traitor list. Which is really the extra antagonist list. - ticker.mode.traitors += new_syndicate_commando.mind - new_syndicate_commando.equip_syndicate_commando(syndicate_leader_selected) - - return new_syndicate_commando - -/datum/admins/proc/makeVoxRaiders() - - var/list/mob/dead/observer/candidates = list() - var/mob/dead/observer/theghost = null - var/time_passed = world.time - var/input = "Disregard shinies, acquire hardware." - - var/leader_chosen = 0 //when the leader is chosen. The last person spawned. - - //Generates a list of candidates from active ghosts. - for(var/mob/dead/observer/G in player_list) - spawn(0) - switch(alert(G,"Do you wish to be considered for a vox raiding party arriving on the station?","Please answer in 30 seconds!","Yes","No")) - if("Yes") - if((world.time-time_passed)>300)//If more than 30 game seconds passed. - return - candidates += G - if("No") - return - else - return - - sleep(300) //Debug. - - for(var/mob/dead/observer/G in candidates) - if(!G.key) - candidates.Remove(G) - - if(candidates.len) - var/max_raiders = 1 - var/raiders = max_raiders - //Spawns vox raiders and equips them. - for (var/obj/effect/landmark/L in world) - if(L.name == "voxstart") - if(raiders<=0) - break - - var/mob/living/carbon/human/new_vox = create_vox_raider(L, leader_chosen) - - while((!theghost || !theghost.client) && candidates.len) - theghost = pick(candidates) - candidates.Remove(theghost) - - if(!theghost) - del(new_vox) - break - - new_vox.key = theghost.key - new_vox << "\blue You are a Vox Primalis, fresh out of the Shoal. Your ship has arrived at a human-meat system hosting the NSV Exodus... or was it the Luna? NSS? Utopia? Nobody is really sure, who cares about stupid meat-names anyway? Everyone is raring to start pillaging! Your current goal is: \red [input]" - new_vox << "\red Don't forget to turn on your nitrogen internals!" - - raiders-- - if(raiders > max_raiders) - return 0 - else - return 0 - return 1 - -/datum/admins/proc/create_vox_raider(obj/spawn_location, leader_chosen = 0) - - var/mob/living/carbon/human/new_vox = new(spawn_location.loc, "Vox") - - new_vox.gender = pick(MALE, FEMALE) - new_vox.h_style = "Short Vox Quills" - new_vox.regenerate_icons() - - var/sounds = rand(2,10) - var/i = 0 - var/newname = "" - - while(i<=sounds) - i++ - newname += pick(list("ti","hi","ki","ya","ta","ha","ka","ya","chi","cha","kah")) - - new_vox.real_name = capitalize(newname) - new_vox.name = new_vox.real_name - new_vox.age = rand(12,20) - - new_vox.dna.ready_dna(new_vox) // Creates DNA. - new_vox.mind_initialize() - new_vox.mind.assigned_role = "MODE" - new_vox.mind.special_role = "Vox Raider" - new_vox.mutations |= NOCLONE //Stops the station crew from messing around with their DNA. - - if(ticker.mode && ( istype( ticker.mode,/datum/game_mode/heist ) ) ) - var/datum/game_mode/heist/M = ticker.mode - if(new_vox.internal_organs_by_name["stack"]) - cortical_stacks |= new_vox.internal_organs_by_name["stack"] - M.raiders[new_vox.mind] = new_vox.internal_organs_by_name["stack"] - - ticker.mode.traitors += new_vox.mind - new_vox.equip_vox_raider() - - return new_vox \ No newline at end of file diff --git a/code/modules/admin/verbs/onlyone.dm b/code/modules/admin/verbs/onlyone.dm deleted file mode 100644 index aa99b4bd46..0000000000 --- a/code/modules/admin/verbs/onlyone.dm +++ /dev/null @@ -1,47 +0,0 @@ -/client/proc/only_one() - if(!ticker) - alert("The game hasn't started yet!") - return - - for(var/mob/living/carbon/human/H in player_list) - if(H.stat == 2 || !(H.client)) continue - if(is_special_character(H)) continue - - ticker.mode.traitors += H.mind - H.mind.special_role = "traitor" - - var/datum/objective/steal/steal_objective = new - steal_objective.owner = H.mind - steal_objective.set_target("nuclear authentication disk") - H.mind.objectives += steal_objective - - var/datum/objective/hijack/hijack_objective = new - hijack_objective.owner = H.mind - H.mind.objectives += hijack_objective - - H << "You are the traitor." - show_objectives(H.mind) - - for (var/obj/item/I in H) - if (istype(I, /obj/item/weapon/implant)) - continue - del(I) - - H.equip_to_slot_or_del(new /obj/item/clothing/under/kilt(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/clothing/head/beret(H), slot_head) - H.equip_to_slot_or_del(new /obj/item/weapon/claymore(H), slot_l_hand) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/weapon/pinpointer(H.loc), slot_l_store) - - var/obj/item/weapon/card/id/W = new(H) - W.name = "[H.real_name]'s ID Card" - W.icon_state = "centcom" - W.access = get_all_accesses() - W.access += get_all_centcom_access() - W.assignment = "Highlander" - W.registered_name = H.real_name - H.equip_to_slot_or_del(W, slot_wear_id) - - message_admins("\blue [key_name_admin(usr)] used THERE CAN BE ONLY ONE!", 1) - log_admin("[key_name(usr)] used there can be only one.") \ No newline at end of file diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 8e0b6b6a65..07d8009219 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -445,50 +445,12 @@ Traitors and the like can also be revived with the previous role mostly intact. var/player_key = G_found.key //Now for special roles and equipment. - switch(new_character.mind.special_role) - if("traitor") - job_master.EquipRank(new_character, new_character.mind.assigned_role, 1) - ticker.mode.equip_traitor(new_character) - if("Wizard") - new_character.loc = pick(wizardstart) - //ticker.mode.learn_basic_spells(new_character) - ticker.mode.equip_wizard(new_character) - if("Mercenary") - var/obj/effect/landmark/synd_spawn = locate("landmark*Syndicate-Spawn") - if(synd_spawn) - new_character.loc = get_turf(synd_spawn) - call(/datum/game_mode/proc/equip_syndicate)(new_character) - if("Ninja") - new_character.equip_space_ninja() - if(ninjastart.len == 0) - new_character << "\red A proper starting location for you could not be found, please report this bug!" - new_character << "\red Attempting to place at a carpspawn." - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "carpspawn") - ninjastart.Add(L) - if(ninjastart.len == 0 && latejoin.len > 0) - new_character << "\red Still no spawneable locations could be found. Defaulting to latejoin." - new_character.loc = pick(latejoin) - else if (ninjastart.len == 0) - new_character << "\red Still no spawneable locations could be found. Aborting." - - if("Death Commando")//Leaves them at late-join spawn. - new_character.equip_death_commando() - new_character.internal = new_character.s_store - new_character.internals.icon_state = "internal1" - else//They may also be a cyborg or AI. - switch(new_character.mind.assigned_role) - if("Cyborg")//More rigging to make em' work and check if they're traitor. - new_character = new_character.Robotize() - if(new_character.mind.special_role=="traitor") - call(/datum/game_mode/proc/add_law_zero)(new_character) - if("AI") - new_character = new_character.AIize() - if(new_character.mind.special_role=="traitor") - call(/datum/game_mode/proc/add_law_zero)(new_character) - //Add aliens. - else - job_master.EquipRank(new_character, new_character.mind.assigned_role, 1)//Or we simply equip them. + var/datum/antagonist/antag_data = get_antag_data(new_character.mind.special_role) + if(antag_data) + antag_data.add_antagonist(new_character.mind) + antag_data.place_mob(new_character) + else + job_master.EquipRank(new_character, new_character.mind.assigned_role, 1) //Announces the character on all the systems, based on the record. if(!issilicon(new_character))//If they are not a cyborg/AI. diff --git a/code/modules/admin/verbs/striketeam.dm b/code/modules/admin/verbs/striketeam.dm index 9f42da94d9..7ba359af68 100644 --- a/code/modules/admin/verbs/striketeam.dm +++ b/code/modules/admin/verbs/striketeam.dm @@ -1,174 +1,55 @@ //STRIKE TEAMS - var/const/commandos_possible = 6 //if more Commandos are needed in the future -var/global/sent_strike_team = 0 /client/proc/strike_team() + set category = "Fun" + set name = "Spawn Strike Team" + set desc = "Spawns a death squad if you want to run an admin event." + + if(!src.holder) + src << "Only administrators may use this command." + return + if(!ticker) usr << "The game hasn't started yet!" return + if(world.time < 6000) usr << "There are [(6000-world.time)/10] seconds remaining before it may be called." return - if(sent_strike_team == 1) - usr << "CentCom is already sending a team." + + var/datum/antagonist/deathsquad/team + + var/choice = input(usr, "Select type of strike team:") as null|anything in list("Death Squad", "Mercenaries") + if(!choice) return - if(alert("Do you want to send in the CentCom death squad? Once enabled, this is irreversible.",,"Yes","No")!="Yes") + + switch(choice) + if("Death Squad") + team = deathsquad + if("Mercenaries") + team = commandos + else + return + + if(team.deployed) + usr << "Someone is already sending a team." return + + if(alert("Do you want to send in a strike team? Once enabled, this is irreversible.",,"Yes","No")!="Yes") + return + alert("This 'mode' will go on until everyone is dead or the station is destroyed. You may also admin-call the evac shuttle when appropriate. Spawned commandos have internals cameras which are viewable through a monitor inside the Spec. Ops. Office. Assigning the team's detailed task is recommended from there. While you will be able to manually pick the candidates from active ghosts, their assignment in the squad will be random.") - var/input = null - while(!input) - input = sanitize(copytext(input(src, "Please specify which mission the death commando squad shall undertake.", "Specify Mission", ""),1,MAX_MESSAGE_LEN)) - if(!input) + choice = null + while(!choice) + choice = sanitize(copytext(input(src, "Please specify which mission the strike team shall undertake.", "Specify Mission", ""),1,MAX_MESSAGE_LEN)) + if(!choice) if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes") return - if(sent_strike_team) + if(team.deployed) usr << "Looks like someone beat you to it." return - sent_strike_team = 1 - - if (emergency_shuttle.can_recall()) - emergency_shuttle.recall() - - var/commando_number = commandos_possible //for selecting a leader - var/leader_selected = 0 //when the leader is chosen. The last person spawned. - -//Code for spawning a nuke auth code. - var/nuke_code - var/temp_code - for(var/obj/machinery/nuclearbomb/N in world) - temp_code = text2num(N.r_code) - if(temp_code)//if it's actually a number. It won't convert any non-numericals. - nuke_code = N.r_code - break - -//Generates a list of commandos from active ghosts. Then the user picks which characters to respawn as the commandos. - var/list/candidates = list() //candidates for being a commando out of all the active ghosts in world. - var/list/commandos = list() //actual commando ghosts as picked by the user. - for(var/mob/dead/observer/G in player_list) - if(!G.client.holder && !G.client.is_afk()) //Whoever called/has the proc won't be added to the list. - if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) - candidates += G.key - for(var/i=commandos_possible,(i>0&&candidates.len),i--)//Decrease with every commando selected. - var/candidate = input("Pick characters to spawn as the commandos. This will go on until there either no more ghosts to pick from or the slots are full.", "Active Players") as null|anything in candidates //It will auto-pick a person when there is only one candidate. - candidates -= candidate //Subtract from candidates. - commandos += candidate//Add their ghost to commandos. - -//Spawns commandos and equips them. - for(var/obj/effect/landmark/L in landmarks_list) - if(commando_number<=0) break - if (L.name == "Commando") - leader_selected = commando_number == 1?1:0 - - var/mob/living/carbon/human/new_commando = create_death_commando(L, leader_selected) - - if(commandos.len) - new_commando.key = pick(commandos) - commandos -= new_commando.key - new_commando.internal = new_commando.s_store - new_commando.internals.icon_state = "internal1" - - //So they don't forget their code or mission. - if(nuke_code) - new_commando.mind.store_memory("Nuke Code: \red [nuke_code].") - new_commando.mind.store_memory("Mission: \red [input].") - - new_commando << "\blue You are a Special Ops. [!leader_selected?"commando":"LEADER"] in the service of Central Command. Check the table ahead for detailed instructions.\nYour current mission is: \red[input]" - - commando_number-- - -//Spawns the rest of the commando gear. - for (var/obj/effect/landmark/L in landmarks_list) - if (L.name == "Commando_Manual") - //new /obj/item/weapon/gun/energy/pulse_rifle(L.loc) - var/obj/item/weapon/paper/P = new(L.loc) - P.info = "

    Good morning soldier!. This compact guide will familiarize you with standard operating procedure. There are three basic rules to follow:
    #1 Work as a team.
    #2 Accomplish your objective at all costs.
    #3 Leave no witnesses.
    You are fully equipped and stocked for your mission--before departing on the Spec. Ops. Shuttle due South, make sure that all operatives are ready. Actual mission objective will be relayed to you by Central Command through your headsets.
    If deemed appropriate, Central Command will also allow members of your team to equip assault power-armor for the mission. You will find the armor storage due West of your position. Once you are ready to leave, utilize the Special Operations shuttle console and toggle the hull doors via the other console.

    In the event that the team does not accomplish their assigned objective in a timely manner, or finds no other way to do so, attached below are instructions on how to operate a Nanotrasen Nuclear Device. Your operations LEADER is provided with a nuclear authentication disk and a pin-pointer for this reason. You may easily recognize them by their rank: Lieutenant, Captain, or Major. The nuclear device itself will be present somewhere on your destination.

    Hello and thank you for choosing Nanotrasen for your nuclear information needs. Today's crash course will deal with the operation of a Fission Class Nanotrasen made Nuclear Device.
    First and foremost, DO NOT TOUCH ANYTHING UNTIL THE BOMB IS IN PLACE. Pressing any button on the compacted bomb will cause it to extend and bolt itself into place. If this is done to unbolt it one must completely log in which at this time may not be possible.
    To make the device functional:
    #1 Place bomb in designated detonation zone
    #2 Extend and anchor bomb (attack with hand).
    #3 Insert Nuclear Auth. Disk into slot.
    #4 Type numeric code into keypad ([nuke_code]).
    Note: If you make a mistake press R to reset the device.
    #5 Press the E button to log onto the device.
    You now have activated the device. To deactivate the buttons at anytime, for example when you have already prepped the bomb for detonation, remove the authentication disk OR press the R on the keypad. Now the bomb CAN ONLY be detonated using the timer. A manual detonation is not an option.
    Note: Toggle off the SAFETY.
    Use the - - and + + to set a detonation time between 5 seconds and 10 minutes. Then press the timer toggle button to start the countdown. Now remove the authentication disk so that the buttons deactivate.
    Note: THE BOMB IS STILL SET AND WILL DETONATE
    Now before you remove the disk if you need to move the bomb you can: Toggle off the anchor, move it, and re-anchor.

    The nuclear authorization code is: [nuke_code ? nuke_code : "None provided"]

    Good luck, soldier!

    " - P.name = "Spec. Ops. Manual" - - for (var/obj/effect/landmark/L in landmarks_list) - if (L.name == "Commando-Bomb") - new /obj/effect/spawner/newbomb/timer/syndicate(L.loc) - del(L) - - message_admins("\blue [key_name_admin(usr)] has spawned a CentCom strike squad.", 1) - log_admin("[key_name(usr)] used Spawn Death Squad.") - return 1 - -/client/proc/create_death_commando(obj/spawn_location, leader_selected = 0) - var/mob/living/carbon/human/new_commando = new(spawn_location.loc) - var/commando_leader_rank = pick("Lieutenant", "Captain", "Major") - var/commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major") - var/commando_name = pick(last_names) - - new_commando.gender = pick(MALE, FEMALE) - - var/datum/preferences/A = new()//Randomize appearance for the commando. - A.randomize_appearance_for(new_commando) - - new_commando.real_name = "[!leader_selected ? commando_rank : commando_leader_rank] [commando_name]" - new_commando.age = !leader_selected ? rand(23,35) : rand(35,45) - - new_commando.dna.ready_dna(new_commando)//Creates DNA. - - //Creates mind stuff. - new_commando.mind_initialize() - new_commando.mind.assigned_role = "MODE" - new_commando.mind.special_role = "Death Commando" - ticker.mode.traitors |= new_commando.mind//Adds them to current traitor list. Which is really the extra antagonist list. - new_commando.equip_death_commando(leader_selected) - return new_commando - -/mob/living/carbon/human/proc/equip_death_commando(leader_selected = 0) - - var/obj/item/device/radio/R = new /obj/item/device/radio/headset(src) - R.set_frequency(DTH_FREQ) - equip_to_slot_or_del(R, slot_l_ear) - if (leader_selected == 0) - equip_to_slot_or_del(new /obj/item/clothing/under/color/green(src), slot_w_uniform) - else - equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom_officer(src), slot_w_uniform) - equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(src), slot_shoes) - equip_to_slot_or_del(new /obj/item/clothing/suit/armor/swat(src), slot_wear_suit) - equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(src), slot_gloves) - equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/deathsquad(src), slot_head) - equip_to_slot_or_del(new /obj/item/clothing/mask/gas/swat(src), slot_wear_mask) - equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(src), slot_glasses) - - equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(src), slot_back) - equip_to_slot_or_del(new /obj/item/weapon/storage/box(src), slot_in_backpack) - - equip_to_slot_or_del(new /obj/item/ammo_magazine/a357(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/weapon/storage/box/flashbangs(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_in_backpack) - if (!leader_selected) - equip_to_slot_or_del(new /obj/item/weapon/plastique(src), slot_in_backpack) - else - equip_to_slot_or_del(new /obj/item/weapon/pinpointer(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/weapon/disk/nuclear(src), slot_in_backpack) - - equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(src), slot_l_store) - equip_to_slot_or_del(new /obj/item/weapon/grenade/flashbang(src), slot_r_store) - equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen(src), slot_s_store) - equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/revolver/mateba(src), slot_belt) - - equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(src), slot_r_hand) - - - implant_loyalty(src) - - - - var/obj/item/weapon/card/id/W = new(src) - W.name = "[real_name]'s ID Card" - W.icon_state = "centcom" - W.access = get_all_accesses()//They get full station access. - W.access += list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage)//Let's add their alloted CentCom access. - W.assignment = "Death Commando" - W.registered_name = real_name - equip_to_slot_or_del(W, slot_wear_id) - - return 1 \ No newline at end of file + team.attempt_spawn(1,commandos_possible) diff --git a/code/modules/admin/verbs/striketeam_syndicate.dm b/code/modules/admin/verbs/striketeam_syndicate.dm deleted file mode 100644 index 6a16f22d1f..0000000000 --- a/code/modules/admin/verbs/striketeam_syndicate.dm +++ /dev/null @@ -1,178 +0,0 @@ -//STRIKE TEAMS - -var/const/syndicate_commandos_possible = 6 //if more Commandos are needed in the future -var/global/sent_syndicate_strike_team = 0 -/client/proc/syndicate_strike_team() - set category = "Fun" - set name = "Spawn Mercenary Strike Team" - set desc = "Spawns a squad of commandos in the Syndicate Mothership if you want to run an admin event." - if(!src.holder) - src << "Only administrators may use this command." - return - if(!ticker) - alert("The game hasn't started yet!") - return -// if(world.time < 6000) -// alert("Not so fast, buddy. Wait a few minutes until the game gets going. There are [(6000-world.time)/10] seconds remaining.") -// return - if(sent_syndicate_strike_team == 1) - alert("Criminal elements are already sending a team, Mr. Dumbass.") - return - if(alert("Do you want to send in the Mercenary Strike Team? Once enabled, this is irreversible.",,"Yes","No")=="No") - return - alert("This 'mode' will go on until everyone is dead or the station is destroyed. You may also admin-call the evac shuttle when appropriate. Spawned mercs have internals cameras which are viewable through a monitor inside the Syndicate Mothership Bridge. Assigning the team's detailed task is recommended from there. While you will be able to manually pick the candidates from active ghosts, their assignment in the squad will be random.") - - var/input = null - while(!input) - input = sanitize(copytext(input(src, "Please specify which mission the strike team shall undertake.", "Specify Mission", ""),1,MAX_MESSAGE_LEN)) - if(!input) - if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes") - return - - if(sent_syndicate_strike_team) - src << "Looks like someone beat you to it." - return - - sent_syndicate_strike_team = 1 - - //if (emergency_shuttle.can_recall()) - // emergency_shuttle.recall() //why, exactly? Admins can do this themselves. - - var/syndicate_commando_number = syndicate_commandos_possible //for selecting a leader - var/syndicate_leader_selected = 0 //when the leader is chosen. The last person spawned. - -//Code for spawning a nuke auth code. - var/nuke_code - var/temp_code - for(var/obj/machinery/nuclearbomb/N in world) - temp_code = text2num(N.r_code) - if(temp_code)//if it's actually a number. It won't convert any non-numericals. - nuke_code = N.r_code - break - -//Generates a list of commandos from active ghosts. Then the user picks which characters to respawn as the commandos. - var/list/candidates = list() //candidates for being a commando out of all the active ghosts in world. - var/list/commandos = list() //actual commando ghosts as picked by the user. - for(var/mob/dead/observer/G in player_list) - if(!G.client.holder && !G.client.is_afk()) //Whoever called/has the proc won't be added to the list. - if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) - candidates += G.key - for(var/i=commandos_possible,(i>0&&candidates.len),i--)//Decrease with every commando selected. - var/candidate = input("Pick characters to spawn as the commandos. This will go on until there either no more ghosts to pick from or the slots are full.", "Active Players") as null|anything in candidates //It will auto-pick a person when there is only one candidate. - candidates -= candidate //Subtract from candidates. - commandos += candidate//Add their ghost to commandos. - -//Spawns commandos and equips them. - for(var/obj/effect/landmark/L in landmarks_list) - if(syndicate_commando_number<=0) break - if (L.name == "Syndicate-Commando") - syndicate_leader_selected = syndicate_commando_number == 1?1:0 - - var/mob/living/carbon/human/new_syndicate_commando = create_syndicate_death_commando(L, syndicate_leader_selected) - - if(commandos.len) - new_syndicate_commando.key = pick(commandos) - commandos -= new_syndicate_commando.key - new_syndicate_commando.internal = new_syndicate_commando.s_store - new_syndicate_commando.internals.icon_state = "internal1" - - //So they don't forget their code or mission. - if(nuke_code) - new_syndicate_commando.mind.store_memory("Nuke Code: \red [nuke_code].") - new_syndicate_commando.mind.store_memory("Mission: \red [input].") - - new_syndicate_commando << "\blue You are an Elite Mercenary. [!syndicate_leader_selected?"commando":"LEADER"] in the service of criminal elements hostile to NanoTrasen. \nYour current mission is: \red[input]" - - syndicate_commando_number-- - -//Spawns the rest of the commando gear. -// for (var/obj/effect/landmark/L) - // if (L.name == "Commando_Manual") - //new /obj/item/weapon/gun/energy/pulse_rifle(L.loc) - // var/obj/item/weapon/paper/P = new(L.loc) - // P.info = "

    Good morning soldier!. This compact guide will familiarize you with standard operating procedure. There are three basic rules to follow:
    #1 Work as a team.
    #2 Accomplish your objective at all costs.
    #3 Leave no witnesses.
    You are fully equipped and stocked for your mission--before departing on the Spec. Ops. Shuttle due South, make sure that all operatives are ready. Actual mission objective will be relayed to you by Central Command through your headsets.
    If deemed appropriate, Central Command will also allow members of your team to equip assault power-armor for the mission. You will find the armor storage due West of your position. Once you are ready to leave, utilize the Special Operations shuttle console and toggle the hull doors via the other console.

    In the event that the team does not accomplish their assigned objective in a timely manner, or finds no other way to do so, attached below are instructions on how to operate a Nanotrasen Nuclear Device. Your operations LEADER is provided with a nuclear authentication disk and a pin-pointer for this reason. You may easily recognize them by their rank: Lieutenant, Captain, or Major. The nuclear device itself will be present somewhere on your destination.

    Hello and thank you for choosing Nanotrasen for your nuclear information needs. Today's crash course will deal with the operation of a Fission Class Nanotrasen made Nuclear Device.
    First and foremost, DO NOT TOUCH ANYTHING UNTIL THE BOMB IS IN PLACE. Pressing any button on the compacted bomb will cause it to extend and bolt itself into place. If this is done to unbolt it one must completely log in which at this time may not be possible.
    To make the device functional:
    #1 Place bomb in designated detonation zone
    #2 Extend and anchor bomb (attack with hand).
    #3 Insert Nuclear Auth. Disk into slot.
    #4 Type numeric code into keypad ([nuke_code]).
    Note: If you make a mistake press R to reset the device.
    #5 Press the E button to log onto the device.
    You now have activated the device. To deactivate the buttons at anytime, for example when you have already prepped the bomb for detonation, remove the authentication disk OR press the R on the keypad. Now the bomb CAN ONLY be detonated using the timer. A manual detonation is not an option.
    Note: Toggle off the SAFETY.
    Use the - - and + + to set a detonation time between 5 seconds and 10 minutes. Then press the timer toggle button to start the countdown. Now remove the authentication disk so that the buttons deactivate.
    Note: THE BOMB IS STILL SET AND WILL DETONATE
    Now before you remove the disk if you need to move the bomb you can: Toggle off the anchor, move it, and re-anchor.

    The nuclear authorization code is: [nuke_code ? nuke_code : "None provided"]

    Good luck, soldier!

    " - // P.name = "Spec. Ops. Manual" - - for (var/obj/effect/landmark/L in landmarks_list) - if (L.name == "Syndicate-Commando-Bomb") - new /obj/effect/spawner/newbomb/timer/syndicate(L.loc) - del(L) - - message_admins("\blue [key_name_admin(usr)] has spawned a mercenary strike squad.", 1) - log_admin("[key_name(usr)] used Spawn Mercenary Squad.") - feedback_add_details("admin_verb","SDTHS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/create_syndicate_death_commando(obj/spawn_location, syndicate_leader_selected = 0) - var/mob/living/carbon/human/new_syndicate_commando = new(spawn_location.loc) - var/syndicate_commando_leader_rank = pick("Lieutenant", "Captain", "Major") - var/syndicate_commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major") - var/syndicate_commando_name = pick(last_names) - - new_syndicate_commando.gender = pick(MALE, FEMALE) - - var/datum/preferences/A = new()//Randomize appearance for the commando. - A.randomize_appearance_for(new_syndicate_commando) - - new_syndicate_commando.real_name = "[!syndicate_leader_selected ? syndicate_commando_rank : syndicate_commando_leader_rank] [syndicate_commando_name]" - new_syndicate_commando.age = !syndicate_leader_selected ? rand(23,35) : rand(35,45) - - new_syndicate_commando.dna.ready_dna(new_syndicate_commando)//Creates DNA. - - //Creates mind stuff. - new_syndicate_commando.mind_initialize() - new_syndicate_commando.mind.assigned_role = "MODE" - new_syndicate_commando.mind.special_role = "Mercenary" - ticker.mode.traitors |= new_syndicate_commando.mind //Adds them to current traitor list. Which is really the extra antagonist list. - new_syndicate_commando.equip_syndicate_commando(syndicate_leader_selected) - del(spawn_location) - return new_syndicate_commando - -/mob/living/carbon/human/proc/equip_syndicate_commando(syndicate_leader_selected = 0) - - var/obj/item/device/radio/R = new /obj/item/device/radio/headset/syndicate(src) - R.set_frequency(SYND_FREQ) //Same frequency as the syndicate team in Nuke mode. - equip_to_slot_or_del(R, slot_l_ear) - equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(src), slot_w_uniform) - equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(src), slot_shoes) - if (!syndicate_leader_selected) - equip_to_slot_or_del(new /obj/item/clothing/suit/space/syndicate/black(src), slot_wear_suit) - else - equip_to_slot_or_del(new /obj/item/clothing/suit/space/syndicate/black/red(src), slot_wear_suit) - equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(src), slot_gloves) - if (!syndicate_leader_selected) - equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/syndicate/black(src), slot_head) - else - equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/syndicate/black/red(src), slot_head) - equip_to_slot_or_del(new /obj/item/clothing/mask/gas/syndicate(src), slot_wear_mask) - equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(src), slot_glasses) - - equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(src), slot_back) - equip_to_slot_or_del(new /obj/item/weapon/storage/box(src), slot_in_backpack) - - equip_to_slot_or_del(new /obj/item/ammo_magazine/c45(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/weapon/plastique(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_in_backpack) - if (!syndicate_leader_selected) - equip_to_slot_or_del(new /obj/item/weapon/plastique(src), slot_in_backpack) - else - equip_to_slot_or_del(new /obj/item/weapon/pinpointer(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/weapon/disk/nuclear(src), slot_in_backpack) - - equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(src), slot_l_store) - equip_to_slot_or_del(new /obj/item/weapon/grenade/empgrenade(src), slot_r_store) - equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen(src), slot_s_store) - equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/silenced(src), slot_belt) - - equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(src), slot_r_hand) //Will change to something different at a later time -- Superxpdude - - var/obj/item/weapon/card/id/syndicate/W = new(src) //Untrackable by AI - W.name = "[real_name]'s ID Card" - W.icon_state = "id" - W.access = get_all_accesses()//They get full station access because obviously the syndicate has HAAAX, and can make special IDs for their most elite members. - W.access += list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage, access_syndicate)//Let's add their forged CentCom access and syndicate access. - W.assignment = "Mercenary" - W.registered_name = real_name - equip_to_slot_or_del(W, slot_wear_id) - - return 1 \ No newline at end of file diff --git a/code/modules/admin/verbs/vox_raiders.dm b/code/modules/admin/verbs/vox_raiders.dm deleted file mode 100644 index 6c34bb92c6..0000000000 --- a/code/modules/admin/verbs/vox_raiders.dm +++ /dev/null @@ -1,69 +0,0 @@ -var/global/vox_tick = 1 - -/mob/living/carbon/human/proc/equip_vox_raider() - - var/obj/item/device/radio/R = new /obj/item/device/radio/headset/syndicate(src) - R.set_frequency(SYND_FREQ) - equip_to_slot_or_del(R, slot_l_ear) - - equip_to_slot_or_del(new /obj/item/clothing/under/vox/vox_robes(src), slot_w_uniform) - equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots/vox(src), slot_shoes) // REPLACE THESE WITH CODED VOX ALTERNATIVES. - equip_to_slot_or_del(new /obj/item/clothing/gloves/yellow/vox(src), slot_gloves) // AS ABOVE. - - switch(vox_tick) - if(1) // Vox raider! - equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/carapace(src), slot_wear_suit) - equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/carapace(src), slot_head) - equip_to_slot_or_del(new /obj/item/weapon/melee/baton/loaded(src), slot_belt) - equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(src), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE. - equip_to_slot_or_del(new /obj/item/device/chameleon(src), slot_l_store) - - var/obj/item/weapon/gun/launcher/spikethrower/W = new(src) - equip_to_slot_or_del(W, slot_r_hand) - - - if(2) // Vox engineer! - equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/pressure(src), slot_wear_suit) - equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/pressure(src), slot_head) - equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(src), slot_belt) - equip_to_slot_or_del(new /obj/item/clothing/glasses/meson(src), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE. - equip_to_slot_or_del(new /obj/item/weapon/storage/box/emps(src), slot_r_hand) - equip_to_slot_or_del(new /obj/item/device/multitool(src), slot_l_hand) - - - if(3) // Vox saboteur! - equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/stealth(src), slot_wear_suit) - equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/stealth(src), slot_head) - equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(src), slot_belt) - equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(src), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE. - equip_to_slot_or_del(new /obj/item/weapon/card/emag(src), slot_l_store) - equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/dartgun/vox/raider(src), slot_r_hand) - equip_to_slot_or_del(new /obj/item/device/multitool(src), slot_l_hand) - - if(4) // Vox medic! - equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/medic(src), slot_wear_suit) - equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/medic(src), slot_head) - equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(src), slot_belt) // Who needs actual surgical tools? - equip_to_slot_or_del(new /obj/item/clothing/glasses/hud/health(src), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE. - equip_to_slot_or_del(new /obj/item/weapon/circular_saw(src), slot_l_store) - equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/dartgun/vox/medical, slot_r_hand) - - equip_to_slot_or_del(new /obj/item/clothing/mask/breath(src), slot_wear_mask) - equip_to_slot_or_del(new /obj/item/weapon/tank/nitrogen(src), slot_back) - equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_r_store) - - var/obj/item/weapon/card/id/syndicate/C = new(src) - C.name = "[real_name]'s Legitimate Human ID Card" - C.icon_state = "id" - C.access = list(access_syndicate) - C.assignment = "Trader" - C.registered_name = real_name - C.registered_user = src - var/obj/item/weapon/storage/wallet/W = new(src) - W.handle_item_insertion(C) - spawn_money(rand(50,150)*10,W) - equip_to_slot_or_del(W, slot_wear_id) - vox_tick++ - if (vox_tick > 4) vox_tick = 1 - - return 1 diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm deleted file mode 100644 index 7fd20efa61..0000000000 --- a/code/modules/events/alien_infestation.dm +++ /dev/null @@ -1,39 +0,0 @@ -/var/global/sent_aliens_to_station = 0 - -/datum/event/alien_infestation - announceWhen = 400 - - var/spawncount = 1 - var/successSpawn = 0 //So we don't make a command report if nothing gets spawned. - - -/datum/event/alien_infestation/setup() - announceWhen = rand(announceWhen, announceWhen + 50) - spawncount = rand(1, 2) - sent_aliens_to_station = 1 - -/datum/event/alien_infestation/announce() - if(successSpawn) - command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg') - - -/datum/event/alien_infestation/start() - var/list/vents = list() - for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in machines) - if(!temp_vent.welded && temp_vent.network && temp_vent.loc.z in config.station_levels) - if(temp_vent.network.normal_members.len > 50) //Stops Aliens getting stuck in small networks. See: Security, Virology - vents += temp_vent - - var/list/candidates = get_alien_candidates() - - while(spawncount > 0 && vents.len && candidates.len) - var/obj/vent = pick(vents) - var/candidate = pick(candidates) - - var/mob/living/carbon/alien/larva/new_xeno = new(vent.loc) - new_xeno.key = candidate - - candidates -= candidate - vents -= vent - spawncount-- - successSpawn = 1 diff --git a/code/modules/events/borers.dm b/code/modules/events/borers.dm deleted file mode 100644 index 4109a66d85..0000000000 --- a/code/modules/events/borers.dm +++ /dev/null @@ -1,33 +0,0 @@ -//Cortical borer spawn event - care of RobRichards1997 with minor editing by Zuhayr. -/datum/event/borer_infestation - announceWhen = 400 - - var/spawncount = 5 - var/successSpawn = 0 //So we don't make a command report if nothing gets spawned. - -/datum/event/borer_infestation/setup() - announceWhen = rand(announceWhen, announceWhen + 50) - spawncount = rand(1, 3) - -/datum/event/borer_infestation/announce() - if(successSpawn) - command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg') - -/datum/event/borer_infestation/start() - var/list/vents = list() - for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in world) - if(!temp_vent.welded && temp_vent.network && temp_vent.loc.z in config.station_levels) - //Stops cortical borers getting stuck in small networks. See: Security, Virology - if(temp_vent.network.normal_members.len > 50) - vents += temp_vent - - var/list/candidates = get_alien_candidates() - while(spawncount > 0 && vents.len && candidates.len) - var/obj/vent = pick_n_take(vents) - var/client/C = pick_n_take(candidates) - - var/mob/living/simple_animal/borer/new_borer = new(vent.loc) - new_borer.key = C.key - - spawncount-- - successSpawn = 1 \ No newline at end of file diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm index 758d50ebdd..df392cfada 100644 --- a/code/modules/events/event_container.dm +++ b/code/modules/events/event_container.dm @@ -153,8 +153,7 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT new /datum/event_meta(EVENT_LEVEL_MODERATE, "Viral Infection", /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 150)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Spider Infestation", /datum/event/spider_infestation, 100, list(ASSIGNMENT_SECURITY = 30), 1), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Ion Storm", /datum/event/ionstorm, 0, list(ASSIGNMENT_AI = 50, ASSIGNMENT_CYBORG = 50, ASSIGNMENT_ENGINEER = 15, ASSIGNMENT_SCIENTIST = 5)), - new /datum/event_meta/alien(EVENT_LEVEL_MODERATE, "Alien Infestation", /datum/event/alien_infestation, 2.5, list(ASSIGNMENT_SECURITY = 1), 1, 0, 5), - new /datum/event_meta/ninja(EVENT_LEVEL_MODERATE, "Space Ninja", /datum/event/space_ninja, 0, list(ASSIGNMENT_SECURITY = 1), 1, 0, 5), + new /datum/event_meta/alien(EVENT_LEVEL_MODERATE, "Random Antagonist", /datum/event/random_antag, 2.5, list(ASSIGNMENT_SECURITY = 1), 1, 0, 5), ) /datum/event_container/major diff --git a/code/modules/events/event_dynamic.dm b/code/modules/events/event_dynamic.dm index 07cebea073..2cc225eaf6 100644 --- a/code/modules/events/event_dynamic.dm +++ b/code/modules/events/event_dynamic.dm @@ -45,15 +45,9 @@ var/list/event_last_fired = list() // Code/WorkInProgress/Cael_Aislinn/Economy/Economy_Events.dm // Code/WorkInProgress/Cael_Aislinn/Economy/Economy_Events_Mundane.dm - if(ticker.mode && ticker.mode.name == "calamity") //Calamity mode messes with some events. - possibleEvents[/datum/event/borer_infestation] = 400 - possibleEvents[/datum/event/economic_event] = 25 - possibleEvents[/datum/event/trivial_news] = 25 - possibleEvents[/datum/event/mundane_news] = 25 - else - possibleEvents[/datum/event/economic_event] = 300 - possibleEvents[/datum/event/trivial_news] = 400 - possibleEvents[/datum/event/mundane_news] = 300 + possibleEvents[/datum/event/economic_event] = 300 + possibleEvents[/datum/event/trivial_news] = 400 + possibleEvents[/datum/event/mundane_news] = 300 possibleEvents[/datum/event/pda_spam] = max(min(25, player_list.len) * 4, 200) possibleEvents[/datum/event/money_lotto] = max(min(5, player_list.len), 50) @@ -89,10 +83,7 @@ var/list/event_last_fired = list() if(active_with_role["Security"] > 0) if(!sent_spiders_to_station) possibleEvents[/datum/event/spider_infestation] = max(active_with_role["Security"], 5) + 5 - if(config.aliens_allowed && !sent_aliens_to_station) - possibleEvents[/datum/event/alien_infestation] = max(active_with_role["Security"], 5) + 2.5 - if(!sent_ninja_to_station && config.ninjas_allowed) - possibleEvents[/datum/event/space_ninja] = max(active_with_role["Security"], 5) + possibleEvents[/datum/event/random_antag] = max(active_with_role["Security"], 5) + 2.5 for(var/event_type in event_last_fired) if(possibleEvents[event_type]) var/time_passed = world.time - event_last_fired[event_type] diff --git a/code/modules/events/random_antagonist.dm b/code/modules/events/random_antagonist.dm new file mode 100644 index 0000000000..dbdaa70983 --- /dev/null +++ b/code/modules/events/random_antagonist.dm @@ -0,0 +1,13 @@ +// The random spawn proc on the antag datum will handle announcing the spawn and whatnot. +/datum/event/random_antag/announce() + return + +/datum/event/random_antag/start() + var/list/valid_types = list() + for(var/antag_type in all_antag_types) + var/datum/antagonist/antag = all_antag_types[antag_type] + if(antag.flags & ANTAG_RANDSPAWN) + valid_types |= antag + if(valid_types.len) + var/datum/antagonist/antag = pick(valid_types) + antag.random_spawn() \ No newline at end of file diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 7022954c6c..d352ee93a7 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -229,8 +229,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp //world << "DEBUG: ticker not null" if(ticker.mode.name == "AI malfunction") //world << "DEBUG: malf mode ticker test" - if(ticker.mode:malf_mode_declared) - stat(null, "Time left: [max(ticker.mode:AI_win_timeleft/(ticker.mode:apcs/3), 0)]") + if(malf.revealed) + stat(null, "Time left: [max(malf.hack_time/(malf.hacked_apcs.len/3), 0)]") if(emergency_shuttle) var/eta_status = emergency_shuttle.get_status_panel_eta() if(eta_status) @@ -492,8 +492,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/ghosts_can_write if(ticker.mode.name == "cult") - var/datum/game_mode/cult/C = ticker.mode - if(C.cult.len > config.cult_ghostwriter_req_cultists) + if(cult.current_antagonists.len > config.cult_ghostwriter_req_cultists) ghosts_can_write = 1 if(!ghosts_can_write) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 6ac676b8f0..fd8be289e9 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -48,8 +48,8 @@ stat(null, "Intent: [a_intent]") stat(null, "Move Mode: [m_intent]") if(ticker && ticker.mode && ticker.mode.name == "AI malfunction") - if(ticker.mode:malf_mode_declared) - stat(null, "Time left: [max(ticker.mode:AI_win_timeleft/(ticker.mode:apcs/3), 0)]") + if(malf.revealed) + stat(null, "Time left: [max(malf.hack_time/(malf.hacked_apcs/3), 0)]") if(emergency_shuttle) var/eta_status = emergency_shuttle.get_status_panel_eta() if(eta_status) @@ -196,6 +196,7 @@ var/datum/organ/external/affected = M.organs_by_name["head"] affected.implants += L L.part = affected + L.implanted(src) /mob/living/carbon/human/proc/is_loyalty_implanted(mob/living/carbon/human/M) for(var/L in M.contents) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 6012adb0dd..ff02684de8 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -251,9 +251,6 @@ emp_act if(prob(I.force)) apply_effect(20, PARALYZE, armor) visible_message("\red [src] has been knocked unconscious!") - if(src != user && I.damtype == BRUTE) - ticker.mode.remove_revolutionary(mind) - if(bloody)//Apply blood if(wear_mask) wear_mask.add_blood(src) @@ -372,13 +369,13 @@ emp_act var/obj/item/I = O mass = I.w_class/THROWNOBJ_KNOCKBACK_DIVISOR var/momentum = speed*mass - + if(O.throw_source && momentum >= THROWNOBJ_KNOCKBACK_SPEED) var/dir = get_dir(O.throw_source, src) visible_message("\red [src] staggers under the impact!","\red You stagger under the impact!") src.throw_at(get_edge_target_turf(src,dir),1,momentum) - + if(!O || !src) return if(O.loc == src && O.sharp) //Projectile is embedded and suitable for pinning. @@ -392,7 +389,7 @@ emp_act /mob/living/carbon/human/embed(var/obj/O, var/def_zone=null) if(!def_zone) ..() - + var/datum/organ/external/affecting = get_organ(def_zone) if(affecting) affecting.embed(O) diff --git a/code/modules/mob/living/carbon/human/login.dm b/code/modules/mob/living/carbon/human/login.dm index d18d503502..7d507c62cb 100644 --- a/code/modules/mob/living/carbon/human/login.dm +++ b/code/modules/mob/living/carbon/human/login.dm @@ -1,6 +1,5 @@ /mob/living/carbon/human/Login() ..() update_hud() - ticker.mode.update_all_synd_icons() //This proc only sounds CPU-expensive on paper. It is O(n^2), but the outer for-loop only iterates through syndicates, which are only prsenet in nuke rounds and even when they exist, there's usually 6 of them. if(species) species.handle_login_special(src) return \ No newline at end of file diff --git a/code/modules/mob/living/login.dm b/code/modules/mob/living/login.dm index 52f0630a39..383a81f13b 100644 --- a/code/modules/mob/living/login.dm +++ b/code/modules/mob/living/login.dm @@ -6,21 +6,5 @@ mind.active = 1 //indicates that the mind is currently synced with a client //If they're SSD, remove it so they can wake back up. player_logged = 0 - - //Round specific stuff like hud updates - if(ticker && ticker.mode) - switch(ticker.mode.name) - if("revolution") - if((mind in ticker.mode.revolutionaries) || (src.mind in ticker.mode:head_revolutionaries)) - ticker.mode.update_rev_icons_added(src.mind) - if("cult") - if(mind in ticker.mode:cult) - ticker.mode.update_cult_icons_added(src.mind) - if("mercenary") - if(mind in ticker.mode:syndicates) - ticker.mode.update_all_synd_icons() - if("mutiny") - var/datum/game_mode/mutiny/mode = get_mutiny_mode() - if(mode) - mode.update_all_icons() + update_antag_icons(mind) return . diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index bb0110cd20..46d878d4b7 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -189,7 +189,7 @@ var/list/ai_verbs_default = list( src << radio_text - if (!(ticker && ticker.mode && (mind in ticker.mode.malf_ai))) + if (!(ticker && ticker.mode && (mind in malf.current_antagonists))) show_laws() src << "These laws may be changed by other players, or by you being the traitor." @@ -312,17 +312,15 @@ var/list/ai_verbs_default = list( /mob/living/silicon/ai/proc/is_malf() if(ticker.mode.name == "AI malfunction") - var/datum/game_mode/malfunction/malf = ticker.mode - for (var/datum/mind/malfai in malf.malf_ai) + for (var/datum/mind/malfai in malf.current_antagonists) if (mind == malfai) return malf return 0 // displays the malf_ai information if the AI is the malf /mob/living/silicon/ai/show_malf_ai() - var/datum/game_mode/malfunction/malf = is_malf() - if(malf && malf.apcs >= 3) - stat(null, "Time until station control secured: [max(malf.AI_win_timeleft/(malf.apcs/3), 0)] seconds") + if(malf && malf.hacked_apcs.len >= 3) + stat(null, "Time until station control secured: [max(malf.hack_time/(malf.hacked_apcs/3), 0)] seconds") // this verb lets the ai see the stations manifest /mob/living/silicon/ai/proc/ai_roster() @@ -585,16 +583,6 @@ var/list/ai_verbs_default = list( holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo4")) return -/*/mob/living/silicon/ai/proc/corereturn() - set category = "Malfunction" - set name = "Return to Main Core" - - var/obj/machinery/power/apc/apc = src.loc - if(!istype(apc)) - src << "\blue You are already in your Main Core." - return - apc.malfvacate()*/ - //Toggles the luminosity and applies it by re-entereing the camera. /mob/living/silicon/ai/proc/toggle_camera_light() set name = "Toggle Camera Light" diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm index 4b408193b7..4a43103da8 100644 --- a/code/modules/mob/living/silicon/ai/death.dm +++ b/code/modules/mob/living/silicon/ai/death.dm @@ -35,7 +35,7 @@ break callshuttle++ - if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || sent_strike_team) + if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction") callshuttle = 0 if(callshuttle == 3) //if all three conditions are met diff --git a/code/modules/mob/living/silicon/ai/latejoin.dm b/code/modules/mob/living/silicon/ai/latejoin.dm index 8aca00a711..b34ceca18b 100644 --- a/code/modules/mob/living/silicon/ai/latejoin.dm +++ b/code/modules/mob/living/silicon/ai/latejoin.dm @@ -36,9 +36,7 @@ var/global/list/empty_playable_ai_cores = list() if(mind.objectives.len) del(mind.objectives) mind.special_role = null - else - if(ticker.mode.name == "AutoTraitor") - var/datum/game_mode/traitor/autotraitor/current_mode = ticker.mode - current_mode.possible_traitors.Remove(src) + + clear_antag_roles(mind) del(src) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/login.dm b/code/modules/mob/living/silicon/login.dm index a95a754eae..3ffefc73c8 100644 --- a/code/modules/mob/living/silicon/login.dm +++ b/code/modules/mob/living/silicon/login.dm @@ -1,6 +1,3 @@ /mob/living/silicon/Login() sleeping = 0 - if(mind && ticker && ticker.mode) - ticker.mode.remove_cultist(mind, 1) - ticker.mode.remove_revolutionary(mind, 1) ..() \ No newline at end of file diff --git a/code/modules/mob/living/silicon/pai/recruit.dm b/code/modules/mob/living/silicon/pai/recruit.dm index 650b20cf7c..f7814b77f3 100644 --- a/code/modules/mob/living/silicon/pai/recruit.dm +++ b/code/modules/mob/living/silicon/pai/recruit.dm @@ -43,8 +43,7 @@ var/datum/paiController/paiController // Global handler for pAI candidates card.setPersonality(pai) card.looking_for_personality = 0 - ticker.mode.update_cult_icons_removed(card.pai.mind) - ticker.mode.update_rev_icons_removed(card.pai.mind) + if(pai.mind) update_antag_icons(pai.mind) pai_candidates -= candidate usr << browse(null, "window=findPai") diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index 80e0f12cf1..557bad2a7e 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -221,16 +221,15 @@ src.healths.icon_state = "health7" if (src.syndicate && src.client) - if(ticker.mode.name == "traitor") - for(var/datum/mind/tra in ticker.mode.traitors) - if(tra.current) - var/I = image('icons/mob/mob.dmi', loc = tra.current, icon_state = "traitor") - src.client.images += I + for(var/datum/mind/tra in traitors.current_antagonists) + if(tra.current) + var/I = image('icons/mob/mob.dmi', loc = tra.current, icon_state = "traitor") + src.client.images += I src.disconnect_from_ai() if(src.mind) if(!src.mind.special_role) src.mind.special_role = "traitor" - ticker.mode.traitors += src.mind + traitors.current_antagonists |= src.mind if (src.cells) if (src.cell) diff --git a/code/modules/mob/living/silicon/robot/login.dm b/code/modules/mob/living/silicon/robot/login.dm index 4299fc730f..eac71acfcd 100644 --- a/code/modules/mob/living/silicon/robot/login.dm +++ b/code/modules/mob/living/silicon/robot/login.dm @@ -2,7 +2,6 @@ ..() regenerate_icons() show_laws(0) - if(mind) ticker.mode.remove_revolutionary(mind) winset(src, null, "mainwindow.macro=borgmacro hotkey_toggle.is-checked=false input.focus=true input.background-color=#D3B5B5") diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index aa83043d14..2c95605574 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -506,15 +506,13 @@ // this function shows information about the malf_ai gameplay type in the status screen /mob/living/silicon/robot/show_malf_ai() ..() - if(ticker.mode.name == "AI malfunction") - var/datum/game_mode/malfunction/malf = ticker.mode - for (var/datum/mind/malfai in malf.malf_ai) - if(connected_ai) - if(connected_ai.mind == malfai) - if(malf.apcs >= 3) - stat(null, "Time until station control secured: [max(malf.AI_win_timeleft/(malf.apcs/3), 0)] seconds") - else if(ticker.mode:malf_mode_declared) - stat(null, "Time left: [max(ticker.mode:AI_win_timeleft/(ticker.mode:apcs/3), 0)]") + for (var/datum/mind/malfai in malf.current_antagonists) + if(connected_ai) + if(connected_ai.mind == malfai) + if(malf.hacked_apcs >= 3) + stat(null, "Time until station control secured: [max(malf.hack_time/(malf.hacked_apcs/3), 0)] seconds") + else if(malf.revealed) + stat(null, "Time left: [max(malf.hack_time/(malf.hacked_apcs.len/3), 0)]") return 0 diff --git a/code/modules/mob/living/simple_animal/borer/borer.dm b/code/modules/mob/living/simple_animal/borer/borer.dm index 43aa9a9d68..9c2e9ca770 100644 --- a/code/modules/mob/living/simple_animal/borer/borer.dm +++ b/code/modules/mob/living/simple_animal/borer/borer.dm @@ -1,5 +1,3 @@ -/datum/game_mode/var/list/borers = list() - /mob/living/simple_animal/borer name = "cortical borer" real_name = "cortical borer" @@ -155,7 +153,7 @@ //If they're not a proper traitor, reset their antag status. if(host.mind.special_role == "Borer Thrall") host << "You are no longer an antagonist." - ticker.mode.borers -= host.mind + borers.hosts -= host.mind host.mind.special_role = null src.loc = get_turf(host) diff --git a/code/modules/mob/living/simple_animal/borer/borer_powers.dm b/code/modules/mob/living/simple_animal/borer/borer_powers.dm index 59f6aed6f0..af2a923c96 100644 --- a/code/modules/mob/living/simple_animal/borer/borer_powers.dm +++ b/code/modules/mob/living/simple_animal/borer/borer_powers.dm @@ -106,7 +106,7 @@ //Update their traitor status. if(host.mind) if(!host.mind.special_role) - ticker.mode.borers |= host.mind + borers.hosts |= host.mind host.mind.special_role = "Borer Thrall" host << "A creeping lassitude surrounds you. Your mind is being invaded by an alien intelligence and that's just fine." host << "You are now a thrall to a cortical borer. Please listen to what they have to say; they're in your head." diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs/constructs.dm similarity index 96% rename from code/modules/mob/living/simple_animal/constructs.dm rename to code/modules/mob/living/simple_animal/constructs/constructs.dm index eae7f3e063..23718fb883 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs/constructs.dm @@ -1,312 +1,309 @@ - -/mob/living/simple_animal/construct - name = "Construct" - real_name = "Construct" - desc = "" - speak_emote = list("hisses") - emote_hear = list("wails","screeches") - response_help = "thinks better of touching" - response_disarm = "flails at" - response_harm = "punches" - icon_dead = "shade_dead" - speed = -1 - a_intent = "harm" - stop_automated_movement = 1 - status_flags = CANPUSH - universal_speak = 1 - attack_sound = 'sound/weapons/punch1.ogg' - min_oxy = 0 - max_oxy = 0 - min_tox = 0 - max_tox = 0 - min_co2 = 0 - max_co2 = 0 - min_n2 = 0 - max_n2 = 0 - minbodytemp = 0 - faction = "cult" - var/list/construct_spells = list() - -/mob/living/simple_animal/construct/New() - ..() - name = text("[initial(name)] ([rand(1, 1000)])") - real_name = name - for(var/spell in construct_spells) - spell_list += new spell(src) - -/mob/living/simple_animal/construct/death() - new /obj/item/weapon/ectoplasm (src.loc) - ..(null,"collapses in a shattered heap.") - ghostize() - del src - - -/mob/living/simple_animal/construct/attack_generic(var/mob/user) - if(istype(user, /mob/living/simple_animal/construct/builder)) - if(health < maxHealth) - adjustBruteLoss(-5) - user.visible_message("\The [user] mends some of \the [src]'s wounds.") - else - user << "\The [src] is undamaged." - return - return ..() - -/mob/living/simple_animal/construct/examine(mob/user) - ..(user) - var/msg = "" - if (src.health < src.maxHealth) - msg += "" - if (src.health >= src.maxHealth/2) - msg += "It looks slightly dented.\n" - else - msg += "It looks severely dented!\n" - msg += "" - msg += "*---------*" - - user << msg - return - -/mob/living/simple_animal/construct/Bump(atom/movable/AM as mob|obj, yes) - if ((!( yes ) || now_pushing)) - return - now_pushing = 1 - if(ismob(AM)) - var/mob/tmob = AM - if(!(tmob.status_flags & CANPUSH)) - now_pushing = 0 - return - - tmob.LAssailant = src - now_pushing = 0 - ..() - if (!istype(AM, /atom/movable)) - return - if (!( now_pushing )) - now_pushing = 1 - if (!( AM.anchored )) - var/t = get_dir(src, AM) - if (istype(AM, /obj/structure/window)) - var/obj/structure/window/W = AM - if(W.is_full_window()) - for(var/obj/structure/window/win in get_step(AM,t)) - now_pushing = 0 - return - step(AM, t) - now_pushing = null - -/mob/living/simple_animal/construct/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(O.force) - var/damage = O.force - if (O.damtype == HALLOSS) - damage = 0 - adjustBruteLoss(damage) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\red \b [src] has been attacked with [O] by [user]. ") - else - usr << "\red This weapon is ineffective, it does no damage." - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\red [user] gently taps [src] with [O]. ") - - - -/////////////////Juggernaut/////////////// - - - -/mob/living/simple_animal/construct/armoured - name = "Juggernaut" - real_name = "Juggernaut" - desc = "A possessed suit of armour driven by the will of the restless dead" - icon = 'icons/mob/mob.dmi' - icon_state = "behemoth" - icon_living = "behemoth" - maxHealth = 250 - health = 250 - response_harm = "harmlessly punches" - harm_intent_damage = 0 - melee_damage_lower = 30 - melee_damage_upper = 30 - attacktext = "smashed their armoured gauntlet into" - mob_size = 20 - speed = 3 - wall_smash = 1 - attack_sound = 'sound/weapons/punch3.ogg' - status_flags = 0 - construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall) - -/mob/living/simple_animal/construct/armoured/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(O.force) - if(O.force >= 11) - var/damage = O.force - if (O.damtype == HALLOSS) - damage = 0 - adjustBruteLoss(damage) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\red \b [src] has been attacked with [O] by [user]. ") - else - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\red \b [O] bounces harmlessly off of [src]. ") - else - usr << "\red This weapon is ineffective, it does no damage." - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\red [user] gently taps [src] with [O]. ") - - -/mob/living/simple_animal/construct/armoured/Life() - weakened = 0 - ..() - -/mob/living/simple_animal/construct/armoured/bullet_act(var/obj/item/projectile/P) - if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)) - var/reflectchance = 80 - round(P.damage/3) - if(prob(reflectchance)) - adjustBruteLoss(P.damage * 0.5) - visible_message("\The [P] was reflected by \the [src]'s shell!", \ - "\The [P] was reflected by \the [src]'s shell!") - - // Find a turf near or on the original location to bounce to - if(P.starting) - var/new_x = P.starting.x + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3) - var/new_y = P.starting.y + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3) - var/turf/curloc = get_turf(src) - - // redirect the projectile - P.redirect(new_x, new_y, curloc, src) - - return -1 // complete projectile permutation - - return (..(P)) - - - -////////////////////////Wraith///////////////////////////////////////////// - - - -/mob/living/simple_animal/construct/wraith - name = "Wraith" - real_name = "Wraith" - desc = "A wicked bladed shell contraption piloted by a bound spirit" - icon = 'icons/mob/mob.dmi' - icon_state = "floating" - icon_living = "floating" - maxHealth = 75 - health = 75 - melee_damage_lower = 25 - melee_damage_upper = 25 - attacktext = "slashed" - speed = -1 - see_in_dark = 7 - attack_sound = 'sound/weapons/bladeslice.ogg' - construct_spells = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift) - - - -/////////////////////////////Artificer///////////////////////// - - - -/mob/living/simple_animal/construct/builder - name = "Artificer" - real_name = "Artificer" - desc = "A bulbous construct dedicated to building and maintaining The Cult of Nar-Sie's armies" - icon = 'icons/mob/mob.dmi' - icon_state = "artificer" - icon_living = "artificer" - maxHealth = 50 - health = 50 - response_harm = "viciously beats" - harm_intent_damage = 5 - melee_damage_lower = 5 - melee_damage_upper = 5 - attacktext = "rammed" - speed = 0 - wall_smash = 1 - attack_sound = 'sound/weapons/punch2.ogg' - construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/construct/lesser, - /obj/effect/proc_holder/spell/aoe_turf/conjure/wall, - /obj/effect/proc_holder/spell/aoe_turf/conjure/floor, - /obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone,) - - -/////////////////////////////Behemoth///////////////////////// - - -/mob/living/simple_animal/construct/behemoth - name = "Behemoth" - real_name = "Behemoth" - desc = "The pinnacle of occult technology, Behemoths are the ultimate weapon in the Cult of Nar-Sie's arsenal." - icon = 'icons/mob/mob.dmi' - icon_state = "behemoth" - icon_living = "behemoth" - maxHealth = 750 - health = 750 - speak_emote = list("rumbles") - response_harm = "harmlessly punches" - harm_intent_damage = 0 - melee_damage_lower = 50 - melee_damage_upper = 50 - attacktext = "brutally crushed" - speed = 5 - wall_smash = 1 - attack_sound = 'sound/weapons/punch4.ogg' - mob_size = 20 - var/energy = 0 - var/max_energy = 1000 - -/mob/living/simple_animal/construct/behemoth/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(O.force) - if(O.force >= 11) - var/damage = O.force - if (O.damtype == HALLOSS) - damage = 0 - adjustBruteLoss(damage) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\red \b [src] has been attacked with [O] by [user]. ") - else - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\red \b [O] bounces harmlessly off of [src]. ") - else - usr << "\red This weapon is ineffective, it does no damage." - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\red [user] gently taps [src] with [O]. ") - - - -////////////////Powers////////////////// - - -/* -/client/proc/summon_cultist() - set category = "Behemoth" - set name = "Summon Cultist (300)" - set desc = "Teleport a cultist to your location" - if (istype(usr,/mob/living/simple_animal/constructbehemoth)) - - if(usr.energy<300) - usr << "\red You do not have enough power stored!" - return - - if(usr.stat) - return - - usr.energy -= 300 - var/list/mob/living/cultists = new - for(var/datum/mind/H in ticker.mode.cult) - if (istype(H.current,/mob/living)) - cultists+=H.current - var/mob/cultist = input("Choose the one who you want to summon", "Followers of Geometer") as null|anything in (cultists - usr) - if(!cultist) - return - if (cultist == usr) //just to be sure. - return - cultist.loc = usr.loc - usr.visible_message("/red [cultist] appears in a flash of red light as [usr] glows with power")*/ + +/mob/living/simple_animal/construct + name = "Construct" + real_name = "Construct" + desc = "" + speak_emote = list("hisses") + emote_hear = list("wails","screeches") + response_help = "thinks better of touching" + response_disarm = "flails at" + response_harm = "punches" + icon_dead = "shade_dead" + speed = -1 + a_intent = "harm" + stop_automated_movement = 1 + status_flags = CANPUSH + universal_speak = 1 + attack_sound = 'sound/weapons/punch1.ogg' + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + minbodytemp = 0 + faction = "cult" + var/list/construct_spells = list() + +/mob/living/simple_animal/construct/New() + ..() + name = text("[initial(name)] ([rand(1, 1000)])") + real_name = name + for(var/spell in construct_spells) + spell_list += new spell(src) + +/mob/living/simple_animal/construct/death() + new /obj/item/weapon/ectoplasm (src.loc) + ..(null,"collapses in a shattered heap.") + ghostize() + del src + + +/mob/living/simple_animal/construct/attack_generic(var/mob/user) + if(istype(user, /mob/living/simple_animal/construct/builder)) + if(health < maxHealth) + adjustBruteLoss(-5) + user.visible_message("\The [user] mends some of \the [src]'s wounds.") + else + user << "\The [src] is undamaged." + return + return ..() + +/mob/living/simple_animal/construct/examine(mob/user) + ..(user) + var/msg = "" + if (src.health < src.maxHealth) + msg += "" + if (src.health >= src.maxHealth/2) + msg += "It looks slightly dented.\n" + else + msg += "It looks severely dented!\n" + msg += "" + msg += "*---------*" + + user << msg + return + +/mob/living/simple_animal/construct/Bump(atom/movable/AM as mob|obj, yes) + if ((!( yes ) || now_pushing)) + return + now_pushing = 1 + if(ismob(AM)) + var/mob/tmob = AM + if(!(tmob.status_flags & CANPUSH)) + now_pushing = 0 + return + + tmob.LAssailant = src + now_pushing = 0 + ..() + if (!istype(AM, /atom/movable)) + return + if (!( now_pushing )) + now_pushing = 1 + if (!( AM.anchored )) + var/t = get_dir(src, AM) + if (istype(AM, /obj/structure/window)) + var/obj/structure/window/W = AM + if(W.is_full_window()) + for(var/obj/structure/window/win in get_step(AM,t)) + now_pushing = 0 + return + step(AM, t) + now_pushing = null + +/mob/living/simple_animal/construct/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(O.force) + var/damage = O.force + if (O.damtype == HALLOSS) + damage = 0 + adjustBruteLoss(damage) + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red \b [src] has been attacked with [O] by [user]. ") + else + usr << "\red This weapon is ineffective, it does no damage." + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red [user] gently taps [src] with [O]. ") + + + +/////////////////Juggernaut/////////////// +/mob/living/simple_animal/construct/armoured + name = "Juggernaut" + real_name = "Juggernaut" + desc = "A possessed suit of armour driven by the will of the restless dead" + icon = 'icons/mob/mob.dmi' + icon_state = "behemoth" + icon_living = "behemoth" + maxHealth = 250 + health = 250 + response_harm = "harmlessly punches" + harm_intent_damage = 0 + melee_damage_lower = 30 + melee_damage_upper = 30 + attacktext = "smashed their armoured gauntlet into" + mob_size = 20 + speed = 3 + wall_smash = 1 + attack_sound = 'sound/weapons/punch3.ogg' + status_flags = 0 + construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall) + +/mob/living/simple_animal/construct/armoured/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(O.force) + if(O.force >= 11) + var/damage = O.force + if (O.damtype == HALLOSS) + damage = 0 + adjustBruteLoss(damage) + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red \b [src] has been attacked with [O] by [user]. ") + else + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red \b [O] bounces harmlessly off of [src]. ") + else + usr << "\red This weapon is ineffective, it does no damage." + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red [user] gently taps [src] with [O]. ") + + +/mob/living/simple_animal/construct/armoured/Life() + weakened = 0 + ..() + +/mob/living/simple_animal/construct/armoured/bullet_act(var/obj/item/projectile/P) + if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)) + var/reflectchance = 80 - round(P.damage/3) + if(prob(reflectchance)) + adjustBruteLoss(P.damage * 0.5) + visible_message("\The [P] was reflected by \the [src]'s shell!", \ + "\The [P] was reflected by \the [src]'s shell!") + + // Find a turf near or on the original location to bounce to + if(P.starting) + var/new_x = P.starting.x + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3) + var/new_y = P.starting.y + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3) + var/turf/curloc = get_turf(src) + + // redirect the projectile + P.redirect(new_x, new_y, curloc, src) + + return -1 // complete projectile permutation + + return (..(P)) + + + +////////////////////////Wraith///////////////////////////////////////////// + + + +/mob/living/simple_animal/construct/wraith + name = "Wraith" + real_name = "Wraith" + desc = "A wicked bladed shell contraption piloted by a bound spirit" + icon = 'icons/mob/mob.dmi' + icon_state = "floating" + icon_living = "floating" + maxHealth = 75 + health = 75 + melee_damage_lower = 25 + melee_damage_upper = 25 + attacktext = "slashed" + speed = -1 + see_in_dark = 7 + attack_sound = 'sound/weapons/bladeslice.ogg' + construct_spells = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift) + + + +/////////////////////////////Artificer///////////////////////// + + + +/mob/living/simple_animal/construct/builder + name = "Artificer" + real_name = "Artificer" + desc = "A bulbous construct dedicated to building and maintaining The Cult of Nar-Sie's armies" + icon = 'icons/mob/mob.dmi' + icon_state = "artificer" + icon_living = "artificer" + maxHealth = 50 + health = 50 + response_harm = "viciously beats" + harm_intent_damage = 5 + melee_damage_lower = 5 + melee_damage_upper = 5 + attacktext = "rammed" + speed = 0 + wall_smash = 1 + attack_sound = 'sound/weapons/punch2.ogg' + construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/construct/lesser, + /obj/effect/proc_holder/spell/aoe_turf/conjure/wall, + /obj/effect/proc_holder/spell/aoe_turf/conjure/floor, + /obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone,) + + +/////////////////////////////Behemoth///////////////////////// + + +/mob/living/simple_animal/construct/behemoth + name = "Behemoth" + real_name = "Behemoth" + desc = "The pinnacle of occult technology, Behemoths are the ultimate weapon in the Cult of Nar-Sie's arsenal." + icon = 'icons/mob/mob.dmi' + icon_state = "behemoth" + icon_living = "behemoth" + maxHealth = 750 + health = 750 + speak_emote = list("rumbles") + response_harm = "harmlessly punches" + harm_intent_damage = 0 + melee_damage_lower = 50 + melee_damage_upper = 50 + attacktext = "brutally crushed" + speed = 5 + wall_smash = 1 + attack_sound = 'sound/weapons/punch4.ogg' + mob_size = 20 + var/energy = 0 + var/max_energy = 1000 + +/mob/living/simple_animal/construct/behemoth/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(O.force) + if(O.force >= 11) + var/damage = O.force + if (O.damtype == HALLOSS) + damage = 0 + adjustBruteLoss(damage) + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red \b [src] has been attacked with [O] by [user]. ") + else + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red \b [O] bounces harmlessly off of [src]. ") + else + usr << "\red This weapon is ineffective, it does no damage." + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red [user] gently taps [src] with [O]. ") + + + +////////////////Powers////////////////// + + +/* +/client/proc/summon_cultist() + set category = "Behemoth" + set name = "Summon Cultist (300)" + set desc = "Teleport a cultist to your location" + if (istype(usr,/mob/living/simple_animal/constructbehemoth)) + + if(usr.energy<300) + usr << "\red You do not have enough power stored!" + return + + if(usr.stat) + return + + usr.energy -= 300 + var/list/mob/living/cultists = new + for(var/datum/mind/H in ticker.mode.cult) + if (istype(H.current,/mob/living)) + cultists+=H.current + var/mob/cultist = input("Choose the one who you want to summon", "Followers of Geometer") as null|anything in (cultists - usr) + if(!cultist) + return + if (cultist == usr) //just to be sure. + return + cultist.loc = usr.loc + usr.visible_message("/red [cultist] appears in a flash of red light as [usr] glows with power")*/ diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/modules/mob/living/simple_animal/constructs/soulstone.dm similarity index 92% rename from code/game/gamemodes/wizard/soulstone.dm rename to code/modules/mob/living/simple_animal/constructs/soulstone.dm index 9b22d7f6d0..339654558b 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/modules/mob/living/simple_animal/constructs/soulstone.dm @@ -174,11 +174,7 @@ var/mob/living/simple_animal/construct/armoured/Z = new /mob/living/simple_animal/construct/armoured (get_turf(T.loc)) Z.key = A.key if(iscultist(U)) - if(ticker.mode.name == "cult") - ticker.mode:add_cultist(Z.mind) - else - ticker.mode.cult+=Z.mind - ticker.mode.update_cult_icons_added(Z.mind) + cult.add_antagonist(Z.mind) del(T) Z << "You are playing a Juggernaut. Though slow, you can withstand extreme punishment, and rip apart enemies and walls alike." Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." @@ -189,11 +185,7 @@ var/mob/living/simple_animal/construct/wraith/Z = new /mob/living/simple_animal/construct/wraith (get_turf(T.loc)) Z.key = A.key if(iscultist(U)) - if(ticker.mode.name == "cult") - ticker.mode:add_cultist(Z.mind) - else - ticker.mode.cult+=Z.mind - ticker.mode.update_cult_icons_added(Z.mind) + cult.add_antagonist(Z.mind) del(T) Z << "You are playing a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls." Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." @@ -204,11 +196,7 @@ var/mob/living/simple_animal/construct/builder/Z = new /mob/living/simple_animal/construct/builder (get_turf(T.loc)) Z.key = A.key if(iscultist(U)) - if(ticker.mode.name == "cult") - ticker.mode:add_cultist(Z.mind) - else - ticker.mode.cult+=Z.mind - ticker.mode.update_cult_icons_added(Z.mind) + cult.add_antagonist(Z.mind) del(T) Z << "You are playing an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, repair allied constructs (by clicking on them), and even create new constructs" Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 44f99bcbb0..98768bfd41 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -398,7 +398,7 @@ var/list/slot_equipment_priority = list( \ if ((stat != 2 || !( ticker ))) usr << "You must be dead to use this!" return - if (ticker.mode.name == "meteor" || ticker.mode.name == "epidemic") //BS12 EDIT + if (ticker.mode.deny_respawn) //BS12 EDIT usr << "Respawn is disabled for this roundtype." return else diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 662715ca21..90e201b382 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -358,8 +358,6 @@ ticker.mode.latespawn(character) - //ticker.mode.latespawn(character) - if(character.mind.assigned_role != "Cyborg") data_core.manifest_inject(character) ticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index b98aa03e84..671be94f53 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -170,16 +170,12 @@ src.update() /obj/machinery/power/apc/Del() - if(malfai && operating) - if (ticker.mode.config_tag == "malfunction") - if (src.z in config.station_levels) //if (is_type_in_list(get_area(src), the_station_areas)) - ticker.mode:apcs-- + if(operating && malf && src.z in config.station_levels) //if (is_type_in_list(get_area(src), the_station_areas)) + malf.hacked_apcs -= src area.power_light = 0 area.power_equip = 0 area.power_environ = 0 area.power_change() - if(occupier) - malfvacate(1) del(wires) if(cell) del(cell) // qdel @@ -740,7 +736,7 @@ /obj/machinery/power/apc/proc/get_malf_status(mob/user) - if (ticker && ticker.mode && (user.mind in ticker.mode.malf_ai) && istype(user, /mob/living/silicon/ai)) + if (malf && (user.mind in malf.current_antagonists) && istype(user, /mob/living/silicon/ai)) if (src.malfai == (user:parent ? user:parent : user)) if (src.occupier == user) return 3 // 3 = User is shunted in this APC @@ -947,9 +943,6 @@ malfai.malfhack = null malfai.malfhacking = 0 locked = 1 - if (ticker.mode.config_tag == "malfunction") - if (src.z in config.station_levels) //if (is_type_in_list(get_area(src), the_station_areas)) - ticker.mode:apcs++ if(usr:parent) src.malfai = usr:parent else @@ -957,14 +950,6 @@ malfai << "Hack complete. The APC is now under your exclusive control." update_icon() - else if (href_list["occupyapc"]) - if(get_malf_status(usr)) - malfoccupy(usr) - - else if (href_list["deoccupyapc"]) - if(get_malf_status(usr)) - malfvacate() - else if (href_list["toggleaccess"]) if(istype(usr, /mob/living/silicon)) if(emagged || (stat & (BROKEN|MAINT))) @@ -977,73 +962,9 @@ /obj/machinery/power/apc/proc/toggle_breaker() operating = !operating - - if(malfai) - if (ticker.mode.config_tag == "malfunction") - if (src.z in config.station_levels) //if (is_type_in_list(get_area(src), the_station_areas)) - operating ? ticker.mode:apcs++ : ticker.mode:apcs-- - src.update() update_icon() -/obj/machinery/power/apc/proc/malfoccupy(var/mob/living/silicon/ai/malf) - return - - if(!istype(malf)) - return - if(istype(malf.loc, /obj/machinery/power/apc)) // Already in an APC - malf << "You must evacuate your current apc first." - return - /*if(!malf.can_shunt) - malf << "You cannot shunt." - return*/ - if(isNotStationLevel(src.z)) - return - src.occupier = new /mob/living/silicon/ai(src,malf.laws,null,1) - src.occupier.adjustOxyLoss(malf.getOxyLoss()) - if(!findtext(src.occupier.name,"APC Copy")) - src.occupier.name = "[malf.name] APC Copy" - if(malf.parent) - src.occupier.parent = malf.parent - else - src.occupier.parent = malf - malf.mind.transfer_to(src.occupier) - src.occupier.eyeobj.name = "[src.occupier.name] (AI Eye)" - if(malf.parent) - del(malf) // qdel - // src.occupier.verbs += /mob/living/silicon/ai/proc/corereturn - src.occupier.verbs += /datum/game_mode/malfunction/proc/takeover - src.occupier.cancel_camera() - if (seclevel2num(get_security_level()) == SEC_LEVEL_DELTA) - for(var/obj/item/weapon/pinpointer/point in world) - point.the_disk = src //the pinpointer will detect the shunted AI - - -/obj/machinery/power/apc/proc/malfvacate(var/forced) - if(!src.occupier) - return - if(src.occupier.parent && src.occupier.parent.stat != 2) - src.occupier.mind.transfer_to(src.occupier.parent) - src.occupier.parent.adjustOxyLoss(src.occupier.getOxyLoss()) - src.occupier.parent.cancel_camera() - del(src.occupier) // qdel - if (seclevel2num(get_security_level()) == SEC_LEVEL_DELTA) - for(var/obj/item/weapon/pinpointer/point in world) - for(var/datum/mind/AI_mind in ticker.mode.malf_ai) - var/mob/living/silicon/ai/A = AI_mind.current // the current mob the mind owns - if(A.stat != DEAD) - point.the_disk = A //The pinpointer tracks the AI back into its core. - - else - src.occupier << "Primary core damaged, unable to return core processes." - if(forced) - src.occupier.loc = src.loc - src.occupier.death() - src.occupier.gib() - for(var/obj/item/weapon/pinpointer/point in world) - point.the_disk = null //the pinpointer will go back to pointing at the nuke disc. - - /obj/machinery/power/apc/proc/ion_act() //intended to be exactly the same as an AI malf attack if(!src.malfhack && src.z in config.station_levels) @@ -1312,10 +1233,6 @@ obj/machinery/power/apc/proc/autoset(var/val, var/on) terminal = null /obj/machinery/power/apc/proc/set_broken() - if(malfai && operating) - if (ticker.mode.config_tag == "malfunction") - if (src.z in config.station_levels) //if (is_type_in_list(get_area(src), the_station_areas)) - ticker.mode:apcs-- // Aesthetically much better! src.visible_message("[src]'s screen flickers with warnings briefly!") spawn(rand(2,5)) @@ -1324,8 +1241,6 @@ obj/machinery/power/apc/proc/autoset(var/val, var/on) operating = 0 update_icon() update() - if(occupier) - malfvacate(1) // overload all the lights in this APC area diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index 0825d9a194..cecdf46a2c 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -511,15 +511,16 @@ var/global/list/uneatable = list( /obj/machinery/singularity/narsie/proc/pickcultist() //Narsie rewards his cultists with being devoured first, then picks a ghost to follow. --NEO var/list/cultists = list() - for(var/datum/mind/cult_nh_mind in ticker.mode.cult) - if(!cult_nh_mind.current) - continue - if(cult_nh_mind.current.stat) - continue - var/turf/pos = get_turf(cult_nh_mind.current) - if(pos.z != src.z) - continue - cultists += cult_nh_mind.current + if(cult && cult.current_antagonists.len) + for(var/datum/mind/cult_nh_mind in cult.current_antagonists) + if(!cult_nh_mind.current) + continue + if(cult_nh_mind.current.stat) + continue + var/turf/pos = get_turf(cult_nh_mind.current) + if(pos.z != src.z) + continue + cultists += cult_nh_mind.current if(cultists.len) acquire(pick(cultists)) return diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm index 4f08f6f0c3..d5a3095e49 100644 --- a/code/modules/reagents/Chemistry-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents.dm @@ -287,11 +287,8 @@ datum on_mob_life(var/mob/living/M as mob) if(ishuman(M)) - if((M.mind in ticker.mode.cult) && prob(10)) - M << "\blue A cooling sensation from inside you brings you an untold calmness." - ticker.mode.remove_cultist(M.mind) - for(var/mob/O in viewers(M, null)) - O.show_message(text("\blue []'s eyes blink and become clearer.", M), 1) // So observers know it worked. + if(M.mind && cult.is_antagonist(M.mind) && prob(10)) + cult.remove_antagonist(M.mind) holder.remove_reagent(src.id, 10 * REAGENTS_METABOLISM) //high metabolism to prevent extended uncult rolls. return diff --git a/code/datums/spells/area_teleport.dm b/code/modules/spells/area_teleport.dm similarity index 96% rename from code/datums/spells/area_teleport.dm rename to code/modules/spells/area_teleport.dm index f30d55455b..05a8e655ed 100644 --- a/code/datums/spells/area_teleport.dm +++ b/code/modules/spells/area_teleport.dm @@ -1,82 +1,82 @@ -/obj/effect/proc_holder/spell/targeted/area_teleport - name = "Area teleport" - desc = "This spell teleports you to a type of area of your selection." - - var/randomise_selection = 0 //if it lets the usr choose the teleport loc or picks it from the list - var/invocation_area = 1 //if the invocation appends the selected area - -/obj/effect/proc_holder/spell/targeted/area_teleport/perform(list/targets, recharge = 1) - var/thearea = before_cast(targets) - if(!thearea || !cast_check(1)) - revert_cast() - return - invocation(thearea) - spawn(0) - if(charge_type == "recharge" && recharge) - start_recharge() - cast(targets,thearea) - after_cast(targets) - -/obj/effect/proc_holder/spell/targeted/area_teleport/before_cast(list/targets) - var/A = null - - if(!randomise_selection) - A = input("Area to teleport to", "Teleport", A) in teleportlocs - else - A = pick(teleportlocs) - - var/area/thearea = teleportlocs[A] - - return thearea - -/obj/effect/proc_holder/spell/targeted/area_teleport/cast(list/targets,area/thearea) - for(var/mob/living/target in targets) - var/list/L = list() - for(var/turf/T in get_area_turfs(thearea.type)) - if(!T.density) - var/clear = 1 - for(var/obj/O in T) - if(O.density) - clear = 0 - break - if(clear) - L+=T - - if(!L.len) - usr <<"The spell matrix was unable to locate a suitable teleport destination for an unknown reason. Sorry." - return - - if(target && target.buckled) - target.buckled.unbuckle_mob() - - var/list/tempL = L - var/attempt = null - var/success = 0 - while(tempL.len) - attempt = pick(tempL) - success = target.Move(attempt) - if(!success) - tempL.Remove(attempt) - else - break - - if(!success) - target.loc = pick(L) - - return - -/obj/effect/proc_holder/spell/targeted/area_teleport/invocation(area/chosenarea = null) - if(!invocation_area || !chosenarea) - ..() - else - switch(invocation_type) - if("shout") - usr.say("[invocation] [uppertext(chosenarea.name)]") - if(usr.gender==MALE) - playsound(usr.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1) - else - playsound(usr.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1) - if("whisper") - usr.whisper("[invocation] [uppertext(chosenarea.name)]") - +/obj/effect/proc_holder/spell/targeted/area_teleport + name = "Area teleport" + desc = "This spell teleports you to a type of area of your selection." + + var/randomise_selection = 0 //if it lets the usr choose the teleport loc or picks it from the list + var/invocation_area = 1 //if the invocation appends the selected area + +/obj/effect/proc_holder/spell/targeted/area_teleport/perform(list/targets, recharge = 1) + var/thearea = before_cast(targets) + if(!thearea || !cast_check(1)) + revert_cast() + return + invocation(thearea) + spawn(0) + if(charge_type == "recharge" && recharge) + start_recharge() + cast(targets,thearea) + after_cast(targets) + +/obj/effect/proc_holder/spell/targeted/area_teleport/before_cast(list/targets) + var/A = null + + if(!randomise_selection) + A = input("Area to teleport to", "Teleport", A) in teleportlocs + else + A = pick(teleportlocs) + + var/area/thearea = teleportlocs[A] + + return thearea + +/obj/effect/proc_holder/spell/targeted/area_teleport/cast(list/targets,area/thearea) + for(var/mob/living/target in targets) + var/list/L = list() + for(var/turf/T in get_area_turfs(thearea.type)) + if(!T.density) + var/clear = 1 + for(var/obj/O in T) + if(O.density) + clear = 0 + break + if(clear) + L+=T + + if(!L.len) + usr <<"The spell matrix was unable to locate a suitable teleport destination for an unknown reason. Sorry." + return + + if(target && target.buckled) + target.buckled.unbuckle_mob() + + var/list/tempL = L + var/attempt = null + var/success = 0 + while(tempL.len) + attempt = pick(tempL) + success = target.Move(attempt) + if(!success) + tempL.Remove(attempt) + else + break + + if(!success) + target.loc = pick(L) + + return + +/obj/effect/proc_holder/spell/targeted/area_teleport/invocation(area/chosenarea = null) + if(!invocation_area || !chosenarea) + ..() + else + switch(invocation_type) + if("shout") + usr.say("[invocation] [uppertext(chosenarea.name)]") + if(usr.gender==MALE) + playsound(usr.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1) + else + playsound(usr.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1) + if("whisper") + usr.whisper("[invocation] [uppertext(chosenarea.name)]") + return \ No newline at end of file diff --git a/code/datums/spells/conjure.dm b/code/modules/spells/conjure.dm similarity index 96% rename from code/datums/spells/conjure.dm rename to code/modules/spells/conjure.dm index 1a48952451..2034bf931f 100644 --- a/code/datums/spells/conjure.dm +++ b/code/modules/spells/conjure.dm @@ -1,87 +1,87 @@ -/obj/effect/proc_holder/spell/aoe_turf/conjure - name = "Conjure" - desc = "This spell conjures objs of the specified types in range." - - var/list/summon_type = list() //determines what exactly will be summoned - //should be text, like list("/obj/machinery/bot/ed209") - - var/summon_lifespan = 0 // 0=permanent, any other time in deciseconds - var/summon_amt = 1 //amount of objects summoned - var/summon_ignore_density = 0 //if set to 1, adds dense tiles to possible spawn places - var/summon_ignore_prev_spawn_points = 0 //if set to 1, each new object is summoned on a new spawn point - - var/list/newVars = list() //vars of the summoned objects will be replaced with those where they meet - //should have format of list("emagged" = 1,"name" = "Wizard's Justicebot"), for example - var/delay = 1//Go Go Gadget Inheritance - -/obj/effect/proc_holder/spell/aoe_turf/conjure/cast(list/targets) - - for(var/turf/T in targets) - if(T.density && !summon_ignore_density) - targets -= T - playsound(src.loc, 'sound/items/welder.ogg', 50, 1) - - if(do_after(usr,delay)) - for(var/i=0,iSome strange aura is blocking the way!" - src.canmove = 0 - spawn(2) src.canmove = 1 - -/obj/effect/dummy/spell_jaunt/ex_act(blah) - return -/obj/effect/dummy/spell_jaunt/bullet_act(blah) +/obj/effect/proc_holder/spell/targeted/ethereal_jaunt + name = "Ethereal Jaunt" + desc = "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls." + + school = "transmutation" + charge_max = 300 + clothes_req = 1 + invocation = "none" + invocation_type = "none" + range = -1 + include_user = 1 + centcomm_cancast = 0 //Prevent people from getting to centcomm + + var phaseshift = 0 + var/jaunt_duration = 50 //in deciseconds + +/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/cast(list/targets) //magnets, so mostly hardcoded + for(var/mob/living/target in targets) + spawn(0) + + if(target.buckled) + var/obj/structure/bed/buckled_to = target.buckled. + buckled_to.unbuckle_mob() + + var/mobloc = get_turf(target.loc) + var/obj/effect/dummy/spell_jaunt/holder = new /obj/effect/dummy/spell_jaunt( mobloc ) + var/atom/movable/overlay/animation = new /atom/movable/overlay( mobloc ) + animation.name = "water" + animation.density = 0 + animation.anchored = 1 + animation.icon = 'icons/mob/mob.dmi' + animation.icon_state = "liquify" + animation.layer = 5 + animation.master = holder + if(phaseshift == 1) + animation.dir = target.dir + flick("phase_shift",animation) + target.loc = holder + target.client.eye = holder + sleep(jaunt_duration) + mobloc = get_turf(target.loc) + animation.loc = mobloc + target.canmove = 0 + sleep(20) + animation.dir = target.dir + flick("phase_shift2",animation) + sleep(5) + if(!target.Move(mobloc)) + for(var/direction in list(1,2,4,8,5,6,9,10)) + var/turf/T = get_step(mobloc, direction) + if(T) + if(target.Move(T)) + break + target.canmove = 1 + target.client.eye = target + del(animation) + del(holder) + else + flick("liquify",animation) + target.loc = holder + target.client.eye = holder + var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread() + steam.set_up(10, 0, mobloc) + steam.start() + sleep(jaunt_duration) + mobloc = get_turf(target.loc) + animation.loc = mobloc + steam.location = mobloc + steam.start() + target.canmove = 0 + sleep(20) + flick("reappear",animation) + sleep(5) + if(!target.Move(mobloc)) + for(var/direction in list(1,2,4,8,5,6,9,10)) + var/turf/T = get_step(mobloc, direction) + if(T) + if(target.Move(T)) + break + target.canmove = 1 + target.client.eye = target + del(animation) + del(holder) + +/obj/effect/dummy/spell_jaunt + name = "water" + icon = 'icons/effects/effects.dmi' + icon_state = "nothing" + var/canmove = 1 + density = 0 + anchored = 1 + +/obj/effect/dummy/spell_jaunt/relaymove(var/mob/user, direction) + if (!src.canmove) return + var/turf/newLoc = get_step(src,direction) + if(!(newLoc.flags & NOJAUNT)) + loc = newLoc + else + user << "Some strange aura is blocking the way!" + src.canmove = 0 + spawn(2) src.canmove = 1 + +/obj/effect/dummy/spell_jaunt/ex_act(blah) + return +/obj/effect/dummy/spell_jaunt/bullet_act(blah) return \ No newline at end of file diff --git a/code/datums/spells/explosion.dm b/code/modules/spells/explosion.dm similarity index 94% rename from code/datums/spells/explosion.dm rename to code/modules/spells/explosion.dm index 7bb7195c2d..b93667ab47 100644 --- a/code/datums/spells/explosion.dm +++ b/code/modules/spells/explosion.dm @@ -1,15 +1,15 @@ -/obj/effect/proc_holder/spell/targeted/explosion - name = "Explosion" - desc = "This spell explodes an area." - - var/ex_severe = 1 - var/ex_heavy = 2 - var/ex_light = 3 - var/ex_flash = 4 - -/obj/effect/proc_holder/spell/targeted/explosion/cast(list/targets) - - for(var/mob/living/target in targets) - explosion(target.loc,ex_severe,ex_heavy,ex_light,ex_flash) - +/obj/effect/proc_holder/spell/targeted/explosion + name = "Explosion" + desc = "This spell explodes an area." + + var/ex_severe = 1 + var/ex_heavy = 2 + var/ex_light = 3 + var/ex_flash = 4 + +/obj/effect/proc_holder/spell/targeted/explosion/cast(list/targets) + + for(var/mob/living/target in targets) + explosion(target.loc,ex_severe,ex_heavy,ex_light,ex_flash) + return \ No newline at end of file diff --git a/code/datums/spells/genetic.dm b/code/modules/spells/genetic.dm similarity index 95% rename from code/datums/spells/genetic.dm rename to code/modules/spells/genetic.dm index cff51ec6ff..bcb7d04280 100644 --- a/code/datums/spells/genetic.dm +++ b/code/modules/spells/genetic.dm @@ -1,31 +1,31 @@ -/obj/effect/proc_holder/spell/targeted/genetic - name = "Genetic" - desc = "This spell inflicts a set of mutations and disabilities upon the target." - - var/disabilities = 0 //bits - var/list/mutations = list() //mutation strings - var/duration = 100 //deciseconds - /* - Disabilities - 1st bit - ? - 2nd bit - ? - 3rd bit - ? - 4th bit - ? - 5th bit - ? - 6th bit - ? - */ - -/obj/effect/proc_holder/spell/targeted/genetic/cast(list/targets) - - for(var/mob/living/target in targets) - for(var/x in mutations) - target.mutations.Add(x) - target.disabilities |= disabilities - target.update_mutations() //update target's mutation overlays - spawn(duration) - for(var/x in mutations) - target.mutations.Remove(x) - target.disabilities &= ~disabilities - target.update_mutations() - +/obj/effect/proc_holder/spell/targeted/genetic + name = "Genetic" + desc = "This spell inflicts a set of mutations and disabilities upon the target." + + var/disabilities = 0 //bits + var/list/mutations = list() //mutation strings + var/duration = 100 //deciseconds + /* + Disabilities + 1st bit - ? + 2nd bit - ? + 3rd bit - ? + 4th bit - ? + 5th bit - ? + 6th bit - ? + */ + +/obj/effect/proc_holder/spell/targeted/genetic/cast(list/targets) + + for(var/mob/living/target in targets) + for(var/x in mutations) + target.mutations.Add(x) + target.disabilities |= disabilities + target.update_mutations() //update target's mutation overlays + spawn(duration) + for(var/x in mutations) + target.mutations.Remove(x) + target.disabilities &= ~disabilities + target.update_mutations() + return \ No newline at end of file diff --git a/code/datums/spells/horsemask.dm b/code/modules/spells/horsemask.dm similarity index 97% rename from code/datums/spells/horsemask.dm rename to code/modules/spells/horsemask.dm index 2ea66dac57..1319f62008 100644 --- a/code/datums/spells/horsemask.dm +++ b/code/modules/spells/horsemask.dm @@ -1,50 +1,50 @@ -/obj/effect/proc_holder/spell/targeted/horsemask - name = "Curse of the Horseman" - desc = "This spell triggers a curse on a target, causing them to wield an unremovable horse head mask. They will speak like a horse! Any masks they are wearing will be disintegrated. This spell does not require robes." - school = "transmutation" - charge_type = "recharge" - charge_max = 150 - charge_counter = 0 - clothes_req = 0 - stat_allowed = 0 - invocation = "KN'A FTAGHU, PUCK 'BTHNK!" - invocation_type = "shout" - range = 7 - selection_type = "range" - var/list/compatible_mobs = list(/mob/living/carbon/human, /mob/living/carbon/monkey) - -/obj/effect/proc_holder/spell/targeted/horsemask/cast(list/targets, mob/user = usr) - if(!targets.len) - user << "No target found in range." - return - - var/mob/living/carbon/target = targets[1] - - if(!(target.type in compatible_mobs)) - user << "It'd be stupid to curse [target] with a horse's head!" - return - - if(!(target in oview(range)))//If they are not in overview after selection. - user << "They are too far away!" - return - - var/obj/item/clothing/mask/horsehead/magic/magichead = new /obj/item/clothing/mask/horsehead/magic - target.visible_message( "[target]'s face lights up in fire, and after the event a horse's head takes its place!", \ - "Your face burns up, and shortly after the fire you realise you have the face of a horse!") - target.equip_to_slot(magichead, slot_wear_mask) - - flick("e_flash", target.flash) - -//item used by the horsehead spell -/obj/item/clothing/mask/horsehead/magic - //flags_inv = null //so you can still see their face... no. How can you recognize someone when their face is completely different? - voicechange = 1 //NEEEEIIGHH - - dropped(mob/user as mob) - canremove = 1 - ..() - - equipped(var/mob/user, var/slot) - if (slot == slot_wear_mask) - canremove = 0 //curses! - ..() +/obj/effect/proc_holder/spell/targeted/horsemask + name = "Curse of the Horseman" + desc = "This spell triggers a curse on a target, causing them to wield an unremovable horse head mask. They will speak like a horse! Any masks they are wearing will be disintegrated. This spell does not require robes." + school = "transmutation" + charge_type = "recharge" + charge_max = 150 + charge_counter = 0 + clothes_req = 0 + stat_allowed = 0 + invocation = "KN'A FTAGHU, PUCK 'BTHNK!" + invocation_type = "shout" + range = 7 + selection_type = "range" + var/list/compatible_mobs = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + +/obj/effect/proc_holder/spell/targeted/horsemask/cast(list/targets, mob/user = usr) + if(!targets.len) + user << "No target found in range." + return + + var/mob/living/carbon/target = targets[1] + + if(!(target.type in compatible_mobs)) + user << "It'd be stupid to curse [target] with a horse's head!" + return + + if(!(target in oview(range)))//If they are not in overview after selection. + user << "They are too far away!" + return + + var/obj/item/clothing/mask/horsehead/magic/magichead = new /obj/item/clothing/mask/horsehead/magic + target.visible_message( "[target]'s face lights up in fire, and after the event a horse's head takes its place!", \ + "Your face burns up, and shortly after the fire you realise you have the face of a horse!") + target.equip_to_slot(magichead, slot_wear_mask) + + flick("e_flash", target.flash) + +//item used by the horsehead spell +/obj/item/clothing/mask/horsehead/magic + //flags_inv = null //so you can still see their face... no. How can you recognize someone when their face is completely different? + voicechange = 1 //NEEEEIIGHH + + dropped(mob/user as mob) + canremove = 1 + ..() + + equipped(var/mob/user, var/slot) + if (slot == slot_wear_mask) + canremove = 0 //curses! + ..() diff --git a/code/datums/spells/inflict_handler.dm b/code/modules/spells/inflict_handler.dm similarity index 94% rename from code/datums/spells/inflict_handler.dm rename to code/modules/spells/inflict_handler.dm index 496eac9195..f9b809c674 100644 --- a/code/datums/spells/inflict_handler.dm +++ b/code/modules/spells/inflict_handler.dm @@ -1,59 +1,59 @@ -/obj/effect/proc_holder/spell/targeted/inflict_handler - name = "Inflict Handler" - desc = "This spell blinds and/or destroys/damages/heals and/or weakens/stuns the target." - - var/amt_weakened = 0 - var/amt_paralysis = 0 - var/amt_stunned = 0 - - //set to negatives for healing - var/amt_dam_fire = 0 - var/amt_dam_brute = 0 - var/amt_dam_oxy = 0 - var/amt_dam_tox = 0 - - var/amt_eye_blind = 0 - var/amt_eye_blurry = 0 - - var/destroys = "none" //can be "none", "gib" or "disintegrate" - -/obj/effect/proc_holder/spell/targeted/inflict_handler/cast(list/targets) - - for(var/mob/living/target in targets) - switch(destroys) - if("gib") - target.gib() - if("gib_brain") - if(ishuman(target) || ismonkey(target)) - var/mob/living/carbon/C = target - if(!C.has_brain()) // Their brain is already taken out - var/obj/item/organ/brain/B = new(C.loc) - B.transfer_identity(C) - target.gib() - if("disintegrate") - target.dust() - - if(!target) - continue - //damage - if(amt_dam_brute > 0) - if(amt_dam_fire >= 0) - target.take_overall_damage(amt_dam_brute,amt_dam_fire) - else if (amt_dam_fire < 0) - target.take_overall_damage(amt_dam_brute,0) - target.heal_overall_damage(0,amt_dam_fire) - else if(amt_dam_brute < 0) - if(amt_dam_fire > 0) - target.take_overall_damage(0,amt_dam_fire) - target.heal_overall_damage(amt_dam_brute,0) - else if (amt_dam_fire <= 0) - target.heal_overall_damage(amt_dam_brute,amt_dam_fire) - target.adjustToxLoss(amt_dam_tox) - target.oxyloss += amt_dam_oxy - //disabling - target.Weaken(amt_weakened) - target.Paralyse(amt_paralysis) - target.Stun(amt_stunned) - - target.eye_blind += amt_eye_blind +/obj/effect/proc_holder/spell/targeted/inflict_handler + name = "Inflict Handler" + desc = "This spell blinds and/or destroys/damages/heals and/or weakens/stuns the target." + + var/amt_weakened = 0 + var/amt_paralysis = 0 + var/amt_stunned = 0 + + //set to negatives for healing + var/amt_dam_fire = 0 + var/amt_dam_brute = 0 + var/amt_dam_oxy = 0 + var/amt_dam_tox = 0 + + var/amt_eye_blind = 0 + var/amt_eye_blurry = 0 + + var/destroys = "none" //can be "none", "gib" or "disintegrate" + +/obj/effect/proc_holder/spell/targeted/inflict_handler/cast(list/targets) + + for(var/mob/living/target in targets) + switch(destroys) + if("gib") + target.gib() + if("gib_brain") + if(ishuman(target) || ismonkey(target)) + var/mob/living/carbon/C = target + if(!C.has_brain()) // Their brain is already taken out + var/obj/item/organ/brain/B = new(C.loc) + B.transfer_identity(C) + target.gib() + if("disintegrate") + target.dust() + + if(!target) + continue + //damage + if(amt_dam_brute > 0) + if(amt_dam_fire >= 0) + target.take_overall_damage(amt_dam_brute,amt_dam_fire) + else if (amt_dam_fire < 0) + target.take_overall_damage(amt_dam_brute,0) + target.heal_overall_damage(0,amt_dam_fire) + else if(amt_dam_brute < 0) + if(amt_dam_fire > 0) + target.take_overall_damage(0,amt_dam_fire) + target.heal_overall_damage(amt_dam_brute,0) + else if (amt_dam_fire <= 0) + target.heal_overall_damage(amt_dam_brute,amt_dam_fire) + target.adjustToxLoss(amt_dam_tox) + target.oxyloss += amt_dam_oxy + //disabling + target.Weaken(amt_weakened) + target.Paralyse(amt_paralysis) + target.Stun(amt_stunned) + + target.eye_blind += amt_eye_blind target.eye_blurry += amt_eye_blurry \ No newline at end of file diff --git a/code/datums/spells/knock.dm b/code/modules/spells/knock.dm similarity index 96% rename from code/datums/spells/knock.dm rename to code/modules/spells/knock.dm index 49d9bb0924..9ebf664942 100644 --- a/code/datums/spells/knock.dm +++ b/code/modules/spells/knock.dm @@ -1,20 +1,20 @@ -/obj/effect/proc_holder/spell/aoe_turf/knock - name = "Knock" - desc = "This spell opens nearby doors and does not require wizard garb." - - school = "transmutation" - charge_max = 100 - clothes_req = 0 - invocation = "AULIE OXIN FIERA" - invocation_type = "whisper" - range = 3 - -/obj/effect/proc_holder/spell/aoe_turf/knock/cast(list/targets) - for(var/turf/T in targets) - for(var/obj/machinery/door/door in T.contents) - spawn(1) - if(istype(door,/obj/machinery/door/airlock)) - var/obj/machinery/door/airlock/A = door - A.unlock(1) //forced because it's magic! - door.open() - return +/obj/effect/proc_holder/spell/aoe_turf/knock + name = "Knock" + desc = "This spell opens nearby doors and does not require wizard garb." + + school = "transmutation" + charge_max = 100 + clothes_req = 0 + invocation = "AULIE OXIN FIERA" + invocation_type = "whisper" + range = 3 + +/obj/effect/proc_holder/spell/aoe_turf/knock/cast(list/targets) + for(var/turf/T in targets) + for(var/obj/machinery/door/door in T.contents) + spawn(1) + if(istype(door,/obj/machinery/door/airlock)) + var/obj/machinery/door/airlock/A = door + A.unlock(1) //forced because it's magic! + door.open() + return diff --git a/code/datums/spells/mind_transfer.dm b/code/modules/spells/mind_transfer.dm similarity index 97% rename from code/datums/spells/mind_transfer.dm rename to code/modules/spells/mind_transfer.dm index c8952cc8a9..80a249615a 100644 --- a/code/datums/spells/mind_transfer.dm +++ b/code/modules/spells/mind_transfer.dm @@ -1,114 +1,114 @@ -/obj/effect/proc_holder/spell/targeted/mind_transfer - name = "Mind Transfer" - desc = "This spell allows the user to switch bodies with a target." - - school = "transmutation" - charge_max = 600 - clothes_req = 0 - invocation = "GIN'YU CAPAN" - invocation_type = "whisper" - range = 1 - var/list/protected_roles = list("Wizard","Changeling","Cultist") //which roles are immune to the spell - var/list/compatible_mobs = list(/mob/living/carbon/human,/mob/living/carbon/monkey) //which types of mobs are affected by the spell. NOTE: change at your own risk - var/base_spell_loss_chance = 20 //base probability of the wizard losing a spell in the process - var/spell_loss_chance_modifier = 7 //amount of probability of losing a spell added per spell (mind_transfer included) - var/spell_loss_amount = 1 //the maximum amount of spells possible to lose during a single transfer - var/msg_wait = 500 //how long in deciseconds it waits before telling that body doesn't feel right or mind swap robbed of a spell - var/paralysis_amount_caster = 20 //how much the caster is paralysed for after the spell - var/paralysis_amount_victim = 20 //how much the victim is paralysed for after the spell - -/* -Urist: I don't feel like figuring out how you store object spells so I'm leaving this for you to do. -Make sure spells that are removed from spell_list are actually removed and deleted when mind transfering. -Also, you never added distance checking after target is selected. I've went ahead and did that. -*/ -/obj/effect/proc_holder/spell/targeted/mind_transfer/cast(list/targets,mob/user = usr) - if(!targets.len) - user << "No mind found." - return - - if(targets.len > 1) - user << "Too many minds! You're not a hive damnit!"//Whaa...aat? - return - - var/mob/living/target = targets[1] - - if(!(target in oview(range)))//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it. - user << "They are too far away!" - return - - if(!(target.type in compatible_mobs)) - user << "Their mind isn't compatible with yours." - return - - if(target.stat == DEAD) - user << "You didn't study necromancy back at the Space Wizard Federation academy." - return - - if(!target.key || !target.mind) - user << "They appear to be catatonic. Not even magic can affect their vacant mind." - return - - if(target.mind.special_role in protected_roles) - user << "Their mind is resisting your spell." - return - - var/mob/living/victim = target//The target of the spell whos body will be transferred to. - var/mob/caster = user//The wizard/whomever doing the body transferring. - - //SPELL LOSS BEGIN - //NOTE: The caster must ALWAYS keep mind transfer, even when other spells are lost. - var/obj/effect/proc_holder/spell/targeted/mind_transfer/m_transfer = locate() in user.spell_list//Find mind transfer directly. - var/list/checked_spells = user.spell_list - checked_spells -= m_transfer //Remove Mind Transfer from the list. - - if(caster.spell_list.len)//If they have any spells left over after mind transfer is taken out. If they don't, we don't need this. - for(var/i=spell_loss_amount,(i>0&&checked_spells.len),i--)//While spell loss amount is greater than zero and checked_spells has spells in it, run this proc. - for(var/j=checked_spells.len,(j>0&&checked_spells.len),j--)//While the spell list to check is greater than zero and has spells in it, run this proc. - if(prob(base_spell_loss_chance)) - checked_spells -= pick(checked_spells)//Pick a random spell to remove. - spawn(msg_wait) - victim << "The mind transfer has robbed you of a spell." - break//Spell lost. Break loop, going back to the previous for() statement. - else//Or keep checking, adding spell chance modifier to increase chance of losing a spell. - base_spell_loss_chance += spell_loss_chance_modifier - - checked_spells += m_transfer//Add back Mind Transfer. - user.spell_list = checked_spells//Set user spell list to whatever the new list is. - //SPELL LOSS END - - //MIND TRANSFER BEGIN - if(caster.mind.special_verbs.len)//If the caster had any special verbs, remove them from the mob verb list. - for(var/V in caster.mind.special_verbs)//Since the caster is using an object spell system, this is mostly moot. - caster.verbs -= V//But a safety nontheless. - - if(victim.mind.special_verbs.len)//Now remove all of the victim's verbs. - for(var/V in victim.mind.special_verbs) - victim.verbs -= V - - var/mob/dead/observer/ghost = victim.ghostize(0) - ghost.spell_list = victim.spell_list//If they have spells, transfer them. Now we basically have a backup mob. - - caster.mind.transfer_to(victim) - victim.spell_list = caster.spell_list//Now they are inside the victim's body. - - if(victim.mind.special_verbs.len)//To add all the special verbs for the original caster. - for(var/V in caster.mind.special_verbs)//Not too important but could come into play. - caster.verbs += V - - ghost.mind.transfer_to(caster) - caster.key = ghost.key //have to transfer the key since the mind was not active - caster.spell_list = ghost.spell_list - - if(caster.mind.special_verbs.len)//If they had any special verbs, we add them here. - for(var/V in caster.mind.special_verbs) - caster.verbs += V - //MIND TRANSFER END - - //Here we paralyze both mobs and knock them out for a time. - caster.Paralyse(paralysis_amount_caster) - victim.Paralyse(paralysis_amount_victim) - - //After a certain amount of time the victim gets a message about being in a different body. - spawn(msg_wait) - caster << "\red You feel woozy and lightheaded. Your body doesn't seem like your own." +/obj/effect/proc_holder/spell/targeted/mind_transfer + name = "Mind Transfer" + desc = "This spell allows the user to switch bodies with a target." + + school = "transmutation" + charge_max = 600 + clothes_req = 0 + invocation = "GIN'YU CAPAN" + invocation_type = "whisper" + range = 1 + var/list/protected_roles = list("Wizard","Changeling","Cultist") //which roles are immune to the spell + var/list/compatible_mobs = list(/mob/living/carbon/human,/mob/living/carbon/monkey) //which types of mobs are affected by the spell. NOTE: change at your own risk + var/base_spell_loss_chance = 20 //base probability of the wizard losing a spell in the process + var/spell_loss_chance_modifier = 7 //amount of probability of losing a spell added per spell (mind_transfer included) + var/spell_loss_amount = 1 //the maximum amount of spells possible to lose during a single transfer + var/msg_wait = 500 //how long in deciseconds it waits before telling that body doesn't feel right or mind swap robbed of a spell + var/paralysis_amount_caster = 20 //how much the caster is paralysed for after the spell + var/paralysis_amount_victim = 20 //how much the victim is paralysed for after the spell + +/* +Urist: I don't feel like figuring out how you store object spells so I'm leaving this for you to do. +Make sure spells that are removed from spell_list are actually removed and deleted when mind transfering. +Also, you never added distance checking after target is selected. I've went ahead and did that. +*/ +/obj/effect/proc_holder/spell/targeted/mind_transfer/cast(list/targets,mob/user = usr) + if(!targets.len) + user << "No mind found." + return + + if(targets.len > 1) + user << "Too many minds! You're not a hive damnit!"//Whaa...aat? + return + + var/mob/living/target = targets[1] + + if(!(target in oview(range)))//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it. + user << "They are too far away!" + return + + if(!(target.type in compatible_mobs)) + user << "Their mind isn't compatible with yours." + return + + if(target.stat == DEAD) + user << "You didn't study necromancy back at the Space Wizard Federation academy." + return + + if(!target.key || !target.mind) + user << "They appear to be catatonic. Not even magic can affect their vacant mind." + return + + if(target.mind.special_role in protected_roles) + user << "Their mind is resisting your spell." + return + + var/mob/living/victim = target//The target of the spell whos body will be transferred to. + var/mob/caster = user//The wizard/whomever doing the body transferring. + + //SPELL LOSS BEGIN + //NOTE: The caster must ALWAYS keep mind transfer, even when other spells are lost. + var/obj/effect/proc_holder/spell/targeted/mind_transfer/m_transfer = locate() in user.spell_list//Find mind transfer directly. + var/list/checked_spells = user.spell_list + checked_spells -= m_transfer //Remove Mind Transfer from the list. + + if(caster.spell_list.len)//If they have any spells left over after mind transfer is taken out. If they don't, we don't need this. + for(var/i=spell_loss_amount,(i>0&&checked_spells.len),i--)//While spell loss amount is greater than zero and checked_spells has spells in it, run this proc. + for(var/j=checked_spells.len,(j>0&&checked_spells.len),j--)//While the spell list to check is greater than zero and has spells in it, run this proc. + if(prob(base_spell_loss_chance)) + checked_spells -= pick(checked_spells)//Pick a random spell to remove. + spawn(msg_wait) + victim << "The mind transfer has robbed you of a spell." + break//Spell lost. Break loop, going back to the previous for() statement. + else//Or keep checking, adding spell chance modifier to increase chance of losing a spell. + base_spell_loss_chance += spell_loss_chance_modifier + + checked_spells += m_transfer//Add back Mind Transfer. + user.spell_list = checked_spells//Set user spell list to whatever the new list is. + //SPELL LOSS END + + //MIND TRANSFER BEGIN + if(caster.mind.special_verbs.len)//If the caster had any special verbs, remove them from the mob verb list. + for(var/V in caster.mind.special_verbs)//Since the caster is using an object spell system, this is mostly moot. + caster.verbs -= V//But a safety nontheless. + + if(victim.mind.special_verbs.len)//Now remove all of the victim's verbs. + for(var/V in victim.mind.special_verbs) + victim.verbs -= V + + var/mob/dead/observer/ghost = victim.ghostize(0) + ghost.spell_list = victim.spell_list//If they have spells, transfer them. Now we basically have a backup mob. + + caster.mind.transfer_to(victim) + victim.spell_list = caster.spell_list//Now they are inside the victim's body. + + if(victim.mind.special_verbs.len)//To add all the special verbs for the original caster. + for(var/V in caster.mind.special_verbs)//Not too important but could come into play. + caster.verbs += V + + ghost.mind.transfer_to(caster) + caster.key = ghost.key //have to transfer the key since the mind was not active + caster.spell_list = ghost.spell_list + + if(caster.mind.special_verbs.len)//If they had any special verbs, we add them here. + for(var/V in caster.mind.special_verbs) + caster.verbs += V + //MIND TRANSFER END + + //Here we paralyze both mobs and knock them out for a time. + caster.Paralyse(paralysis_amount_caster) + victim.Paralyse(paralysis_amount_victim) + + //After a certain amount of time the victim gets a message about being in a different body. + spawn(msg_wait) + caster << "\red You feel woozy and lightheaded. Your body doesn't seem like your own." diff --git a/code/datums/spells/projectile.dm b/code/modules/spells/projectile.dm similarity index 96% rename from code/datums/spells/projectile.dm rename to code/modules/spells/projectile.dm index 9bd1a34f18..24c79a0a1c 100644 --- a/code/datums/spells/projectile.dm +++ b/code/modules/spells/projectile.dm @@ -1,83 +1,83 @@ -/obj/effect/proc_holder/spell/targeted/projectile - name = "Projectile" - desc = "This spell summons projectiles which try to hit the targets." - - var/proj_icon = 'icons/obj/projectiles.dmi' - var/proj_icon_state = "spell" - var/proj_name = "a spell projectile" - - var/proj_trail = 0 //if it leaves a trail - var/proj_trail_lifespan = 0 //deciseconds - var/proj_trail_icon = 'icons/obj/wizard.dmi' - var/proj_trail_icon_state = "trail" - - var/proj_type = "/obj/effect/proc_holder/spell/targeted" //IMPORTANT use only subtypes of this - - var/proj_lingering = 0 //if it lingers or disappears upon hitting an obstacle - var/proj_homing = 1 //if it follows the target - var/proj_insubstantial = 0 //if it can pass through dense objects or not - var/proj_trigger_range = 0 //the range from target at which the projectile triggers cast(target) - - var/proj_lifespan = 15 //in deciseconds * proj_step_delay - var/proj_step_delay = 1 //lower = faster - -/obj/effect/proc_holder/spell/targeted/projectile/cast(list/targets, mob/user = usr) - - for(var/mob/living/target in targets) - spawn(0) - var/obj/effect/proc_holder/spell/targeted/projectile - if(istext(proj_type)) - var/projectile_type = text2path(proj_type) - projectile = new projectile_type(user) - if(istype(proj_type,/obj/effect/proc_holder/spell)) - projectile = new /obj/effect/proc_holder/spell/targeted/trigger(user) - projectile:linked_spells += proj_type - projectile.icon = proj_icon - projectile.icon_state = proj_icon_state - projectile.set_dir(get_dir(target,projectile)) - projectile.name = proj_name - - var/current_loc = usr.loc - - projectile.loc = current_loc - - for(var/i = 0,i < proj_lifespan,i++) - if(!projectile) - break - - if(proj_homing) - if(proj_insubstantial) - projectile.set_dir(get_dir(projectile,target)) - projectile.loc = get_step_to(projectile,target) - else - step_to(projectile,target) - else - if(proj_insubstantial) - projectile.loc = get_step(projectile,dir) - else - step(projectile,dir) - - if(!proj_lingering && projectile.loc == current_loc) //if it didn't move since last time - del(projectile) - break - - if(proj_trail && projectile) - spawn(0) - if(projectile) - var/obj/effect/overlay/trail = new /obj/effect/overlay(projectile.loc) - trail.icon = proj_trail_icon - trail.icon_state = proj_trail_icon_state - trail.density = 0 - spawn(proj_trail_lifespan) - del(trail) - - if(projectile.loc in range(target.loc,proj_trigger_range)) - projectile.perform(list(target)) - break - - current_loc = projectile.loc - - sleep(proj_step_delay) - - if(projectile) +/obj/effect/proc_holder/spell/targeted/projectile + name = "Projectile" + desc = "This spell summons projectiles which try to hit the targets." + + var/proj_icon = 'icons/obj/projectiles.dmi' + var/proj_icon_state = "spell" + var/proj_name = "a spell projectile" + + var/proj_trail = 0 //if it leaves a trail + var/proj_trail_lifespan = 0 //deciseconds + var/proj_trail_icon = 'icons/obj/wizard.dmi' + var/proj_trail_icon_state = "trail" + + var/proj_type = "/obj/effect/proc_holder/spell/targeted" //IMPORTANT use only subtypes of this + + var/proj_lingering = 0 //if it lingers or disappears upon hitting an obstacle + var/proj_homing = 1 //if it follows the target + var/proj_insubstantial = 0 //if it can pass through dense objects or not + var/proj_trigger_range = 0 //the range from target at which the projectile triggers cast(target) + + var/proj_lifespan = 15 //in deciseconds * proj_step_delay + var/proj_step_delay = 1 //lower = faster + +/obj/effect/proc_holder/spell/targeted/projectile/cast(list/targets, mob/user = usr) + + for(var/mob/living/target in targets) + spawn(0) + var/obj/effect/proc_holder/spell/targeted/projectile + if(istext(proj_type)) + var/projectile_type = text2path(proj_type) + projectile = new projectile_type(user) + if(istype(proj_type,/obj/effect/proc_holder/spell)) + projectile = new /obj/effect/proc_holder/spell/targeted/trigger(user) + projectile:linked_spells += proj_type + projectile.icon = proj_icon + projectile.icon_state = proj_icon_state + projectile.set_dir(get_dir(target,projectile)) + projectile.name = proj_name + + var/current_loc = usr.loc + + projectile.loc = current_loc + + for(var/i = 0,i < proj_lifespan,i++) + if(!projectile) + break + + if(proj_homing) + if(proj_insubstantial) + projectile.set_dir(get_dir(projectile,target)) + projectile.loc = get_step_to(projectile,target) + else + step_to(projectile,target) + else + if(proj_insubstantial) + projectile.loc = get_step(projectile,dir) + else + step(projectile,dir) + + if(!proj_lingering && projectile.loc == current_loc) //if it didn't move since last time + del(projectile) + break + + if(proj_trail && projectile) + spawn(0) + if(projectile) + var/obj/effect/overlay/trail = new /obj/effect/overlay(projectile.loc) + trail.icon = proj_trail_icon + trail.icon_state = proj_trail_icon_state + trail.density = 0 + spawn(proj_trail_lifespan) + del(trail) + + if(projectile.loc in range(target.loc,proj_trigger_range)) + projectile.perform(list(target)) + break + + current_loc = projectile.loc + + sleep(proj_step_delay) + + if(projectile) del(projectile) \ No newline at end of file diff --git a/code/datums/spell.dm b/code/modules/spells/spell.dm similarity index 92% rename from code/datums/spell.dm rename to code/modules/spells/spell.dm index c7c12b097b..cfee510475 100644 --- a/code/datums/spell.dm +++ b/code/modules/spells/spell.dm @@ -1,286 +1,302 @@ -/obj/effect/proc_holder - var/panel = "Debug"//What panel the proc holder needs to go on. - -var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin verb for now - -/obj/effect/proc_holder/spell - name = "Spell" - desc = "A wizard spell" - density = 0 - opacity = 0 - - var/school = "evocation" //not relevant at now, but may be important later if there are changes to how spells work. the ones I used for now will probably be changed... maybe spell presets? lacking flexibility but with some other benefit? - - var/charge_type = "recharge" //can be recharge or charges, see charge_max and charge_counter descriptions; can also be based on the holder's vars now, use "holder_var" for that - - var/charge_max = 100 //recharge time in deciseconds if charge_type = "recharge" or starting charges if charge_type = "charges" - var/charge_counter = 0 //can only cast spells if it equals recharge, ++ each decisecond if charge_type = "recharge" or -- each cast if charge_type = "charges" - - var/holder_var_type = "bruteloss" //only used if charge_type equals to "holder_var" - var/holder_var_amount = 20 //same. The amount adjusted with the mob's var when the spell is used - - var/clothes_req = 1 //see if it requires clothes - var/stat_allowed = 0 //see if it requires being conscious/alive, need to set to 1 for ghostpells - var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell - var/invocation_type = "none" //can be none, whisper and shout - var/range = 7 //the range of the spell; outer radius for aoe spells - var/message = "" //whatever it says to the guy affected by it - var/selection_type = "view" //can be "range" or "view" - - var/overlay = 0 - var/overlay_icon = 'icons/obj/wizard.dmi' - var/overlay_icon_state = "spell" - var/overlay_lifespan = 0 - - var/sparks_spread = 0 - var/sparks_amt = 0 //cropped at 10 - var/smoke_spread = 0 //1 - harmless, 2 - harmful - var/smoke_amt = 0 //cropped at 10 - - var/critfailchance = 0 - var/centcomm_cancast = 1 //Whether or not the spell should be allowed on z2 - -/obj/effect/proc_holder/spell/proc/cast_check(skipcharge = 0,mob/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell - - if(!(src in usr.spell_list)) - usr << "\red You shouldn't have this spell! Something's wrong." - return 0 - - if(usr.z == 2 && !centcomm_cancast) //Certain spells are not allowed on the centcomm zlevel - return 0 - - if(!skipcharge) - switch(charge_type) - if("recharge") - if(charge_counter < charge_max) - usr << "[name] is still recharging." - return 0 - if("charges") - if(!charge_counter) - usr << "[name] has no charges left." - return 0 - - if(usr.stat && !stat_allowed) - usr << "Not when you're incapacitated." - return 0 - - if(ishuman(usr) || ismonkey(usr)) - if(istype(usr.wear_mask, /obj/item/clothing/mask/muzzle)) - usr << "Mmmf mrrfff!" - return 0 - - if(clothes_req) //clothes check - if(!istype(usr, /mob/living/carbon/human)) - usr << "You aren't a human, Why are you trying to cast a human spell, silly non-human? Casting human spells is for humans." - return 0 - if(!istype(usr:wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(user:wear_suit, /obj/item/clothing/suit/space/void/wizard)) - usr << "I don't feel strong enough without my robe." - return 0 - if(!istype(usr:shoes, /obj/item/clothing/shoes/sandal)) - usr << "I don't feel strong enough without my sandals." - return 0 - if(!istype(usr:head, /obj/item/clothing/head/wizard) && !istype(user:head, /obj/item/clothing/head/helmet/space/void/wizard)) - usr << "I don't feel strong enough without my hat." - return 0 - - if(!skipcharge) - switch(charge_type) - if("recharge") - charge_counter = 0 //doesn't start recharging until the targets selecting ends - if("charges") - charge_counter-- //returns the charge if the targets selecting fails - if("holdervar") - adjust_var(user, holder_var_type, holder_var_amount) - - return 1 - -/obj/effect/proc_holder/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount - - switch(invocation_type) - if("shout") - if(prob(50))//Auto-mute? Fuck that noise - usr.say(invocation) - else - usr.say(replacetext(invocation," ","`")) - if(usr.gender==MALE) - playsound(usr.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1) - else - playsound(usr.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1) - if("whisper") - if(prob(50)) - usr.whisper(invocation) - else - usr.whisper(replacetext(invocation," ","`")) - -/obj/effect/proc_holder/spell/New() - ..() - - charge_counter = charge_max - -/obj/effect/proc_holder/spell/Click() - if(cast_check()) - choose_targets() - return 1 - -/obj/effect/proc_holder/spell/proc/choose_targets(mob/user = usr) //depends on subtype - /targeted or /aoe_turf - return - -/obj/effect/proc_holder/spell/proc/start_recharge() - while(charge_counter < charge_max) - sleep(1) - charge_counter++ - -/obj/effect/proc_holder/spell/proc/perform(list/targets, recharge = 1) //if recharge is started is important for the trigger spells - before_cast(targets) - invocation() - spawn(0) - if(charge_type == "recharge" && recharge) - start_recharge() - if(prob(critfailchance)) - critfail(targets) - else - cast(targets) - after_cast(targets) - -/obj/effect/proc_holder/spell/proc/before_cast(list/targets) - if(overlay) - for(var/atom/target in targets) - var/location - if(istype(target,/mob/living)) - location = target.loc - else if(istype(target,/turf)) - location = target - var/obj/effect/overlay/spell = new /obj/effect/overlay(location) - spell.icon = overlay_icon - spell.icon_state = overlay_icon_state - spell.anchored = 1 - spell.density = 0 - spawn(overlay_lifespan) - del(spell) - -/obj/effect/proc_holder/spell/proc/after_cast(list/targets) - for(var/atom/target in targets) - var/location - if(istype(target,/mob/living)) - location = target.loc - else if(istype(target,/turf)) - location = target - if(istype(target,/mob/living) && message) - target << text("[message]") - if(sparks_spread) - var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread() - sparks.set_up(sparks_amt, 0, location) //no idea what the 0 is - sparks.start() - if(smoke_spread) - if(smoke_spread == 1) - var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread() - smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is - smoke.start() - else if(smoke_spread == 2) - var/datum/effect/effect/system/smoke_spread/bad/smoke = new /datum/effect/effect/system/smoke_spread/bad() - smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is - smoke.start() - -/obj/effect/proc_holder/spell/proc/cast(list/targets) - return - -/obj/effect/proc_holder/spell/proc/critfail(list/targets) - return - -/obj/effect/proc_holder/spell/proc/revert_cast(mob/user = usr) //resets recharge or readds a charge - switch(charge_type) - if("recharge") - charge_counter = charge_max - if("charges") - charge_counter++ - if("holdervar") - adjust_var(user, holder_var_type, -holder_var_amount) - - return - -/obj/effect/proc_holder/spell/proc/adjust_var(mob/living/target = usr, type, amount) //handles the adjustment of the var when the spell is used. has some hardcoded types - switch(type) - if("bruteloss") - target.adjustBruteLoss(amount) - if("fireloss") - target.adjustFireLoss(amount) - if("toxloss") - target.adjustToxLoss(amount) - if("oxyloss") - target.adjustOxyLoss(amount) - if("stunned") - target.AdjustStunned(amount) - if("weakened") - target.AdjustWeakened(amount) - if("paralysis") - target.AdjustParalysis(amount) - else - target.vars[type] += amount //I bear no responsibility for the runtimes that'll happen if you try to adjust non-numeric or even non-existant vars - return - -/obj/effect/proc_holder/spell/targeted //can mean aoe for mobs (limited/unlimited number) or one target mob - var/max_targets = 1 //leave 0 for unlimited targets in range, 1 for one selectable target in range, more for limited number of casts (can all target one guy, depends on target_ignore_prev) in range - var/target_ignore_prev = 1 //only important if max_targets > 1, affects if the spell can be cast multiple times at one person from one cast - var/include_user = 0 //if it includes usr in the target list - -/obj/effect/proc_holder/spell/aoe_turf //affects all turfs in view or range (depends) - var/inner_radius = -1 //for all your ring spell needs - -/obj/effect/proc_holder/spell/targeted/choose_targets(mob/user = usr) - var/list/targets = list() - - switch(max_targets) - if(0) //unlimited - for(var/mob/living/target in view_or_range(range, user, selection_type)) - targets += target - if(1) //single target can be picked - if(range < 0) - targets += user - else - var/possible_targets = list() - - for(var/mob/living/M in view_or_range(range, user, selection_type)) - if(!include_user && user == M) - continue - possible_targets += M - - targets += input("Choose the target for the spell.", "Targeting") as mob in possible_targets - else - var/list/possible_targets = list() - for(var/mob/living/target in view_or_range(range, user, selection_type)) - possible_targets += target - for(var/i=1,i<=max_targets,i++) - if(!possible_targets.len) - break - if(target_ignore_prev) - var/target = pick(possible_targets) - possible_targets -= target - targets += target - else - targets += pick(possible_targets) - - if(!include_user && (user in targets)) - targets -= user - - if(!targets.len) //doesn't waste the spell - revert_cast(user) - return - - perform(targets) - - return - -/obj/effect/proc_holder/spell/aoe_turf/choose_targets(mob/user = usr) - var/list/targets = list() - - for(var/turf/target in view_or_range(range,user,selection_type)) - if(!(target in view_or_range(inner_radius,user,selection_type))) - targets += target - - if(!targets.len) //doesn't waste the spell - revert_cast() - return - - perform(targets) - +/client/proc/give_spell(mob/T as mob in mob_list) // -- Urist + set category = "Fun" + set name = "Give Spell" + set desc = "Gives a spell to a mob." + var/list/spell_names = list() + for(var/v in spells) + // "/obj/effect/proc_holder/spell/" 30 symbols ~Intercross21 + spell_names.Add(copytext("[v]", 31, 0)) + var/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in spell_names + if(!S) return + var/path = text2path("/obj/effect/proc_holder/spell/[S]") + T.spell_list += new path + feedback_add_details("admin_verb","GS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + log_admin("[key_name(usr)] gave [key_name(T)] the spell [S].") + message_admins("\blue [key_name_admin(usr)] gave [key_name(T)] the spell [S].", 1) + +/obj/effect/proc_holder + var/panel = "Debug"//What panel the proc holder needs to go on. + +var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin verb for now + +/obj/effect/proc_holder/spell + name = "Spell" + desc = "A wizard spell" + density = 0 + opacity = 0 + + var/school = "evocation" //not relevant at now, but may be important later if there are changes to how spells work. the ones I used for now will probably be changed... maybe spell presets? lacking flexibility but with some other benefit? + + var/charge_type = "recharge" //can be recharge or charges, see charge_max and charge_counter descriptions; can also be based on the holder's vars now, use "holder_var" for that + + var/charge_max = 100 //recharge time in deciseconds if charge_type = "recharge" or starting charges if charge_type = "charges" + var/charge_counter = 0 //can only cast spells if it equals recharge, ++ each decisecond if charge_type = "recharge" or -- each cast if charge_type = "charges" + + var/holder_var_type = "bruteloss" //only used if charge_type equals to "holder_var" + var/holder_var_amount = 20 //same. The amount adjusted with the mob's var when the spell is used + + var/clothes_req = 1 //see if it requires clothes + var/stat_allowed = 0 //see if it requires being conscious/alive, need to set to 1 for ghostpells + var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell + var/invocation_type = "none" //can be none, whisper and shout + var/range = 7 //the range of the spell; outer radius for aoe spells + var/message = "" //whatever it says to the guy affected by it + var/selection_type = "view" //can be "range" or "view" + + var/overlay = 0 + var/overlay_icon = 'icons/obj/wizard.dmi' + var/overlay_icon_state = "spell" + var/overlay_lifespan = 0 + + var/sparks_spread = 0 + var/sparks_amt = 0 //cropped at 10 + var/smoke_spread = 0 //1 - harmless, 2 - harmful + var/smoke_amt = 0 //cropped at 10 + + var/critfailchance = 0 + var/centcomm_cancast = 1 //Whether or not the spell should be allowed on z2 + +/obj/effect/proc_holder/spell/proc/cast_check(skipcharge = 0,mob/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell + + if(!(src in usr.spell_list)) + usr << "\red You shouldn't have this spell! Something's wrong." + return 0 + + if(usr.z == 2 && !centcomm_cancast) //Certain spells are not allowed on the centcomm zlevel + return 0 + + if(!skipcharge) + switch(charge_type) + if("recharge") + if(charge_counter < charge_max) + usr << "[name] is still recharging." + return 0 + if("charges") + if(!charge_counter) + usr << "[name] has no charges left." + return 0 + + if(usr.stat && !stat_allowed) + usr << "Not when you're incapacitated." + return 0 + + if(ishuman(usr) || ismonkey(usr)) + if(istype(usr.wear_mask, /obj/item/clothing/mask/muzzle)) + usr << "Mmmf mrrfff!" + return 0 + + if(clothes_req) //clothes check + if(!istype(usr, /mob/living/carbon/human)) + usr << "You aren't a human, Why are you trying to cast a human spell, silly non-human? Casting human spells is for humans." + return 0 + if(!istype(usr:wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(user:wear_suit, /obj/item/clothing/suit/space/void/wizard)) + usr << "I don't feel strong enough without my robe." + return 0 + if(!istype(usr:shoes, /obj/item/clothing/shoes/sandal)) + usr << "I don't feel strong enough without my sandals." + return 0 + if(!istype(usr:head, /obj/item/clothing/head/wizard) && !istype(user:head, /obj/item/clothing/head/helmet/space/void/wizard)) + usr << "I don't feel strong enough without my hat." + return 0 + + if(!skipcharge) + switch(charge_type) + if("recharge") + charge_counter = 0 //doesn't start recharging until the targets selecting ends + if("charges") + charge_counter-- //returns the charge if the targets selecting fails + if("holdervar") + adjust_var(user, holder_var_type, holder_var_amount) + + return 1 + +/obj/effect/proc_holder/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount + + switch(invocation_type) + if("shout") + if(prob(50))//Auto-mute? Fuck that noise + usr.say(invocation) + else + usr.say(replacetext(invocation," ","`")) + if(usr.gender==MALE) + playsound(usr.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1) + else + playsound(usr.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1) + if("whisper") + if(prob(50)) + usr.whisper(invocation) + else + usr.whisper(replacetext(invocation," ","`")) + +/obj/effect/proc_holder/spell/New() + ..() + + charge_counter = charge_max + +/obj/effect/proc_holder/spell/Click() + if(cast_check()) + choose_targets() + return 1 + +/obj/effect/proc_holder/spell/proc/choose_targets(mob/user = usr) //depends on subtype - /targeted or /aoe_turf + return + +/obj/effect/proc_holder/spell/proc/start_recharge() + while(charge_counter < charge_max) + sleep(1) + charge_counter++ + +/obj/effect/proc_holder/spell/proc/perform(list/targets, recharge = 1) //if recharge is started is important for the trigger spells + before_cast(targets) + invocation() + spawn(0) + if(charge_type == "recharge" && recharge) + start_recharge() + if(prob(critfailchance)) + critfail(targets) + else + cast(targets) + after_cast(targets) + +/obj/effect/proc_holder/spell/proc/before_cast(list/targets) + if(overlay) + for(var/atom/target in targets) + var/location + if(istype(target,/mob/living)) + location = target.loc + else if(istype(target,/turf)) + location = target + var/obj/effect/overlay/spell = new /obj/effect/overlay(location) + spell.icon = overlay_icon + spell.icon_state = overlay_icon_state + spell.anchored = 1 + spell.density = 0 + spawn(overlay_lifespan) + del(spell) + +/obj/effect/proc_holder/spell/proc/after_cast(list/targets) + for(var/atom/target in targets) + var/location + if(istype(target,/mob/living)) + location = target.loc + else if(istype(target,/turf)) + location = target + if(istype(target,/mob/living) && message) + target << text("[message]") + if(sparks_spread) + var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread() + sparks.set_up(sparks_amt, 0, location) //no idea what the 0 is + sparks.start() + if(smoke_spread) + if(smoke_spread == 1) + var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread() + smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is + smoke.start() + else if(smoke_spread == 2) + var/datum/effect/effect/system/smoke_spread/bad/smoke = new /datum/effect/effect/system/smoke_spread/bad() + smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is + smoke.start() + +/obj/effect/proc_holder/spell/proc/cast(list/targets) + return + +/obj/effect/proc_holder/spell/proc/critfail(list/targets) + return + +/obj/effect/proc_holder/spell/proc/revert_cast(mob/user = usr) //resets recharge or readds a charge + switch(charge_type) + if("recharge") + charge_counter = charge_max + if("charges") + charge_counter++ + if("holdervar") + adjust_var(user, holder_var_type, -holder_var_amount) + + return + +/obj/effect/proc_holder/spell/proc/adjust_var(mob/living/target = usr, type, amount) //handles the adjustment of the var when the spell is used. has some hardcoded types + switch(type) + if("bruteloss") + target.adjustBruteLoss(amount) + if("fireloss") + target.adjustFireLoss(amount) + if("toxloss") + target.adjustToxLoss(amount) + if("oxyloss") + target.adjustOxyLoss(amount) + if("stunned") + target.AdjustStunned(amount) + if("weakened") + target.AdjustWeakened(amount) + if("paralysis") + target.AdjustParalysis(amount) + else + target.vars[type] += amount //I bear no responsibility for the runtimes that'll happen if you try to adjust non-numeric or even non-existant vars + return + +/obj/effect/proc_holder/spell/targeted //can mean aoe for mobs (limited/unlimited number) or one target mob + var/max_targets = 1 //leave 0 for unlimited targets in range, 1 for one selectable target in range, more for limited number of casts (can all target one guy, depends on target_ignore_prev) in range + var/target_ignore_prev = 1 //only important if max_targets > 1, affects if the spell can be cast multiple times at one person from one cast + var/include_user = 0 //if it includes usr in the target list + +/obj/effect/proc_holder/spell/aoe_turf //affects all turfs in view or range (depends) + var/inner_radius = -1 //for all your ring spell needs + +/obj/effect/proc_holder/spell/targeted/choose_targets(mob/user = usr) + var/list/targets = list() + + switch(max_targets) + if(0) //unlimited + for(var/mob/living/target in view_or_range(range, user, selection_type)) + targets += target + if(1) //single target can be picked + if(range < 0) + targets += user + else + var/possible_targets = list() + + for(var/mob/living/M in view_or_range(range, user, selection_type)) + if(!include_user && user == M) + continue + possible_targets += M + + targets += input("Choose the target for the spell.", "Targeting") as mob in possible_targets + else + var/list/possible_targets = list() + for(var/mob/living/target in view_or_range(range, user, selection_type)) + possible_targets += target + for(var/i=1,i<=max_targets,i++) + if(!possible_targets.len) + break + if(target_ignore_prev) + var/target = pick(possible_targets) + possible_targets -= target + targets += target + else + targets += pick(possible_targets) + + if(!include_user && (user in targets)) + targets -= user + + if(!targets.len) //doesn't waste the spell + revert_cast(user) + return + + perform(targets) + + return + +/obj/effect/proc_holder/spell/aoe_turf/choose_targets(mob/user = usr) + var/list/targets = list() + + for(var/turf/target in view_or_range(range,user,selection_type)) + if(!(target in view_or_range(inner_radius,user,selection_type))) + targets += target + + if(!targets.len) //doesn't waste the spell + revert_cast() + return + + perform(targets) + return \ No newline at end of file diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/modules/spells/spellbook.dm similarity index 98% rename from code/game/gamemodes/wizard/spellbook.dm rename to code/modules/spells/spellbook.dm index 716045a721..66ba38726e 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/modules/spells/spellbook.dm @@ -1,208 +1,211 @@ -/obj/item/weapon/spellbook - name = "spell book" - desc = "The legendary book of spells of the wizard." - icon = 'icons/obj/library.dmi' - icon_state ="book" - throw_speed = 1 - throw_range = 5 - w_class = 2.0 - var/uses = 5 - var/temp = null - var/max_uses = 5 - var/op = 1 - - -/obj/item/weapon/spellbook/attack_self(mob/user as mob) - user.set_machine(src) - var/dat - if(temp) - dat = "[temp]

    Clear" - else - dat = "The Book of Spells:
    " - dat += "Spells left to memorize: [uses]
    " - dat += "
    " - dat += "Memorize which spell:
    " - dat += "The number after the spell name is the cooldown time.
    " - dat += "Magic Missile (10)
    " - dat += "Fireball (10)
    " - //dat += "Disintegrate (60)
    " - dat += "Disable Technology (60)
    " - dat += "Smoke (10)
    " - dat += "Blind (30)
    " - dat += "Mind Transfer (60)
    " - dat += "Forcewall (10)
    " - dat += "Blink (2)
    " - dat += "Teleport (60)
    " - dat += "Mutate (60)
    " - dat += "Ethereal Jaunt (60)
    " - dat += "Knock (10)
    " - dat += "Curse of the Horseman (15)
    " -// if(op) -// dat += "Summon Guns (One time use, global spell)
    " - dat += "
    " - dat += "Artefacts:
    " - dat += "Powerful items imbued with eldritch magics. Summoning one will count towards your maximum number of spells.
    " - dat += "It is recommended that only experienced wizards attempt to wield such artefacts.
    " - dat += "
    " - dat += "Staff of Change
    " - dat += "
    " - dat += "Mental Focus
    " - dat += "
    " - dat += "Six Soul Stone Shards and the spell Artificer
    " - dat += "
    " - dat += "Mastercrafted Armor Set
    " - dat += "
    " - dat += "Staff of Animation
    " - dat += "
    " - dat += "Scrying Orb
    " - dat += "
    " - if(op) - dat += "Re-memorize Spells
    " - user << browse(dat, "window=radio") - onclose(user, "radio") - return - -/obj/item/weapon/spellbook/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["spell_choice"]) - if(href_list["spell_choice"] == "rememorize") - var/area/wizard_station/A = locate() - if(usr in A.contents) - uses = max_uses - H.spellremove(usr) - temp = "All spells have been removed. You may now memorize a new set of spells." - feedback_add_details("wizard_spell_learned","UM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - else - temp = "You may only re-memorize spells whilst located inside the wizard sanctuary." - else if(uses >= 1 && max_uses >=1) - uses-- - /* - */ - var/list/available_spells = list(magicmissile = "Magic Missile", fireball = "Fireball", disintegrate = "Disintegrate", disabletech = "Disable Tech", smoke = "Smoke", blind = "Blind", mindswap = "Mind Transfer", forcewall = "Forcewall", blink = "Blink", teleport = "Teleport", mutate = "Mutate", etherealjaunt = "Ethereal Jaunt", knock = "Knock", horseman = "Curse of the Horseman", summonguns = "Summon Guns", staffchange = "Staff of Change", mentalfocus = "Mental Focus", soulstone = "Six Soul Stone Shards and the spell Artificer", armor = "Mastercrafted Armor Set", staffanimate = "Staff of Animation") - var/already_knows = 0 - for(var/obj/effect/proc_holder/spell/aspell in H.spell_list) - if(available_spells[href_list["spell_choice"]] == aspell.name) - already_knows = 1 - temp = "You already know that spell." - uses++ - break - /* - */ - if(!already_knows) - switch(href_list["spell_choice"]) - if("magicmissile") - feedback_add_details("wizard_spell_learned","MM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.spell_list += new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile(H) - temp = "This spell fires several, slow moving, magic projectiles at nearby targets. If they hit a target, it is paralyzed and takes minor damage." - if("fireball") - feedback_add_details("wizard_spell_learned","FB") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.spell_list += new /obj/effect/proc_holder/spell/dumbfire/fireball(H) - temp = "This spell fires a fireball in the direction you're facing and does not require wizard garb. Be careful not to fire it at people that are standing next to you." - if("disintegrate") - feedback_add_details("wizard_spell_learned","DG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.spell_list += new /obj/effect/proc_holder/spell/targeted/inflict_handler/disintegrate(H) - temp = "This spell instantly kills somebody adjacent to you with the vilest of magick. It has a long cooldown." - if("disabletech") - feedback_add_details("wizard_spell_learned","DT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.spell_list += new /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech(H) - temp = "This spell disables all weapons, cameras and most other technology in range." - if("smoke") - feedback_add_details("wizard_spell_learned","SM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.spell_list += new /obj/effect/proc_holder/spell/targeted/smoke(H) - temp = "This spell spawns a cloud of choking smoke at your location and does not require wizard garb." - if("blind") - feedback_add_details("wizard_spell_learned","BD") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.spell_list += new /obj/effect/proc_holder/spell/targeted/trigger/blind(H) - temp = "This spell temporarly blinds a single person and does not require wizard garb." - if("mindswap") - feedback_add_details("wizard_spell_learned","MT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.spell_list += new /obj/effect/proc_holder/spell/targeted/mind_transfer(H) - temp = "This spell allows the user to switch bodies with a target. Careful to not lose your memory in the process." - if("forcewall") - feedback_add_details("wizard_spell_learned","FW") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/forcewall(H) - temp = "This spell creates an unbreakable wall that lasts for 30 seconds and does not need wizard garb." - if("blink") - feedback_add_details("wizard_spell_learned","BL") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.spell_list += new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink(H) - temp = "This spell randomly teleports you a short distance. Useful for evasion or getting into areas if you have patience." - if("teleport") - feedback_add_details("wizard_spell_learned","TP") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.spell_list += new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(H) - temp = "This spell teleports you to a type of area of your selection. Very useful if you are in danger, but has a decent cooldown, and is unpredictable." - if("mutate") - feedback_add_details("wizard_spell_learned","MU") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.spell_list += new /obj/effect/proc_holder/spell/targeted/genetic/mutate(H) - temp = "This spell causes you to turn into a hulk and gain telekinesis for a short while." - if("etherealjaunt") - feedback_add_details("wizard_spell_learned","EJ") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.spell_list += new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(H) - temp = "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls." - if("knock") - feedback_add_details("wizard_spell_learned","KN") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/knock(H) - temp = "This spell opens nearby doors and does not require wizard garb." - if("horseman") - feedback_add_details("wizard_spell_learned","HH") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.spell_list += new /obj/effect/proc_holder/spell/targeted/horsemask(H) - temp = "This spell will curse a person to wear an unremovable horse mask (it has glue on the inside) and speak like a horse. It does not require a wizard garb. Do note the curse will disintegrate the target's current mask if they are wearing one." - if("summonguns") - feedback_add_details("wizard_spell_learned","SG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.rightandwrong() - max_uses-- - temp = "Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill eachother. Just be careful not to get hit in the crossfire!" - if("staffchange") - feedback_add_details("wizard_spell_learned","ST") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - new /obj/item/weapon/gun/energy/staff(get_turf(H)) - temp = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself" - max_uses-- - if("mentalfocus") - feedback_add_details("wizard_spell_learned","MF") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - new /obj/item/weapon/gun/energy/staff/focus(get_turf(H)) - temp = "An artefact that channels the will of the user into destructive bolts of force." - max_uses-- - if("soulstone") - feedback_add_details("wizard_spell_learned","SS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - new /obj/item/weapon/storage/belt/soulstone/full(get_turf(H)) - H.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct(H) - temp = "Soul Stone Shards are ancient tools capable of capturing and harnessing the spirits of the dead and dying. The spell Artificer allows you to create arcane machines for the captured souls to pilot." - max_uses-- - if("armor") - feedback_add_details("wizard_spell_learned","HS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - new /obj/item/clothing/shoes/sandal(get_turf(H)) //In case they've lost them. - new /obj/item/clothing/gloves/purple(get_turf(H))//To complete the outfit - new /obj/item/clothing/suit/space/void/wizard(get_turf(H)) - new /obj/item/clothing/head/helmet/space/void/wizard(get_turf(H)) - temp = "An artefact suit of armor that allows you to cast spells while providing more protection against attacks and the void of space." - max_uses-- - if("staffanimation") - feedback_add_details("wizard_spell_learned","SA") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - new /obj/item/weapon/gun/energy/staff/animate(get_turf(H)) - temp = "An artefact that spits bolts of life-force which causes objects which are hit by it to animate and come to life! This magic doesn't affect machines." - max_uses-- - if("scrying") - feedback_add_details("wizard_spell_learned","SO") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - new /obj/item/weapon/scrying(get_turf(H)) - if (!(XRAY in H.mutations)) - H.mutations.Add(XRAY) - H.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS) - H.see_in_dark = 8 - H.see_invisible = SEE_INVISIBLE_LEVEL_TWO - H << "The walls suddenly disappear." - temp = "You have purchased a scrying orb, and gained x-ray vision." - max_uses-- - else - if(href_list["temp"]) - temp = null - attack_self(H) - - return +// This is a bloody terrible place to put the spellbook, but it doesn't belong in the +// roundmode code and the wizard's staff is in weapons.dm for some fucking reason. ~Z + +/obj/item/weapon/spellbook + name = "spell book" + desc = "The legendary book of spells of the wizard." + icon = 'icons/obj/library.dmi' + icon_state ="book" + throw_speed = 1 + throw_range = 5 + w_class = 2.0 + var/uses = 5 + var/temp = null + var/max_uses = 5 + var/op = 1 + + +/obj/item/weapon/spellbook/attack_self(mob/user as mob) + user.set_machine(src) + var/dat + if(temp) + dat = "[temp]

    Clear" + else + dat = "The Book of Spells:
    " + dat += "Spells left to memorize: [uses]
    " + dat += "
    " + dat += "Memorize which spell:
    " + dat += "The number after the spell name is the cooldown time.
    " + dat += "Magic Missile (10)
    " + dat += "Fireball (10)
    " + //dat += "Disintegrate (60)
    " + dat += "Disable Technology (60)
    " + dat += "Smoke (10)
    " + dat += "Blind (30)
    " + dat += "Mind Transfer (60)
    " + dat += "Forcewall (10)
    " + dat += "Blink (2)
    " + dat += "Teleport (60)
    " + dat += "Mutate (60)
    " + dat += "Ethereal Jaunt (60)
    " + dat += "Knock (10)
    " + dat += "Curse of the Horseman (15)
    " +// if(op) +// dat += "Summon Guns (One time use, global spell)
    " + dat += "
    " + dat += "Artefacts:
    " + dat += "Powerful items imbued with eldritch magics. Summoning one will count towards your maximum number of spells.
    " + dat += "It is recommended that only experienced wizards attempt to wield such artefacts.
    " + dat += "
    " + dat += "Staff of Change
    " + dat += "
    " + dat += "Mental Focus
    " + dat += "
    " + dat += "Six Soul Stone Shards and the spell Artificer
    " + dat += "
    " + dat += "Mastercrafted Armor Set
    " + dat += "
    " + dat += "Staff of Animation
    " + dat += "
    " + dat += "Scrying Orb
    " + dat += "
    " + if(op) + dat += "Re-memorize Spells
    " + user << browse(dat, "window=radio") + onclose(user, "radio") + return + +/obj/item/weapon/spellbook/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["spell_choice"]) + if(href_list["spell_choice"] == "rememorize") + var/area/wizard_station/A = locate() + if(usr in A.contents) + uses = max_uses + H.spellremove(usr) + temp = "All spells have been removed. You may now memorize a new set of spells." + feedback_add_details("wizard_spell_learned","UM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + else + temp = "You may only re-memorize spells whilst located inside the wizard sanctuary." + else if(uses >= 1 && max_uses >=1) + uses-- + /* + */ + var/list/available_spells = list(magicmissile = "Magic Missile", fireball = "Fireball", disintegrate = "Disintegrate", disabletech = "Disable Tech", smoke = "Smoke", blind = "Blind", mindswap = "Mind Transfer", forcewall = "Forcewall", blink = "Blink", teleport = "Teleport", mutate = "Mutate", etherealjaunt = "Ethereal Jaunt", knock = "Knock", horseman = "Curse of the Horseman", summonguns = "Summon Guns", staffchange = "Staff of Change", mentalfocus = "Mental Focus", soulstone = "Six Soul Stone Shards and the spell Artificer", armor = "Mastercrafted Armor Set", staffanimate = "Staff of Animation") + var/already_knows = 0 + for(var/obj/effect/proc_holder/spell/aspell in H.spell_list) + if(available_spells[href_list["spell_choice"]] == aspell.name) + already_knows = 1 + temp = "You already know that spell." + uses++ + break + /* + */ + if(!already_knows) + switch(href_list["spell_choice"]) + if("magicmissile") + feedback_add_details("wizard_spell_learned","MM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.spell_list += new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile(H) + temp = "This spell fires several, slow moving, magic projectiles at nearby targets. If they hit a target, it is paralyzed and takes minor damage." + if("fireball") + feedback_add_details("wizard_spell_learned","FB") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.spell_list += new /obj/effect/proc_holder/spell/dumbfire/fireball(H) + temp = "This spell fires a fireball in the direction you're facing and does not require wizard garb. Be careful not to fire it at people that are standing next to you." + if("disintegrate") + feedback_add_details("wizard_spell_learned","DG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.spell_list += new /obj/effect/proc_holder/spell/targeted/inflict_handler/disintegrate(H) + temp = "This spell instantly kills somebody adjacent to you with the vilest of magick. It has a long cooldown." + if("disabletech") + feedback_add_details("wizard_spell_learned","DT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.spell_list += new /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech(H) + temp = "This spell disables all weapons, cameras and most other technology in range." + if("smoke") + feedback_add_details("wizard_spell_learned","SM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.spell_list += new /obj/effect/proc_holder/spell/targeted/smoke(H) + temp = "This spell spawns a cloud of choking smoke at your location and does not require wizard garb." + if("blind") + feedback_add_details("wizard_spell_learned","BD") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.spell_list += new /obj/effect/proc_holder/spell/targeted/trigger/blind(H) + temp = "This spell temporarly blinds a single person and does not require wizard garb." + if("mindswap") + feedback_add_details("wizard_spell_learned","MT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.spell_list += new /obj/effect/proc_holder/spell/targeted/mind_transfer(H) + temp = "This spell allows the user to switch bodies with a target. Careful to not lose your memory in the process." + if("forcewall") + feedback_add_details("wizard_spell_learned","FW") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/forcewall(H) + temp = "This spell creates an unbreakable wall that lasts for 30 seconds and does not need wizard garb." + if("blink") + feedback_add_details("wizard_spell_learned","BL") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.spell_list += new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink(H) + temp = "This spell randomly teleports you a short distance. Useful for evasion or getting into areas if you have patience." + if("teleport") + feedback_add_details("wizard_spell_learned","TP") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.spell_list += new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(H) + temp = "This spell teleports you to a type of area of your selection. Very useful if you are in danger, but has a decent cooldown, and is unpredictable." + if("mutate") + feedback_add_details("wizard_spell_learned","MU") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.spell_list += new /obj/effect/proc_holder/spell/targeted/genetic/mutate(H) + temp = "This spell causes you to turn into a hulk and gain telekinesis for a short while." + if("etherealjaunt") + feedback_add_details("wizard_spell_learned","EJ") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.spell_list += new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(H) + temp = "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls." + if("knock") + feedback_add_details("wizard_spell_learned","KN") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/knock(H) + temp = "This spell opens nearby doors and does not require wizard garb." + if("horseman") + feedback_add_details("wizard_spell_learned","HH") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.spell_list += new /obj/effect/proc_holder/spell/targeted/horsemask(H) + temp = "This spell will curse a person to wear an unremovable horse mask (it has glue on the inside) and speak like a horse. It does not require a wizard garb. Do note the curse will disintegrate the target's current mask if they are wearing one." + if("summonguns") + feedback_add_details("wizard_spell_learned","SG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + rightandwrong() + max_uses-- + temp = "Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill eachother. Just be careful not to get hit in the crossfire!" + if("staffchange") + feedback_add_details("wizard_spell_learned","ST") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + new /obj/item/weapon/gun/energy/staff(get_turf(H)) + temp = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself" + max_uses-- + if("mentalfocus") + feedback_add_details("wizard_spell_learned","MF") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + new /obj/item/weapon/gun/energy/staff/focus(get_turf(H)) + temp = "An artefact that channels the will of the user into destructive bolts of force." + max_uses-- + if("soulstone") + feedback_add_details("wizard_spell_learned","SS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + new /obj/item/weapon/storage/belt/soulstone/full(get_turf(H)) + H.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct(H) + temp = "Soul Stone Shards are ancient tools capable of capturing and harnessing the spirits of the dead and dying. The spell Artificer allows you to create arcane machines for the captured souls to pilot." + max_uses-- + if("armor") + feedback_add_details("wizard_spell_learned","HS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + new /obj/item/clothing/shoes/sandal(get_turf(H)) //In case they've lost them. + new /obj/item/clothing/gloves/purple(get_turf(H))//To complete the outfit + new /obj/item/clothing/suit/space/void/wizard(get_turf(H)) + new /obj/item/clothing/head/helmet/space/void/wizard(get_turf(H)) + temp = "An artefact suit of armor that allows you to cast spells while providing more protection against attacks and the void of space." + max_uses-- + if("staffanimation") + feedback_add_details("wizard_spell_learned","SA") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + new /obj/item/weapon/gun/energy/staff/animate(get_turf(H)) + temp = "An artefact that spits bolts of life-force which causes objects which are hit by it to animate and come to life! This magic doesn't affect machines." + max_uses-- + if("scrying") + feedback_add_details("wizard_spell_learned","SO") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + new /obj/item/weapon/scrying(get_turf(H)) + if (!(XRAY in H.mutations)) + H.mutations.Add(XRAY) + H.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS) + H.see_in_dark = 8 + H.see_invisible = SEE_INVISIBLE_LEVEL_TWO + H << "The walls suddenly disappear." + temp = "You have purchased a scrying orb, and gained x-ray vision." + max_uses-- + else + if(href_list["temp"]) + temp = null + attack_self(H) + + return diff --git a/code/datums/spells/trigger.dm b/code/modules/spells/trigger.dm similarity index 96% rename from code/datums/spells/trigger.dm rename to code/modules/spells/trigger.dm index 1b7f2b330f..5e2ed8475f 100644 --- a/code/datums/spells/trigger.dm +++ b/code/modules/spells/trigger.dm @@ -1,28 +1,28 @@ -/obj/effect/proc_holder/spell/targeted/trigger - name = "Trigger" - desc = "This spell triggers another spell or a few." - - var/list/linked_spells = list() //those are just referenced by the trigger spell and are unaffected by it directly - var/list/starting_spells = list() //those are added on New() to contents from default spells and are deleted when the trigger spell is deleted to prevent memory leaks - -/obj/effect/proc_holder/spell/targeted/trigger/New() - ..() - - for(var/spell in starting_spells) - var/spell_to_add = text2path(spell) - new spell_to_add(src) //should result in adding to contents, needs testing - -/obj/effect/proc_holder/spell/targeted/trigger/Del() - for(var/spell in contents) - del(spell) - - ..() - -/obj/effect/proc_holder/spell/targeted/trigger/cast(list/targets) - for(var/mob/living/target in targets) - for(var/obj/effect/proc_holder/spell/spell in contents) - spell.perform(list(target),0) - for(var/obj/effect/proc_holder/spell/spell in linked_spells) - spell.perform(list(target),0) - +/obj/effect/proc_holder/spell/targeted/trigger + name = "Trigger" + desc = "This spell triggers another spell or a few." + + var/list/linked_spells = list() //those are just referenced by the trigger spell and are unaffected by it directly + var/list/starting_spells = list() //those are added on New() to contents from default spells and are deleted when the trigger spell is deleted to prevent memory leaks + +/obj/effect/proc_holder/spell/targeted/trigger/New() + ..() + + for(var/spell in starting_spells) + var/spell_to_add = text2path(spell) + new spell_to_add(src) //should result in adding to contents, needs testing + +/obj/effect/proc_holder/spell/targeted/trigger/Del() + for(var/spell in contents) + del(spell) + + ..() + +/obj/effect/proc_holder/spell/targeted/trigger/cast(list/targets) + for(var/mob/living/target in targets) + for(var/obj/effect/proc_holder/spell/spell in contents) + spell.perform(list(target),0) + for(var/obj/effect/proc_holder/spell/spell in linked_spells) + spell.perform(list(target),0) + return \ No newline at end of file diff --git a/code/datums/spells/turf_teleport.dm b/code/modules/spells/turf_teleport.dm similarity index 97% rename from code/datums/spells/turf_teleport.dm rename to code/modules/spells/turf_teleport.dm index 02dd5f71b4..d59bff313a 100644 --- a/code/datums/spells/turf_teleport.dm +++ b/code/modules/spells/turf_teleport.dm @@ -1,34 +1,34 @@ -/obj/effect/proc_holder/spell/targeted/turf_teleport - name = "Turf Teleport" - desc = "This spell teleports the target to the turf in range." - - var/inner_tele_radius = 1 - var/outer_tele_radius = 2 - - var/include_space = 0 //whether it includes space tiles in possible teleport locations - var/include_dense = 0 //whether it includes dense tiles in possible teleport locations - -/obj/effect/proc_holder/spell/targeted/turf_teleport/cast(list/targets) - for(var/mob/living/target in targets) - var/list/turfs = new/list() - for(var/turf/T in range(target,outer_tele_radius)) - if(T in range(target,inner_tele_radius)) continue - if(istype(T,/turf/space) && !include_space) continue - if(T.density && !include_dense) continue - if(T.x>world.maxx-outer_tele_radius || T.xworld.maxy-outer_tele_radius || T.yworld.maxx-outer_tele_radius || T.xworld.maxy-outer_tele_radius || T.y