1 #include "critter_purple.h"
2
3 #include "../../game.h"
4 #include "../../player.h"
5 #include "../../sound/SoundManager.h"
6 #include "../../trig.h"
7 #include "../ai.h"
8 #include "../stdai.h"
9
10 #define STATE_IDLE 1 // waiting for player to come near
11 #define STATE_PREPARE_JUMP 2 // on ground, prepare to jump
12 #define STATE_JUMP 3 // jumping up
13 #define STATE_HOVER 4 // hovering and firing
14 #define STATE_END_JUMP 5 // falling back down
15
16 #define CRITTER_DAMAGE 2 // normal damage
17 #define CRITTER_FALL_DAMAGE 3 // damage if it falls on you
18
INITFUNC(AIRoutines)19 INITFUNC(AIRoutines)
20 {
21 ONTICK(OBJ_CRITTER_SHOOTING_PURPLE, ai_critter_shooting_purple);
22 ONTICK(OBJ_CRITTER_SHOT, ai_generic_angled_shot);
23 }
24
25 /*
26 void c------------------------------() {}
27 */
28
29 // used only for purple ones in maze
ai_critter_shooting_purple(Object * o)30 void ai_critter_shooting_purple(Object *o)
31 {
32
33 switch (o->state)
34 {
35 case 0:
36 o->state = STATE_IDLE;
37 o->damage = CRITTER_DAMAGE;
38 case STATE_IDLE:
39 {
40 o->frame = 0; // assume not at attention
41 if (o->timer >= 8)
42 {
43 if (pdistlx(96 * CSFI) && pdistly2(96 * CSFI, 32 * CSFI))
44 {
45 FACEPLAYER;
46
47 // close enough to attack?
48 if (pdistlx(48 * CSFI))
49 {
50 o->state = STATE_PREPARE_JUMP;
51 o->frame = 0;
52 o->timer = 0;
53 }
54 else
55 { // no, but stand at "attention"
56 o->frame = 1;
57 }
58 }
59 }
60 else
61 {
62 o->timer++;
63 }
64
65 // also attack if shot
66 if (o->shaketime)
67 {
68 o->state = STATE_PREPARE_JUMP;
69 o->frame = 0;
70 o->timer = 0;
71 }
72 }
73 break;
74
75 case STATE_PREPARE_JUMP:
76 {
77 o->frame = 1;
78 if (++o->timer > 8)
79 {
80 FACEPLAYER;
81
82 o->state = STATE_JUMP;
83 o->timer = 0;
84 o->frame = 2;
85
86 NXE::Sound::SoundManager::getInstance()->playSfx(NXE::Sound::SFX::SND_ENEMY_JUMP);
87 o->yinertia = -0x5ff;
88 }
89 }
90 break;
91
92 case STATE_JUMP:
93 {
94 if (o->yinertia > 0x100 || (o->blockd && ++o->timer > 16)) // failsafe
95 {
96 o->ymark = o->y;
97
98 o->state = STATE_HOVER;
99 o->frame = 3;
100 o->timer = 0;
101
102 o->CurlyTargetHere(60, 100);
103 }
104 }
105 break;
106
107 case STATE_HOVER:
108 { // sinusoidal hover
109 o->yinertia += (o->y > o->ymark) ? -0x10 : 0x10;
110 LIMITY(0x200);
111
112 FACEPLAYER;
113 ANIMATE(0, 3, 5);
114
115 // time to end flight?
116 if (++o->timer > 60 || o->blocku)
117 {
118 o->damage = CRITTER_FALL_DAMAGE;
119 o->state = STATE_END_JUMP;
120 o->frame = 2;
121 break;
122 }
123
124 if ((o->timer % 4) == 1)
125 NXE::Sound::SoundManager::getInstance()->playSfx(NXE::Sound::SFX::SND_CRITTER_FLY);
126
127 if ((o->timer % 30) == 6)
128 {
129 EmFireAngledShot(o, OBJ_CRITTER_SHOT, 6, 0x600);
130 NXE::Sound::SoundManager::getInstance()->playSfx(NXE::Sound::SFX::SND_EM_FIRE);
131 }
132
133 if (o->blockd)
134 o->yinertia = -0x200;
135 }
136 break;
137
138 case STATE_END_JUMP:
139 {
140 if (o->blockd)
141 {
142 o->damage = 2;
143 o->xinertia = 0;
144 o->timer = 0;
145 o->frame = 0;
146 o->state = 0;
147 NXE::Sound::SoundManager::getInstance()->playSfx(NXE::Sound::SFX::SND_THUD);
148 }
149 }
150 break;
151 }
152
153 if (o->state != STATE_HOVER)
154 {
155 o->yinertia += 0x20;
156 LIMITY(0x5ff);
157 }
158 }
159