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