source: 2013/30/DenisZ/CastleMaster/CastleMaster/CastleMaster/Units/Mobs/MobRanger.cs @ 4646

Revision 4646, 6.6 KB checked in by dezhidki, 6 years ago (diff)

Muokattu sotilaita viimeiseen muotoon.

Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using CastleMaster.Graphics;
6using CastleMaster.World;
7using CastleMaster.Players;
8using IsometricEngineTest.Ai.Orders;
9using CastleMaster.Entities;
10using CastleMaster.Ai.Orders;
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 AnimationHelper 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 AnimationHelper(5, 5, false, 3);
48            hitAnimation.RoundEnded += delegate()
49            {
50                if (target != null)
51                    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);
52            };
53        }
54
55        public override int TypeID
56        {
57            get { return 1; }
58        }
59
60        private void StartAttack()
61        {
62            isAttacking = true;
63            hitAnimation.Start();
64        }
65
66        private void StopAttack()
67        {
68            isAttacking = false;
69            target = null;
70            currentOrderType = OrderType.NONE;
71        }
72
73        private void PauseAttack()
74        {
75            isAttacking = false;
76            hitAnimation.Stop();
77            hitAnimation.Reset();
78        }
79
80        private void CreateAttackOrder(Unit u, int orderAmount, bool wasCalledBefore)
81        {
82            currentOrderType = OrderType.ATTACK;
83            attackRange = u.Width + ATTACK_RANGE_OFFSET;
84            attackRangeSqr = attackRange * attackRange;
85            SetOrder(new OrderMove(u.X, u.Z, attackRange, orderAmount * 2.0F, true, !wasCalledBefore));
86            target = u;
87        }
88
89        public override void Damage(Unit attacker, int damage, float dir, float pushPower)
90        {
91            base.Damage(attacker, damage, dir, pushPower);
92            if (!isAttacking && currentOrderType == OrderType.NONE)
93                CreateAttackOrder(attacker, 1, false);
94        }
95
96        protected override void OnOrderFinished()
97        {
98            base.OnOrderFinished();
99            if (currentOrderType == OrderType.ATTACK)
100                StartAttack();
101            else if (currentOrderType == OrderType.WALK)
102                currentOrderType = OrderType.NONE;
103            else if (currentOrderType == OrderType.AVOID)
104            {
105                currentOrderType = OrderType.ATTACK;
106                attack = true;
107            }
108        }
109
110        public override Order GetNextOrder()
111        {
112            if (attack)
113            {
114                attack = false;
115                return new OrderMove(target.X, target.Z, attackRange, excludeEndSolidness: true);
116            }
117            return base.GetNextOrder();
118        }
119
120        public override void OnFunctionClick(float x, float z, int sameOrders, bool wasCalledBefore)
121        {
122            Unit u = Owner.SelectUnit(Game.GetEnemyTeam(Owner.Team));
123            if (u != null)
124                CreateAttackOrder(u, sameOrders, wasCalledBefore);
125            else
126            {
127                if (target != null) StopAttack();
128                currentOrderType = OrderType.WALK;
129                SetOrder(new OrderMove(x, z, createNewPathFinder: !wasCalledBefore, stopOnMoveFail: true));
130            }
131            lastSameOrderAmount = sameOrders;
132        }
133
134        public override void Update()
135        {
136            base.Update();
137
138            if (isAttacking)
139            {
140                if (DistanceToSqr(target.X, target.Z) > attackRangeSqr)
141                {
142                    isAttacking = false;
143                    CreateAttackOrder(target, 1, false);
144                }
145                else
146                {
147                    UpdateDir(target.X, target.Z);
148                    hitAnimation.UpdateStep();
149                    if (target.Removed)
150                        StopAttack();
151                }
152                if (target == null || target.Removed)
153                    StopAttack();
154            }
155            else if (!isAttacking && currentOrderType == OrderType.NONE)
156            {
157                List<Unit> units = level.GetNearbyEnemyUnits(Game.GetEnemyTeam(Owner.Team), (int)(x / Viewport.TILESIZE), (int)(z / Viewport.TILESIZE), 5);
158                if (units.Count > 0)
159                    CreateAttackOrder(units[0], 1, false);
160            }
161            else if (!isAttacking && currentOrderType == OrderType.ATTACK)
162            {
163                float dist = lastSameOrderAmount * 20.0F;
164                if (currentOrder != null && currentOrder is OrderMove && ((OrderMove)currentOrder).FailingToMove && DistanceToSqr(target.X, target.Z) < attackRangeSqr + dist * dist)
165                {
166                    int tp = level.GetClosestDiagonalOpenPos(this);
167                    if (tp > 0)
168                    {
169                        currentOrderType = OrderType.AVOID;
170                        SetOrder(new OrderMove(tp % level.Width * Viewport.TILESIZE, tp / level.Width * Viewport.TILESIZE, stopOnMoveFail: true));
171                    }
172                }
173                if (target == null || target.Removed)
174                {
175                    StopAttack();
176                    StopCurrentOrder();
177                }
178            }
179
180            spriteX = isAttacking ? hitAnimation.CurrentFrame : walkingAnimation.CurrentFrame;
181        }
182
183        public override void Render(RenderHelper renderer)
184        {
185            base.Render(renderer);
186            renderer.Render(ScreenPos, spriteX, dirID, Resources.SPRITESHEET_RANGER, colorizer, Viewport.ZOOM);
187        }
188    }
189}
Note: See TracBrowser for help on using the repository browser.