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