public bool Damage(SCAttack attack, IntegerVector origin, IntegerVector hitPoint) { if (this.Invincible) return false; //TODO - Normalize knockback effect to 16 directions Vector2 knockbackDirection = ((Vector2)(hitPoint - origin)).normalized; this.Actor.Velocity = knockbackDirection * attack.KnockbackPower; this.Invincible = true; _invincibilityTimer.reset(attack.HitInvincibilityDuration + FREEZE_FRAMES); _invincibilityTimer.start(); this.localNotifier.SendEvent(_freezeFrameEvent); _hitStunEvent.NumFrames = attack.HitStunDuration; this.localNotifier.SendEvent(_hitStunEvent); return true; }
private SCAttack.HitboxKeyframe? getKeyframeForUpdateFrame(SCAttack attack, int updateFrame) { SCAttack.HitboxKeyframe? keyframe = null; for (int i = 0; i < attack.HitboxKeyframes.Length; ++i) { if (attack.HitboxKeyframes[i].Frame <= updateFrame) keyframe = attack.HitboxKeyframes[i]; else break; } return keyframe; }
public SCAttack.VelocityBoost? GetCurrentVelocityBoost(SCAttack currentAttack) { return currentAttack.GetVelocityBoostForFrame(this.Animator.Elapsed); }
public void UpdateHitBoxes(SCAttack currentAttack, SCAttack.HurtboxState hurtboxState) { if (currentAttack == null) { for (int i = 0; i < this.DamageBoxes.Length; ++i) { this.DamageBoxes[i].transform.localPosition = Vector2.zero; this.DamageBoxes[i].enabled = false; } } else { SCAttack.HitboxKeyframe? keyframe = getKeyframeForUpdateFrame(currentAttack, this.Animator.Elapsed); if (keyframe.HasValue) { if (keyframe.Value.HurtboxState != hurtboxState) { bool success = this.HurtboxChangeCallback(keyframe.Value.HurtboxState); if (!success) return; } GameObject collided = null; IntegerRectCollider collider = null; for (int i = 0; i < this.DamageBoxes.Length; ++i) { if (i < keyframe.Value.HitboxCount) { this.DamageBoxes[i].enabled = true; this.DamageBoxes[i].transform.localPosition = (Vector2)keyframe.Value.HitboxPositions[i]; this.DamageBoxes[i].Size = keyframe.Value.HitboxSizes[i]; if (collided == null) { collided = this.DamageBoxes[i].CollideFirst(0, 0, this.DamagableLayers); if (collided != null) collider = this.DamageBoxes[i]; } } else { this.DamageBoxes[i].enabled = false; } } // Apply damage if we hit if (collided != null) { Damagable otherDamagable = collided.GetComponent<Damagable>(); if (otherDamagable != null) { IntegerVector hitPoint = collided.GetComponent<IntegerCollider>().ClosestContainedPoint((Vector2)collider.transform.position); bool landedHit = otherDamagable.Damage(currentAttack, (Vector2)this.Actor.transform.position, hitPoint); if (landedHit) { if (_freezeFrameEvent == null) _freezeFrameEvent = new FreezeFrameEvent(Damagable.FREEZE_FRAMES); this.localNotifier.SendEvent(_freezeFrameEvent); if (this.Damagable != null) this.Damagable.SetInvincible(Damagable.FREEZE_FRAMES); PooledObject hitEffect = this.HitEffect.Retain(); hitEffect.transform.position = (Vector2)hitPoint; hitEffect.GetComponent<HitEffectHandler>().InitializeWithFreezeFrames(Damagable.FREEZE_FRAMES); } } } } } }
private void updateHurtboxForState(SCAttack.HurtboxState state) { switch (state) { default: case SCAttack.HurtboxState.Normal: this.Hurtbox.Offset = this.MoveSet.NormalHitboxSpecs.Center; this.Hurtbox.Size = this.MoveSet.NormalHitboxSpecs.Size; break; case SCAttack.HurtboxState.Ducking: this.Hurtbox.Offset = this.MoveSet.DuckHitboxSpecs.Center; this.Hurtbox.Size = this.MoveSet.DuckHitboxSpecs.Size; break; } }
private bool attemptHurtboxStateChange(SCAttack.HurtboxState newState) { if (newState == this.HurtboxState) return true; updateHurtboxForState(newState); if (this.Hurtbox.CollideFirst(0, 0, this.HaltMovementMask) != null) { // We collided when trying to stand up, so boot out of attack into ducking position _currentAttack = null; updateHurtboxForState(this.HurtboxState); return false; } this.HurtboxState = newState; return true; }
public CharacterUpdateFinishedEvent(SCAttack currentAttack = null) { this.Name = NAME; this.CurrentAttack = currentAttack; }