4 // Copyright 2007, 2008 Lancer-X/ASCEAI
6 // This file is part of Meritous Recharged.
8 // Meritous Recharged is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
13 // Meritous Recharged is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with Meritous Recharged. If not, see <http://www.gnu.org/licenses/>.
26 #include <SDL_image.h>
29 #include "levelblit.h"
38 SDL_Surface
*invis_enemy
;
43 int room_active
[3000];
47 int max_activate_dist
= 0;
88 struct enemy
*next_active
;
93 struct RoomConnection
*m_exit
;
101 struct bullet
*parent
;
136 struct diamond
*next
;
137 struct diamond
*next_in_room
;
138 struct diamond
*prv_in_room
;
148 int total_enemies
= 0;
149 int killed_enemies
= 0;
150 int total_bullets
= 0;
151 int active_enemies
= 0;
154 struct enemy
*enemy_stack
= NULL
;
155 struct bullet
*bullet_stack
= NULL
;
156 struct enemy
*active_stack
= NULL
;
157 struct diamond
*gem_stack
= NULL
;
159 struct diamond
*room_gems
[3000] = {NULL
};
161 struct enemyloc
*enemy_loc_stack
[20][20] = {{NULL
}};
163 struct enemy
*CreateEnemy(int enemy_x
, int enemy_y
, int enemy_room
);
164 struct enemy
*CreateEnemyEx(int enemy_x
, int enemy_y
, int enemy_room
, int enemy_type
);
165 void SCreateGem(int x
, int y
, int r
, int v
);
166 void ActivateEnemies(int room
);
167 void SoupUpEnemies(int boss
);
169 void SpawnLaser(int x
, int y
, float dir
, int fire_time
, int duration
, float turn
, int dmg
);
173 struct enemy
*ec
, *ed
;
174 struct bullet
*bc
, *bd
;
175 struct diamond
*dc
, *dd
;
203 for (i
= 0; i
< 3000; i
++) {
211 int GetRoomDist(int room1
, int room2
);
212 int FindRoomDist(int room1
, int room2
)
214 struct RoomConnection
*follow
;
218 if (room1
== room2
) return 0;
221 searched
[room1
] = csearch
;
223 follow
= rooms
[room1
].con
;
224 while (follow
!= NULL
) {
225 if (searched
[follow
->c
] != csearch
) {
226 cdist
= GetRoomDist(follow
->c
, room2
);
238 int GetRoomDist(int room1
, int room2
)
243 static struct GRD_Box
*g
[50][50] = {{NULL
}};
258 if (g
[gx
][gy
] == NULL
) {
259 g
[gx
][gy
] = malloc(sizeof(struct GRD_Box
));
260 for (iy
= 0; iy
< 60; iy
++) {
261 for (ix
= 0; ix
< 60; ix
++) {
262 g
[gx
][gy
]->d
[ix
][iy
] = -1;
267 if (g
[gx
][gy
]->d
[dx
][dy
] == -1) {
268 g
[gx
][gy
]->d
[dx
][dy
] = FindRoomDist(room1
, room2
);
271 return g
[gx
][gy
]->d
[dx
][dy
];
274 void AddEnemyLoc(struct enemy
*e
, int x
, int y
)
276 struct enemyloc
*next
;
279 next
= enemy_loc_stack
[x
][y
];
280 enemy_loc_stack
[x
][y
] = malloc(sizeof(struct enemyloc
));
281 enemy_loc_stack
[x
][y
]->n
= next
;
282 enemy_loc_stack
[x
][y
]->e
= e
;
285 struct enemyloc
*GetEnemyLoc(int s_x
, int s_y
)
287 return enemy_loc_stack
[s_x
/ 1100 + 1][s_y
/ 1100 + 1];
290 void AddEnemyPos(struct enemy
*e
)
292 int x_loc
, y_loc
, ix
, iy
;
293 x_loc
= (e
->x
) / 1100;
294 y_loc
= (e
->y
) / 1100;
295 AddEnemyLoc(e
, x_loc
, y_loc
);
296 ix
= ((e
->x
- screen
->w
) / 1100);
297 iy
= ((e
->y
- screen
->h
) / 1100);
299 AddEnemyLoc(e
, ix
, y_loc
);
302 AddEnemyLoc(e
, x_loc
, iy
);
304 if ((x_loc
!= ix
) && (y_loc
!= iy
)) {
305 AddEnemyLoc(e
, ix
, iy
);
309 void WriteEnemyData()
316 while (ptr
!= NULL
) {
317 if (!ptr
->delete_me
) n
++;
322 while (ptr
!= NULL
) {
323 if (!ptr
->delete_me
) {
327 FWInt(ptr
->enemy_type
);
330 SavingScreen(2, (float)i
/ (float)n
);
344 while (ptr
!= NULL
) {
345 if (!ptr
->delete_me
) n
++;
350 while (ptr
!= NULL
) {
351 if (!ptr
->delete_me
) {
359 SavingScreen(3, (float)i
/ (float)n
);
366 void WriteCreatureData()
368 FWInt(total_enemies
);
369 FWInt(killed_enemies
);
382 for (i
= 0; i
< n
; i
++) {
387 CreateEnemyEx(x
, y
, room
, t
);
391 LoadingScreen(2, (float)i
/ (float)n
);
400 int x
, y
, room
, value
;
404 for (i
= 0; i
< n
; i
++) {
409 SCreateGem(x
, y
, room
, value
);
412 LoadingScreen(3, (float)i
/ (float)n
);
418 void ActivateVisited()
423 for (i
= 0; i
< 3000; i
++) {
424 if (rooms
[i
].visited
) {
428 LoadingScreen(4, (float)i
/ 3000.0);
434 void ReadCreatureData()
436 total_enemies
= FRInt();
437 killed_enemies
= FRInt();
444 SDL_Surface
*enemy_sprites
[10];
446 struct enemy
* AllocateEnemy()
448 return malloc(sizeof(struct enemy
));
451 struct bullet
* AllocateBullet()
453 return malloc(sizeof(struct bullet
));
456 struct diamond
* AllocateGem()
458 return malloc(sizeof(struct diamond
));
461 struct enemy
*CreateEnemy(int enemy_x
, int enemy_y
, int enemy_room
)
465 enemy_type
= rand() % (rooms
[enemy_room
].s_dist
/ 5 + 1);
466 if (rooms
[enemy_room
].room_type
== 5) enemy_type
+= rand()%3;
467 if (enemy_type
> 8) enemy_type
= rand()%3+6;
469 if (rooms
[enemy_room
].s_dist
>= 15) {
470 if (rand()%64 == 0) {
476 return CreateEnemyEx(enemy_x
, enemy_y
, enemy_room
, enemy_type
);
479 struct enemy
*CreateEnemyEx(int enemy_x
, int enemy_y
, int enemy_room
, int enemy_type
)
481 struct enemy
*new_enemy
;
483 new_enemy
= AllocateEnemy();
484 new_enemy
->x
= enemy_x
;
485 new_enemy
->y
= enemy_y
;
486 new_enemy
->room
= enemy_room
;
488 rooms
[enemy_room
].enemies
++;
489 new_enemy
->deaths
= 0;
490 new_enemy
->t
= rand() % 65536;
491 new_enemy
->active
= 0;
492 new_enemy
->curr_follow
= -1;
493 new_enemy
->teleport_v
= 0;
495 new_enemy
->m_exit
= NULL
;
497 new_enemy
->dying
= 0;
498 new_enemy
->delete_me
= 0;
500 new_enemy
->last_room
= -1;
501 new_enemy
->p_last_room
= -1;
503 new_enemy
->enemy_type
= enemy_type
;
505 new_enemy
->followdepth
= 4;
507 switch (enemy_type
) {
509 new_enemy
->image
= enemy_sprites
[0];
510 new_enemy
->lives
= 1;
512 new_enemy
->speed
= 3;
513 new_enemy
->fire_rate
= 20;
514 new_enemy
->min_gems
= 0;
515 new_enemy
->max_gems
= 3;
516 new_enemy
->creationcost
= 1;
519 new_enemy
->image
= enemy_sprites
[1];
520 new_enemy
->lives
= 1;
522 new_enemy
->speed
= 4;
523 new_enemy
->fire_rate
= 25;
524 new_enemy
->min_gems
= 2;
525 new_enemy
->max_gems
= 6;
526 new_enemy
->creationcost
= 1;
529 new_enemy
->image
= enemy_sprites
[2];
530 new_enemy
->lives
= 1;
531 new_enemy
->str
= 180;
532 new_enemy
->speed
= 5;
533 new_enemy
->fire_rate
= 40;
534 new_enemy
->min_gems
= 8;
535 new_enemy
->max_gems
= 15;
536 new_enemy
->creationcost
= 1;
539 new_enemy
->image
= enemy_sprites
[3];
540 new_enemy
->lives
= 2;
541 new_enemy
->str
= 220;
542 new_enemy
->speed
= 3;
543 new_enemy
->fire_rate
= 24;
544 new_enemy
->min_gems
= 12;
545 new_enemy
->max_gems
= 20;
546 new_enemy
->creationcost
= 1;
549 new_enemy
->image
= enemy_sprites
[4];
550 new_enemy
->lives
= 1;
551 new_enemy
->str
= 360;
552 new_enemy
->speed
= 3;
553 new_enemy
->fire_rate
= 32;
554 new_enemy
->min_gems
= 18;
555 new_enemy
->max_gems
= 32;
556 new_enemy
->creationcost
= 2;
559 new_enemy
->image
= enemy_sprites
[5];
560 new_enemy
->lives
= 1;
561 new_enemy
->str
= 450;
562 new_enemy
->speed
= 3;
563 new_enemy
->fire_rate
= 2;
564 new_enemy
->min_gems
= 32;
565 new_enemy
->max_gems
= 64;
566 new_enemy
->creationcost
= 2;
569 new_enemy
->image
= enemy_sprites
[6];
570 new_enemy
->lives
= 2;
571 new_enemy
->str
= 450;
572 new_enemy
->speed
= 4;
573 new_enemy
->fire_rate
= 10;
574 new_enemy
->min_gems
= 50;
575 new_enemy
->max_gems
= 100;
576 new_enemy
->creationcost
= 2;
579 new_enemy
->image
= enemy_sprites
[7];
580 new_enemy
->lives
= 1;
581 new_enemy
->str
= 500;
582 new_enemy
->speed
= 4;
583 new_enemy
->fire_rate
= 27;
584 new_enemy
->min_gems
= 80;
585 new_enemy
->max_gems
= 160;
586 new_enemy
->creationcost
= 3;
589 new_enemy
->image
= enemy_sprites
[8];
590 new_enemy
->lives
= 4;
591 new_enemy
->str
= 500;
592 new_enemy
->speed
= 2;
593 new_enemy
->fire_rate
= 8;
594 new_enemy
->min_gems
= 200;
595 new_enemy
->max_gems
= 400;
596 new_enemy
->creationcost
= 4;
599 new_enemy
->image
= enemy_sprites
[0];
600 new_enemy
->lives
= 1;
601 new_enemy
->str
= rooms
[enemy_room
].s_dist
* 20;
602 new_enemy
->speed
= 3;
603 new_enemy
->fire_rate
= 21;
604 new_enemy
->min_gems
= 300;
605 new_enemy
->max_gems
= 600;
606 new_enemy
->creationcost
= 3;
609 new_enemy
->image
= enemy_sprites
[9];
610 new_enemy
->lives
= 8;
611 new_enemy
->str
= 500;
612 new_enemy
->speed
= 1;
613 new_enemy
->fire_rate
= 4;
614 new_enemy
->min_gems
= 5000;
615 new_enemy
->max_gems
= 6000;
616 new_enemy
->followdepth
= 8;
617 new_enemy
->creationcost
= 6;
622 new_enemy
->str
= new_enemy
->str
* 4 / 5;
623 new_enemy
->fire_rate
+= (new_enemy
->fire_rate
/ 2);
624 new_enemy
->speed
*= 2;
627 if (rooms
[new_enemy
->room
].room_type
== 5) {
628 new_enemy
->str
= new_enemy
->str
* 3 / 2;
629 if (new_enemy
->str
> 1500) new_enemy
->str
= 1500;
630 new_enemy
->fire_rate
= new_enemy
->fire_rate
- 1;
633 new_enemy
->blit_pos
= (rand()%(new_enemy
->image
->w
/ (new_enemy
->image
->h
/new_enemy
->lives
)))*(new_enemy
->image
->h
/new_enemy
->lives
);
634 new_enemy
->next_active
= NULL
;
636 new_enemy
->next
= enemy_stack
;
637 enemy_stack
= new_enemy
;
639 AddEnemyPos(new_enemy
);
646 void SCreateGem(int x
, int y
, int r
, int v
)
648 struct diamond
*new_gem
;
650 if (TileData
[Get(x
/ 32, y
/ 32)].Is_Solid
) {
653 if (GetRoom(x
/ 32, y
/ 32) != r
) {
660 new_gem
= AllocateGem();
665 new_gem
->delete_me
= 0;
666 new_gem
->t
= rand()%65536;
667 new_gem
->next
= gem_stack
;
668 new_gem
->next_in_room
= room_gems
[r
];
670 if (room_gems
[r
] != NULL
) {
671 room_gems
[r
]->prv_in_room
= new_gem
;
675 new_gem
->prv_in_room
= NULL
;
677 room_gems
[r
] = new_gem
;
682 void CreateGem(int x
, int y
, int r
, int v
)
685 if ( (rand()%1000) < ((int)log(v
)/4 + (player_hp
== 1)*5 + 2) ) {
686 SCreateGem(x
, y
, r
, 31337);
688 SCreateGem(x
, y
, r
, v
);
692 float PlayerDir(int x
, int y
)
694 float dy
= player_y
+12 - y
;
695 float dx
= player_x
+8 - x
;
696 return atan2(dy
, dx
);
699 int PlayerDist(int x
, int y
)
701 int d
= sqrt(sqr(x
-(player_x
+8))+sqr(y
-(player_y
+12)));
705 struct bullet
*CreateBullet(int x
, int y
, struct enemy
*firer
, int bullet_type
, float dir
, float spd
)
707 struct bullet
*new_shot
;
709 new_shot
= AllocateBullet();
712 new_shot
->firer
= firer
;
714 new_shot
->room
= firer
->room
;
716 new_shot
->room
= GetRoom(x
/ 32, y
/ 32);
719 new_shot
->delete_me
= 0;
720 new_shot
->t
= rand() % 65536;
722 new_shot
->speed
= spd
;
723 new_shot
->invuln
= 0;
724 new_shot
->parent
= NULL
;
726 switch (bullet_type
) {
732 new_shot
->invuln
= 1;
736 new_shot
->invuln
= 1;
738 new_shot
->fire_time
= 30;
739 new_shot
->duration
= 30;
740 new_shot
->turn
= 0.0;
741 new_shot
->speed
= 0.0;
748 new_shot
->invuln
= 1;
756 new_shot
->invuln
= 1;
760 new_shot
->invuln
= 1;
764 new_shot
->invuln
= 1;
768 new_shot
->speed
*= 0.8;
770 new_shot
->next
= bullet_stack
;
771 bullet_stack
= new_shot
;
777 struct bullet
*FireLaser(int x
, int y
, struct enemy
*firer
, float dir
, int fire_time
, int duration
, float turn
, int dmg
)
781 b
= CreateBullet(x
, y
, firer
, 2, dir
, 0);
782 b
->fire_time
= fire_time
;
783 b
->duration
= duration
;
785 b
->shield_damage
= dmg
;
788 f_total
= b
->fire_time
+ b
->duration
;
789 if (b
->duration
> 1) {
791 b
->fire_time
= f_total
- b
->duration
;
793 b
->shield_damage
= (b
->shield_damage
+ 1) / 2;
798 void InitEnemySprites()
800 enemy_sprites
[0] = IMG_Load("dat/i/mons1.png");
801 SDL_SetColorKey(enemy_sprites
[0], SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 255);
802 enemy_sprites
[1] = IMG_Load("dat/i/mons2.png");
803 SDL_SetColorKey(enemy_sprites
[1], SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 255);
804 enemy_sprites
[2] = IMG_Load("dat/i/mons3.png");
805 SDL_SetColorKey(enemy_sprites
[2], SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 255);
806 enemy_sprites
[3] = IMG_Load("dat/i/mons4.png");
807 SDL_SetColorKey(enemy_sprites
[3], SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 255);
808 enemy_sprites
[4] = IMG_Load("dat/i/mons5.png");
809 SDL_SetColorKey(enemy_sprites
[4], SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 255);
810 enemy_sprites
[5] = IMG_Load("dat/i/mons6.png");
811 SDL_SetColorKey(enemy_sprites
[5], SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 255);
812 enemy_sprites
[6] = IMG_Load("dat/i/mons7.png");
813 SDL_SetColorKey(enemy_sprites
[6], SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 255);
814 enemy_sprites
[7] = IMG_Load("dat/i/mons8.png");
815 SDL_SetColorKey(enemy_sprites
[7], SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 255);
816 enemy_sprites
[8] = IMG_Load("dat/i/mons9.png");
817 SDL_SetColorKey(enemy_sprites
[8], SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 255);
818 enemy_sprites
[9] = IMG_Load("dat/i/mons10.png");
819 SDL_SetColorKey(enemy_sprites
[9], SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 255);
821 reticle
= IMG_Load("dat/i/reticle.png");
822 SDL_SetColorKey(reticle
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 255);
824 inrange
= IMG_Load("dat/i/inrange.png");
825 SDL_SetColorKey(inrange
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 255);
827 invis_enemy
= IMG_Load("dat/i/hidden_monster.png");
828 SDL_SetColorKey(invis_enemy
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 255);
831 void ActivateSingleEnemy(struct enemy
*t
)
833 struct enemy
*new_active
;
835 if (t
->active
) return;
837 if (t
->enemy_type
!= 10) {
838 if (t
->enemy_type
== 9) {
839 if (max_activate_dist
< 10) return;
842 if (t
->enemy_type
> (max_activate_dist
/ 5 + 2)) return;
848 new_active
->next_active
= active_stack
;
849 active_stack
= new_active
;
855 void XActivateSingleEnemy(struct enemy
*t
)
857 if (rooms
[t
->room
].room_type
== 2) return;
858 if (rooms
[t
->room
].room_type
== 3) return;
860 ActivateSingleEnemy(t
);
866 int cr_w
, cr_h
, cr_x
, cr_y
;
874 max_activate_dist
= 0;
878 for (ny
= 0; ny
< 20; ny
++) {
879 for (nx
= 0; nx
< 20; nx
++) {
880 enemy_loc_stack
[nx
][ny
] = NULL
;
890 for (i
= 0; i
< 3000; i
++) {
897 for (c_room
= 1; c_room
< 3000; c_room
++) {
898 cr_x
= rooms
[c_room
].x
+ 1;
899 cr_y
= rooms
[c_room
].y
+ 1;
900 cr_w
= rooms
[c_room
].w
- 2;
901 cr_h
= rooms
[c_room
].h
- 2;
902 room_size
= cr_w
* cr_h
;
904 n_enemies
= rand() % ((room_size
/ 4) + 1);
906 if (rooms
[c_room
].room_type
== 2) {
910 if (rooms
[c_room
].room_type
== 3) {
911 n_enemies
+= (n_enemies
+ room_size
) / 2;
914 if (rooms
[c_room
].room_type
== 5) {
918 while (n_enemies
> 0) {
921 e_x
= cr_x
* 32 + 32 + rand() % (cr_w
* 32 - 64 + 1);
922 e_y
= cr_y
* 32 + 32 + rand() % (cr_h
* 32 - 64 + 1);
924 if ((!IsSolid(Get( (e_x
-16) /32, (e_y
-16) /32)))&&(!IsSolid(Get( (e_x
+16) /32, (e_y
-16) /32)))) {
925 if ((!IsSolid(Get( (e_x
-16) /32, (e_y
+16) /32)))&&(!IsSolid(Get( (e_x
+16) /32, (e_y
+16) /32)))) {
926 n_enemies
-= (CreateEnemy(e_x
, e_y
, c_room
))->creationcost
;
932 if (c_room
% 100 == 99) {
933 LoadingScreen(2, (float)c_room
/ 3000.0);
941 void InitEnemiesAfter()
944 if (current_boss
> 0) {
946 int max
= current_boss
;
950 for (i
= 1; i
<= max
; i
++) {
958 int EnemyMovement(struct enemy
*e
, int move_x
, int move_y
)
960 if (!IsSolid(Get( (move_x
- 12)/32, (move_y
- 12)/32))) {
961 if (!IsSolid(Get( (move_x
+ 12)/32, (move_y
- 12)/32))) {
962 if (!IsSolid(Get( (move_x
- 12)/32, (move_y
+ 12)/32))) {
963 if (!IsSolid(Get( (move_x
+ 12)/32, (move_y
+ 12)/32))) {
974 // Only activate SOME enemies. A room can only be ZActivated once
975 void ZActivateEnemies(int room
)
978 struct RoomConnection
*rc
;
980 if (room_active
[room
]) return;
981 room_active
[room
] = 1;
986 // 1/4 chance of activating each enemy
988 if (t
->room
== room
) {
989 if (t
->active
== 0) {
990 XActivateSingleEnemy(t
);
997 // 1/3 chance of activating each adjacent room
998 rc
= rooms
[room
].con
;
1000 if (rand()%3 == 0) {
1001 ZActivateEnemies(rc
->c
);
1007 void ActivateEnemies(int room
)
1010 struct RoomConnection
*rc
;
1014 if (rooms
[room
].s_dist
> max_activate_dist
) {
1015 max_activate_dist
= rooms
[room
].s_dist
;
1019 if (t
->room
== room
) {
1020 if (t
->active
== 0) {
1021 ActivateSingleEnemy(t
);
1023 if (rooms
[room
].room_type
== 3) {
1024 t
->teleport_v
= (rand() % 1500) + 50;
1031 // 1/2 chance of activating each adjacent room
1032 rc
= rooms
[room
].con
;
1033 while (rc
!= NULL
) {
1034 if (rand()%2 == 0) {
1035 if ((rooms
[rc
->c
].room_type
!= 2) && (rooms
[rc
->c
].room_type
!= 3)) {
1036 ZActivateEnemies(rc
->c
);
1043 int CanEnterRoom(int room
)
1045 if (room
== 0) return 0;
1046 if (rooms
[room
].room_type
== 2) return 0;
1047 if (rooms
[room
].room_type
== 3) return 0;
1048 if (rooms
[room
].room_type
== 5) return 0;
1049 if (rooms
[room
].room_type
== 6) return 0;
1051 if (artifacts
[11]) {
1052 if (rooms
[room
].enemies
> 3) {
1059 int CanLeaveRoom(int room
)
1061 if (room
== 0) return 0;
1062 if (rooms
[room
].room_type
== 2) return 0;
1063 if (rooms
[room
].room_type
== 3) return 0;
1064 if (rooms
[room
].room_type
== 5) return 0;
1065 if (rooms
[room
].room_type
== 6) return 0;
1070 int RecurseFind(struct enemy
*e
, int room
, int depth
)
1072 struct RoomConnection
*follow
;
1074 int mindpth
= 1000000;
1075 follow
= rooms
[room
].con
;
1077 if (CanEnterRoom(room
) == 0) return 0;
1079 if (room
== player_room
) return depth
+1;
1080 if (searched
[room
] == csearch
) {
1081 if (searchdist
[room
] < depth
)
1084 if (depth
> e
->followdepth
) return 0;
1085 if ((e
->last_room
== room
) && (e
->p_last_room
== player_room
)) return 0;
1087 searched
[room
] = csearch
;
1088 searchdist
[room
] = depth
;
1090 while (follow
!= NULL
) {
1091 if ((dpth
= RecurseFind(e
, follow
->c
, depth
+1)) > 0) {
1092 if (dpth
< mindpth
) {
1099 if (mindpth
!= 1000000) {
1107 int FollowPlayer(struct enemy
*e
, struct RoomConnection
**rcon
)
1109 struct RoomConnection
*follow
;
1110 int mindepth
= 1000000;
1112 int mdist
= 1000000;
1117 follow
= rooms
[e
->room
].con
;
1119 while (follow
!= NULL
) {
1120 if (follow
->c
== player_room
) {
1121 if (CanEnterRoom(follow
->c
)) {
1123 e
->curr_follow
= (*rcon
)->c
;
1130 // Recursively follow the player, to a certain depth
1131 follow
= rooms
[e
->room
].con
;
1134 // Are we already following the player into a room?
1136 /*if (e->curr_follow != -1) {
1137 // See if this room is the best FIRST
1138 newdepth = RecurseFind(e, e->curr_follow, 0);
1140 mindepth = newdepth;
1145 while (follow
!= NULL
) {
1146 if (CanEnterRoom(follow
->c
)) {
1147 newdepth
= RecurseFind(e
, follow
->c
, 0);
1148 rdepth
[follow
->c
] = newdepth
;
1150 if (mindepth
> newdepth
) {
1151 mindepth
= newdepth
;
1158 if (mindepth
!= 1000000) {
1159 follow
= rooms
[e
->room
].con
;
1160 while (follow
!= NULL
) {
1161 if (CanEnterRoom(follow
->c
)) {
1162 newdepth
= rdepth
[follow
->c
];
1163 if (newdepth
== mindepth
) {
1164 ndist
= PlayerDist(follow
->x
*32+16, follow
->y
*32+16);
1165 if (ndist
< mdist
) {
1174 e
->curr_follow
= (*rcon
)->c
;
1180 void KillEnemy(struct enemy
*t
)
1182 static int lastkill
= 0;
1185 if (t
->dying
> 0) return;
1186 if (t
->teleport_v
> 0) return;
1187 if (t
->delete_me
) return;
1189 ct
= SDL_GetTicks();
1191 if ((ct
- lastkill
) > 100) {
1192 SND_Pos("dat/a/enemyhit.wav", 128, PlayerDist(t
->x
, t
->y
));
1199 void ArtifactRoomUnlock(int room
)
1202 int x
, y
, rx
, ry
, rt
;
1208 if ((e
->delete_me
== 0) && (e
->room
== room
)) {
1216 for (y
= 0; y
< rooms
[room
].h
; y
++) {
1217 for (x
= 0; x
< rooms
[room
].w
; x
++) {
1218 rx
= x
+ rooms
[room
].x
;
1219 ry
= y
+ rooms
[room
].y
;
1222 if ((rt
>= 21) && (rt
<= 24)) {
1223 Put(rx
, ry
, rt
- 21 + 13, room
);
1230 tot_treasures
= 2 + rand() % (rooms
[room
].s_dist
/ 8 + 1);
1231 while (placed
< tot_treasures
) {
1232 x
= rooms
[room
].x
+ (rand() % (rooms
[room
].w
- 2));
1233 y
= rooms
[room
].y
+ (rand() % (rooms
[room
].h
- 2));
1234 //printf("Attempting %d, %d\n", x, y);
1235 if ((x
+y
)%2 == (placed
>0)) {
1236 //printf("Correct placement type\n");
1237 if (!IsSolid(Get(x
, y
))) {
1238 //printf("Not solid\n");
1239 Put(x
, y
, 26, room
);
1247 rooms
[room
].room_type
= 4;
1250 void EnemySound(int t
, int dist
)
1252 static int last_e_sound
= 0;
1253 static int last_delay
= 150;
1254 int curr_e_sound
= SDL_GetTicks();
1256 if ((curr_e_sound
- last_delay
) < last_e_sound
) {
1262 SND_Pos("dat/a/mons0shot.wav", 48, dist
);
1266 SND_Pos("dat/a/mons1shot.wav", 112, dist
);
1270 SND_Pos("dat/a/mons2shot.wav", 110, dist
);
1274 SND_Pos("dat/a/mons3shot.wav", 110, dist
);
1278 SND_Pos("dat/a/mons4shot.wav", 110, dist
);
1282 SND_Pos("dat/a/mons5shot.wav", 80, dist
);
1286 SND_Pos("dat/a/mons6shot.wav", 110, dist
);
1290 SND_Pos("dat/a/mons7shot.wav", 110, dist
);
1294 SND_Pos("dat/a/mons8shot.wav", 110, dist
);
1298 SND_Pos("dat/a/mons9shot.wav", 110, dist
);
1302 SND_Pos("dat/a/mons10shot.wav", 110, dist
);
1311 last_e_sound
= curr_e_sound
;
1314 void MoveEnemy(struct enemy
*e
)
1319 int door_x
=0, door_y
=0;
1320 int enemy_fire_type
;
1323 struct RoomConnection
*con_traverse
;
1324 struct RoomConnection
*rcon
;
1330 if (e
->teleport_v
> 0) {
1335 if (e
->enemy_type
< 10) {
1336 enemy_fire_type
= e
->enemy_type
;
1338 enemy_fire_type
= rand()%10;
1341 if (e
->dying
== 0) {
1342 if ((e
->t
% e
->fire_rate
) == 0) {
1343 if (e
->room
== player_room
) {
1344 switch (enemy_fire_type
) {
1346 EnemySound(0, PlayerDist(e
->x
, e
->y
));
1347 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
), 1.5);
1348 if (e
->enemy_type
==10) e
->fire_rate
= 20;
1352 EnemySound(1, PlayerDist(e
->x
, e
->y
));
1353 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
)+0.1, 2.1);
1354 CreateBullet(e
->x
, e
->y
, e
, 3, PlayerDir(e
->x
, e
->y
), 2.4);
1355 CreateBullet(e
->x
, e
->y
, e
, 3, PlayerDir(e
->x
, e
->y
)-0.1, 2.1);
1356 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
), 1.7);
1357 if (e
->enemy_type
==10) e
->fire_rate
= 25;
1361 EnemySound(2, PlayerDist(e
->x
, e
->y
));
1362 for (dp
= 0; dp
< M_PI
*2; dp
+= 0.25) {
1363 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
)+dp
, 1.1);
1366 for (i
= 0; i
< 20; i
++) {
1367 CreateBullet(e
->x
, e
->y
, e
, 0, dp
, (float)i
* 0.1 + 2.5);
1369 if (e
->enemy_type
==10) e
->fire_rate
= 40;
1373 EnemySound(3, PlayerDist(e
->x
, e
->y
));
1374 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
), 2.5);
1375 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
)+0.1, 2.5);
1376 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
)+0.2, 2.5);
1377 CreateBullet(e
->x
, e
->y
, e
, 1, PlayerDir(e
->x
, e
->y
), 1.5);
1378 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
)-0.2, 2.2);
1379 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
)-0.3, 2.2);
1380 if (e
->enemy_type
==10) e
->fire_rate
= 24;
1384 EnemySound(4, PlayerDist(e
->x
, e
->y
));
1385 for (dp
= 0; dp
< M_PI
* 0.66; dp
+= 0.2) {
1386 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
)+0.5 - dp
, 1.8+(dp
/2));
1387 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
)-0.4 + dp
, 1.8+(dp
/2));
1389 FireLaser(e
->x
, e
->y
, e
, PlayerDir(e
->x
, e
->y
), 24, 4, 20.0, 6);
1390 if (e
->enemy_type
==10) e
->fire_rate
= 32;
1394 EnemySound(5, PlayerDist(e
->x
, e
->y
));
1395 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
), 4);
1396 if (e
->enemy_type
==10) e
->fire_rate
= 2;
1400 EnemySound(6, PlayerDist(e
->x
, e
->y
));
1401 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
)+0.25, 6);
1402 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
)+0.25, 4);
1404 CreateBullet(e
->x
, e
->y
, e
, 5, PlayerDir(e
->x
, e
->y
) - 0.05, 4.99);
1405 CreateBullet(e
->x
, e
->y
, e
, 5, PlayerDir(e
->x
, e
->y
), 4.99);
1406 CreateBullet(e
->x
, e
->y
, e
, 5, PlayerDir(e
->x
, e
->y
) + 0.05, 4.99);
1408 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
)-0.25, 5);
1409 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
)-0.25, 3);
1410 if (e
->enemy_type
==10) e
->fire_rate
= 10;
1414 EnemySound(7, PlayerDist(e
->x
, e
->y
));
1415 for (dp
= 0; dp
< M_PI
* 0.66; dp
+= 0.1) {
1416 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
)+0.5 - dp
, 1.8+(dp
/2));
1417 CreateBullet(e
->x
, e
->y
, e
, 3, PlayerDir(e
->x
, e
->y
)-0.4 + dp
, 1.8+(dp
/2));
1419 CreateBullet(e
->x
, e
->y
, e
, 3, PlayerDir(e
->x
, e
->y
)+0.5 - dp
*2, 4+(dp
*2));
1420 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
)-0.4 + dp
*2, 4+(dp
*2));
1422 FireLaser(e
->x
, e
->y
, e
, (float)e
->t
/ 25.0, 16, 10, 0.08, 4);
1423 FireLaser(e
->x
, e
->y
, e
, (float)e
->t
/ 25.0 + M_PI
*2/4, 16, 10, 0.08, 4);
1424 FireLaser(e
->x
, e
->y
, e
, (float)e
->t
/ 25.0 + M_PI
*4/4, 16, 10, 0.08, 4);
1425 FireLaser(e
->x
, e
->y
, e
, (float)e
->t
/ 25.0 + M_PI
*6/4, 16, 10, 0.08, 4);
1426 if (e
->enemy_type
==10) e
->fire_rate
= 27;
1430 EnemySound(8, PlayerDist(e
->x
, e
->y
));
1431 for (dp
= 0; dp
< 1; dp
+= 0.1) {
1432 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
) + M_PI
/2 + dp
, 3 + dp
/2);
1433 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
), 4 + dp
);
1434 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
) - M_PI
/2 - dp
, 3 + dp
/2);
1436 CreateBullet(e
->x
, e
->y
, e
, 6, (e
->t
/ e
->fire_rate
)*0.7, 2);
1437 if (e
->enemy_type
==10) e
->fire_rate
= 8;
1441 i
= rand()%((rand()%(PlayerDist(e
->x
, e
->y
)+1))+1);
1443 EnemySound(9, PlayerDist(e
->x
, e
->y
));
1444 dpf
= (float)(2000 - e
->str
) / 2500.0;
1445 for (dp
= 0; dp
< 1; dp
+= dpf
) {
1446 (CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
) + 0.1 - dp
/5.0, 3.5 + dp
/3.0));
1447 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
) + (2*M_PI
/ 3) + 0.1 - dp
/5.0, 3.5 + dp
/3.0);
1448 CreateBullet(e
->x
, e
->y
, e
, 0, PlayerDir(e
->x
, e
->y
) + (4*M_PI
/ 3) + 0.1 - dp
/5.0, 3.5 + dp
/3.0);
1450 CreateBullet(e
->x
, e
->y
, e
, 4, PlayerDir(e
->x
, e
->y
) + 0.1 - dp
/5.0, 7 + dp
*5);
1451 CreateBullet(e
->x
, e
->y
, e
, 4, PlayerDir(e
->x
, e
->y
) + (2*M_PI
/ 3) + 0.1 - dp
/5.0, 7 + dp
*5);
1452 CreateBullet(e
->x
, e
->y
, e
, 4, PlayerDir(e
->x
, e
->y
) + (4*M_PI
/ 3) + 0.1 - dp
/5.0, 7 + dp
*5);
1455 if (e
->enemy_type
==10) e
->fire_rate
= 21;
1464 if ((e
->t
% e
->speed
) == 0) {
1465 if (player_room
== e
->room
) {
1467 if (e
->t
% (e
->speed
* (8 + rand()%6)) == 0) {
1468 e
->move_dir
= (float)(rand()%256) / 256.0 * M_PI
* 2.0;
1470 move_x
= e
->x
+ cos(e
->move_dir
)*5;
1471 move_y
= e
->y
+ sin(e
->move_dir
)*5;
1473 EnemyMovement(e
, move_x
, move_y
);
1475 if (CanLeaveRoom(e
->room
)) {
1476 // Try to follow the player into the next room
1478 // Are we already moving towards an exit?
1480 if (e
->m_exit
!= NULL
) {
1483 door_x
= (rcon
->x
+ (rcon
->x
- rcon
->x2
))*32+16;
1484 door_y
= (rcon
->y
+ (rcon
->y
- rcon
->y2
))*32+16;
1488 con_traverse
= rooms
[e
->room
].con
;
1489 nearest
= PlayerDist(e
->x
, e
->y
);
1491 while (con_traverse
!= NULL
) {
1492 i
= PlayerDist(con_traverse
->x2
* 32 + 16, con_traverse
->y2
* 32 + 16);
1494 if ((i
< nearest
) && CanEnterRoom(GetRoom(con_traverse
->x2
, con_traverse
->y2
))) {
1496 rcon
= con_traverse
;
1498 con_traverse
= con_traverse
->n
;
1502 door_x
= (rcon
->x
+ (rcon
->x
- rcon
->x2
))*32+16;
1503 door_y
= (rcon
->y
+ (rcon
->y
- rcon
->y2
))*32+16;
1511 // Are we near the door?
1512 if (( abs(door_x
- e
->x
) + abs(door_y
- e
->y
))<6) {
1513 // Go through the door
1514 e
->last_room
= e
->room
;
1515 e
->p_last_room
= player_room
;
1516 e
->x
= (rcon
->x2
+ (rcon
->x2
- rcon
->x
))*32+16;
1517 e
->y
= (rcon
->y2
+ (rcon
->y2
- rcon
->y
))*32+16;
1518 rooms
[e
->room
].enemies
--;
1519 e
->room
= (rcon
->c
);
1520 rooms
[e
->room
].enemies
++;
1521 e
->curr_follow
= -1;
1526 // Move towards the door
1527 e
->move_dir
= atan2(door_y
- e
->y
, door_x
- e
->x
);
1528 move_x
= e
->x
+ cos(e
->move_dir
)*5;
1529 move_y
= e
->y
+ sin(e
->move_dir
)*5;
1531 EnemyMovement(e
, move_x
, move_y
);
1541 if (e
->dying
== 3) {
1544 if (!b
->delete_me
) {
1545 if (b
->firer
== e
) {
1547 CreateGem(b
->x
, b
->y
, b
->room
, (e
->max_gems
+ e
->min_gems
) / 5 + (artifacts
[2] * (e
->max_gems
+ e
->min_gems
) / 4));
1553 if (e
->dying
>= 20) {
1554 if ((e
->lives
>= 4)&&training
) {
1555 actual_lives
= e
->lives
* 3 / 4;
1557 actual_lives
= e
->lives
;
1561 if (e
->deaths
>= actual_lives
) {
1566 rooms
[e
->room
].enemies
--;
1567 n_gems
= e
->min_gems
+ rand()%(e
->max_gems
- e
->min_gems
+ 1);
1568 for (i
= 0; i
< n_gems
; i
++) {
1569 CreateGem(e
->x
- 16 + rand()%32, e
->y
- 16 + rand()%32, e
->room
, 1+rand()%4 + (artifacts
[2]*rand()%3));
1571 if (rooms
[e
->room
].room_type
== 3) {
1572 ArtifactRoomUnlock(e
->room
);
1581 void MoveBullet(struct bullet
*e
)
1586 static int last_shield_hit_sound
= 0;
1587 int c_shield_hit_sound
;
1591 if ( (boss_fight_mode
!= 0) && (boss_fight_mode
!= 2) && (e
->dying
== 0) ) {
1595 if (e
->dying
== 0) {
1600 e
->dir
= (e
->dir
+ PlayerDir(e
->x
, e
->y
)) / 2;
1604 e
->x
+= cos(e
->dir
) * e
->speed
;
1605 e
->y
+= sin(e
->dir
) * e
->speed
;
1608 if (e
->t
% 20 == 19) {
1609 if (e
->t
% 40 >= 20)
1610 CreateBullet(e
->x
, e
->y
, e
->firer
, 3, e
->dir
+ M_PI
/2, e
->speed
* 0.75);
1612 CreateBullet(e
->x
, e
->y
, e
->firer
, 3, e
->dir
- M_PI
/2, e
->speed
* 0.75);
1616 if (e
->t
% 40 == 39) {
1617 (FireLaser(e
->x
, e
->y
, e
->firer
, (float)e
->t
/ 30.0, 20, 10, 0.05, 2))->parent
= e
;
1618 (FireLaser(e
->x
, e
->y
, e
->firer
, (float)e
->t
/ 30.0 + M_PI
*2/3, 20, 10, 0.05, 2))->parent
= e
;
1619 (FireLaser(e
->x
, e
->y
, e
->firer
, (float)e
->t
/ 30.0 + M_PI
*4/3, 20, 10, 0.05, 2))->parent
= e
;
1626 if (e
->t
% 20 == 9) {
1627 n
= CreateBullet(e
->x
, e
->y
, e
->firer
, 5, e
->dir
+ M_PI
/4, e
->speed
);
1628 n
->natural_dir
= e
->dir
;
1630 e
->natural_dir
= e
->dir
;
1634 if (e
->t
% 20 == 19) {
1635 e
->dir
= e
->natural_dir
;
1639 e
->dir
= PlayerDir(e
->x
, e
->y
);
1644 if (IsSolid(Get(e
->x
/32, e
->y
/32))) {
1646 if (e
->room
== player_room
) {
1647 e
->dir
= PlayerDir(e
->x
, e
->y
);
1649 if (IsSolid(Get((e
->x
+ cos(e
->dir
) * e
->speed
* 1.5)/32, (e
->y
+ sin(e
->dir
) * e
->speed
* 1.5)/32))) e
->dying
= 1;
1660 if (e
->parent
!= NULL
) {
1661 e
->x
= e
->parent
->x
;
1662 e
->y
= e
->parent
->y
;
1664 if (e
->firer
!= NULL
) {
1669 if (e
->dying
== 0) {
1670 if ((e
->t
> e
->fire_time
)&&(e
->t
<= (e
->fire_time
+ e
->duration
))) {
1673 while (!IsSolid(Get((fx
)/32, (fy
)/32))) {
1674 if (player_dying
== 0) {
1675 if (PlayerDist(fx
, fy
) < 30) {
1676 // hits player shield
1677 if ((player_shield
> 0)&&(shield_hp
> 0)) {
1678 shield_hp
-= e
->shield_damage
;
1679 if (shield_hp
>= 0) {
1687 if (PlayerDist(fx
, fy
) < 4 - (2 * artifacts
[5])) {
1689 SND_Pos("dat/a/playerhurt.wav", 128, 0);
1695 fx
+= cos(e
->dir
)*2;
1696 fy
+= sin(e
->dir
)*2;
1700 if (e
->dir
> PlayerDir(e
->x
, e
->y
)) {
1701 e
->dir
-= (e
->dir
- PlayerDir(e
->x
, e
->y
)) / (e
->turn
- 9.00);
1702 e
->dir
-= (e
->dir
- PlayerDir(e
->x
, e
->y
)) / (e
->turn
- 9.00);
1704 e
->dir
+= (PlayerDir(e
->x
, e
->y
) - e
->dir
) / (e
->turn
- 9.00);
1709 if (e
->t
> (e
->fire_time
+ e
->duration
)) {
1715 pdist
= PlayerDist(e
->x
, e
->y
);
1718 if (player_dying
== 0) {
1719 if (player_shield
> 0) {
1720 if (shield_hp
> 0) {
1726 c_shield_hit_sound
= SDL_GetTicks();
1728 if ((c_shield_hit_sound
- 150) > last_shield_hit_sound
) {
1729 SND_Pos("dat/a/shieldhit.wav", 50, 0);
1730 last_shield_hit_sound
= c_shield_hit_sound
;
1732 while (PlayerDist(e
->x
, e
->y
) < 30) {
1733 e
->x
+= cos(e
->dir
) * e
->speed
;
1734 e
->y
+= sin(e
->dir
) * e
->speed
;
1741 if (e
->dying
== 0) {
1742 if (pdist
< 6 - (2 * artifacts
[5])) {
1743 if (player_dying
== 0) {
1744 SND_Pos("dat/a/playerhurt.wav", 128, 0);
1752 if ((e
->dying
== 1) && (e
->img
== 8)) {
1753 SpawnLaser(e
->x
- cos(e
->dir
) * e
->speed
, e
->y
- sin(e
->dir
) * e
->speed
, PlayerDir(e
->x
, e
->y
), 10, 10, 0.0, player_shield
/ 6);
1756 if (GetRoom((e
->x
)/32, (e
->y
)/32) != e
->room
) {
1763 if (e
->dying
>= 10) {
1770 void DrawEnemy(struct enemy
*e
, SDL_Surface
*scr
)
1774 static SDL_Surface
*teleflash
= NULL
;
1776 if (e
->delete_me
) return;
1777 draw_pos
.x
= e
->x
- e
->image
->h
/2/e
->lives
- scroll_x
;
1778 draw_pos
.y
= e
->y
- e
->image
->h
/2/e
->lives
- scroll_y
;
1780 surf_pos
.x
= e
->blit_pos
;
1781 surf_pos
.y
= e
->image
->h
/e
->lives
*e
->deaths
;
1782 surf_pos
.w
= e
->image
->h
/e
->lives
;
1783 surf_pos
.h
= e
->image
->h
/e
->lives
;
1785 if (e
->teleport_v
< 8) {
1787 if (e
->dying
== 0) {
1788 SDL_BlitSurface(e
->image
, &surf_pos
, scr
, &draw_pos
);
1790 if ((e
->deaths
+1) >= e
->lives
) {
1791 surf_pos
.w
= e
->image
->h
/e
->lives
* (20 - e
->dying
) / 20;
1792 surf_pos
.h
= surf_pos
.w
;
1793 surf_pos
.x
+= (e
->image
->h
/e
->lives
- surf_pos
.w
)/2;
1794 surf_pos
.y
+= (e
->image
->h
/e
->lives
- surf_pos
.w
)/2;
1795 draw_pos
.x
+= (e
->image
->h
/e
->lives
- surf_pos
.w
)/2;
1796 draw_pos
.y
+= (e
->image
->h
/e
->lives
- surf_pos
.w
)/2;
1798 surf_pos
.w
= e
->image
->h
/e
->lives
* (20 - e
->dying
/2) / 20;
1799 surf_pos
.h
= surf_pos
.w
;
1800 surf_pos
.x
+= (e
->image
->h
/e
->lives
- surf_pos
.w
)/2;
1801 surf_pos
.y
+= (e
->image
->h
/e
->lives
- surf_pos
.w
)/2;
1802 draw_pos
.x
+= (e
->image
->h
/e
->lives
- surf_pos
.w
)/2;
1803 draw_pos
.y
+= (e
->image
->h
/e
->lives
- surf_pos
.w
)/2;
1805 SDL_BlitSurface(e
->image
, &surf_pos
, scr
, &draw_pos
);
1808 if (((e
->t
% 8) == 1) && (!game_paused
)) {
1809 e
->blit_pos
= (e
->blit_pos
+ e
->image
->h
/e
->lives
) % e
->image
->w
;
1812 draw_pos
.x
= e
->x
- e
->image
->h
/e
->lives
/2 - scroll_x
;
1813 draw_pos
.y
= e
->y
- e
->image
->h
/e
->lives
/2 - scroll_y
;
1815 draw_pos
.x
-= (128-e
->image
->h
/e
->lives
)/2;
1816 draw_pos
.y
-= (128-e
->image
->h
/e
->lives
)/2;
1818 if (magic_circuit
>= e
->str
) {
1819 SDL_BlitSurface(reticle
, NULL
, scr
, &draw_pos
);
1822 draw_pos
.x
= e
->x
- e
->image
->h
/e
->lives
/2 - scroll_x
;
1823 draw_pos
.y
= e
->y
- e
->image
->h
/e
->lives
/2 - scroll_y
;
1825 draw_pos
.x
-= (128-e
->image
->h
/e
->lives
)/2;
1826 draw_pos
.y
-= (128-e
->image
->h
/e
->lives
)/2;
1828 if (sqrt(sqr(e
->x
- player_x
) + sqr(e
->y
- player_y
)) < circuit_range
) {
1829 SDL_BlitSurface(inrange
, NULL
, scr
, &draw_pos
);
1833 if (e
->teleport_v
< 24) {
1834 if (teleflash
== NULL
) {
1835 teleflash
= IMG_Load("dat/i/teleflash.png");
1836 SDL_SetColorKey(teleflash
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 0);
1839 surf_pos
.x
= 48*((e
->teleport_v
) / 3);
1844 draw_pos
.x
= e
->x
- 24 - scroll_x
;
1845 draw_pos
.y
= e
->y
- 24 - scroll_y
;
1846 SDL_BlitSurface(teleflash
, &surf_pos
, scr
, &draw_pos
);
1850 void DrawBullet(struct bullet
*b
)
1853 int x1
, y1
, x2
, y2
, xo1
, yo1
;
1856 static SDL_Surface
*d_star_small
= NULL
, *d_star_big
= NULL
, *d_star_ls
= NULL
;
1857 SDL_Rect draw_pos
, surf_pos
;
1858 if (b
->delete_me
) return;
1861 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 6+(b
->dying
/ 2), b
->dying
*10);
1862 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 3+(b
->dying
/ 2), 255-b
->dying
*10);
1864 if ((b
->t
% 8) < 4) {
1865 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 6, 0);
1866 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 4, 255);
1868 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 6, 255);
1869 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 4, 0);
1874 if (d_star_big
== NULL
) {
1875 d_star_big
= IMG_Load("dat/i/star1.png");
1876 SDL_SetColorKey(d_star_big
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 255);
1879 if (b
->dying
== 0) {
1880 surf_pos
.x
= b
->x
- 16 - scroll_x
;
1881 surf_pos
.y
= b
->y
- 16 - scroll_y
;
1882 draw_pos
.x
= (b
->t
% 8)*32;
1886 SDL_BlitSurface(d_star_big
, &draw_pos
, screen
, &surf_pos
);
1888 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 4+(b
->dying
), b
->dying
*10);
1889 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 2+(b
->dying
), 255-b
->dying
*10);
1893 // IMMA CHARGIN MAH LAZER
1894 if (b
->t
<= b
->fire_time
) {
1895 z
= (b
->t
* 150 / (b
->fire_time
+1)) + 80;
1899 while (!IsSolid(Get((fx
)/32, (fy
)/32))) {
1900 DrawRect(fx
-1-scroll_x
, fy
-1-scroll_y
, 4, 4, z
/2);
1901 fx
+= cos(b
->dir
)*2;
1902 fy
+= sin(b
->dir
)*2;
1904 if ((player_shield
> 0)&&(shield_hp
> 0)&&(PlayerDist(fx
, fy
) < 30)) break;
1905 if (PlayerDist(fx
, fy
) < 4) break;
1907 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 5, (z
+255)/2.4);
1908 DrawCircle(fx
-cos(b
->dir
)*2 - scroll_x
, fy
-sin(b
->dir
)*2 - scroll_y
, 4, z
/2);
1912 while (!IsSolid(Get((fx
)/32, (fy
)/32))) {
1913 DrawRect(fx
-scroll_x
, fy
-scroll_y
, 2, 2, z
);
1914 fx
+= cos(b
->dir
)*2;
1915 fy
+= sin(b
->dir
)*2;
1917 if ((player_shield
> 0)&&(shield_hp
> 0)&&(PlayerDist(fx
, fy
) < 30)) break;
1918 if (PlayerDist(fx
, fy
) < 4) break;
1921 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 3, (z
+255)/2);
1922 DrawCircle(fx
-cos(b
->dir
)*2 - scroll_x
, fy
-sin(b
->dir
)*2 - scroll_y
, 2, z
);
1926 if ((b
->t
> b
->fire_time
) && (b
->t
<= b
->fire_time
+ b
->duration
)) {
1927 z
= 255 - ((b
->t
- b
->fire_time
) * 200 / (b
->duration
+1));
1931 while (!IsSolid(Get((fx
)/32, (fy
)/32))) {
1932 DrawRect(fx
-3-scroll_x
, fy
-3-scroll_y
, 8, 8, z
*2/3);
1933 fx
+= cos(b
->dir
)*2;
1934 fy
+= sin(b
->dir
)*2;
1936 if ((player_shield
> 0)&&(shield_hp
> 0)&&(PlayerDist(fx
, fy
) < 30)) break;
1937 if (PlayerDist(fx
, fy
) < 4) break;
1939 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 9, (z
+255)/2.4);
1940 DrawCircle(fx
-cos(b
->dir
)*2 - scroll_x
, fy
-sin(b
->dir
)*2 - scroll_y
, 8, z
*2/3);
1943 while (!IsSolid(Get((fx
)/32, (fy
)/32))) {
1944 DrawRect(fx
-2-scroll_x
, fy
-2-scroll_y
, 6, 6, z
);
1945 fx
+= cos(b
->dir
)*2;
1946 fy
+= sin(b
->dir
)*2;
1948 x1
= fx
+ rand()%12 - rand()%12 - scroll_x
;
1949 y1
= fy
+ rand()%12 - rand()%12 - scroll_y
;
1950 DrawRect(x1
, y1
, 2, 2, rand()%(z
+1));
1952 if ((player_shield
> 0)&&(shield_hp
> 0)&&(PlayerDist(fx
, fy
) < 30)) break;
1953 if (PlayerDist(fx
, fy
) < 4) break;
1956 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 7, (z
+255)/2);
1957 DrawCircle(fx
-cos(b
->dir
)*2 - scroll_x
, fy
-sin(b
->dir
)*2 - scroll_y
, 6, z
);
1961 if (d_star_small
== NULL
) {
1962 d_star_small
= IMG_Load("dat/i/star2.png");
1963 SDL_SetColorKey(d_star_small
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 255);
1965 if (b
->dying
== 0) {
1966 surf_pos
.x
= b
->x
- 8 - scroll_x
;
1967 surf_pos
.y
= b
->y
- 8 - scroll_y
;
1968 draw_pos
.x
= (b
->t
% 8)*16;
1972 SDL_BlitSurface(d_star_small
, &draw_pos
, screen
, &surf_pos
);
1974 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 4+(b
->dying
/2), b
->dying
*10);
1975 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 2+(b
->dying
/2), 255-b
->dying
*10);
1979 if (b
->dying
== 0) {
1980 x1
= b
->x
+ cos(b
->dir
)*(2) - scroll_x
;
1981 y1
= b
->y
+ sin(b
->dir
)*(2) - scroll_y
;
1983 x2
= b
->x
- cos(b
->dir
)*(80) - scroll_x
;
1984 y2
= b
->y
- sin(b
->dir
)*(80) - scroll_y
;
1985 for (i
= 0; i
< 40; i
++) {
1986 xo1
= (x2
- x1
)*i
/40 + x1
;
1987 yo1
= (y2
- y1
)*i
/40 + y1
;
1990 if (i
> 10) z
= (40 - i
)/7;
1992 DrawRect(xo1
- z
- 2, yo1
- z
- 2, z
*2 + 4, z
*2 + 4, 200);
1994 for (i
= 0; i
< 40; i
++) {
1995 xo1
= (x2
- x1
)*i
/40 + x1
;
1996 yo1
= (y2
- y1
)*i
/40 + y1
;
1999 if (i
> 10) z
= (40 - i
)/7;
2001 DrawRect(xo1
- z
, yo1
- z
, z
*2, z
*2, 255);
2004 DrawCircleEx(b
->x
- scroll_x
, b
->y
- scroll_y
, b
->dying
* 2 + 1, b
->dying
* 1.75 - 1, 230);
2005 DrawCircleEx(b
->x
- scroll_x
, b
->y
- scroll_y
, b
->dying
* 2, b
->dying
* 1.75, 255);
2010 i
= 4+(b
->dying
/ 5);
2011 DrawRect(b
->x
- scroll_x
- (i
-1/2), b
->y
- scroll_y
- (i
-1/2), i
, i
, b
->dying
*10);
2012 i
= 2+(b
->dying
/ 5);
2013 DrawRect(b
->x
- scroll_x
- (i
-1/2), b
->y
- scroll_y
- (i
-1/2), i
, i
, 255-b
->dying
*10);
2015 if ((b
->t
% 8) < 4) {
2016 DrawRect(b
->x
- scroll_x
- 1, b
->y
- scroll_y
- 1, 4, 4, 0);
2017 DrawRect(b
->x
- scroll_x
, b
->y
- scroll_y
, 2, 2, 255);
2019 DrawRect(b
->x
- scroll_x
- 1, b
->y
- scroll_y
- 1, 4, 4, 255);
2020 DrawRect(b
->x
- scroll_x
, b
->y
- scroll_y
, 2, 2, 0);
2025 if (d_star_ls
== NULL
) {
2026 d_star_ls
= IMG_Load("dat/i/star3.png");
2027 SDL_SetColorKey(d_star_ls
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 255);
2029 if (b
->dying
== 0) {
2030 surf_pos
.x
= b
->x
- 16 - scroll_x
;
2031 surf_pos
.y
= b
->y
- 16 - scroll_y
;
2032 draw_pos
.x
= (b
->t
% 8)*32;
2036 SDL_BlitSurface(d_star_ls
, &draw_pos
, screen
, &surf_pos
);
2038 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 4+(b
->dying
), 255-b
->dying
*10);
2039 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 2+(b
->dying
), b
->dying
*10);
2044 if ((b
->t
% 8) < 4) {
2045 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 8, 0);
2046 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 5, 255);
2048 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 8, 255);
2049 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 5, 0);
2054 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 12+(b
->dying
), b
->dying
*10);
2055 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 6+(b
->dying
), 255-b
->dying
*10);
2057 if ((b
->t
% 6) < 3) {
2058 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 12, 0);
2059 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 8, 255);
2061 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 12, 255);
2062 DrawCircle(b
->x
- scroll_x
, b
->y
- scroll_y
, 8, 0);
2068 void DrawGem(struct diamond
*g
)
2070 static SDL_Surface
*d_sprite
= NULL
;
2072 static char hp_icon
[2];
2075 unsigned char fxp
= (SDL_GetTicks() / 300)%2 ? 255 : 0;
2077 if (g
->delete_me
) return;
2079 if (d_sprite
== NULL
) {
2080 d_sprite
= IMG_Load("dat/i/gem.png");
2081 SDL_SetColorKey(d_sprite
, SDL_SRCCOLORKEY
| SDL_RLEACCEL
, 255);
2086 if (g
->value
== 1) gemtype
= 2;
2087 if ((g
->value
> 1)&&(g
->value
< 5)) gemtype
= 1;
2088 if (g
->value
>= 5) gemtype
= 0;
2090 if (g
->value
!= 31337) {
2092 surf_pos
.x
= g
->x
- 4 - scroll_x
;
2093 surf_pos
.y
= g
->y
- 4 - scroll_y
;
2094 draw_pos
.x
= (g
->t
% 4) * 8 + 32 * gemtype
;
2099 SDL_BlitSurface(d_sprite
, &draw_pos
, screen
, &surf_pos
);
2101 DrawCircle(g
->x
- scroll_x
, g
->y
- scroll_y
, 6, (rand()%64) ^ fxp
);
2102 draw_text(g
->x
- 4 - scroll_x
, g
->y
- 4 - scroll_y
, hp_icon
, (200+rand()%56) ^ fxp
);
2108 void xprintf(char *s
)
2114 void DrawInvisible(int x
, int y
)
2117 dest
.x
= x
- scroll_x
- 24;
2118 dest
.y
= y
- scroll_y
- 24;
2119 SDL_BlitSurface(invis_enemy
, NULL
, screen
, &dest
);
2127 struct enemyloc
*els
;
2129 if ((rooms
[player_room
].room_type
!= 3)&&(rooms
[player_room
].room_type
!= 2)) {
2132 g
= room_gems
[player_room
];
2134 if ((g
->room
== player_room
)&&(g
->delete_me
== 0)&&(g
->value
!= 31337)) {
2137 g
= g
->next_in_room
;
2139 g
= room_gems
[player_room
];
2141 if ((g
->room
== player_room
)&&(g
->delete_me
== 0)&&(g
->value
== 31337)) {
2144 g
= g
->next_in_room
;
2150 if (!t
->delete_me
) {
2151 if ((t
->room
== player_room
) && (t
->enemy_type
!= 9)) {
2152 DrawEnemy(t
, screen
);
2158 // Draw invisible enemies (if possible)
2165 if (((!t
->delete_me
)&&((t
->room
!= player_room
)||(t
->enemy_type
== 9)))) {
2166 DrawInvisible(t
->x
, t
->y
);
2171 // Draw the inactives
2172 if (!artifacts
[11]) {
2173 els
= GetEnemyLoc(scroll_x
, scroll_y
);
2174 while (els
!= NULL
) {
2176 if (((!t
->delete_me
)&&((t
->room
!= player_room
)||(t
->enemy_type
== 9)))&&(t
->active
== 0)) {
2177 if ((t
->x
+24 >= scroll_x
) && (t
->y
+24 >= scroll_y
)) {
2178 if (t
->x
-24 <= (scroll_x
+639)) {
2179 if (t
->y
-24 <= (scroll_y
+479)) {
2180 if ((rooms
[t
->room
].room_type
!= 2) && (rooms
[t
->room
].room_type
!= 3)) {
2181 DrawInvisible(t
->x
, t
->y
);
2194 if (!b
->delete_me
) {
2195 if (b
->room
== player_room
) {
2209 struct bullet
*b_del
;
2210 struct diamond
*g_del
;
2212 if ((rooms
[player_room
].room_type
!= 3)&&(rooms
[player_room
].room_type
!= 2)) {
2214 g
= room_gems
[player_room
];
2216 if ((g
->room
== player_room
)&&(g
->delete_me
== 0)) {
2218 g
->x
+= (player_x
+4 - g
->x
)/10;
2219 g
->y
+= (player_y
+12 - g
->y
)/10;
2221 if (PlayerDist(g
->x
, g
->y
) < 20) {
2225 if (g
->value
== 31337) {
2226 if (player_hp
< (3 + (player_shield
== 30)*3)) {
2227 SND_Pos("dat/a/crystal.wav", 64, 0);
2231 SND_Pos("dat/a/tone.wav", 64, 0);
2233 if (player_lives
== 1) {
2234 player_lives_part
+= 15;
2236 if (player_lives
< 10) {
2237 player_lives_part
+= 4;
2239 player_lives_part
+= 1;
2242 if (player_lives_part
>= 88) {
2243 player_lives_part
-= 88;
2245 SND_Pos("dat/a/crystal2.wav", 100, 0);
2251 player_gems
+= g
->value
;
2255 g
= g
->next_in_room
;
2261 if (!t
->delete_me
) {
2262 if ((rooms
[t
->room
].room_type
!= 3) || (t
->room
== player_room
))
2270 if (!b
->delete_me
) {
2276 // delete old bullets
2278 if ((b
!= NULL
)&&(b
->delete_me
)) {
2285 if (b
->next
!= NULL
) {
2286 if (b
->next
->delete_me
) {
2289 b
->next
= b
->next
->next
;
2298 if ((g
!= NULL
)&&(g
->delete_me
)) {
2299 // Remove room reference
2301 if (g
== room_gems
[g
->room
]) {
2302 room_gems
[g
->room
] = g
->next_in_room
;
2303 if (room_gems
[g
->room
] != NULL
) {
2304 room_gems
[g
->room
]->prv_in_room
= NULL
;
2307 if (g
->prv_in_room
!= NULL
) {
2308 g
->prv_in_room
->next_in_room
= g
->next_in_room
;
2311 if (g
->next_in_room
!= NULL
) {
2312 g
->next_in_room
->prv_in_room
= g
->prv_in_room
;
2322 if (g
->next
!= NULL
) {
2323 if (g
->next
->delete_me
) {
2324 // Remove room reference
2325 assert( (g
->next
->prv_in_room
!= NULL
) || (room_gems
[g
->next
->room
] == g
->next
) );
2327 if (g
->next
== room_gems
[g
->next
->room
]) {
2328 room_gems
[g
->next
->room
] = g
->next
->next_in_room
;
2329 if (room_gems
[g
->next
->room
] != NULL
) {
2330 room_gems
[g
->next
->room
]->prv_in_room
= NULL
;
2333 g
->next
->prv_in_room
->next_in_room
= g
->next
->next_in_room
;
2334 if (g
->next
->next_in_room
!= NULL
) {
2335 g
->next
->next_in_room
->prv_in_room
= g
->next
->prv_in_room
;
2340 g
->next
= g
->next
->next
;
2347 // delete old monsters
2350 while (t
->delete_me
) {
2354 if (t
== NULL
) break;
2358 if (t
== active_stack
)
2359 assert(t
->delete_me
== 0);
2361 assert(!t
->delete_me
);
2363 if (t
->next_active
!= NULL
) {
2364 while (t
->next_active
->delete_me
) {
2365 t
->next_active
= t
->next_active
->next_active
;
2366 if (t
->next_active
== NULL
) break;
2373 void HurtEnemies(int x
, int y
, int range
, int power
)
2380 e_range
= sqrt(sqr(t
->x
- x
) + sqr(t
->y
- y
));
2381 if (e_range
< range
) {
2382 if (power
>= t
->str
) {
2383 if (t
->room
== GetRoom(x
/32, y
/32)) {
2392 void CircuitBullets(int x
, int y
, int r
)
2397 if (!b
->delete_me
) {
2398 if (b
->dying
== 0) {
2399 if (b
->invuln
== 0) {
2400 if (sqrt(sqr(b
->x
- x
) + sqr(b
->y
- y
)) < r
) {
2410 int IsCrystalSummonPossible()
2412 if(total_gems
== 0) {
2416 int total_rooms
= 0;
2417 for (i
= 0; i
< 3000; i
++) {
2418 if(room_gems
[i
] != NULL
) {
2420 if(total_rooms
> 1 || i
!= player_room
) {
2428 unsigned int CrystalSummon()
2437 for (i
= 0; i
< 3000; i
++) {
2438 if(i
!= player_room
) {
2439 room_gems
[i
] = NULL
;
2444 if (g
->room
!= player_room
) {
2445 if (!g
->delete_me
) {
2446 if (rooms
[g
->room
].room_type
!= 3) {
2447 g
->room
= player_room
;
2448 rg_x
= rooms
[player_room
].x
* 32 + 32 + rand()%(rooms
[player_room
].w
*32-64);
2449 rg_y
= rooms
[player_room
].y
* 32 + 32 + rand()%(rooms
[player_room
].h
*32-64);
2450 if (player_room
== 0) {
2451 rg_x
= (rooms
[player_room
].x
+5) * 32 + 32 + rand()%(8*32);
2452 rg_y
= (rooms
[player_room
].y
+5) * 32 + 32 + rand()%(5*32);
2454 while (IsSolid(Get(rg_x
/32, rg_y
/32))) {
2455 rg_x
= rooms
[player_room
].x
* 32 + 32 + rand()%(rooms
[player_room
].w
*32-64);
2456 rg_y
= rooms
[player_room
].y
* 32 + 32 + rand()%(rooms
[player_room
].h
*32-64);
2457 if (player_room
== 0) {
2458 rg_x
= (rooms
[player_room
].x
+5) * 32 + 32 + rand()%(8*32);
2459 rg_y
= (rooms
[player_room
].y
+5) * 32 + 32 + rand()%(5*32);
2467 g
->next_in_room
= room_gems
[g
->room
];
2468 g
->prv_in_room
= NULL
;
2469 if (room_gems
[g
->room
] != NULL
) {
2470 room_gems
[g
->room
]->prv_in_room
= g
;
2472 room_gems
[g
->room
] = g
;
2484 struct enemy
*en
[20000];
2490 if (e
->delete_me
== 0) {
2491 if (e
->active
== 0) {
2500 XActivateSingleEnemy(e
);
2504 void ClearBossBullets()
2506 struct bullet
*b
= bullet_stack
;
2508 if (!b
->delete_me
) {
2509 if (b
->firer
== NULL
) {
2517 void SpawnBullet(int x
, int y
, int bullet_type
, float dir
, float spd
, int invuln
)
2521 if ( (current_boss
== 3) && (player_shield
== 30) && (boss_fight_mode
== 2) ) {
2524 b
= CreateBullet(x
, y
, NULL
, bullet_type
, dir
, spd
);
2529 void SpawnLaser(int x
, int y
, float dir
, int fire_time
, int duration
, float turn
, int dmg
)
2531 FireLaser(x
, y
, NULL
, dir
, fire_time
, duration
, turn
, dmg
);
2534 void CullEnemies(int nth
)
2542 if (e
->delete_me
== 0) {
2543 if (rooms
[e
->room
].room_type
== 0) {
2544 if ( (i
% nth
) == (nth
- 1)) {
2548 rooms
[e
->room
].enemies
--;
2557 void SoupUpEnemies(int boss
)
2561 float str_multiplier
;
2566 if (circuit_size
> 1500) {
2570 str_multiplier
= 1.0 + (1.0/3.0)*(float)boss
;
2571 fr_divider
= 1.0 + (2.0/3.0)*(float)boss
;
2574 if (e
->delete_me
== 0) {
2575 if (e
->enemy_type
!= 10) {
2576 if (e
->str
< str_limit
) {
2577 if ((e
->str
* 2) < str_limit
) {
2578 e
->str
= e
->str
* str_multiplier
;
2583 e
->fire_rate
= (int)((float)e
->fire_rate
/ fr_divider
) + 1;
2584 e
->speed
= (int)((float)e
->speed
/ fr_divider
) + 1;
2585 e
->min_gems
*= str_multiplier
;
2586 e
->max_gems
*= str_multiplier
;
2593 void CurseSingleEnemy(struct enemy
*e
)
2595 static int ActiveRooms
[3000];
2596 static int NActiveRooms
= 0;
2600 if (NActiveRooms
== 0) {
2601 for (i
= 0; i
< 3000; i
++) {
2602 if ((rooms
[i
].room_type
== 0) || (rooms
[i
].room_type
== 4)) {
2603 ActiveRooms
[NActiveRooms
++] = i
;
2608 rm
= ActiveRooms
[rand()%NActiveRooms
];
2609 while ((rooms
[rm
].enemies
> 3) || (rooms
[rm
].visited
== 0)) {
2610 rm
= ActiveRooms
[rand()%NActiveRooms
];
2613 e
->x
= rooms
[rm
].w
* 16 + rooms
[rm
].x
* 32;
2614 e
->y
= rooms
[rm
].h
* 16 + rooms
[rm
].y
* 32;
2615 rooms
[e
->room
].enemies
--;
2617 rooms
[e
->room
].enemies
++;
2619 e
->image
= enemy_sprites
[9];
2623 e
->fire_rate
= (rand()%4)+1;
2626 e
->followdepth
= 12;
2627 e
->creationcost
= 6;
2630 ActivateSingleEnemy(e
);
2641 if (e
->delete_me
== 0) {
2642 if ( (i
% 5) == (4)) {
2643 CurseSingleEnemy(e
);
2649 rooms
[e
->room
].enemies
--;