Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds rave wizard #928

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions modular_ss220/antagonists/_antagonists.dme
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@
#include "code/configuration/antag_mix_configuration.dm"
#include "code/mind/memory_edit.dm"
#include "code/antag_mix/antag_mix.dm"
#include "code/rave_wizard/rave_wizard_event.dm"
#include "code/rave_wizard/summon_disco_ball.dm"
#include "code/rave_wizard/dancing_field.dm"
#include "code/rave_wizard/beer_missiles.dm"
#include "code/rave_wizard/great_revelry.dm"
#include "code/rave_wizard/rocker_touch.dm"
52 changes: 52 additions & 0 deletions modular_ss220/antagonists/code/rave_wizard/beer_missiles.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#define HIT_MISSILE_EFFECT_DURATION 10 SECONDS
HelmsDeepState marked this conversation as resolved.
Show resolved Hide resolved

/obj/effect/proc_holder/spell/projectile/beer_missile
name = "Beer Missile"
desc = "This spell fires several, slow moving, magic beer bottles at nearby targets"
school = "evocation"
base_cooldown = 60
clothes_req = FALSE
invocation_type = "shout"
cooldown_min = 60 //35 deciseconds reduction per rank
proj_icon = 'icons/obj/drinks.dmi'
proj_icon_state = "beer"
proj_name = "A bottle of beer"
proj_lingering = 1
proj_type = "/obj/effect/proc_holder/spell/inflict_handler/beer_missile"
proj_lifespan = 20
proj_step_delay = 5
proj_trail_icon = 'icons/obj/drinks.dmi'
proj_trail = 1
proj_trail_lifespan = 5
proj_trail_icon_state = "beer"
action_icon_state = "no_state"
action_background_icon_state = "missile"
action_icon = 'modular_ss220/antagonists/icons/rave.dmi'
sound = 'sound/magic/magic_missile.ogg'

/obj/effect/proc_holder/spell/projectile/beer_missile/create_new_targeting()
var/datum/spell_targeting/targeted/T = new()
T.allowed_type = /mob/living
T.max_targets = INFINITY
return T

/obj/effect/proc_holder/spell/inflict_handler/beer_missile
sound = "shatter"

/obj/effect/proc_holder/spell/inflict_handler/beer_missile/cast(list/targets, mob/user = usr)
for(var/mob/living/target in targets)
target.AdjustKnockDown(HIT_MISSILE_EFFECT_DURATION)
target.AdjustDizzy(HIT_MISSILE_EFFECT_DURATION)
target.AdjustSlur(HIT_MISSILE_EFFECT_DURATION)
target.AdjustConfused(HIT_MISSILE_EFFECT_DURATION)
target.AdjustEyeBlurry(HIT_MISSILE_EFFECT_DURATION)
target.AdjustDrowsy(HIT_MISSILE_EFFECT_DURATION)
target.AdjustDruggy(HIT_MISSILE_EFFECT_DURATION)
. = ..()

/datum/spellbook_entry/beer_missile
name = "Magic beer missiles"
spell_type = /obj/effect/proc_holder/spell/projectile/beer_missile
category = "Rave"

#undef HIT_MISSILE_EFFECT_DURATION
62 changes: 62 additions & 0 deletions modular_ss220/antagonists/code/rave_wizard/dancing_field.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/obj/effect/proc_holder/spell/aoe/conjure/timestop/dance
name = "Dance Time"
desc = "This spell makes everyone dance in it's range. Enchanted targets cannot attack, but projectiles harm as usual"
invocation = "DAN SIN FIVA"
action_icon_state = "no_state"
action_background_icon_state = "dance_field"
action_icon = 'modular_ss220/antagonists/icons/rave.dmi'
summon_lifespan = 100
summon_type = list(/obj/effect/timestop/dancing/wizard)

/obj/effect/timestop/dancing
name = "Dancing field"
desc = "Feel the heat"
icon = 'modular_ss220/antagonists/icons/160x160.dmi'
icon_state = "dancing_ball"
var/sound_type = list('modular_ss220/antagonists/sound/music1.mp3',
'modular_ss220/antagonists/sound/music2.mp3',
'modular_ss220/antagonists/sound/music3.mp3',
'modular_ss220/antagonists/sound/music4.mp3',
'modular_ss220/antagonists/sound/music5.mp3',
'modular_ss220/antagonists/sound/music6.mp3')

