/// <summary> /// Uses a weapon/object on an entity /// Finds components with the InteractUsing interface and calls their function /// </summary> public void Interaction(IEntity user, IEntity weapon, IEntity attacked, GridCoordinates clickLocation) { var attackMsg = new AttackByMessage(user, weapon, attacked, clickLocation); RaiseLocalEvent(attackMsg); if (attackMsg.Handled) { return; } var attackBys = attacked.GetAllComponents <IInteractUsing>().ToList(); var attackByEventArgs = new InteractUsingEventArgs { User = user, ClickLocation = clickLocation, Using = weapon, Target = attacked }; // all AttackBys should only happen when in range / unobstructed, so no range check is needed if (InteractionChecks.InRangeUnobstructed(attackByEventArgs)) { foreach (var attackBy in attackBys) { if (attackBy.InteractUsing(attackByEventArgs)) { // If an InteractUsing returns a status completion we finish our attack return; } } } var afterAtkMsg = new AfterAttackMessage(user, weapon, attacked, clickLocation); RaiseLocalEvent(afterAtkMsg); if (afterAtkMsg.Handled) { return; } // If we aren't directly attacking the nearby object, lets see if our item has an after attack we can do var afterAttacks = weapon.GetAllComponents <IAfterInteract>().ToList(); var afterAttackEventArgs = new AfterInteractEventArgs { User = user, ClickLocation = clickLocation, Target = attacked }; foreach (var afterAttack in afterAttacks) { afterAttack.AfterInteract(afterAttackEventArgs); } }
/// <summary> /// Will have two behaviors, either "uses" the weapon at range on the entity if it is capable of accepting that action /// Or it will use the weapon itself on the position clicked, regardless of what was there /// </summary> public void RangedInteraction(IEntity user, IEntity weapon, IEntity attacked, GridCoordinates clickLocation) { var rangedMsg = new RangedAttackMessage(user, weapon, attacked, clickLocation); RaiseLocalEvent(rangedMsg); if (rangedMsg.Handled) { return; } var rangedAttackBys = attacked.GetAllComponents <IRangedInteract>().ToList(); var rangedAttackByEventArgs = new RangedInteractEventArgs { User = user, Using = weapon, ClickLocation = clickLocation }; // See if we have a ranged attack interaction foreach (var t in rangedAttackBys) { if (t.RangedInteract(rangedAttackByEventArgs)) { // If an InteractUsing returns a status completion we finish our attack return; } } var afterAtkMsg = new AfterAttackMessage(user, weapon, attacked, clickLocation); RaiseLocalEvent(afterAtkMsg); if (afterAtkMsg.Handled) { return; } var afterAttacks = weapon.GetAllComponents <IAfterInteract>().ToList(); var afterAttackEventArgs = new AfterInteractEventArgs { User = user, ClickLocation = clickLocation, Target = attacked }; //See if we have a ranged attack interaction foreach (var afterAttack in afterAttacks) { afterAttack.AfterInteract(afterAttackEventArgs); } }
/// <summary> /// We didn't click on any entity, try doing an AfterInteract on the click location /// </summary> private void InteractAfter(IEntity user, IEntity weapon, GridCoordinates clickLocation) { var message = new AfterAttackMessage(user, weapon, null, clickLocation); RaiseLocalEvent(message); if (message.Handled) { return; } var afterInteracts = weapon.GetAllComponents <IAfterInteract>().ToList(); var afterInteractEventArgs = new AfterInteractEventArgs { User = user, ClickLocation = clickLocation }; foreach (var afterInteract in afterInteracts) { afterInteract.AfterInteract(afterInteractEventArgs); } }