mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-21 04:57:57 +01:00
Improved Cain & Abel wisp animations (#93294)
## About The Pull Request Cleaned up C&A code and made wisps orbit the user instead of being positioned around them at static offsets (also firing now removes them one by one as they're fired) https://github.com/user-attachments/assets/18a45b44-739e-4d7f-9269-98c84f5342e7 The animate code is mildly cursed because BYOND has... quirks, when it comes to looping tag animations, so we need to explicitly stop the animation, and cannot use a blank frame (time = 0) to start it (and SINE_EASING just looks better despite not being correct) ## Why It's Good For The Game Looks prettier ## Changelog 🆑 image: Cain & Abel wisps now orbit around the user instead of being static code: Cleaned up Cain & Abel code /🆑
This commit is contained in:
@@ -24,39 +24,40 @@
|
||||
reach = 2
|
||||
attack_icon = 'icons/effects/effects.dmi'
|
||||
attack_icon_state = "cain_abel_attack"
|
||||
///our current combo count
|
||||
/// Our current combo count
|
||||
var/combo_count = 0
|
||||
///the maximum combo we can reach
|
||||
/// The maximum combo we can reach
|
||||
var/max_combo = 6
|
||||
///percentage boost we get on every combo
|
||||
/// Percentage boost we get on every combo
|
||||
var/damage_boost = 1.15
|
||||
///pixel offsets of our wisps
|
||||
var/static/list/wisp_offsets = list(
|
||||
list(9, 12),
|
||||
list(14, 0),
|
||||
list(9, -12),
|
||||
list(-9, 12),
|
||||
list(-14, 0),
|
||||
list(-9, -12),
|
||||
)
|
||||
///what throw mode we're using
|
||||
/// Animation positions used by wisps
|
||||
var/static/list/animation_steps
|
||||
/// What throw mode we're using
|
||||
var/throw_mode = THROW_MODE_CRYSTALS
|
||||
///flames we have up!
|
||||
/// Flames we have up!
|
||||
var/list/current_wisps = list()
|
||||
///cooldown till we can throw blades again
|
||||
/// Cooldown till we can throw blades again
|
||||
COOLDOWN_DECLARE(throw_cooldown)
|
||||
|
||||
/obj/item/cain_and_abel/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/two_handed, require_twohands = TRUE, force_unwielded = force, force_wielded = force)
|
||||
if (length(animation_steps))
|
||||
return
|
||||
|
||||
animation_steps = list(
|
||||
new /datum/abel_wisp_frame(-18, -2, MOB_LAYER, EASE_OUT, EASE_IN),
|
||||
new /datum/abel_wisp_frame(-6, -6, ABOVE_MOB_LAYER, EASE_IN, EASE_OUT),
|
||||
new /datum/abel_wisp_frame(6, -6, ABOVE_MOB_LAYER, EASE_IN, EASE_OUT),
|
||||
new /datum/abel_wisp_frame(18, -2, MOB_LAYER, EASE_OUT, EASE_IN),
|
||||
new /datum/abel_wisp_frame(6, 2, BELOW_MOB_LAYER, EASE_IN, EASE_OUT),
|
||||
new /datum/abel_wisp_frame(-6, 2, BELOW_MOB_LAYER, EASE_IN, EASE_OUT),
|
||||
)
|
||||
|
||||
/obj/item/cain_and_abel/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change)
|
||||
. = ..()
|
||||
if(!isliving(old_loc))
|
||||
return
|
||||
|
||||
unset_user(old_loc)
|
||||
if(isliving(old_loc))
|
||||
unset_user(old_loc)
|
||||
|
||||
/obj/item/cain_and_abel/proc/unset_user(mob/living/source)
|
||||
if(HAS_TRAIT(source, TRAIT_RELAYING_ATTACKER))
|
||||
@@ -65,7 +66,6 @@
|
||||
set_combo(new_value = 0, user = source)
|
||||
UnregisterSignal(source, list(COMSIG_ATOM_WAS_ATTACKED))
|
||||
|
||||
|
||||
/obj/item/cain_and_abel/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
|
||||
@@ -92,8 +92,6 @@
|
||||
|
||||
for(var/index in 0 to (length(current_wisps) - 1))
|
||||
addtimer(CALLBACK(src, PROC_REF(fire_wisp), user, interacting_with), index * 0.15 SECONDS)
|
||||
|
||||
set_combo(new_value = 0, user = user)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/item/cain_and_abel/attack(mob/living/target, mob/living/carbon/human/user)
|
||||
@@ -117,29 +115,55 @@
|
||||
user.balloon_alert(user, "crystals [throw_mode == THROW_MODE_CRYSTALS ? "activated" : "deactivated"]")
|
||||
return TRUE
|
||||
|
||||
/obj/item/cain_and_abel/proc/set_combo(new_value, mob/living/user)
|
||||
combo_count = (new_value <= max_combo) ? new_value : 0
|
||||
handle_wisps(user)
|
||||
/obj/item/cain_and_abel/proc/set_combo(new_value, mob/living/user, instant = FALSE)
|
||||
new_value = clamp(new_value, 0, max_combo)
|
||||
if (new_value == combo_count)
|
||||
return
|
||||
|
||||
/obj/item/cain_and_abel/proc/handle_wisps(mob/living/user)
|
||||
var/should_remove = length(current_wisps) > combo_count
|
||||
var/wisps_to_alter = abs(combo_count - length(current_wisps))
|
||||
|
||||
for(var/i = 1, i <= wisps_to_alter, i++)
|
||||
if(!should_remove)
|
||||
if (new_value > combo_count)
|
||||
for (var/i in 1 to new_value - combo_count)
|
||||
add_wisp(user)
|
||||
continue
|
||||
var/obj/my_wisp = current_wisps[i]
|
||||
remove_wisp(my_wisp)
|
||||
else
|
||||
for (var/i in 1 to combo_count - new_value)
|
||||
remove_wisp(current_wisps[i], instant)
|
||||
|
||||
combo_count = new_value
|
||||
|
||||
/obj/item/cain_and_abel/proc/add_wisp(mob/living/user)
|
||||
var/obj/effect/overlay/blood_wisp/new_wisp = new(src)
|
||||
current_wisps += new_wisp
|
||||
var/list/position = wisp_offsets[length(current_wisps)]
|
||||
user.vis_contents += new_wisp
|
||||
new_wisp.pixel_x = position[1]
|
||||
new_wisp.pixel_y = position[2]
|
||||
RegisterSignal(new_wisp, COMSIG_QDELETING, PROC_REF(on_wisp_delete))
|
||||
for (var/wisp_index in 1 to length(current_wisps))
|
||||
var/obj/effect/overlay/blood_wisp/wisp = current_wisps[wisp_index]
|
||||
var/spawn_index = floor(length(animation_steps) / length(current_wisps) * wisp_index)
|
||||
var/datum/abel_wisp_frame/spawn_position = animation_steps[spawn_index]
|
||||
|
||||
// Latest added wisp is teleported to its spawn position, others animate from their current position
|
||||
if (wisp_index == length(current_wisps))
|
||||
wisp.pixel_w = spawn_position.x
|
||||
wisp.pixel_z = spawn_position.y
|
||||
wisp.layer = spawn_position.layer
|
||||
else
|
||||
animate(wisp, tag = "wisp_anim_x")
|
||||
animate(wisp, tag = "wisp_anim_y")
|
||||
|
||||
var/start_index = spawn_index % length(animation_steps) + 1
|
||||
var/datum/abel_wisp_frame/position = animation_steps[start_index]
|
||||
animate(wisp, pixel_w = position.x, layer = position.layer, time = 0.6 SECONDS, loop = -1, tag = "wisp_anim_x")
|
||||
// We need to animate x and y coordinates separately as they have different easing steps
|
||||
for (var/frame_index in 1 to length(animation_steps) - 1)
|
||||
// Get actual index starting from our *next* animation step, not initial position
|
||||
var/anim_index = (start_index + frame_index - 1) % length(animation_steps) + 1
|
||||
position = animation_steps[anim_index]
|
||||
animate(time = 0.6 SECONDS, pixel_w = position.x, layer = position.layer, easing = SINE_EASING | position.x_easing)
|
||||
|
||||
animate(wisp, time = 0.6 SECONDS, pixel_z = position.y, loop = -1, tag = "wisp_anim_y")
|
||||
for (var/frame_index in 1 to length(animation_steps) - 1)
|
||||
// Get actual index starting from our *next* animation step, not initial position
|
||||
var/anim_index = (start_index + frame_index - 1) % length(animation_steps) + 1
|
||||
position = animation_steps[anim_index]
|
||||
animate(time = 0.6 SECONDS, pixel_z = position.y, easing = SINE_EASING | position.y_easing)
|
||||
|
||||
/obj/item/cain_and_abel/proc/on_wisp_delete(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
@@ -148,7 +172,27 @@
|
||||
|
||||
/obj/item/cain_and_abel/proc/fire_wisp(atom/user, atom/target)
|
||||
user.fire_projectile(/obj/projectile/dagger_wisp, target)
|
||||
set_combo(combo_count - 1, user, TRUE)
|
||||
|
||||
/obj/item/cain_and_abel/proc/remove_wisp(obj/wisp_to_remove)
|
||||
/obj/item/cain_and_abel/proc/remove_wisp(obj/wisp_to_remove, instant = FALSE)
|
||||
if (instant)
|
||||
qdel(wisp_to_remove)
|
||||
return
|
||||
animate(wisp_to_remove, alpha = 0, time = 0.2 SECONDS)
|
||||
QDEL_IN(wisp_to_remove, 0.2 SECONDS)
|
||||
|
||||
/// Frame data for cain & abel wisps so we don't have to make list monstrocities
|
||||
/datum/abel_wisp_frame
|
||||
var/x = 0
|
||||
var/y = 0
|
||||
var/layer = MOB_LAYER
|
||||
var/x_easing = NONE
|
||||
var/y_easing = NONE
|
||||
|
||||
/datum/abel_wisp_frame/New(x, y, layer, x_easing, y_easing)
|
||||
. = ..()
|
||||
src.x = x
|
||||
src.y = y
|
||||
src.layer = layer
|
||||
src.x_easing = x_easing
|
||||
src.y_easing = y_easing
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
//effect when we're swinging wildly around
|
||||
/obj/effect/temp_visual/dagger_slash
|
||||
name = "Blood Wisp"
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
anchored = TRUE
|
||||
vis_flags = VIS_INHERIT_DIR | VIS_INHERIT_PLANE
|
||||
@@ -19,10 +18,10 @@
|
||||
|
||||
//flames we collect around our body
|
||||
/obj/effect/overlay/blood_wisp
|
||||
name = "Blood Wisp"
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
anchored = TRUE
|
||||
vis_flags = VIS_INHERIT_DIR | VIS_INHERIT_PLANE
|
||||
layer = ABOVE_HUD_PLANE
|
||||
vis_flags = VIS_INHERIT_PLANE
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "blood_wisp"
|
||||
light_power = 2
|
||||
|
||||
Reference in New Issue
Block a user