/obj/effect/timestop/dancing/timestop()
playsound(get_turf(src), pick(sound_type), 100, 1, -1)
for(var/i in 1 to duration-1)
for(var/A in orange (freezerange, loc))
if(isliving(A))
var/mob/living/dancestoped_mob = A
if(dancestoped_mob in immune)
continue
dancestoped_mob.notransform = TRUE
dancestoped_mob.anchored = TRUE
if(ishostile(dancestoped_mob))
var/mob/living/simple_animal/hostile/H = dancestoped_mob
H.AIStatus = AI_OFF
H.LoseTarget()
if(prob(50))
HelmsDeepState marked this conversation as resolved.
Show resolved Hide resolved
dancestoped_mob.emote(pick(list("spin","dance")))
if(prob(20))
dancestoped_mob.emote("flip")
stopped_atoms |= dancestoped_mob
for(var/mob/living/M in stopped_atoms)
if(get_dist(get_turf(M),get_turf(src)) > freezerange) //If they lagged/ran past the timestop somehow, just ignore them
unfreeze_mob(M)
stopped_atoms -= M
sleep(1)
for(var/mob/living/M in stopped_atoms)
unfreeze_mob(M)
qdel(src)
return
HelmsDeepState marked this conversation as resolved.
Show resolved Hide resolved

/datum/spellbook_entry/dancestop
name = "Dance Stop"
spell_type = /obj/effect/proc_holder/spell/aoe/conjure/timestop/dance
category = "Rave"

/obj/effect/timestop/dancing/wizard
duration = 100

/obj/effect/timestop/dancing/wizard/New()
..()
timestop()
45 changes: 45 additions & 0 deletions modular_ss220/antagonists/code/rave_wizard/great_revelry.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/obj/effect/proc_holder/spell/great_revelry
name = "Ritual of Great Revelry"
desc = "Gives everyone a beckoning bottle of alcohol, forcing them to drop an item from their hand."

school = "transmutation"
base_cooldown = 300
clothes_req = TRUE
invocation = "none"
invocation_type = "none"
cooldown_min = 100 //50 deciseconds reduction per rank
nonabstract_req = TRUE
var/list/beverages = list(/obj/item/reagent_containers/drinks/bottle/vodka,
/obj/item/reagent_containers/drinks/bottle/whiskey,
/obj/item/reagent_containers/drinks/bottle/tequila,
/obj/item/reagent_containers/drinks/bottle/absinthe/premium,
/obj/item/reagent_containers/drinks/bottle/absinthe,
/obj/item/reagent_containers/drinks/bottle/hcider,
/obj/item/reagent_containers/drinks/bottle/fernet)
action_icon_state = "no_state"
action_background_icon_state = "revelry"
action_icon = 'modular_ss220/antagonists/icons/rave.dmi'

/obj/effect/proc_holder/spell/great_revelry/create_new_targeting()
return new /datum/spell_targeting/self

/obj/effect/proc_holder/spell/great_revelry/cast(list/targets, mob/user = usr)
for(var/mob/living/carbon/human/H in GLOB.player_list)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Однобуковка aga

var/turf/T = get_turf(H)
if(T && is_away_level(T.z))
return
if(H.stat == DEAD || H?.client)
return
if(iswizard(H) || H?.mind.offstation_role)
return
Comment on lines +32 to +34

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Уверен что тут должен быть return а не continue?

var/alcohol_type = pick(beverages)
var/obj/item/reagent_containers/drinks/bottle/B = new alcohol_type(get_turf(H))
playsound(get_turf(H),'modular_ss220/antagonists/sound/beer_can_open.mp3', 50, TRUE)
H.drop_item() //drops item in active hand
HelmsDeepState marked this conversation as resolved.
Show resolved Hide resolved
var/in_hand = H.put_in_hands(B)
to_chat(H, "<span class='warning'>\A [B] appears [in_hand ? "in your hand" : "at your feet"]!</span>")
HelmsDeepState marked this conversation as resolved.
Show resolved Hide resolved

/datum/spellbook_entry/great_revelry
name = "Ritual of Great Revelry"
spell_type = /obj/effect/proc_holder/spell/great_revelry
category = "Rave"
125 changes: 125 additions & 0 deletions modular_ss220/antagonists/code/rave_wizard/rave_wizard_event.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#define SPELLBOOK_AVAILABLE_POINTS 4
#define MAGIVENDS_PRODUCTS_REFILL_VALUE 20
#define WIZARD_GREETING ("<span class='danger'>Вы — маг рейва!</span>")
#define WIZARD_WIKI ("<span class='motd'>На вики-странице доступна более подробная информация: ([GLOB.configuration.url.wiki_url]/index.php/Wizard)</span>")
HelmsDeepState marked this conversation as resolved.
Show resolved Hide resolved
#define RAVE_WIZARD_EVENT_WEIGHT 5

/datum/event/rave_wizard

