-
Notifications
You must be signed in to change notification settings - Fork 522
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reimplements halloween pumpkin helmets event (#4623)
# About the pull request <!-- Remove this text and explain what the purpose of your PR is. Mention if you have tested your changes. If you changed a map, make sure you used the mapmerge tool. If this is an Issue Correction, you can type "Fixes Issue #169420" to link the PR to the corresponding Issue number #169420. Remember: something that is self-evident to you might not be to others. Explain your rationale fully, even if you feel it goes without saying. --> This reimplements the Halloween Pumpkins spawning on map and being carvable as helmets which was apparetnly a thing a number of years ago # Explain why it's good for the game Variety # Changelog :cl: Firartix and Frans_Feiffer add: Readded Halloween pumpkin helmets. /:cl: --------- Co-authored-by: harryob <[email protected]>
- Loading branch information
Showing
9 changed files
with
289 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Essentially the same as decorators but that apply to the whole game state instead of individual atoms | ||
SUBSYSTEM_DEF(game_decorator) | ||
name = "Game Decorator" | ||
init_order = SS_INIT_DECORATOR | ||
flags = SS_NO_FIRE | ||
|
||
/datum/controller/subsystem/game_decorator/Initialize() | ||
. = ..() | ||
for(var/decorator_type in subtypesof(/datum/game_decorator)) | ||
var/datum/game_decorator/decorator = new decorator_type() | ||
if(!decorator.is_active_decor()) | ||
continue | ||
if(!decorator.defer_decoration) | ||
decorator.decorate() | ||
CHECK_TICK | ||
|
||
return SS_INIT_SUCCESS | ||
|
||
/datum/game_decorator | ||
var/defer_decoration = TRUE //! So map decoration is done post-setup after nightmare and spawners | ||
|
||
/datum/game_decorator/New() | ||
if(defer_decoration) | ||
RegisterSignal(SSdcs, COMSIG_GLOB_MODE_POSTSETUP, PROC_REF(defered_decoration)) | ||
|
||
/datum/game_decorator/proc/is_active_decor() | ||
return FALSE | ||
|
||
/datum/game_decorator/proc/defered_decoration(dcs) | ||
SIGNAL_HANDLER | ||
decorate() | ||
|
||
/datum/game_decorator/proc/decorate() | ||
set waitfor = FALSE | ||
return |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/datum/game_decorator/halloween | ||
|
||
/datum/game_decorator/halloween/is_active_decor() | ||
return (get_days_remaining() != -1) | ||
|
||
/// Get the number of days remaining to event, or -1 if not applicable | ||
/datum/game_decorator/halloween/proc/get_days_remaining() | ||
. = -1 | ||
var/cur_day = text2num(time2text(world.timeofday, "DD")) | ||
var/cur_mon = text2num(time2text(world.timeofday, "MM")) | ||
if(cur_mon == 10) | ||
return max(0, 31 - cur_day) | ||
if(cur_mon == 11 && cur_day < 4) | ||
return 0 | ||
|
||
/// Pumpkins decorator: adds patches of carvable/wearable pumpkins around the ground level | ||
/datum/game_decorator/halloween/pumpkins | ||
var/pumpkin_count = 60 //! Amount of pumpkins to place | ||
var/pumpkin_count_decrease = 1 //! Amount of pumpkins to remove per day to halloween | ||
var/pumpkin_prob_corruption = 20 | ||
var/pumpkin_prob_decrease = 0.5 //! Chance reduction per day before halloween | ||
var/exclusion_range = 10 | ||
|
||
/datum/game_decorator/halloween/pumpkins/decorate() | ||
var/list/turf/valid_turfs = list() | ||
var/list/ground_levels = SSmapping.levels_by_trait(ZTRAIT_GROUND) | ||
for(var/ground_z in ground_levels) | ||
var/list/turf/all_turfs = block(locate(1, 1, ground_z), locate(world.maxx, world.maxy, ground_z)) | ||
for(var/turf/open/turf in all_turfs) | ||
if(turf.is_groundmap_turf) | ||
var/valid = TRUE | ||
for(var/atom/movable/movable as anything in turf.contents) | ||
if(movable.density && movable.can_block_movement) | ||
valid = FALSE | ||
break | ||
if(valid) | ||
valid_turfs += turf | ||
CHECK_TICK | ||
|
||
var/list/turf/picked_turfs = list() | ||
for(var/step in 1 to (pumpkin_count - pumpkin_count_decrease * get_days_remaining())) | ||
if(!length(valid_turfs)) | ||
break | ||
var/turf/considered_turf = pick(valid_turfs) | ||
var/x_min = max(1, considered_turf.x - exclusion_range) | ||
var/y_min = max(1, considered_turf.y - exclusion_range) | ||
var/x_max = min(world.maxx, considered_turf.x + exclusion_range) | ||
var/y_max = min(world.maxy, considered_turf.y + exclusion_range) | ||
var/list/turf/denied_turfs = block(locate(x_min, y_min, considered_turf.z), locate(x_max, y_max, considered_turf.z)) | ||
valid_turfs -= denied_turfs | ||
picked_turfs += considered_turf | ||
|
||
var/corruption_chance = pumpkin_prob_corruption - (get_days_remaining() * pumpkin_prob_decrease) | ||
for(var/turf/target in picked_turfs) | ||
if(prob(corruption_chance)) | ||
new /obj/structure/pumpkin_patch/corrupted(target) | ||
else | ||
new /obj/structure/pumpkin_patch(target) | ||
|
||
/// Cobweb decorator: adds more and more cobwebs as you go through the month | ||
/datum/game_decorator/halloween/cobwebs | ||
/// How much prob() chance to put a cobweb during halloween proper | ||
var/base_chance = 25 | ||
/// How much to remove per day before date | ||
var/ramp_chance = 0.5 | ||
/// How much to scale cobwebs alpha down per day (1 - ramp_scale * days, affects alpha & size) | ||
var/ramp_scale = 0.01 | ||
/// Extra randomness removed onto scale before full blown halloween | ||
var/scale_rand = 0.3 | ||
|
||
/datum/game_decorator/halloween/cobwebs/decorate() | ||
for(var/turf/closed/wall/almayer/turf in world) | ||
if(is_mainship_level(turf.z)) | ||
decorate_turf(turf) | ||
CHECK_TICK | ||
|
||
/datum/game_decorator/halloween/cobwebs/proc/decorate_turf(turf/closed/wall/almayer/turf) | ||
var/static/list/order = list(NORTHWEST, SOUTHEAST, NORTHEAST, SOUTHWEST) // Ordering of wall_connections | ||
if(length(turf.wall_connections) < 4) | ||
return | ||
|
||
var/event_progress = get_days_remaining() | ||
var/placement_chance = base_chance - (event_progress * ramp_chance) | ||
for(var/i = 1 to 4) | ||
var/diag = order[i] | ||
if(turf.wall_connections[i] != "5") // CORNER_CLOCKWISE | CORNER_COUNTERCLOCKWISE as string - don't ask me | ||
continue | ||
if(!prob(placement_chance)) | ||
continue | ||
|
||
// Skip this if this corner is result of a door connection (mostly for Almayer shutters) | ||
var/valid = TRUE | ||
for(var/a_cardinal in cardinal) | ||
var/cardinal_dir = diag & a_cardinal | ||
if(!a_cardinal) // We check cardinals contributing to that diagonal | ||
continue | ||
var/turf/target = get_step(turf, cardinal_dir) | ||
if(locate(/obj/structure/machinery/door) in target) | ||
valid = FALSE | ||
break | ||
|
||
if(valid) // Actually place cobweb | ||
var/turf/target = get_step(turf, diag) | ||
if(istype(target, /turf/open)) | ||
var/scale = 1 - ramp_scale * event_progress | ||
scale -= scale_rand * rand() | ||
new /obj/effect/decal/cleanable/cobweb2/dynamic(target, diag, scale) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/// Patches of pumpkins spawned at roundstart from where marines can get their carvable pumpkins | ||
/obj/structure/pumpkin_patch | ||
icon = 'icons/misc/events/pumpkins.dmi' | ||
name = "patch of pumpkins" | ||
var/empty_name = "\proper vines" | ||
|
||
can_block_movement = FALSE | ||
unslashable = TRUE | ||
health = 400 // To avoid explosions and stray gunfire destroying them too easily | ||
layer = LOWER_ITEM_LAYER | ||
|
||
var/has_vines = TRUE //! Whether there's still vines to display or not | ||
var/pumpkin_count = 3 //! Amount of pumpkins currently in the patch | ||
var/icon_prefix //! Prefix to prepend to icon states, for corrupted pumpkins | ||
var/pumpkin_type = /obj/item/clothing/head/pumpkin | ||
|
||
/obj/structure/pumpkin_patch/Initialize(mapload, ...) | ||
. = ..() | ||
update_icon() | ||
|
||
/obj/structure/pumpkin_patch/update_icon() | ||
overlays?.Cut() | ||
. = ..() | ||
switch(pumpkin_count) | ||
if(3) icon_state = "[icon_prefix]pumpkins_full" | ||
if(2) icon_state = "[icon_prefix]pumpkins_half" | ||
if(1) icon_state = "[icon_prefix]pumpkin" | ||
else icon_state = "empty" | ||
if(has_vines) | ||
overlays += image(icon, loc, "[icon_prefix]vines") | ||
|
||
/obj/structure/pumpkin_patch/attack_hand(mob/user) | ||
if(pumpkin_count < 1) | ||
to_chat(user, SPAN_WARNING("No more pumpkins here...")) | ||
return | ||
if(!user.get_active_hand()) //if active hand is empty | ||
pumpkin_count-- | ||
var/obj/item/clothing/head/pumpkin/pumpkin = new pumpkin_type(loc) | ||
user.put_in_hands(pumpkin) | ||
playsound(loc, 'sound/effects/vegetation_hit.ogg', 25, 1) | ||
update_icon() | ||
if(pumpkin_count < 1) | ||
if(!has_vines) | ||
qdel(src) | ||
else | ||
name = empty_name | ||
return | ||
return ..() | ||
|
||
/obj/structure/pumpkin_patch/attackby(obj/item/tool, mob/user) | ||
if(has_vines && (tool.sharp == IS_SHARP_ITEM_ACCURATE || tool.sharp == IS_SHARP_ITEM_BIG)) | ||
to_chat(user, SPAN_NOTICE("You cut down the vines.")) | ||
playsound(loc, "alien_resin_break", 25) | ||
has_vines = FALSE | ||
update_icon() | ||
if(pumpkin_count < 1 && !has_vines) | ||
qdel(src) | ||
return | ||
return ..() | ||
|
||
/obj/structure/pumpkin_patch/corrupted | ||
icon_prefix = "cor_" | ||
name = "patch of corrupted pumpkins" | ||
empty_name = "\proper corrupted vines" | ||
pumpkin_type = /obj/item/clothing/head/pumpkin/corrupted |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/// Carved Pumpkin from the Halloween event | ||
/obj/item/clothing/head/pumpkin | ||
name = "pumpkin" | ||
icon = 'icons/misc/events/pumpkins.dmi' | ||
item_icons = list( | ||
WEAR_HEAD = 'icons/misc/events/pumpkins.dmi', | ||
) | ||
desc = "An ominous looking pumpkin. Would look pretty spooky if worn on your head..." | ||
w_class = SIZE_MEDIUM | ||
flags_inv_hide = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEALLHAIR | ||
flags_armor_protection = BODY_FLAG_HEAD|BODY_FLAG_EYES | ||
flags_inventory = COVEREYES|BLOCKSHARPOBJ|COVERMOUTH | ||
flags_cold_protection = BODY_FLAG_HEAD | ||
flags_heat_protection = BODY_FLAG_HEAD | ||
min_cold_protection_temperature = HELMET_MIN_COLD_PROT | ||
max_heat_protection_temperature = HELMET_MAX_HEAT_PROT | ||
armor_melee = CLOTHING_ARMOR_MEDIUM | ||
armor_bullet = CLOTHING_ARMOR_MEDIUM | ||
armor_laser = CLOTHING_ARMOR_MEDIUMLOW | ||
armor_energy = CLOTHING_ARMOR_NONE | ||
armor_bomb = CLOTHING_ARMOR_LOW | ||
armor_bio = CLOTHING_ARMOR_MEDIUM | ||
armor_rad = CLOTHING_ARMOR_LOW | ||
armor_internaldamage = CLOTHING_ARMOR_MEDIUM | ||
health = 5 | ||
force = 15 | ||
var/prefix = "" //! Icon state prefix for corrupted pumpkin variants | ||
var/carved_icon = "" //! Currently carved pumpkin overlay | ||
var/carvable_icons = list("smile", "cheeky", "bugeyes", "upside_down_smile", "skelly", "ff") | ||
|
||
/obj/item/clothing/head/pumpkin/Initialize(mapload, ...) | ||
. = ..() | ||
update_icon() | ||
|
||
/obj/item/clothing/head/pumpkin/update_icon() | ||
. = ..() | ||
if(carved_icon) | ||
icon_state = "[prefix]pumpkin_carved" | ||
else | ||
icon_state = "[prefix]pumpkin" | ||
item_state_slots = list( | ||
WEAR_HEAD = "[prefix]pumpkin_onmob", | ||
) | ||
|
||
/obj/item/clothing/head/pumpkin/mob_can_equip(mob/user, slot, disable_warning) | ||
if(slot == WEAR_HEAD && !carved_icon) | ||
to_chat(user, SPAN_WARNING("You can't put on a full pumpkin! Empty and carve it with a sharp object first.")) | ||
return FALSE | ||
. = ..() | ||
|
||
/obj/item/clothing/head/pumpkin/attackby(obj/item/tool, mob/user) | ||
if(!carved_icon && (tool.sharp == IS_SHARP_ITEM_ACCURATE || tool.sharp == IS_SHARP_ITEM_BIG)) | ||
var/choice = tgui_input_list(user, "Select the pattern to carve on your pumpkin!", "Pumpkin Carving", carvable_icons) | ||
if(choice) | ||
playsound(loc, 'sound/effects/vegetation_hit.ogg', 25, 1) | ||
carved_icon = choice | ||
name = "carved pumpkin" | ||
update_icon() | ||
else | ||
return ..() | ||
|
||
/obj/item/clothing/head/pumpkin/get_mob_overlay(mob/user_mob, slot) | ||
var/image/pumpkin = ..() | ||
if(carved_icon && slot == WEAR_HEAD) | ||
var/image/overlay = overlay_image(icon, "[prefix]pumpkin_[carved_icon]") | ||
pumpkin.overlays += overlay | ||
return pumpkin | ||
|
||
/obj/item/clothing/head/pumpkin/corrupted | ||
name = "corrupted pumpkin" | ||
prefix = "cor_" | ||
carvable_icons = list("cry", "sob", "sad", "why", "spooky", "ff") |
Oops, something went wrong.