1 /*
2 Copyright (C) 2009-2021 Parallel Realities
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18 */
19
20 #include "../headers.h"
21
22 #include "../audio/audio.h"
23 #include "../audio/music.h"
24 #include "../collisions.h"
25 #include "../entity.h"
26 #include "../game.h"
27 #include "../graphics/animation.h"
28 #include "../graphics/decoration.h"
29 #include "../system/error.h"
30 #include "../system/properties.h"
31 #include "../system/random.h"
32
33 extern Entity *self;
34
35 static void entityWait(void);
36 static void drop(void);
37 static void touch(Entity *);
38 static void initialise(void);
39 static void chasePlayer(void);
40 static void idle(void);
41 static void addDust(void);
42
addBoulderBoss(int x,int y,char * name)43 Entity *addBoulderBoss(int x, int y, char *name)
44 {
45 Entity *e = getFreeEntity();
46
47 if (e == NULL)
48 {
49 showErrorAndExit("No free slots to add the Boulder Boss");
50 }
51
52 loadProperties("boss/boulder_boss", e);
53
54 e->x = x;
55 e->y = y;
56
57 e->action = &initialise;
58
59 e->draw = &drawLoopingAnimationToMap;
60 e->touch = NULL;
61 e->die = &entityDie;
62
63 setEntityAnimation(e, "STAND");
64
65 return e;
66 }
67
initialise()68 static void initialise()
69 {
70 if (self->health == 0)
71 {
72 if (self->active == TRUE)
73 {
74 self->thinkTime--;
75
76 fadeOutMusic(3000);
77
78 if (self->thinkTime <= 0)
79 {
80 self->x = self->startX;
81 self->y = self->startY;
82
83 self->touch = &touch;
84
85 self->flags &= ~(NO_DRAW|FLY);
86
87 self->flags |= ATTACKING;
88
89 self->action = &drop;
90
91 self->health = 1;
92 }
93 }
94
95 else
96 {
97 self->thinkTime = 120;
98 }
99 }
100
101 else
102 {
103 self->flags &= ~(NO_DRAW|FLY);
104
105 self->touch = &pushEntity;
106
107 self->frameSpeed = 0;
108
109 self->action = &idle;
110 }
111 }
112
drop()113 static void drop()
114 {
115 if (self->flags & ON_GROUND)
116 {
117 self->thinkTime = 30;
118
119 playSoundToMap("sound/common/crash", -1, self->x, self->y, 0);
120
121 shakeScreen(STRONG, self->thinkTime / 2);
122
123 addDust();
124
125 self->action = &entityWait;
126 }
127
128 doNothing();
129 }
130
entityWait()131 static void entityWait()
132 {
133 self->thinkTime--;
134
135 if (self->thinkTime <= 0)
136 {
137 playDefaultBossMusic();
138
139 playSoundToMap("sound/boss/boulder_boss/roll", BOSS_CHANNEL, self->x, self->y, -1);
140
141 setEntityAnimation(self, "WALK");
142
143 self->endX = -2.0f;
144
145 self->thinkTime = 65;
146
147 self->action = &chasePlayer;
148
149 syncBoulderFrameSpeed();
150 }
151 }
152
chasePlayer()153 static void chasePlayer()
154 {
155 long onGround = self->flags & ON_GROUND;
156
157 self->dirX -= 0.02f;
158
159 self->thinkTime--;
160
161 if (self->thinkTime <= 0)
162 {
163 self->thinkTime = 65;
164
165 self->endX -= 0.08f;
166
167 self->frameSpeed++;
168 }
169
170 if (self->dirX <= self->endX)
171 {
172 self->dirX = self->endX;
173 }
174
175 checkToMap(self);
176
177 if (onGround == 0 && (self->flags && ON_GROUND))
178 {
179 shakeScreen(LIGHT, 5);
180
181 addDust();
182 }
183
184 if (self->dirX == 0 && abs(self->endX) > 2)
185 {
186 self->action = &idle;
187
188 self->touch = &pushEntity;
189
190 self->frameSpeed = 0;
191
192 self->active = FALSE;
193
194 playSoundToMap("sound/common/crash", -1, self->x, self->y, 0);
195
196 shakeScreen(STRONG, 90);
197
198 self->thinkTime = 90;
199
200 fadeBossMusic();
201
202 self->health = 1;
203
204 addDust();
205
206 stopSound(BOSS_CHANNEL);
207 }
208
209 syncBoulderFrameSpeed();
210 }
211
idle()212 static void idle()
213 {
214
215 }
216
touch(Entity * other)217 static void touch(Entity *other)
218 {
219 Entity *temp = self;
220
221 if (other->die != NULL)
222 {
223 self = other;
224
225 self->die();
226
227 self = temp;
228 }
229 }
230
addDust()231 static void addDust()
232 {
233 int i;
234
235 for (i=0;i<25;i++)
236 {
237 addSmoke(self->x + prand() % self->w, self->y + self->h - prand() % 10, "decoration/dust");
238 }
239 }
240