/datum/event/rave_wizard/start()
INVOKE_ASYNC(src, PROC_REF(wrappedstart))

/datum/event/rave_wizard/proc/wrappedstart()

var/image/source = image('modular_ss220/antagonists/icons/rave.dmi', "rave_poll")
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a rave Space Wizard?", ROLE_WIZARD, TRUE, poll_time = 40 SECONDS, source = source)
var/mob/dead/observer/new_wizard = null

if(!length(candidates))
kill()
return

new_wizard = pick(candidates)

if(new_wizard)

var/mob/living/carbon/human/new_character = makeBody(new_wizard)
new_character.mind.make_rave_wizard()
// This puts them at the wizard spawn, worry not
new_character.equip_to_slot_or_del(new /obj/item/reagent_containers/drinks/mugwort(new_wizard), SLOT_HUD_IN_BACKPACK)
new_character.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses, SLOT_HUD_GLASSES)
populate_magivends()
// The first wiznerd can get their mugwort from the wizard's den, new ones will also need mugwort!
dust_if_respawnable(new_wizard)
return TRUE
else
. = FALSE
CRASH("The candidates list for rave wizard contained non-observer entries!")

// ripped from -tg-'s wizcode, because whee lets make a very general proc for a very specific gamemode
// This probably wouldn't do half bad as a proc in __HELPERS
// Lemme know if this causes species to mess up spectacularly or anything
/datum/event/rave_wizard/proc/makeBody(mob/dead/observer/ghost_candidate)
if(!ghost_candidate?.key)
return // Let's not steal someone's soul here
var/mob/living/carbon/human/new_character = new(pick(GLOB.latejoin))
ghost_candidate.client.prefs.active_character.copy_to(new_character)
new_character.key = ghost_candidate.key
return new_character

/datum/event/rave_wizard/proc/populate_magivends()
for(var/obj/machinery/economy/vending/magivend/magic in GLOB.machines)
for(var/key in magic.products)
magic.products[key] = MAGIVENDS_PRODUCTS_REFILL_VALUE // and so, there was prosperity for mages everywhere
magic.product_records.Cut()
magic.build_inventory(magic.products, magic.product_records)

/datum/mind/proc/make_rave_wizard()
if(!(src in SSticker.mode.wizards))
SSticker.mode.wizards += src
special_role = SPECIAL_ROLE_WIZARD
assigned_role = SPECIAL_ROLE_WIZARD
//ticker.mode.learn_basic_spells(current)
if(!GLOB.wizardstart.len)
current.loc = pick(GLOB.latejoin)
to_chat(current, "HOT INSERTION, GO GO GO")
else
current.loc = pick(GLOB.wizardstart)

SSticker.mode.equip_wizard(current)
src.learn_rave_spells()
for(var/obj/item/spellbook/S in current.contents)
S.op = 0
S.remove_harmful_spells_and_items()
S.uses = SPELLBOOK_AVAILABLE_POINTS
SSticker.mode.forge_rave_wizard_objectives(src)
SSticker.mode.greet_rave_wizard(src)
SSticker.mode.update_wiz_icons_added(src)
SSticker.mode.name_wizard(current)

/datum/mind/proc/learn_rave_spells()
var/spell_paths = list(/obj/effect/proc_holder/spell/projectile/beer_missile,
/obj/effect/proc_holder/spell/aoe/conjure/timestop/dance,
/obj/effect/proc_holder/spell/great_revelry,
/obj/effect/proc_holder/spell/touch/rocker,
/obj/effect/proc_holder/spell/aoe/conjure/summon_disco)
for(var/spell_path in spell_paths)
var/S = new spell_path
src.AddSpell(S)

/obj/item/spellbook/proc/remove_harmful_spells_and_items()
src.main_categories -= "Magical Items"
src.main_categories -= "Loadouts"
src.spell_categories -= "Offensive"
src.spell_categories -= "Rituals"
HelmsDeepState marked this conversation as resolved.
Show resolved Hide resolved

/datum/game_mode/proc/greet_rave_wizard(datum/mind/wizard, you_are=1)
HelmsDeepState marked this conversation as resolved.
Show resolved Hide resolved
SEND_SOUND(wizard.current, sound('sound/ambience/antag/ragesmages.ogg'))
var/list/messages = list()
if(you_are)
messages.Add(WIZARD_GREETING)

messages.Add(wizard.prepare_announce_objectives(title = FALSE))
messages.Add(WIZARD_WIKI)
to_chat(wizard.current, chat_box_red(messages.Join("<br>")))
wizard.current.create_log(MISC_LOG, "[wizard.current] was made into a wizard")

