public override void Update() { foreach (AttackerProperty attacker in attackers.Values) { // Prüfen, ob überhaupt ein Ziel existiert if (attacker.AttackTarget == null) { continue; } AttackableProperty attackable = attacker.AttackTarget; if (Item.GetDistance(attacker.Item, attackable.Item) <= attacker.AttackRange + attackable.AttackableRadius) { // Zum ersten mal im Angriffsbereich if (!attackable.AttackerItems.Contains(attacker)) { attackable.AddAttackerItem(attacker); attacker.RecoveryCounter = 0; } else { // Mit jeder weiteren Runde im Angriffsradius lädt der Recovery Counter. attacker.RecoveryCounter++; } // Informiere Attackable über einen Angreifer attackable.NoteAttackerItem(attacker); // Angriff if (attacker.RecoveryCounter >= attacker.AttackRecoveryTime) { int hitpoints = attacker.AttackStrength; attackable.AttackableHealth -= hitpoints; attackable.AttackerHit(attacker, hitpoints); attacker.AttackHit(attackable, hitpoints); attacker.RecoveryCounter = -1; } } else { // Vorher im Angriffsbereich gewesen? if (attackable.AttackerItems.Contains(attacker)) { attackable.RemoveAttackerItem(attacker); } } } // Tote Elemente aussortieren foreach (AttackableProperty attackable in attackables.Values) { if (attackable.AttackableHealth <= 0) { attackable.Kill(); Engine.RemoveItem(attackable.Item); } } }
public override void Remove(Item item) { // Entferne angreifbares Objekt if (item.ContainsProperty <AttackableProperty>() && attackables.ContainsKey(item.Id)) { // Angriffe auf ein entferntes Element stoppen AttackableProperty attackable = attackables[item.Id]; foreach (AttackerProperty attacker in attackers.Values) { if (attacker.AttackTarget == attackable) { attacker.StopAttack(); } } // entfernen attackables.Remove(item.Id); } // Entferne angreifendes Objekt if (item.ContainsProperty <AttackerProperty>() && attackers.ContainsKey(item.Id)) { // Angriffe stoppen AttackerProperty attacker = attackers[item.Id]; attacker.StopAttack(); // entfernen attackers.Remove(item.Id); } }
public DebugAttackableItem(ITypeResolver resolver, Vector2 pos) : base(resolver, pos, Angle.Right) { attackable = new AttackableProperty(this, 5, 100, 100); AddProperty(attackable); }
public AnthillItem(SimulationContext context, AntFaction faction, Vector2 position) : base(context, faction, position, HillRadius, Angle.Right) { var attackable = new AttackableProperty(this); if (attackable != null) { attackable.OnAttackableHealthChanged += (item, value) => { // Sollten die Hitpoints unter 0 kommen, ist der Ameisenhügel zerstört if (value <= 0) Engine.RemoveItem(this); }; } }
public AnthillItem(SimulationContext context, AntFaction faction, Vector2 position) : base(context, faction, position, HillRadius, Angle.Right) { var attackable = new AttackableProperty(this); if (attackable != null) { attackable.OnAttackableHealthChanged += (item, value) => { // Sollten die Hitpoints unter 0 kommen, ist der Ameisenhügel zerstört if (value <= 0) { Engine.RemoveItem(this); } }; } }
/// <summary> /// Internal call to perform a hit. /// </summary> /// <param name="item">Attacked Item</param> /// <param name="hitpoints">Hitpoints</param> internal void AttackHit(AttackableProperty item, int hitpoints) { if (OnAttackHit != null) OnAttackHit(item.Item, hitpoints); }
/// <summary> /// Attacks the given Item. /// </summary> /// <param name="item">Item</param> public void Attack(AttackableProperty item) { // Handling des alten Ziels if (AttackTarget != null) { // Ziel ändert sich nicht - alles gut if (AttackTarget == item) return; // Altes Ziel entfernen StopAttack(); } // Neues Ziel - Counter muss resettet werden RecoveryCounter = 0; // Prüfen, ob Attacker Teil der Simulation ist if (Item.Engine == null) throw new NotSupportedException("Attacker is not Part of the Simulation"); // Prüfen, ob Attackable Teil der Simulation ist if (item.Item.Engine == null || item.Item.Engine != Item.Engine) throw new NotSupportedException("Attackable is not Part of the same Simulation"); // Prüfen, ob sich das Element gerade selbst angreifen will if (item.Item == Item) throw new NotSupportedException("Item can not attack itself"); // Ziel einfügen AttackTarget = item; }
private void InitAttackableItem(Vector2 pos) { AttackableItem = new DebugAttackableItem(pos); Attackable = AttackableItem.GetProperty<AttackableProperty>(); Engine.InsertItem(AttackableItem); }
public void CleanupEngine() { AttackerItem = null; AttackableItem = null; CollectorItem = null; CollectableItem = null; Attacker = null; Attackable = null; Collector = null; Collectable = null; Map = null; Engine = null; }
/// <summary> /// Default Constructor for the Type Mapper. /// </summary> /// <param name="faction">Faction</param> /// <param name="item">Item</param> /// <param name="interop">UnitInterop</param> public InteractionInterop(Faction faction, FactionItem item, UnitInterop interop) : base(faction, item, interop) { #region Collector sugar = item.GetProperty <SugarCollectorProperty>(); if (sugar == null) { throw new ArgumentException("Item does not contain SugarCollector"); } apple = item.GetProperty <AppleCollectorProperty>(); if (apple == null) { throw new ArgumentException("Item does not contain AppleCollector"); } #endregion #region Carrier carrier = item.GetProperty <CarrierProperty>(); if (carrier == null) { throw new ArgumentException("Item does not contain CarrierProperty"); } #endregion #region Attackable attackable = item.GetProperty <AttackableProperty>(); if (attackable == null) { throw new ArgumentException("Item does not contain AttackableProperty"); } attackable.OnKill += i => { if (OnKill != null) { OnKill(); } }; attackable.OnAttackerHit += (i, value) => { if (OnHit != null) { OnHit(value); } }; attackable.OnNewAttackerItem += i => { var info = Item.GetItemInfo(i.Item); if (!attackerItems.Contains(info)) { attackerItems.Add(info); } }; attackable.OnLostAttackerItem += i => { var info = Item.GetItemInfo(i.Item); if (attackerItems.Contains(info)) { attackerItems.Remove(info); } }; #endregion #region Attacker attacker = item.GetProperty <AttackerProperty>(); if (attacker == null) { throw new ArgumentException("Item does not contain AttackerProperty"); } #endregion // Automatic Resource Transfer on Anthill Collision. var collidable = item.GetProperty <CollidableProperty>(); if (collidable == null) { throw new ArgumentException("Item does not contain AttackerProperty"); } collidable.OnCollision += (i, value) => { // Ignore if it's not a Anthill if (!(value is AnthillItem)) { return; } var anthill = value as AnthillItem; // Ignore if it's not the right faction if (anthill.Faction != item.Faction) { return; } // Transfer all collectables Give(anthill); }; }
/// <summary> /// Registers Ants /// </summary> /// <param name="typeMapper">Type Mapper</param> /// <param name="settings">Settings</param> private void RegisterAnt(ITypeMapper typeMapper, KeyValueStore settings) { // Ant Item settings.Set <AntItem>("ZickZackAngle", 10, "Correction Angle after Sprint"); settings.Set <AntItem>("ZickZackRange", 30f, "Distance to go every Sprint"); settings.Set <AntItem>("RotationSpeed", 20, "Maximum Rotation Angle per Round"); settings.Set <AntItem>("DropSugar", false, "Will an Ant leave a small Sugar on Drop"); settings.Set <AntItem>("MarkerDelay", 10, "Time in Rounds between Marker-Drops"); typeMapper.RegisterItem <AntItem, AntState, AntInfo>(this, "Ant"); // Walking settings.Set <AntItem>("MaxSpeed", 1f, "Maximum Speed of an Ant"); typeMapper.AttachItemProperty <AntItem, WalkingProperty>(this, "Ant Walking", (i) => { WalkingProperty property = new WalkingProperty(i); // Set Maximum Speed based on the current Settings // TODO: Check for Castes property.MaximumSpeed = i.Settings.GetFloat <AntItem>("MaxSpeed").Value; // Bind Item Orientation to Walk-Direction property.Direction = i.Orientation; i.OrientationChanged += (item, v) => { property.Direction = v; }; return(property); }); // Collision settings.Set <AntItem>("Mass", 1f, "Collision Mass of an Ant"); typeMapper.AttachItemProperty <AntItem, CollidableProperty>(this, "Ant Collidable", (i) => { CollidableProperty property = new CollidableProperty(i); // Set Mass to Settings property.CollisionFixed = false; property.CollisionMass = i.Settings.GetFloat <AntItem>("Mass").Value; // Bind Collision Radius to Item Radius property.CollisionRadius = i.Radius; i.RadiusChanged += (item, v) => { property.CollisionRadius = v; }; return(property); }); // Visibility typeMapper.AttachItemProperty <AntItem, VisibleProperty>(this, "Ant Visible", (i) => { VisibleProperty property = new VisibleProperty(i); // Bind Visibility Radius to the Item Radius property.VisibilityRadius = i.Radius; i.RadiusChanged += (item, v) => { property.VisibilityRadius = v; }; return(property); }); // Sighting settings.Set <AntItem>("ViewRange", 20f, "View Range of an Ant"); settings.Set <AntItem>("ViewAngle", 360, "View Angle of an Ant"); typeMapper.AttachItemProperty <AntItem, SightingProperty>(this, "Ant Sighting", (i) => { SightingProperty property = new SightingProperty(i); // Set View Range and Angle property.ViewRange = i.Settings.GetFloat <AntItem>("ViewRange").Value; property.ViewAngle = i.Settings.GetFloat <AntItem>("ViewAngle").Value; // Bind View Direction to the Item Orientation property.ViewDirection = i.Orientation; i.OrientationChanged += (item, v) => { property.ViewDirection = v; }; return(property); }); // Sniffer typeMapper.AttachItemProperty <AntItem, SnifferProperty>(this, "Ant Sniffer"); // Carrier settings.Set <AntItem>("CarrierStrength", 10f, "Carrier Strength of an Ant"); typeMapper.AttachItemProperty <AntItem, CarrierProperty>(this, "Ant Carrier", (i) => { CarrierProperty property = new CarrierProperty(i); property.CarrierStrength = i.Settings.GetFloat <AntItem>("CarrierStrength").Value; return(property); }); // Attackable settings.Set <AntItem>("MaxHealth", 100f, "Maximum Health for an Ant"); typeMapper.AttachItemProperty <AntItem, AttackableProperty>(this, "Ant Attackable", (i) => { AttackableProperty property = new AttackableProperty(i); // Bind Attackable Radius to Item Radius property.AttackableRadius = i.Radius; i.RadiusChanged += (item, v) => { property.AttackableRadius = v; }; // Health property.AttackableMaximumHealth = settings.GetInt <AntItem>("MaxHealth").Value; property.AttackableHealth = settings.GetInt <AntItem>("MaxHealth").Value; return(property); }); // Attacker settings.Set <AntItem>("AttackRange", 3f, "Attack Range for a Bug"); settings.Set <AntItem>("RecoveryTime", 2, "Recovery Time in Rounds for a Bug"); settings.Set <AntItem>("AttackStrength", 5, "Attach Strength for a Bug"); typeMapper.AttachItemProperty <AntItem, AttackerProperty>(this, "Ant Attacker", (i) => { AttackerProperty property = new AttackerProperty(i); property.AttackRange = i.Settings.GetFloat <AntItem>("AttackRange").Value; property.AttackRecoveryTime = i.Settings.GetInt <AntItem>("RecoveryTime").Value; property.AttackStrength = i.Settings.GetInt <AntItem>("AttackStrength").Value; return(property); }); // Collector settings.Set <AntItem>("SugarCapacity", 5, "Maximum Capacity for Sugar"); settings.Set <AntItem>("AppleCapacity", 2, "Maximum Capacity for Apple"); typeMapper.AttachItemProperty <AntItem, SugarCollectorProperty>(this, "Ant Sugar Collectable", (i) => { SugarCollectorProperty property = new SugarCollectorProperty(i); property.Capacity = i.Settings.GetInt <AntItem>("SugarCapacity").Value; return(property); }); typeMapper.AttachItemProperty <AntItem, AppleCollectorProperty>(this, "Ant Apple Collectable", (i) => { AppleCollectorProperty property = new AppleCollectorProperty(i); property.Capacity = i.Settings.GetInt <AntItem>("AppleCapacity").Value; return(property); }); // TODO: Optional, wenn _settings.ANT_APPLECOLLECT | _settings.ANT_APPLE_CAPACITY, 0); }
/// <summary> /// Registers classic Bugs /// </summary> /// <param name="typeMapper">Type Mapper</param> /// <param name="settings">Settings</param> private void RegisterClassicBug(ITypeMapper typeMapper, KeyValueStore settings) { // Classic Bug typeMapper.RegisterItem <ClassicBugItem, BugState, BugInfo>(this, "Classic Bug"); // Walking settings.Set <ClassicBugItem>("MaxSpeed", 2f, "Maximum Speed of a Classic Bug"); typeMapper.AttachItemProperty <ClassicBugItem, WalkingProperty>(this, "Classic Bug Walking", (i) => { WalkingProperty property = new WalkingProperty(i); // Set Walking Speed property.MaximumSpeed = i.Settings.GetFloat <ClassicBugItem>("MaxSpeed").Value; // Bind Direction to the Items Orientation property.Direction = i.Orientation; i.OrientationChanged += (item, v) => { property.Direction = v; }; return(property); }); // Collision settings.Set <ClassicBugItem>("Mass", 10f, "Collision Mass of a Classic Bug"); typeMapper.AttachItemProperty <ClassicBugItem, CollidableProperty>(this, "Classic Bug Collidable", (i) => { CollidableProperty property = new CollidableProperty(i); // Set Collision Mass property.CollisionFixed = false; property.CollisionMass = i.Settings.GetFloat <ClassicBugItem>("Mass").Value; // Bind Collision Radius to the Item Radius property.CollisionRadius = i.Radius; i.RadiusChanged += (item, v) => { property.CollisionRadius = v; }; return(property); }); // Visibility typeMapper.AttachItemProperty <ClassicBugItem, VisibleProperty>(this, "Classic Bug Visible", (i) => { VisibleProperty property = new VisibleProperty(i); // Bind Visibility Radius to the Item Radius property.VisibilityRadius = i.Radius; i.RadiusChanged += (item, v) => { property.VisibilityRadius = v; }; return(property); }); // Sighting settings.Set <ClassicBugItem>("ViewRange", 20f, "View Range of a Classic Bug"); settings.Set <ClassicBugItem>("ViewAngle", 360, "View Angle of a Classic Bug"); typeMapper.AttachItemProperty <ClassicBugItem, SightingProperty>(this, "Classic Bug Sighting", (i) => { SightingProperty property = new SightingProperty(i); // Set View Range and Angle property.ViewRange = i.Settings.GetFloat <ClassicBugItem>("ViewRange").Value; property.ViewAngle = i.Settings.GetFloat <ClassicBugItem>("ViewAngle").Value; // Bind View Direction to the Item Orientation property.ViewDirection = i.Orientation; i.OrientationChanged += (item, v) => { property.ViewDirection = v; }; return(property); }); // Sniffer typeMapper.AttachItemProperty <ClassicBugItem, SnifferProperty>(this, "Classic Bug Sniffer"); // Attackable settings.Set <ClassicBugItem>("MaxHealth", 1000, "Maximum Health of a Classic Bug"); typeMapper.AttachItemProperty <ClassicBugItem, AttackableProperty>(this, "Classic Bug Attackable", (i) => { AttackableProperty property = new AttackableProperty(i); // Bind Attackable Radius to Item Radius property.AttackableRadius = i.Radius; i.RadiusChanged += (item, v) => { property.AttackableRadius = v; }; // Health property.AttackableMaximumHealth = settings.GetInt <ClassicBugItem>("MaxHealth").Value; property.AttackableHealth = settings.GetInt <ClassicBugItem>("MaxHealth").Value; return(property); }); // Attacker settings.Set <ClassicBugItem>("AttackRange", 5f, "Attack Range for a Classic Bug"); settings.Set <ClassicBugItem>("RecoveryTime", 5, "Recovery Time in Rounds for a Classic Bug"); settings.Set <ClassicBugItem>("AttackStrength", 10, "Attach Strength for a Classic Bug"); typeMapper.AttachItemProperty <ClassicBugItem, AttackerProperty>(this, "Classic Bug Attacker", (i) => { AttackerProperty property = new AttackerProperty(i); property.AttackRange = i.Settings.GetFloat <ClassicBugItem>("AttackRange").Value; property.AttackRecoveryTime = i.Settings.GetInt <ClassicBugItem>("RecoveryTime").Value; property.AttackStrength = i.Settings.GetInt <ClassicBugItem>("AttackStrength").Value; return(property); }); }
/// <summary> /// Registers Anthills /// </summary> /// <param name="typeMapper">Type Mapper</param> /// <param name="settings">Settings</param> private void RegisterAnthill(ITypeMapper typeMapper, KeyValueStore settings) { // Anthill typeMapper.RegisterItem <AnthillItem, AnthillState, AnthillInfo>(this, "Anthill"); // Collision typeMapper.AttachItemProperty <AnthillItem, CollidableProperty>(this, "Anthill Collidable", (i) => { CollidableProperty property = new CollidableProperty(i); // Set Collision Mass property.CollisionFixed = true; property.CollisionMass = 0f; // Bind Radius to the Item Radius property.CollisionRadius = i.Radius; i.RadiusChanged += (item, v) => { property.CollisionRadius = v; }; return(property); }); // Visibility typeMapper.AttachItemProperty <AnthillItem, VisibleProperty>(this, "Anthill Visible", (i) => { VisibleProperty property = new VisibleProperty(i); // Bind Visibility Radius to the Item Radius property.VisibilityRadius = i.Radius; i.RadiusChanged += (item, v) => { property.VisibilityRadius = v; }; return(property); }); // Attackable settings.Set <AnthillItem>("Attackable", false, "Enables the possibility to destroy Anthills"); settings.Set <AnthillItem>("MaxHealth", 1000, "Maximum Health of an Anthill"); settings.Set <AnthillItem>("Buildable", false, "Can an Anthill build by ants"); typeMapper.AttachItemProperty <AnthillItem, AttackableProperty>(this, "Anthill Attackable", (i) => { // Check Attackable Switch if (!i.Settings.GetBool <AnthillItem>("Attackable").Value) { return(null); } AttackableProperty property = new AttackableProperty(i); // Bind Attackable Radius to Item Radius property.AttackableRadius = i.Radius; i.RadiusChanged += (item, v) => { property.AttackableRadius = v; }; // Health property.AttackableMaximumHealth = settings.GetInt <AnthillItem>("MaxHealth").Value; property.AttackableHealth = settings.GetInt <AnthillItem>("MaxHealth").Value; return(property); }); // Collectable typeMapper.AttachItemProperty <AnthillItem, SugarCollectableProperty>(this, "Anthill Sugarsafe"); // TODO: Radius typeMapper.AttachItemProperty <AnthillItem, AppleCollectableProperty>(this, "Anthill Applesafe"); // TODO: Radius }
public AttackableInfo(Item item, ItemProperty property, Item observer) : base(item, property, observer) { this.property = property as AttackableProperty; }