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