/datum/game_mode/proc/forge_rave_wizard_objectives(datum/mind/wizard)
wizard.add_mind_objective(/datum/objective/wizrave)

/datum/objective/wizrave
explanation_text = "Устройте вечеринку, о которой потомки будут слагать легенды."
needs_target = FALSE
completed = TRUE

/datum/event_container/major/New()
. = ..()
var/datum/event_meta/nothing_event = available_events[1]
nothing_event.weight -= RAVE_WIZARD_EVENT_WEIGHT
available_events += list(new /datum/event_meta(EVENT_LEVEL_MAJOR, "Rave Wizard", /datum/event/rave_wizard, RAVE_WIZARD_EVENT_WEIGHT, is_one_shot = TRUE))

#undef MAGIVENDS_PRODUCTS_REFILL_VALUE
#undef WIZARD_GREETING
#undef WIZARD_WIKI
#undef SPELLBOOK_AVAILABLE_POINTS
#undef RAVE_WIZARD_EVENT_WEIGHT
89 changes: 89 additions & 0 deletions modular_ss220/antagonists/code/rave_wizard/rocker_touch.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#define DRUGS_AMOUNT_INJECTED_BY_TUMOR 20
#define ALCOHOL_AMOUNT_INJECTED_BY_TUMOR 20

/obj/effect/proc_holder/spell/touch/rocker
name = "Rocker Touch"
desc = "Teach those foolish suits how to spend time in style"
hand_path = /obj/item/melee/touch_attack/rocker
school = "transmutation"
base_cooldown = 30 SECONDS
clothes_req = TRUE
action_icon_state = "no_state"
action_background_icon_state = "curse"
action_icon = 'modular_ss220/antagonists/icons/rave.dmi'

/obj/item/melee/touch_attack/rocker
name = "rocker touch"
desc = "It's time for anti corpo party to start"
catchphrase = "YRTAP SIBENG"
on_use_sound = 'modular_ss220/antagonists/sound/metal_riff.mp3'
icon_state = "banana_touch"
item_state = "banana_touch"

/datum/spellbook_entry/rocker_curse
name = "Alcoholism curse"
spell_type = /obj/effect/proc_holder/spell/touch/rocker
category = "Rave"
cost = 1

/obj/item/melee/touch_attack/rocker/afterattack(atom/target, mob/living/carbon/user, proximity)
if(!proximity || target == user || !ishuman(target) || !iscarbon(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED))
return

var/datum/effect_system/smoke_spread/s = new

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Однобуковка aga

s.set_up(5, FALSE, target)
s.start()

var/mob/living/carbon/human/H = target
H.rocker_touched()
..()

/mob/living/carbon/human/proc/rocker_touched()
var/obj/item/organ/internal/chrome_tumor/tumor = new
tumor.insert(src)
AdjustWeakened(6 SECONDS)
unEquip(w_uniform, TRUE)
unEquip(shoes, TRUE)
unEquip(wear_suit, TRUE)
equipOutfit(new /datum/outfit/rocker_cursed)

/obj/item/organ/internal/chrome_tumor
name = "chrome tumor"
desc = "Shiny metallic tumor"
origin_tech = "biotech=1"
w_class = WEIGHT_CLASS_TINY
parent_organ = "groin"
slot = "liver_tumor"
destroy_on_removal = TRUE //no icon, so just let it die
unremovable = TRUE
var/poisoned_offset = 0
var/suffering_delay = 1200

/obj/item/organ/internal/chrome_tumor/on_life()
if(poisoned_offset < world.time)
poisoned_offset = world.time + suffering_delay
if(prob(75))
owner?.reagents.add_reagent("beer", ALCOHOL_AMOUNT_INJECTED_BY_TUMOR) //TODO change to choose from set of reagents
if(prob(50))
owner?.reagents.add_reagent("space_drugs", DRUGS_AMOUNT_INJECTED_BY_TUMOR) //TODO change to choose from set of reagents


/obj/item/organ/internal/chrome_tumor/insert(mob/living/carbon/M, special = 0)
. = ..()
poisoned_offset = world.time

/datum/outfit/rocker_cursed
name = "Cursed Rocker"
uniform = /obj/item/clothing/under/color/black/nodrop
shoes = /obj/item/clothing/shoes/jackboots/nodrop
suit = /obj/item/clothing/suit/leathercoat/nodrop
r_hand = /obj/item/instrument/eguitar

/obj/item/clothing/under/color/black/nodrop
flags = NODROP

/obj/item/clothing/shoes/jackboots/nodrop
flags = NODROP

/obj/item/clothing/suit/leathercoat/nodrop
flags = NODROP
Loading
Loading