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

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

Muokattu sotilaita viimeiseen muotoon.

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