2 Copyright (C) 2004 Parallel Realities
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.
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.
13 See the GNU General Public License for more details.
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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 void throwAndDamageEntity(Entity
*ent
, int damage
, int minDX
, int maxDX
, int DY
)
25 if ((ent
== &player
) && (game
.missionOver
> 0))
30 if (!(ent
->flags
& ENT_EXPLODES
))
32 audio
.playSound(SND_HIT
, CH_ANY
);
33 for (int i
= 0 ; i
< 4 ; i
++)
35 addBlood(ent
, Math::rrand(-5, 5), Math::rrand(-6, -3), i
);
40 audio
.playSound(SND_CLANG
, CH_ANY
);
41 addColorParticles(ent
->x
, ent
->y
, Math::rrand(25, 75), -1);
44 if ((ent
== &player
) && (engine
.cheatInvulnerable
))
48 ent
->health
-= damage
;
57 ent
->health
-= damage
;
62 if (player
.health
<= 0)
64 audio
.playSound(SND_DEATH1
+ Math::prand() % 3, CH_DEATH
);
68 Math::removeBit(&player
.flags
, ENT_FLIES
);
70 player
.setSprites(graphics
.getSprite("BobRight", true), graphics
.getSprite("BobLeft", true), graphics
.getSprite("BobSpin", true));
74 ent
->health
-= damage
;
77 ((Math::prand() % 2) == 0) ? ent
->dx
= -minDX
: ent
->dx
= maxDX
;
89 bool checkBrickContactX(Entity
*ent
)
91 int new_ent_x
= (int)round((ent
->x
+ ent
->dx
) * 100) / 100;
92 int ent_y
= (int)round(ent
->y
* 100) / 100;
93 int x1
= new_ent_x
>> BRICKSHIFT
;
94 int x2
= (new_ent_x
+ ent
->width
- 1) >> BRICKSHIFT
;
95 int y1
= ent_y
>> BRICKSHIFT
;
96 int y2
= (ent_y
+ ent
->height
- 1) >> BRICKSHIFT
;
98 if ((x1
< 0) || (x2
< 0) || (y1
< 0) || (y2
< 0))
103 int mapAttribute
= map
.data
[x1
][y2
];
105 evaluateMapAttribute(ent
, mapAttribute
);
107 if ((ent
->flags
& ENT_SWIMS
) && (mapAttribute
== MAP_AIR
))
112 if ((map
.isSolid(x1
, y1
)) || (map
.isSolid(x1
, y2
)))
114 ent
->x
= (x1
+ 1) * BRICKSIZE
;
116 // if (map.isSolid(x1, y2))
118 // ent->falling = false;
124 else if (ent
->dx
> 0)
126 if ((map
.isSolid(x2
, y1
)) || (map
.isSolid(x2
, y2
)))
128 ent
->x
= (x2
* BRICKSIZE
) - ent
->width
;
130 // if (map.isSolid(x1, y2))
132 // ent->falling = false;
142 bool checkBrickContactY(Entity
*ent
)
144 int ent_x
= (int)round(ent
->x
* 100) / 100;
145 int new_ent_y
= (int)round((ent
->y
+ ent
->dy
) * 100) / 100;
146 int x1
= ent_x
>> BRICKSHIFT
;
147 int x2
= (ent_x
+ ent
->width
- 1) >> BRICKSHIFT
;
148 int y1
= new_ent_y
>> BRICKSHIFT
;
149 int y2
= (new_ent_y
+ ent
->height
- 1) >> BRICKSHIFT
;
151 if ((x1
< 0) || (x2
< 0) || (y1
< 0) || (y2
< 0))
156 int mapAttribute
= map
.data
[x1
][y2
];
160 mapAttribute
= map
.data
[x1
][y1
];
163 evaluateMapAttribute(ent
, mapAttribute
);
165 if (ent
->flags
& ENT_SWIMS
)
167 switch (mapAttribute
)
173 case MAP_AIR_CEILING_1
:
176 if (map
.isCavesTileset
)
181 case MAP_AIR_CEILING_2
:
182 if (map
.isGrasslandsTileset
)
192 if ((map
.isSolid(x1
, y1
)) || (map
.isSolid(x2
, y1
)))
194 ent
->y
= (y1
+ 1) * BRICKSIZE
;
195 ent
->falling
= false;
200 else if (ent
->dy
> 0)
204 if ((map
.isSolid(x1
, y2
)) || (map
.isSolid(x2
, y2
)))
206 ent
->falling
= false;
208 ent
->y
= (y2
* BRICKSIZE
) - ent
->height
;
210 if ((map
.isSolid(x1
, y2
)) && (!map
.isBreakable(x1
, y2
)) && (!map
.isNoReset(x1
, y2
)))
212 if ((ent
== &player
) && (player
.environment
== ENV_AIR
))
214 game
.setCheckPoint(x1
* BRICKSIZE
, (y2
* BRICKSIZE
) - BRICKSIZE
);
218 game
.setObjectiveCheckPoint();
223 if ((map
.isSolid(x2
, y2
)) && (!map
.isBreakable(x2
, y2
)) && (!map
.isNoReset(x2
, y2
)))
225 if ((ent
== &player
) && (player
.environment
== ENV_AIR
))
227 game
.setCheckPoint(x2
* BRICKSIZE
, (y2
* BRICKSIZE
) - BRICKSIZE
);
230 game
.setObjectiveCheckPoint();
242 void moveEntity(Entity
*ent
)
244 if (ent
->owner
->flags
& ENT_TELEPORTING
)
246 int diffX
= (abs((int)ent
->x
- (int)ent
->dx
) / 20);
247 int diffY
= (abs((int)ent
->y
- (int)ent
->dy
) / 20);
249 // add teleport particles so we can see where thing are going (no sound)
250 addTeleportParticles(ent
->x
+ Math::prand() % ent
->width
, ent
->y
+ Math::prand() % ent
->height
, 3, -1);
252 Math::limitInt(&diffX
, 3, 30);
253 Math::limitInt(&diffY
, 3, 30);
255 if (ent
->x
> ent
->dx
) ent
->x
-= diffX
;
256 if (ent
->x
< ent
->dx
) ent
->x
+= diffX
;
257 if (ent
->y
> ent
->dy
) ent
->y
-= diffY
;
258 if (ent
->y
< ent
->dy
) ent
->y
+= diffY
;
260 if (Collision::collision(ent
->x
, ent
->y
, ent
->width
, ent
->height
, ent
->dx
, ent
->dy
, ent
->width
, ent
->height
))
262 Math::removeBit(&ent
->flags
, ENT_TELEPORTING
);
263 addTeleportParticles(ent
->x
+ (ent
->width
/ 2), ent
->y
+ (ent
->height
/ 2), 25, SND_TELEPORT3
);
264 ent
->dx
= ent
->dy
= 0;
265 ent
->environment
= ENV_AIR
;
269 if (player
.flags
& ENT_FLIES
)
271 player
.setSprites(graphics
.getSprite("JPBobRight", true), graphics
.getSprite("JPBobLeft", true), graphics
.getSprite("BobSpin", true));
275 player
.setSprites(graphics
.getSprite("BobRight", true), graphics
.getSprite("BobLeft", true), graphics
.getSprite("BobSpin", true));
279 // raise to the floor
280 int x1
= (int)ent
->x
>> BRICKSHIFT
;
281 int x2
= ((int)ent
->x
+ ent
->width
- 1) >> BRICKSHIFT
;
282 int y2
= ((int)ent
->y
+ ent
->height
- 1) >> BRICKSHIFT
;
283 if ((map
.isSolid(x1
, y2
)) || (map
.isSolid(x2
, y2
)))
285 ent
->y
= (y2
* BRICKSIZE
) - ent
->height
;
288 debug(("%s reappeared at %f:%f\n", ent
->name
, ent
->x
, ent
->y
));
294 if (ent
->owner
!= ent
)
303 if ((!(ent
->flags
& ENT_WEIGHTLESS
)) && (!(ent
->flags
& ENT_FLIES
)) && (!(ent
->flags
& ENT_SWIMS
)))
308 else if (!(ent
->flags
& ENT_FLIES
))
310 if (ent
->environment
== ENV_AIR
)
314 // This is what makes swimming work:
315 else if ((!config
.isControl(CONTROL::UP
)) && (!config
.isControl(CONTROL::DOWN
)))
323 if ((checkBrickContactX(ent
)) || (checkObstacleContact(ent
, 0)) || (checkTrainContact(ent
, 0)))
330 if (ent
->flags
& ENT_SLIDES
)
338 if ((checkBrickContactY(ent
)) || (checkObstacleContact(ent
, 1)) || (checkTrainContact(ent
, 1)))
340 if ((ent
->flags
& ENT_BOUNCES
) && (ent
->dy
>= 3))
342 ent
->dy
= (0 - ent
->dy
/ 2);
353 checkSwitchContact(ent
);
354 checkTeleportContact(ent
);
356 // Math::limitFloat(&ent->x, 10, (MAPWIDTH * BRICKSIZE) - 20);
365 else if (ent
->x
> (MAPWIDTH
* BRICKSIZE
) - 20)
367 ent
->x
= (MAPWIDTH
* BRICKSIZE
) - 20;