Ignore emulated mouseevents (in the game).
[runemen.git] / src / rune2.c
blobe887bbd192f3bff79107ba4275123261ae0d8c7e
1 #include "libs/savepng/savepng.h"
2 #include "libs/lazyass/lazyass.h"
3 #include "libs/binaryheap/binhl.h"
4 #include "libs/SDL_inprint/SDL2_inprint.h"
6 #include "rune.h"
7 #include "runeconf.h"
8 #include "mana.h"
9 #include "game.h"
10 #include "ui.h"
11 #include "draw.h"
12 #include "utils.h"
15 #define PASS_DEL 25
16 //#define PASS_DEL 1
18 faction_t *your;
20 void init_factions() {
22 memset(factions, 0, sizeof(faction_t) * 8);
24 strcpy(factions[0].title, "Your Kingdom");
25 factions[0].color.r = 0;
26 factions[0].color.g = 0;
27 factions[0].color.b = 0xff;
28 factions[0].gold = 10000;
30 strcpy(factions[1].title, "Reavers");
31 factions[1].color.r = 0xff;
32 factions[1].color.g = 0;
33 factions[1].color.b = 0;
34 factions[1].gold = 10000;
38 #include "draw.h"
40 void clear_house(int id) {
41 house_t *h = &houses[id];
42 h->tile = 0;
43 h->w = 2;
44 h->h = 2;
47 void clear_unit(int id) {
48 unit_t *u = &units[id];
49 u->tile = 0;
50 u->dmg = 0;
51 u->level = 0;
52 u->exp = 0;
53 u->link = NULL;
54 u->link_id = 0;
55 u->pool = NULL;
57 int i;
58 for (i = 0; i < MAX_STAT; i++) {
59 u->base_stat[i] = 0;
60 u->rune_stat[i] = 0;
61 u->calc_stat[i] = 0;
62 u->stat_bid[i] = 0;
64 u->ref_count[i] = 0;
67 u->axis_refs[UAXIS_TYPE] = &u->tile;
68 u->axis_refs[UAXIS_MODE] = &u->mode;
69 u->axis_refs[UAXIS_FRAME] = &u->frame;
72 void init_houses() {
73 num_houses = 0;
74 int i;
75 for (i = 0; i < MAX_HOUSES; i++) {
76 clear_house(i);
79 house_t *h;
80 h = &houses[0];
81 h->tile = 1;
84 void init_units() {
85 num_units = 0;
86 int i;
87 for (i = 0; i < MAX_UNITS; i++) {
88 clear_unit(i);
92 int add_house(Uint32 tx, Uint32 ty) {
93 int id = num_houses;
95 house_p *m = &bhouses[ui.builder];
97 house_t *h = &houses[id];
98 clear_house(id);
100 h->tile = ui.builder;//m->tile;
101 h->x = tx;
102 h->y = ty;
103 h->w = m->w;
104 h->h = m->h;
106 h->built = 0;
107 h->hp = 1;
108 h->max_hp = 100;
110 h->faction = 0;/* :( */
112 h->capacity = h->w * h->h;
114 your->gold -= m->gold_cost;
116 num_houses++;
118 return id;
121 void stress_unit(int id, int dmg) {
122 unit_t *u = &units[id];
123 u->dmg += dmg;
126 void kill_unit(int id) {
127 unit_t *u = &units[id];
128 u->tile = 0;
130 // remove_wtf(id);
131 /* When devotee dies, his link to lord is removed */
132 if (u->link) {
133 ///* Lord is alarmed */
134 //unit_t *l = u->link;
135 //while (l->link) l = l->link;
136 //l->baloon = 1;
138 u->link->ref_count[u->link_stat]--;
139 u->link->ref_counts--;
140 u->link = NULL;
142 /* When lord dies, his devotees are freed! */
143 if (u->ref_count[u->link_stat]) {
144 int i;
145 for (i = 0; i < num_units; i++) {
146 if (units[i].link == u) {
147 units[i].baloon = 1;
148 units[i].link = NULL;
149 u->ref_count[u->link_stat]--;
150 u->ref_counts--;
154 rebuild_pools();
157 void add_reaver() {
158 int id = num_units;
160 unit_t *u = &units[id];
161 clear_unit(id);
163 strcpy(u->name, "Path Finder");
164 u->tile = 18;
165 u->base_stat[S_STR] = 5;
166 u->base_stat[S_DEX] = 0;
167 u->base_stat[S_CON] = 5;
168 u->base_stat[S_INT] = 0;
170 u->frame = 0;
171 u->color = 0x6c441c;
173 u->energy = 0;
174 u->progress = 0;
176 num_units++;
178 u->x = rand() % LEVEL_W;
179 u->y = rand() % LEVEL_H;
180 u->tx = u->x;
181 u->ty = u->y;
183 u->faction = 1;
186 void add_peasant() {
187 int id = num_units;
189 unit_t *u = &units[id];
190 clear_unit(id);
192 generate_name(u);
193 u->tile = 2;
194 u->base_stat[S_STR] = 5;
195 u->base_stat[S_DEX] = 0;
196 u->base_stat[S_CON] = 5;
197 u->base_stat[S_INT] = 0;
199 u->frame = 0;
200 u->color = 0x6c441c;
202 u->energy = 0;
203 u->progress = 0;
205 num_units++;
207 u->x = rand() % LEVEL_W;
208 u->y = rand() % LEVEL_H;
209 u->tx = u->x;
210 u->ty = u->y;
212 u->axis_refs[UAXIS_TYPE] = &u->tile;
213 u->axis_refs[UAXIS_MODE] = &u->mode;
214 u->axis_refs[UAXIS_FRAME] = &u->frame;
216 u->faction = 0;
220 int find_houseT(Uint32 tx, Uint32 ty) {
221 int i;
222 for (i = 0; i < num_houses; i++) {
223 house_t *h = &houses[i];
224 if (tx >= h->x && tx <= h->x+(h->w-1) &&
225 ty >= h->y && ty <= h->y+(h->h-1))
227 return i;
230 return -1;
233 int find_house(Uint32 x, Uint32 y) {
234 return find_houseT(
235 (ui.x + ui.vx) / TILE_W,
236 (ui.y + ui.vy) / TILE_H
240 int find_unitT(Uint32 tx, Uint32 ty) {
241 int i;
242 for (i = 0; i < num_units; i++) {
243 unit_t *u = &units[i];
244 unit_p *p = &bunits[u->tile];
245 if (u->visiting) continue;
246 if (tx >= u->x && tx <= u->x+(p->w-1) &&
247 ty >= u->y && ty <= u->y+(p->h-1))
249 return i;
252 return -1;
255 int find_unit(Uint32 x, Uint32 y) {
256 x += ui.vx;
257 y += ui.vy;
258 int i;
259 for (i = 0; i < num_units; i++) {
260 unit_t *u = &units[i];
261 unit_p *p = &bunits[u->tile];
262 if (u->visiting) continue;
263 if (x >= u->x * TILE_W + u->ox
264 && x <= u->x * TILE_W + u->ox + (TILE_W * p->w)
265 && y >= (u->y-(p->h-1)) * TILE_H + u->oy
266 && y <= (u->y-(p->h-1)) * TILE_H + u->oy + (TILE_H * p->h))
268 return i;
271 return -1;
274 int xcollide(Uint32 tx, Uint32 ty, Uint8 w, Uint8 h) {
275 int i, j;
276 for (j = 0; j < h; j++) {
277 for (i = 0; i < w; i++) {
278 if (find_houseT(tx + i, ty + j) != -1) return 1;
279 if (find_unitT (tx + i, ty + j) != -1) return 1;
282 return 0;
285 #include "SDL2_particles.h"
287 particle_system psystems[128];
288 int num_psystems = 0;
290 void add_fire(Sint16 x, Sint16 y, Uint16 limit) {
291 int id = num_psystems++;
292 particle_system *ps = &psystems[id];
294 ps->x = x;
295 ps->y = y;
296 ps->limit = limit;
297 ps->init = &basic_particle_init;
298 ps->move = &basic_particle_move;
299 ps->reset = &basic_particle_reset;
300 ps->spawn = 0;
303 void update_particles() {
304 int i;
305 for (i = 0; i < num_psystems; i++) {
306 particle_system *ps = &psystems[i];
307 PS_Update(ps);
311 void draw_particles(SDL_Renderer *target, Uint32 bx, Uint32 by) {
313 SDL_Color reds[16] = { { 0xff } };
315 int i;
316 for (i = 0; i < num_psystems; i++) {
317 particle_system *ps = &psystems[i];
318 if (!ps->limit) continue;
319 PS_Render(target, ps, reds, 1, bx, by);
324 void init_fog() {
325 int tx, ty;
327 for (ty = 0; ty < LEVEL_H; ty++) {
328 for (tx = 0; tx < LEVEL_W; tx++) {
329 fog[ty][tx] = 1;
330 scent_human[ty][tx] = 0;
335 void calc_fog() {
337 int tx, ty;
339 for (ty = 0; ty < LEVEL_H; ty++) {
340 for (tx = 0; tx < LEVEL_W; tx++) {
341 // fog[ty][tx] = 1;
342 if (scent_human[ty][tx] > 0) scent_human[ty][tx]--;
343 if (scent_human[ty][tx] > 255) scent_human[ty][tx] = 255;
346 int i;
348 for (i = 0; i < num_houses; i++) {
349 house_t *h = &houses[i];
350 int j, k, bl = h->h/2;
351 for (j = -h->h+bl; j < h->h+bl+1; j++) {
352 if (h->y + j < 0) continue;
353 if (h->y + j >= LEVEL_H) break;
354 for (k = -h->w; k < h->w+1; k++) {
355 if (h->x + k < 0) continue;
356 if (h->x + k >= LEVEL_W) break;
357 fog[h->y + j][h->x + k] = 0;
362 for (i = 0; i < num_units; i++) {
363 unit_t *u = &units[i];
364 unit_p *p = &bunits[u->tile];
365 int j, k;
366 for (j = -1; j < 2; j++) {
367 if (u->y + j < 0) continue;
368 if (u->y + j >= LEVEL_H) break;
369 for (k = -1; k < 2; k++) {
370 if (u->x + k < 0) continue;
371 if (u->x + k >= LEVEL_W) break;
372 fog[u->y + j][u->x + k] = 0;
373 scent_human[u->y + j][u->x + k] += p->base_scent[SCENT_HUMAN];
380 void draw_ui(SDL_Renderer *screen) {
381 SDL_Rect src = { 0, 0, 640, 480 };
382 SDL_Rect dst = { 0, 0, LOG_WIDTH, LOG_HEIGHT };
383 SDL_RenderCopy(screen, uibg, &src, &dst);
385 draw_goldbox(screen, 2, 3, 0, your->ore);
386 draw_goldbox(screen, 80, 3, 1, your->gold);
388 draw_minimap(screen);
390 if (ui.unit != -1) draw_unitbox(screen);
391 else if (ui.house != -1) draw_housebox(screen);
392 else {
393 draw_buildset(screen);
394 draw_pinbox(screen);
397 if (ui.hint != -1) draw_hintbox(screen);
399 incolor(0xffffff, 0);
400 rprintf(screen, LOG_WIDTH - 128, 0, "FPS: %d", ui.fps);
403 void draw_screen(SDL_Renderer *screen) {
405 SDL_SetRenderDrawColor(screen, 0x11, 0x33, 0x11, 255);
406 SDL_RenderClear(screen);
408 draw_houses(screen);
410 draw_units(screen);
412 if (ui.draw_fog) draw_fog(screen);
413 if (ui.draw_scent) draw_scent(screen);
415 draw_particles(screen, 100,100);
417 if (ui.draw_overlays) draw_overlays(screen, ui.unit, 0, 0, NULL);
419 if (ui.draw_path) draw_paths(screen, ui.unit, 0, 0);
421 if (ui.draw_pools) draw_pools(screen);
423 if (ui.builder > -1) draw_builder(screen);
424 if (ui.stat > -1) draw_forcible(screen);
426 draw_ui(screen);
430 void prepare_units() {
431 int i;
432 Uint8 lx, ly;
433 lx = ly = 0;
434 for (i = 0; i < num_bunits; i++) {
435 unit_p *u = &bunits[i];
436 //u->x = lx;
437 //u->y = ly;
438 ly += u->h;
439 printf("unit %s stands on %d, %d, occupies %d, %d\n", u->title, lx, ly, u->w, u->h);
440 if (ly >= 14) {
441 ly = 0;
442 lx += 5;
447 void init_game() {
449 init_factions();
451 your = &factions[0];
453 reset_ui();
455 add_fire(100,100,25000);
457 num_pools = 0;
459 ui.vx = 0;
460 ui.vy = 0;
462 SDL_InitSine();
464 SDL_Color tcol = { 0xff, 0xff, 0xff };
466 tiles = ASS_LoadTexture("data/gfx/runelord.bmp", &tcol);
468 printf("Tiles: %p, %s\n", tiles, SDL_GetError());
469 // prepare_units();
471 cfg_load("data/rune.cfg");
473 uibg = ASS_LoadTexture("data/gfx/woodui.bmp", &tcol);
475 SDL_Color magenta = { 0xff, 0, 0xff };
477 small_font = ASS_LoadTexture("data/fonts/oddball6x8.bmp", &magenta);
479 mid_font = ASS_LoadTexture("data/fonts/webby8.bmp", &magenta);
481 large_font = NULL; /* aka inline */
483 infont(large_font);
485 init_units();
487 init_houses();
489 init_fog();
491 int i;
492 for (i = 0; i < 50; i++) {
494 add_peasant();
498 units[0].x = units[0].y = units[0].tx = units[0].ty = 5;
500 units[1].tx = units[1].x = (units[1].x - 3);
501 units[1].ty = units[1].y = (units[1].y + 2);
502 units[2].tx = units[2].x = (units[2].x - 2);
503 units[2].ty = units[2].y = (units[2].y + 4);
504 // random_links();
507 void focus_on_unit() {
508 unit_t *u = &units[ui.unit];
509 ui.vx = u->tx * TILE_W - LOG_WIDTH / 2;
510 ui.vy = u->ty * TILE_H - LOG_HEIGHT / 2;
512 if (ui.vx < 0) ui.vx = 0;
513 if (ui.vy < 0) ui.vy = 0;
516 void do_update_grids(void) {
517 int i, j;
519 for (j = 0; j < LEVEL_H; j++)
520 for (i = 0; i < LEVEL_W; i++) {
522 unit_grid[j][i] = NULL;
523 house_grid[j][i] = NULL;
527 for (i = 0; i < num_units; i++) {
529 unit_t *unit = &units[i];
530 unit_grid[unit->ty][unit->tx] = unit;
535 void do_update_links(void) {
536 update_stats(1);
537 // rebuild_pools();
538 collect_pools();
539 distrib_pools();
540 update_stats(0);
543 void do_scroll_out() {
544 if (ui.unit == -1) return;
545 unit_t *su = &units[ui.unit];
547 int fs[MAX_UNITS];
549 int f = 0;
550 int i;
551 for (i = 0; i < num_units; i++) if (units[i].link == su) fs[f++] = i;
552 if (f > 0) {
553 i = rand() % f;
554 printf("Rand is: %d\n", i);
555 ui.unit = fs[i];
556 focus_on_unit();
560 void do_scroll_in() {
561 if (ui.unit == -1) return;
562 unit_t *u = &units[ui.unit];
564 if (u->link) {
565 ui.unit = u->link_id;
566 unit_t *u2 = &units[ui.unit];
567 focus_on_unit();
571 void do_pin_click() {
573 Uint32 x = pinbox.x;
574 Uint32 y = pinbox.y;
576 Uint32 w = PANE_WIDTH;
577 Uint32 h = 16;
579 int i;
580 for (i = 0; i < num_units; i++) {
581 unit_t *u = &units[i];
582 if (u->tile && u->pin) {
583 if (ui.x >= x + 8 && ui.y >= y + 4 && ui.x <= x + 120 && ui.y <= y + 4 + 16) {
584 ui.unit = i;
585 break;
587 if (ui.x >= x + 120 + 8 && ui.y >= y + 4 && ui.x <= x + 120 + 16 && ui.y <= y + 4 + 6) {
588 u->pin = 0;
589 break;
591 y += 16;
597 void do_minimap_click() {
599 int x = ui.x - minimap.x;
600 int y = ui.y - minimap.y;
602 int z = 2;
604 int vx = x * z;
605 int vy = y * z;
607 ui.vx = vx;
608 ui.vy = vy;
612 void do_button() {
613 unit_t *u = &units[ui.unit];
615 int btn = ui.btn;
616 if (u->tile == U_PEASANT) {
617 int cost = 0;
618 int next = U_PEASANT;
619 switch (btn) {
620 case 0: next = U_MILITIA; cost = 250; break;
621 case 1: next = U_ARCHER; u->base_stat[S_DEX]+=5; cost = 200; break;
622 case 2: next = U_KNIGHT; cost = 350; break;
623 case 3: next = U_FLAMER+rand()%4; cost = 500; break;
624 default: break;
626 if (cost) {
627 your->gold -= cost;
628 u->tile = next;
633 void do_event_click(Uint32 x, Uint32 y) {
635 //printf("Clicked on %d, %d\n", x, y);
637 /* Building houses? */
638 if (ui.builder != -1) {
640 if (ui.hover_top == overMap) {
642 if (ui.hover_xcollide) {
643 //game.log("Can't place here");
644 return;
645 } else {
647 /* build house */
648 ui.house = add_house(ui.hover_tx, ui.hover_ty);
649 ui.builder = -1;
653 return;
656 switch (ui.hover) {
658 /* UI PANE */
660 case overMinimap:
662 do_minimap_click();
664 break;
665 case overBuildButton:
667 ui.builder = ui.hover_id;
669 break;
670 case overPinBox:
672 do_pin_click();
674 break;
675 case overUnitPin:
677 units[ui.unit].pin = 1 - units[ui.unit].pin;
679 break;
680 case overUnitStat:
682 /* Start rune linking */
683 if (units[ui.unit].link == NULL) ui.stat = ui.hover_id;
685 break;
686 case overUnitSkill:
688 /* Start upgrade */
689 if (units[ui.unit].link == NULL) ui.btn = ui.hover_id;
691 do_button();
692 ui.btn = -1;
694 break;
696 /* GAME MAP */
698 case overUnit:
700 /* rune-link */
701 if (ui.stat != -1) {
702 if (ui.hover_id != ui.unit) { // add other verefications, like factions, costs, etc
704 add_link(ui.unit, ui.hover_id, ui.stat);
706 ui.unit = ui.hover_id; /* Also select */
708 /* Stop rune-linking, if it's not possible */
709 if (units[ui.unit].link != NULL || units[ui.unit].ref_count[ui.stat] > 1) ui.stat = -1;
712 /* select */
713 else {
714 ui.house = -1;
715 ui.unit = ui.hover_id;
718 break;
719 case overHouse:
721 ui.unit = -1;
722 ui.house = ui.hover_id;
724 break;
725 default:break;
730 void do_event_key(int sym) {
731 if (sym == SDLK_1) ui.game_speed = 25;
732 if (sym == SDLK_5) ui.game_speed = 1;
734 if (sym == SDLK_s) ui.draw_scent = 1 - ui.draw_scent;
735 if (sym == SDLK_t) ui.draw_path = 1 - ui.draw_path;
736 if (sym == SDLK_f) ui.draw_fog = 1 - ui.draw_fog;
737 if (sym == SDLK_l) ui.draw_overlays = 1 - ui.draw_overlays;
738 if (sym == SDLK_p) ui.draw_pools = 1 - ui.draw_pools;
740 if (sym == SDLK_z) add_reaver();
741 if (sym == SDLK_a) add_peasant();
742 if (sym == SDLK_n) units[ui.unit].tile++;
743 if (sym == SDLK_k) stress_unit(ui.unit,1000);
744 if (sym == SDLK_r) rebuild_pools();
745 if (sym == SDLK_c) collect_pools();
746 //if (sym == SDLK_x) prop_pools();
747 if (sym == SDLK_d) distrib_pools();
748 if (sym == SDLK_e && ui.unit) units[ui.unit].gold += 100;
749 if (sym == SDLK_g) {
750 if (ui.unit != -1) {
751 units[ui.unit].tx = ui.x / 16;
752 units[ui.unit].ty = ui.y / 16;
754 if (ui.house != -1) {
755 houses[ui.house].hp += 20;
757 return;
761 void do_event_cancel() {
762 if (ui.stat != -1) {
763 ui.stat = -1;
764 return;
766 ui.unit = -1;
767 ui.builder = -1;
768 ui.house = -1;
769 ui.stat = -1;
770 ui.btn = -1;
771 return;
774 void do_event(SDL_Event *e) {
776 int tracking_mouse = 0;
778 if (e->type == SDL_FINGERDOWN) {
780 ui.x = (int) (e->tfinger.x * LOG_WIDTH);
781 ui.y = (int) (e->tfinger.x * LOG_HEIGHT);
783 do_event_click(ui.x, ui.y);
785 if (e->type == SDL_MOUSEMOTION && e->motion.which != SDL_TOUCH_MOUSEID) {
786 ui.x = e->motion.x;
787 ui.y = e->motion.y;
789 if (ui.dragging) {
790 ui.vx -= e->motion.xrel;
791 ui.vy -= e->motion.yrel;
793 if (ui.vx < 0) ui.vx = 0;
794 if (ui.vy < 0) ui.vy = 0;
797 tracking_mouse = 1;
798 track_mouse();
800 if ((e->type == SDL_MOUSEBUTTONDOWN || e->type == SDL_MOUSEBUTTONUP) && e->button.which != SDL_TOUCH_MOUSEID) {
801 ui.x = e->button.x;
802 ui.y = e->button.y;
804 tracking_mouse = 1;
805 track_mouse();
807 if (e->type == SDL_KEYDOWN) {
809 do_event_key(e->key.keysym.sym);
812 if (e->type == SDL_MOUSEWHEEL) {
813 if (e->wheel.y > 0) {
814 do_scroll_in();
815 } else if (e->wheel.y < 0) {
816 do_scroll_out();
819 if (e->type == SDL_MOUSEBUTTONDOWN && e->button.which != SDL_TOUCH_MOUSEID) {
820 if (e->button.button == 2) { /* hold middle button */
821 ui.dragging = 1;
823 if (e->button.button == 1) { /* left click (handled on mousedown for smoother UI animations) */
824 do_event_click(ui.x, ui.y);
827 if (e->type == SDL_MOUSEBUTTONUP && e->button.which != SDL_TOUCH_MOUSEID) {
828 if (e->button.button == 2) { /* release middle button */
829 ui.dragging = 0;
831 if (e->button.button == 3) { /* right click */
832 do_event_cancel();
836 /* Mouse moved */
837 if (tracking_mouse) track_mouse();
841 int turns = 0;
842 void do_unit_in_house(unit_t *u, house_t *h) {
844 /* Unloading gold */
845 if (u->gold >= 100 && h->tile == 7) {
846 u->progress++;
847 if (u->progress >= 10) {
848 u->progress = 0;
849 u->gold -= 100;
850 your->gold += 100;
853 else
854 /* Mining inside */
855 if (h->tile == 2 && u->gold < 100) {
856 u->progress++;
857 if (u->progress >= 10) {
858 u->progress = 0;
859 int mined = u->calc_stat[S_STR] * 3;
860 u->gold += mined;
861 u->stat_bid[S_STR] = 1;
864 else
865 /* Seeking shelter? */
866 if (u->dmg) {
869 else
870 /* Leaving */
872 u->visiting = NULL;
873 h->visitors--;
877 void do_unit_hit_unit(unit_t *u, int j) {
878 unit_t *target = &units[j];
880 if (target->faction == u->faction) return;
882 u->mode = ANIM_HIT;
884 stress_unit(j, 2);
887 void do_unit_hit_house(unit_t *u, int k) {
888 house_t *h = &houses[k];
889 /* Attacking ? */
890 if (u->faction != h->faction) {
894 /* Building ? */
895 if (h->built == 0) {
896 u->progress++;
897 if (u->progress >= 10) {
898 u->progress = 0;
899 h->hp++;
901 if (h->hp >= h->max_hp) {
902 h->built = 1;
905 else
906 /* Entering mine */
907 if (h->tile == 2)
909 if (!u->visiting && h->visitors < h->capacity)
911 u->visiting = h;
912 h->visitors++;
915 else
916 /* Mining ? */
917 if (h->tile == 2) {
918 u->progress++;
919 if (u->progress >= 10) {
920 u->progress = 0;
921 u->gold++;
924 else
925 /* Visiting (to unload gold) ? */
926 if (h->tile == 7 && u->gold >= 100) {
927 if (!u->visiting && h->visitors < h->capacity)
929 u->visiting = h;
930 h->visitors++;
933 //printf("%s HITTING HOUSE %s\n", u->name, h->title);
936 void do_unit_walk(unit_t *u) {
938 int next_x = 0;
939 int next_y = 0;
941 if (u->x < u->tx) next_x = + 1;
942 if (u->x > u->tx) next_x = - 1;
943 if (u->y < u->ty) next_y = + 1;
944 if (u->y > u->ty) next_y = - 1;
945 //printf("Walk: %d, %d\n", next_x, next_y);
946 #ifndef ALLOW_DIAGONALS
947 if (next_x && next_y) if (rand() % 2) next_y = 0; else next_x = 0;
948 #endif
949 int k = find_houseT(next_x + u->x, next_y + u->y);
950 if (k != -1) {
951 do_unit_hit_house(u, k);
952 return;
955 int j = find_unitT(next_x + u->x, next_y + u->y);
956 if (j != -1) {
957 do_unit_hit_unit(u, j);
958 return;
961 u->ox = - next_x * TILE_W;
962 u->oy = - next_y * TILE_H;
964 next_x += u->x;
965 next_y += u->y;
967 u->x = next_x;
968 u->y = next_y;
970 u->mode = ANIM_WALK;
971 if (u->gold) {
972 u->mode = ANIM_CARRY;
976 void do_unit_anim(unit_t *u) {
977 unit_p *p = &bunits[u->tile];
979 Uint8 anim = u->mode;
981 if (u->gold) {
982 u->mode = ANIM_CARRY;
984 anim = u->mode;
986 if (u->framecnt >= p->anims[anim]) {
987 u->framecnt = 0;
989 if (p->anim[anim][u->framecnt] < 0) {
990 u->framecnt += p->anim[anim][u->framecnt];
992 if (u->framecnt <= 0) {
993 u->framecnt = 0;
995 //if (u->mode)
997 static const char anim_names[10][80] = {
998 "Idle",
999 "Walk",
1000 "Carry",
1001 "Hit",
1002 "Death",
1003 "Face",
1005 //printf("Mode: %d(%s) Frame counter: %d/%d => %d\n", u->mode, anim_names[u->mode], u->framecnt, p->anims[u->mode], p->anim[u->mode][u->framecnt]);
1006 u->frame = p->anim[u->mode][u->framecnt];
1008 u->framecnt++;
1009 //if (u->mode == 1) u->frame = 1 - u->frame;
1010 //else u->frame = 0;
1013 void do_scroll() {
1014 int step = 8;
1015 if (ui.y >= 480-1) ui.vy += step;
1016 if (ui.y <= 0) ui.vy -= step;
1017 if (ui.x >= 640-1) ui.vx += step;
1018 if (ui.x <= 0) ui.vx -= step;
1019 if (ui.vy > 200) ui.vy = 200;
1020 if (ui.vy < 0) ui.vy = 0;
1021 if (ui.vx < 0) ui.vx = 0;
1024 void do_tick() {
1026 binh_list unit_list = { 0 };
1028 int max_energy = 1000;
1029 int i;
1030 for (i = 0; i < num_units; i++) {
1031 binhl_push(&unit_list, i, 1000 - units[i].energy);
1034 ui.freq++;
1035 if (ui.freq > 1000) ui.freq = 0;
1037 //int i;
1038 int xunits = 0;
1039 //for (i = 0; i < num_units; i++) {
1040 while (unit_list.len) {
1041 xunits++;
1042 i = binhl_pop(&unit_list);
1043 unit_t *u = &units[i];
1044 if (u->energy == 0) break;
1045 if (u->visiting) {
1046 if (u->energy >= 10) {
1047 do_unit_in_house(u, u->visiting);
1049 u->energy -= 10;
1051 continue;
1053 if (u->ox != 0 || u->oy != 0) {
1054 if (u->energy >= 5) {
1055 #ifndef ALLOW_DIAGONALS
1056 if (u->ox) u->ox += (u->ox > 0 ? -1 : 1);
1057 else u->oy += (u->oy > 0 ? -1 : 1);
1058 #else
1059 u->ox += (u->ox > 0 ? -1 : 1);
1060 u->oy += (u->oy > 0 ? -1 : 1);
1061 #endif
1062 u->energy -= 5;
1064 continue;
1066 if (u->x != u->tx || u->y != u->ty) {
1068 if (u->energy >= 10) {
1069 do_unit_walk(u);
1070 u->energy -= 10;
1072 } else u->mode = 0;
1074 update_particles();
1076 if (ui.hover_top == overMap) track_mouse_map();
1079 void do_phase() {
1080 // do_update_links();
1082 int i;
1083 for (i = 0; i < num_units; i++) {
1084 unit_t *u = &units[i];
1086 u->energy += 5;
1087 u->energy += u->calc_stat[S_DEX] * 3;
1088 if (u->energy > (u->calc_stat[S_DEX]+1) * 10) u->energy = (u->calc_stat[S_DEX]+1) * 10;
1090 if (u->dmg) {
1091 if (u->mode != ANIM_DEATH) u->framecnt = 0;
1092 u->mode = ANIM_DEATH;
1093 u->energy = 0;
1094 // continue;
1097 do_unit_anim(u);
1099 calc_fog();
1102 void do_turn() {
1103 int i;
1104 for (i = 0; i < num_units; i++) {
1105 unit_t *u = &units[i];
1106 u->baloon = 0;
1107 unit_pick_strategy(i);
1111 void time_tick() {
1113 static Uint32 wait = 0;
1114 static Uint32 ticks = 0;
1115 static Uint32 phases = 0;
1117 Uint32 tick = SDL_GetTicks();
1118 Uint32 pass = tick - wait;
1120 if (ticks % 2) do_scroll();
1122 if (pass > ui.game_speed) {
1123 wait = tick;
1124 do_tick();
1125 ticks++;
1127 if (ticks >= 10) {
1128 ticks = 0;
1129 do_phase();
1130 phases++;
1132 if (phases >= 10) {
1133 phases = 0;
1134 do_turn();
1135 turns++;
1139 int rune_main(int argc, char* argv[]) {
1140 int weight = 640;
1141 int height = 480;
1143 SDL_Window* window;
1144 SDL_Renderer *screen;
1145 Uint32 fs = 0;//SDL_FULLSCREEN;
1147 /* Init SDL */
1148 if (SDL_Init(SDL_INIT_VIDEO) < 0) {
1149 fprintf(stderr, "SDL initialization failed: %s\n", SDL_GetError());
1150 exit(-1);
1153 /* Create window */
1154 window = SDL_CreateWindow("RuneMen",
1155 //SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
1156 300, 0,
1157 weight * 2, height * 2,
1158 SDL_WINDOW_SHOWN);
1160 if (window == NULL) {
1161 fprintf(stderr, "Window creation failed: %s\n", SDL_GetError());
1162 SDL_Quit();
1163 exit(-1);
1166 /* Create renderer */
1167 screen = SDL_CreateRenderer(window, -1, 0);
1169 if (screen == NULL) {
1170 fprintf(stderr, "Renderer creation failed: %s\n", SDL_GetError());
1171 SDL_DestroyWindow(window);
1172 SDL_Quit();
1173 exit(-1);
1176 /* Scale the window */
1177 SDL_RenderSetLogicalSize(screen, LOG_WIDTH, LOG_HEIGHT);
1179 /* Draw lines, points and rects with alpha blending */
1180 SDL_SetRenderDrawBlendMode(screen, SDL_BLENDMODE_BLEND);
1182 ASS_Init(screen);
1184 inrenderer(screen);
1185 prepare_inline_font();
1187 mainRenderer = screen;
1189 int game_mode = 0;
1191 //int next = mainmenu_loop(screen);
1192 //if (next == -1) goto done;
1193 int loops = 300000;
1195 init_game();
1197 while (loops)
1199 SDL_Event event = { 0 };
1200 while (SDL_PollEvent(&event)) {
1201 if (event.type == SDL_QUIT) loops = 0;
1202 if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE) loops = 0;
1203 do_event(&event);
1206 time_tick();
1208 draw_screen(screen);
1210 ui.fps = count_fps();
1212 SDL_RenderPresent(screen);
1213 SDL_Delay(10);
1215 done:
1216 fprintf(stdout, "Normal termination...\n");
1218 ASS_Quit();
1219 kill_inline_font();
1220 SDL_DestroyRenderer(screen);
1221 SDL_DestroyWindow(window);
1222 SDL_Quit();
1223 return 0;