source: 2013/30/DenisZ/CastleMaster/CastleMaster/CastleMaster/Units/Mobs/MobWarrior.cs @ 4756

Revision 4756, 7.1 KB checked in by dezhidki, 8 years ago (diff)
  • Nimi muutettu (Sound2D -> Audio)
  • Lisätty perusäänet
  • Muokattu Ctrl + RMouse kombinaatiota
    • Nyt voi myös klikata sen sijaan että valitsee laatikolla
Line 
1using CastleMaster.Ai.Orders;
2using CastleMaster.Graphics;
3using CastleMaster.Players;
4using CastleMaster.World;
5using IsometricEngineTest.Ai.Orders;
6using System.Collections.Generic;
7using CastleMaster.Sound;
8using Microsoft.Xna.Framework.Audio;
9
10namespace CastleMaster.Units.Mobs
11{
12    public class MobWarrior : Mob
13    {
14        private enum OrderType { ATTACK, WALK, AVOID, NONE }
15
16        private float ATTACK_RANGE_OFFSET = 25.0F;
17        private float attackRange, attackRangeSqr;
18
19        private Unit target;
20        private OrderType currentOrderType = OrderType.NONE;
21        private bool isAttacking = false;
22        private int maxDamage = 6;
23        private TimerHelper hitAnimation;
24        private int spriteX;
25        private float pushPower = 5.0F;
26        private int lastSameOrderAmount = 0;
27        private bool engageAttack = false;
28
29        public MobWarrior(Level level, Player owner)
30            : base(level, owner)
31        {
32            HasHealth = true;
33            maxHealth = 50;
34
35            spriteSize.X = 17;
36            spriteSize.Y = 20;
37            screenRectOffset.Update(8, 12, 8 + spriteSize.X, 12 + spriteSize.Y);
38            renderOffset.Y = 20;
39
40            highlightOffset.X = 11;
41
42            rectOffset.Update(-4.0F, -4.0F, 5.0F, 5.0F);
43            isSolid = true;
44            moveSpeed = 1.25F;
45            hitAnimation = new TimerHelper(8, 5, false, 3);
46            hitAnimation.RoundEnded += delegate
47            {
48                if (target != null)
49                {
50                    int damage = Game.Random.Next(1, maxDamage + 1);
51                    Hit(target, damage, Direction, pushPower);
52                    if (damage == maxDamage)
53                        Audio.PlaySound3D(emitter, screenPos, "sword2");
54                    else
55                        Audio.PlaySound3D(emitter, screenPos, "sword1");
56                }
57            };
58        }
59
60        public override int TypeID
61        {
62            get { return 2; }
63        }
64
65        public Unit Target { get { return target; } }
66
67        public override void OnRemoved()
68        {
69            base.OnRemoved();
70            Audio.PlaySound3D(emitter, screenPos, "death3");
71        }
72
73        private void StartAttack()
74        {
75            isAttacking = true;
76            hitAnimation.Start();
77        }
78
79        private void StopAttack()
80        {
81            isAttacking = false;
82            target = null;
83            currentOrderType = OrderType.NONE;
84            StopCurrentOrder();
85        }
86
87        private void PauseAttack()
88        {
89            isAttacking = false;
90            hitAnimation.Stop();
91            hitAnimation.Reset();
92        }
93
94        public void CreateAttackOrder(Unit u, int orderAmount, bool wasCalledBefore)
95        {
96            currentOrderType = OrderType.ATTACK;
97            attackRange = u.Width / 2 + ATTACK_RANGE_OFFSET;
98            attackRangeSqr = attackRange * attackRange;
99            SetOrder(new OrderMove(u.X, u.Z, attackRange, orderAmount * 2.0F, true, !wasCalledBefore));
100            target = u;
101        }
102
103        public override void Damage(Unit attacker, int damage, float dir, float pushPower)
104        {
105            base.Damage(attacker, damage, dir, pushPower);
106            if (!isAttacking && currentOrderType == OrderType.NONE)
107                CreateAttackOrder(attacker, 1, false);
108        }
109
110        protected override void OnOrderFinished()
111        {
112            base.OnOrderFinished();
113            if (currentOrderType == OrderType.ATTACK)
114                StartAttack();
115            else if (currentOrderType == OrderType.WALK)
116                currentOrderType = OrderType.NONE;
117            else if (currentOrderType == OrderType.AVOID)
118            {
119                currentOrderType = OrderType.ATTACK;
120                engageAttack = true;
121            }
122        }
123
124        public override Order GetNextOrder()
125        {
126            if (engageAttack)
127            {
128                engageAttack = false;
129                return new OrderMove(target.X, target.Z, attackRange, excludeEndSolidness: true);
130            }
131            return base.GetNextOrder();
132        }
133
134        public override void OnFunctionClick(float x, float z, int sameOrders, bool wasCalledBefore)
135        {
136            Unit u = Owner.SelectUnit(Game.GetEnemyTeam(Owner.Team));
137            if (u != null)
138                CreateAttackOrder(u, sameOrders, wasCalledBefore);
139            else
140            {
141                if (target != null) StopAttack();
142                currentOrderType = OrderType.WALK;
143                SetOrder(new OrderMove(x, z, createNewPathFinder: !wasCalledBefore, stopOnMoveFail: true));
144            }
145            lastSameOrderAmount = sameOrders;
146        }
147
148        public override void Update()
149        {
150            base.Update();
151
152            if (isAttacking)
153            {
154                if (DistanceToSqr(target.X, target.Z) > attackRangeSqr)
155                {
156                    isAttacking = false;
157                    CreateAttackOrder(target, 1, false);
158                }
159                else
160                {
161                    UpdateDir(target.X, target.Z);
162                    hitAnimation.UpdateStep();
163                    if (target.Removed)
164                        StopAttack();
165                }
166                if (target == null || target.Removed || (typeof(UnitBuilding).IsAssignableFrom(target.GetType()) && ((UnitBuilding)target).IsDestroyed))
167                    StopAttack();
168            }
169            else if (!isAttacking && currentOrderType == OrderType.NONE)
170            {
171                List<Unit> units = level.GetNearbyEnemyUnits(Game.GetEnemyTeam(Owner.Team), (int)(x / Viewport.TILESIZE), (int)(z / Viewport.TILESIZE), 3);
172                if (units.Count > 0)
173                    CreateAttackOrder(units[0], 1, false);
174            }
175            else if (!isAttacking && currentOrderType == OrderType.ATTACK)
176            {
177                float dist = lastSameOrderAmount * 12.0F;
178                if (currentOrder != null && currentOrder is OrderMove && ((OrderMove)currentOrder).FailingToMove && DistanceToSqr(target.X, target.Z) < attackRangeSqr + dist * dist)
179                {
180                    int tp = level.GetClosestDiagonalOpenPos(this);
181                    if (tp > 0)
182                    {
183                        currentOrderType = OrderType.AVOID;
184                        SetOrder(new OrderMove(tp % level.Width * Viewport.TILESIZE, tp / level.Width * Viewport.TILESIZE, stopOnMoveFail: true));
185                    }
186                }
187                if (target == null || target.Removed || (typeof(UnitBuilding).IsAssignableFrom(target.GetType()) && ((UnitBuilding)target).IsDestroyed))
188                    StopAttack();
189            }
190
191            spriteX = isAttacking ? hitAnimation.CurrentFrame : walkingAnimation.CurrentFrame;
192        }
193
194        public override void Render(RenderHelper renderer)
195        {
196            base.Render(renderer);
197            renderer.Render(ScreenPos, spriteX, dirID, Owner.Team.SpriteSheetWarrior, colorizer, Viewport.ZOOM);
198        }
199    }
200}
Note: See TracBrowser for help on using the repository browser.