diff --git a/code/game/objects/items/stacks/flags.dm b/code/game/objects/items/stacks/flags.dm index 484d2779f5f8..e032e2c80157 100644 --- a/code/game/objects/items/stacks/flags.dm +++ b/code/game/objects/items/stacks/flags.dm @@ -76,3 +76,206 @@ newflag.icon_state = "[newflag.base_state]_open" newflag.visible_message("[user] plants [newflag] firmly in the ground.") src.use(1) + + +/// PLANTABLE FLAG + +/obj/structure/flag/plantable + name = "flag" + desc = "A flag of something. This one looks like you could dismantle it." + icon = 'icons/obj/structures/plantable_flag.dmi' + pixel_x = 9 // All flags need to be offset to the right by 9 to be centered. + layer = ABOVE_XENO_LAYER + health = 150 + unacidable = TRUE + + /// The typepath for the flag item that gets spawned when the flag is taken down. + var/flag_type = /obj/item/flag/plantable + /// Used to limit the spam of the warcry_extra_sound + COOLDOWN_DECLARE(warcry_cooldown_struc) + +/obj/structure/flag/plantable/attack_hand(mob/user) + ..() + disassemble(user, flag_type) + +/// Proc for dismantling the flag into an item that can be picked up. +/obj/structure/flag/plantable/proc/disassemble(mob/user, flag_type) + if(user.action_busy) + return + + user.visible_message(SPAN_NOTICE("[user] starts taking [src] down..."), SPAN_NOTICE("You start taking [src] down...")) + + playsound(loc, 'sound/effects/flag_raising.ogg', 30) + if(!do_after(user, 6 SECONDS, INTERRUPT_ALL, BUSY_ICON_GENERIC)) + return + + playsound(loc, 'sound/effects/flag_raised.ogg', 30) + user.visible_message(SPAN_NOTICE("[user] starts takes [src] down!"), SPAN_NOTICE("You take [src] down!")) + var/obj/item/flag/plantable/flag_item = new flag_type(loc) + user.put_in_hands(flag_item) + COOLDOWN_START(flag_item, warcry_cooldown_item, COOLDOWN_TIMELEFT(src, warcry_cooldown_struc)) + qdel(src) + +/// Proc for when the flag gets forcefully dismantled (due to general damage, explosions, etc.) +/obj/structure/flag/plantable/proc/demolish(flag_type) + playsound(loc, 'sound/effects/flag_raised.ogg', 30) + visible_message(SPAN_WARNING("[src] crumples to the ground!")) + var/obj/item/flag/plantable/flag_item = new flag_type(loc) + COOLDOWN_START(flag_item, warcry_cooldown_item, COOLDOWN_TIMELEFT(src, warcry_cooldown_struc)) + qdel(src) + +// Procs for handling damage. +/obj/structure/flag/plantable/update_health(damage) + if(damage) + health -= damage + if(health <= 0) + demolish(flag_type) + +/obj/structure/flag/plantable/ex_act(severity) + if(health <= 0) + return + update_health(severity) + +/obj/structure/flag/plantable/attack_alien(mob/living/carbon/xenomorph/xeno) + if(xeno.a_intent == INTENT_HARM) + if(unslashable) + return + xeno.animation_attack_on(src) + playsound(loc, 'sound/effects/metalhit.ogg', 25, 1) + xeno.visible_message(SPAN_DANGER("[xeno] slashes [src]!"), SPAN_DANGER("We slash [src]!"), null, 5, CHAT_TYPE_XENO_COMBAT) + update_health(rand(xeno.melee_damage_lower, xeno.melee_damage_upper)) + return XENO_ATTACK_ACTION + else + to_chat(xeno, SPAN_WARNING("We stare at [src] cluelessly.")) + return XENO_NONCOMBAT_ACTION + +/obj/structure/flag/plantable/bullet_act(obj/projectile/bullet) + bullet_ping(bullet) + visible_message(SPAN_DANGER("[src] is hit by [bullet]!"), null, 4, CHAT_TYPE_TAKING_HIT) + update_health(bullet.damage) + return TRUE + +/obj/structure/flag/plantable/attackby(obj/item/weapon, mob/living/user) + if(!indestructible) + visible_message(SPAN_DANGER("[src] has been hit by [user] with [weapon]!"), null, 5, CHAT_TYPE_MELEE_HIT) + user.animation_attack_on(src) + playsound(loc, 'sound/effects/metalhit.ogg', 25, 1) + update_health(weapon.force * weapon.demolition_mod) + +/obj/item/flag/plantable + name = "plantable flag" + desc = "A flag of something. This one looks ready to be planted into the ground." + w_class = SIZE_LARGE + throw_range = 2 + icon = 'icons/obj/structures/plantable_flag.dmi' + inhand_x_dimension = 64 + inhand_y_dimension = 64 + unacidable = TRUE + item_icons = list( + WEAR_L_HAND = 'icons/mob/humans/onmob/items_lefthand_64.dmi', + WEAR_R_HAND = 'icons/mob/humans/onmob/items_righthand_64.dmi' + ) + + /// The typepath of the flag structure that gets spawned when the flag is planted. + var/flag_type = /obj/structure/flag/plantable + /// Used to check if nearby mobs belong to a faction when calculating for the stronger warcry. + var/faction + /// Does the flag play a unique warcry when planted? (Only while on harm intent.) + var/play_warcry = FALSE + /// The warcry's sound path. + var/warcry_sound + /// When there are more than 14 allies nearby, play this stronger warcry. + var/warcry_extra_sound + /// How many nearby allies do we need for the stronger warcry to be played? + var/allies_required = 14 + /// Used to limit the spam of the warcry_extra_sound + COOLDOWN_DECLARE(warcry_cooldown_item) + +/obj/item/flag/plantable/get_examine_text(mob/user) + . = ..() + if(play_warcry && user.faction == faction) + . += SPAN_NOTICE("Planting the flag while in HARM intent will cause you to bellow out a rallying warcry!") + +/// Proc for turning the flag item into a structure. +/obj/item/flag/plantable/proc/plant_flag(mob/living/user, play_warcry = FALSE, warcry_sound, warcry_extra_sound, faction) + if(user.action_busy) + return + + if(SSinterior.in_interior(user)) + to_chat(usr, SPAN_WARNING("There's no way to plant [src] in here!")) + return + + var/turf/turf_to_plant = get_step(user, user.dir) + if(istype(turf_to_plant, /turf/open)) + var/turf/open/floor = turf_to_plant + if(!floor.allow_construction || istype(floor, /turf/open/space)) + to_chat(user, SPAN_WARNING("You cannot deploy [src] here, find a more secure surface!")) + return + else + to_chat(user, SPAN_WARNING("[turf_to_plant] is blocking you from deploying [src]!")) + return + + for(var/obj/object in turf_to_plant) + if(object.density) + to_chat(usr, SPAN_WARNING("You need a clear, open area to plant [src], something is blocking the way in front of you!")) + return + + user.visible_message(SPAN_NOTICE("[user] starts planting [src] into the ground..."), SPAN_NOTICE("You start planting [src] into the ground...")) + playsound(user, 'sound/effects/flag_raising.ogg', 30) + if(!do_after(user, 6 SECONDS, INTERRUPT_ALL, BUSY_ICON_GENERIC)) + return + + user.visible_message(SPAN_NOTICE("[user] plants [src] into the ground!"), SPAN_NOTICE("You plant [src] into the ground!")) + var/obj/structure/flag/plantable/planted_flag = new flag_type(turf_to_plant) + + // If there are more than 14 allies nearby, play a stronger rallying cry. + // Otherwise, play the default warcry sound if there is one. If not, play a generic flag raising sfx. + if(play_warcry && user.faction == faction && user.a_intent == INTENT_HARM) + var/allies_nearby = 0 + if(COOLDOWN_FINISHED(src, warcry_cooldown_item)) + for (var/mob/living/carbon/human in orange(planted_flag, 7)) + if (human.is_dead() || human.faction != faction) + continue + allies_nearby++ + if (prob(40) && human != user) + human.emote("warcry") + + user.show_speech_bubble("warcry") + if(allies_nearby >= allies_required) + playsound(user, warcry_extra_sound, 40) + // Start a cooldown on the flag structure. This way we can keep track of the cooldown when the flag is hoisted and taken down. + COOLDOWN_START(planted_flag, warcry_cooldown_struc, 90 SECONDS) + user.manual_emote("shouts an invigorating rallying cry!") + else + playsound(user, warcry_sound, 30) + user.manual_emote("shouts an inspiring cry!") + // Ditto. If the cooldown isn't finished we have to transfer the leftover time to the structure. + COOLDOWN_START(planted_flag, warcry_cooldown_struc, COOLDOWN_TIMELEFT(src, warcry_cooldown_item)) + else + playsound(loc, 'sound/effects/flag_raised.ogg', 30) + + qdel(src) + +/obj/item/flag/plantable/attack_self(mob/user) + ..() + plant_flag(user, play_warcry, warcry_sound, warcry_extra_sound, faction) + +// UNITED AMERICAS FLAG // +////////////////////////// + +/obj/item/flag/plantable/ua + name = "\improper United Americas flag" + desc = "The flag of the United Americas. This one looks ready to be planted into the ground." + icon = 'icons/obj/structures/plantable_flag.dmi' + icon_state = "flag_ua" + flag_type = /obj/structure/flag/plantable/ua + faction = FACTION_MARINE + play_warcry = TRUE + warcry_sound = 'sound/effects/flag_warcry_ua.ogg' + warcry_extra_sound = 'sound/effects/flag_warcry_ua_extra.ogg' + +/obj/structure/flag/plantable/ua + name = "\improper United Americas flag" + desc = "The flag of the United Americas. Semper fi." + icon_state = "flag_ua_planted" + flag_type = /obj/item/flag/plantable/ua diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index f93f2dab0984..2dc064aa86d4 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -416,7 +416,7 @@ var/offset_x = worn_x_dimension var/offset_y = worn_y_dimension - if(inhands) + if(inhands == 1 || inhands == 0) offset_x = inhand_x_dimension offset_y = inhand_y_dimension diff --git a/icons/mob/humans/onmob/items_lefthand_64.dmi b/icons/mob/humans/onmob/items_lefthand_64.dmi index 057d7f1cad66..d005d8c5f049 100644 Binary files a/icons/mob/humans/onmob/items_lefthand_64.dmi and b/icons/mob/humans/onmob/items_lefthand_64.dmi differ diff --git a/icons/mob/humans/onmob/items_righthand_64.dmi b/icons/mob/humans/onmob/items_righthand_64.dmi index 599ef5935f2e..72335e39bfff 100644 Binary files a/icons/mob/humans/onmob/items_righthand_64.dmi and b/icons/mob/humans/onmob/items_righthand_64.dmi differ diff --git a/icons/obj/structures/plantable_flag.dmi b/icons/obj/structures/plantable_flag.dmi new file mode 100644 index 000000000000..c92311529be3 Binary files /dev/null and b/icons/obj/structures/plantable_flag.dmi differ diff --git a/maps/map_files/USS_Almayer/USS_Almayer.dmm b/maps/map_files/USS_Almayer/USS_Almayer.dmm index 9617bfaccb6c..b4a195ae5969 100644 --- a/maps/map_files/USS_Almayer/USS_Almayer.dmm +++ b/maps/map_files/USS_Almayer/USS_Almayer.dmm @@ -2665,6 +2665,7 @@ /obj/item/device/radio/marine, /obj/item/device/radio/marine, /obj/item/folded_tent/cmd, +/obj/item/flag/plantable/ua, /turf/open/floor/almayer/redfull, /area/almayer/command/cic) "asR" = ( diff --git a/sound/effects/.wav b/sound/effects/.wav new file mode 100644 index 000000000000..a5aa273379f6 Binary files /dev/null and b/sound/effects/.wav differ diff --git a/sound/effects/flag_lowering.ogg b/sound/effects/flag_lowering.ogg new file mode 100644 index 000000000000..d514e097913d Binary files /dev/null and b/sound/effects/flag_lowering.ogg differ diff --git a/sound/effects/flag_raised.ogg b/sound/effects/flag_raised.ogg new file mode 100644 index 000000000000..5da7eca55acb Binary files /dev/null and b/sound/effects/flag_raised.ogg differ diff --git a/sound/effects/flag_raising.ogg b/sound/effects/flag_raising.ogg new file mode 100644 index 000000000000..cc2770f2ecb8 Binary files /dev/null and b/sound/effects/flag_raising.ogg differ diff --git a/sound/effects/flag_warcry_ua.ogg b/sound/effects/flag_warcry_ua.ogg new file mode 100644 index 000000000000..eb0ddecc66eb Binary files /dev/null and b/sound/effects/flag_warcry_ua.ogg differ diff --git a/sound/effects/flag_warcry_ua_extra.ogg b/sound/effects/flag_warcry_ua_extra.ogg new file mode 100644 index 000000000000..c723cca44620 Binary files /dev/null and b/sound/effects/flag_warcry_ua_extra.ogg differ