4 #include "libs/lazyass/lazyass.h"
5 #include "libs/libcsslike/cssdom.h"
13 unit_p bunits
[MAX_BUNITS
];
14 house_p bhouses
[MAX_BHOUSES
];
19 char pseudo_marker
[80];
21 char unit_classes
[MAX_BUNITS
][128];
22 char house_classes
[MAX_BHOUSES
][128];
24 #define TL_OR_PIX(NAM, MULT) \
25 if (NAM ## U[0] == 't' && NAM ## U[1] == 0) NAM = NAM * MULT; \
26 else if (NAM ## U[0] != 'p' || NAM ## U[1] != 'x' || NAM ## U[2] != 0) { \
27 fprintf(stderr, "Unknown unit '%s', please use 't' or 'px'\n", NAM ## U); \
31 void wipe_animation(animation_t
*anim
) {
35 anim
->plane
.x
= anim
->plane
.y
= 0;
36 anim
->plane
.w
= TILE_W
;
37 anim
->plane
.h
= TILE_H
;
41 void compute_houses() {
45 for (i
= 0; i
< MAX_BHOUSES
; i
++) {
47 house_p
*housep
= &bhouses
[i
];
49 housep
->w
= housep
->body
.plane
.w
/ TILE_W
;
50 housep
->h
= housep
->body
.plane
.h
/ TILE_H
;
56 void compute_units() {
60 for (i
= 0; i
< num_bunits
; i
++) {
62 unit_p
*unitp
= &bunits
[i
];
64 unitp
->w
= unitp
->body
.plane
.w
/ TILE_W
;
65 unitp
->h
= unitp
->body
.plane
.h
/ TILE_H
;
67 /* Copy body to face, but replace "frame" ref with "faceframe" ref */
68 memcpy(&unitp
->face
, &unitp
->body
, sizeof(animation_t
));
69 for (j
= 0; j
< MAX_AAXIS
; j
++) {
70 if (unitp
->face
.axis_modifier
[j
] == UAXIS_FRAME
) {
71 unitp
->face
.axis_modifier
[j
] = UAXIS_FACEFRAME
;
79 void rcfg_parse_frames(animation_t
*anim
, Uint8 anim_index
, const char *value
) {
85 strncpy(cut
, value
, sizeof(cut
) - 1);
88 next
= strtok(cut
, ",");
91 //printf("Animation %d, frame %d --> %d\n", anim_index, nf, fr);
92 anim
->frame
[anim_index
][num_frames
] = frame
;
93 next
= strtok(NULL
, ",");
96 anim
->num_frames
[anim_index
] = num_frames
;
99 int rcfg_apply_animation(animation_t
*anim
, const char *name
, const char *value
) {
103 #define _eq(STR) (!strcasecmp(name, STR))
104 #define _veq(STR) (!strcasecmp(value, STR))
105 #define _sveq(STR) (!strcasecmp(subvalue, STR))
109 anim
->image
= ASS_LoadTexture(value
, &white
);
110 printf("Loading image: %s for someone...\n", value
);
114 if (_eq("tile-size")) {
117 if (sscanf(value
, "%d%s %d%s", &a
, aU
, &b
, bU
) == 4) {
118 TL_OR_PIX(a
, TILE_W
);
119 TL_OR_PIX(b
, TILE_H
);
120 } else printf("Tile size must in Nu Nu format (N=number, u=unit(px,t))\n");
123 //printf("Unit %d plane: %d, %d\n", id, unitp->plane.x, unitp->plane.y);
126 if (_eq("tile-plane")) {
128 char aU
[4], bU
[4], cU
[4], dU
[4];
129 //printf("Scanning '%s'\n", value);
130 if (sscanf(value
, "%d%s %d%s %d%s %d%s", &a
, aU
, &b
, bU
, &c
, cU
, &d
, dU
) == 8) {
131 TL_OR_PIX(a
, TILE_W
);
132 TL_OR_PIX(b
, TILE_H
);
133 TL_OR_PIX(c
, TILE_W
);
134 TL_OR_PIX(d
, TILE_H
);
139 } else if (sscanf(value
, "%d%s %d%s", &a
, aU
, &b
, bU
) == 4) {
140 TL_OR_PIX(a
, TILE_W
);
141 TL_OR_PIX(b
, TILE_H
);
146 } else { printf("Tile plane must in Nu Nu or Nu Nu Nu Nu format (N=number, u=unit(px,t))\n"); return -1; }
148 //printf("Unit %d plane: %d, %d\n", 0, anim->plane.x, anim->plane.y);
151 if (_eq("tile-axis")) {
153 char subvalue
[12], aU
[4], bU
[4];//, cU[4], dU[4];
154 if (sscanf(value
, "%s %d%s %d%s %d %d", subvalue
, &a
, aU
, &b
, bU
, &c
, &d
) == 7) {
155 TL_OR_PIX(a
, TILE_W
);
156 TL_OR_PIX(b
, TILE_H
);
157 c
= c
* anim
->plane
.w
;
158 d
= d
* anim
->plane
.h
;
159 //TL_OR_PIX(c, anim->plane.w);
160 //TL_OR_PIX(d, anim->plane.h);
161 } else if (sscanf(value
, "%s %d %d", subvalue
, &c
, &d
) == 3) {
164 c
= c
* anim
->plane
.w
;
165 d
= d
* anim
->plane
.h
;
166 //TL_OR_PIX(c, anim->plane.w);
167 //TL_OR_PIX(d, anim->plane.h);
168 } else { printf("Tile axis must be in S D D or S Nu Nu D D format (D=number, N=number, u=unit(px,t), S=string)\n"); return -1;}
169 //printf("Receiving offset '%s' multX %d multY %d offX %d offY %d\n",subvalue, a,b, c,d);
171 Uint8 anim_name
= 0xFF;
173 if (_sveq("num")) anim_name
= UAXIS_TYPE
;
174 else if (_sveq("frame")) anim_name
= UAXIS_FRAME
;
175 else if (_sveq("mode")) anim_name
= UAXIS_MODE
;
177 if (anim_name
!= 0xFF) {
181 for (i
= 0; i
< anim
->num_axises
; i
++) {
182 if (anim
->axis_modifier
[i
] == anim_name
) {
188 axis_id
= anim
->num_axises
++;
190 taxis
= &anim
->axis_offset
[axis_id
];
195 anim
->axis_modifier
[axis_id
] = anim_name
;
197 else { printf("Please supply hardcoded axis identifier (num, frame)\n"); }
199 else err
= 1; /* Not an animation param */
208 int rcfg_house_count(dom_iter
* this, void* ptr
) {
211 for (i
= 0; i
< MAX_BHOUSES
; i
++) {
212 house_p
*housep
= &bhouses
[i
];
214 wipe_animation(&housep
->body
);
215 //wipe_animation(&housep->face);
218 housep
->body
.image
= ASS_LoadTexture("data/gfx/runelord.bmp", &white
);
222 pseudo_marker
[0] = 0;
227 int rcfg_house_pick(dom_iter
* this, void* ptr
) {
229 house_p
*housep
= ptr
;
231 if (ptr
== bhouses
) {
235 this->next
= (housep
+1);
239 if (this->cursor
++ > num_bhouses
) {
246 char* rcfg_house_test(void *ptr
, const char *name
) {
247 #define _eq(STR) (!strcasecmp(name, STR))
248 house_p
*housep
= (house_p
*)ptr
;
249 int num
= (housep
- bhouses
);
251 if (_eq("type")) return "building";
255 snprintf(buf
, sizeof(buf
), "%d", num
);
264 return house_classes
[num
];
272 int rcfg_house_apply(void *ptr
, const char *name
, const char *value
) {
273 #define _eq(STR) (!strcasecmp(name, STR))
274 #define _veq(STR) (!strcasecmp(value, STR))
275 #define _sveq(STR) (!strcasecmp(subvalue, STR))
277 house_p
*housep
= ptr
;
278 int num
= (housep
- bhouses
);
280 //printf(" Applying value %s = %s for house %d %s (%s)\n", name, value, num, housep->title, housep->id);
283 strncpy(housep
->id
, value
, LEN_HOUSE_ID
);
285 /* If we have a pseudo-mark, auto-apply it to this house's class */
286 if (pseudo_marker
[0]) {
287 char *cc
= house_classes
[num
];
288 strncat(cc
, " ", sizeof(house_classes
[0]));
289 strncat(cc
, pseudo_marker
, sizeof(house_classes
[0]));
295 num_bhouses
= num
+ 1;
296 if (num_bhouses
> MAX_BHOUSES
) num_bhouses
= MAX_HOUSES
;
300 if (_eq("pseudo-mark")) {
301 strncpy(pseudo_marker
, value
, sizeof(pseudo_marker
));
305 char *cc
= house_classes
[num
];
306 strncat(cc
, " ", sizeof(house_classes
[0]));
307 strncat(cc
, value
, sizeof(house_classes
[0]));
311 strncpy(housep
->title
, value
, LEN_HOUSE_TITLE
);
314 if (_eq("icon")) housep
->icon
= atoi(value
);
316 if (_eq("gold")) housep
->gold_cost
= atoi(value
);
318 if (!rcfg_apply_animation(&housep
->body
, name
, value
)) {
322 if (_eq("offset-unbuilt")) {
325 if (sscanf(value
, "%d%s %d%s", &a
, aU
, &b
, bU
) == 4) {
326 if (aU
[0] != 't' || aU
[1] != 0) {printf("The only unit type supported is 't'\n");return -1;}
327 if (bU
[0] != 't' || bU
[1] != 0) {printf("The only unit type supported is 't'\n");return -1;}
328 housep
->unbuilt
.x
= a
* 16;
329 housep
->unbuilt
.y
= b
* 16;
330 } else { printf("Tile size must in `Nu Nu` format (N=number, u=unit(px,t))\n"); }
333 if (_eq("animation-idle")) {
334 rcfg_parse_frames(&housep
->body
, ANIM_BUILT
, value
);
337 if (_eq("animation-building")) {
338 rcfg_parse_frames(&housep
->body
, ANIM_BUILDING
, value
);
341 if (_eq("animation-working")) {
342 rcfg_parse_frames(&housep
->body
, ANIM_WORK
, value
);
345 if (_eq("animation-damaged")) {
346 rcfg_parse_frames(&housep
->body
, ANIM_DAMAGE
, value
);
349 if (_eq("animation-icon")) {
350 rcfg_parse_frames(&housep
->body
, ANIM_ICON
, value
);
352 else { printf(" Ignoring value %s = %s for house %d %s (%s)\n", name
, value
, num
, housep
->title
, housep
->id
); }
360 int rcfg_units_count(dom_iter
* this, void* ptr
) {
363 for (i
= 0; i
< MAX_BUNITS
; i
++) {
364 unit_classes
[i
][0] = 0;
365 unit_p
*unit
= &bunits
[i
];
367 wipe_animation(&unit
->body
);
368 wipe_animation(&unit
->face
);
370 unit
->body
.image
= ASS_LoadTexture("data/gfx/runelord.bmp", &white
);
373 pseudo_marker
[0] = 0;
378 int rcfg_units_pick(dom_iter
* this, void* ptr
) {
386 this->next
= (unitp
+1);
390 if (this->cursor
++ > num_bunits
) {
397 char* rcfg_units_test(void *ptr
, const char *name
) {
398 #define _eq(STR) (!strcasecmp(name, STR))
401 if (_eq("type")) return "unit";
405 sprintf(buf
, "%d", (unitp
-bunits
));
414 return unit_classes
[(unitp
-bunits
)];
417 //printf("Testing.. %s\n", name);
423 int rcfg_units_apply(void *ptr
, const char *name
, const char *value
) {
424 #define _eq(STR) (!strcasecmp(name, STR))
425 #define _veq(STR) (!strcasecmp(value, STR))
426 #define _sveq(STR) (!strcasecmp(subvalue, STR))
429 int num
= (unitp
- bunits
);
432 strncpy(unitp
->id
, value
, LEN_UNIT_ID
);
434 /* If we have a pseudo-mark, auto-apply it to this unit's class */
435 if (pseudo_marker
[0]) {
436 char *cc
= unit_classes
[num
];
437 strncat(cc
, " ", sizeof(unit_classes
[num
]));
438 strncat(cc
, pseudo_marker
, sizeof(unit_classes
[num
]));
444 num_bunits
= num
+ 1;
445 if (num_bunits
> MAX_BUNITS
) num_bunits
= MAX_BUNITS
;
449 if (_eq("pseudo-mark")) {
450 strncpy(pseudo_marker
, value
, sizeof(pseudo_marker
));
455 char *cc
= unit_classes
[num
];
456 strncat(cc
, " ", sizeof(unit_classes
[0]));
457 strncat(cc
, value
, sizeof(unit_classes
[0]));
458 //printf("Attaching class: %s\n", value);
462 strncpy(unitp
->title
, value
, LEN_UNIT_TITLE
);
467 if (sscanf(value
, "%d %d %d %d %d %d", &a
, &b
, &c
, &d
, &e
, &f
) == 6) {
468 unitp
->base_stat
[0] = a
;
469 unitp
->base_stat
[1] = b
;
470 unitp
->base_stat
[2] = c
;
471 unitp
->base_stat
[3] = d
;
472 unitp
->base_stat
[4] = e
;
473 unitp
->base_stat
[5] = f
;
474 } else printf("Stats must be in 1 2 3 4 5 6 format (six space-separated numbers)\n");
477 if (_eq("str")) unitp
->base_stat
[0] = atoi(value
);
479 if (_eq("dex")) unitp
->base_stat
[1] = atoi(value
);
481 if (_eq("con")) unitp
->base_stat
[2] = atoi(value
);
483 if (_eq("int")) unitp
->base_stat
[3] = atoi(value
);
485 if (_eq("met")) unitp
->base_stat
[4] = atoi(value
);
487 if (_eq("chr")) unitp
->base_stat
[5] = atoi(value
);
491 if (sscanf(value
, "%d %d %d %d %d %d", &a
, &b
, &c
, &d
, &e
, &f
) == 6) {
492 unitp
->base_stat
[6] = a
;
493 unitp
->base_stat
[7] = b
;
494 unitp
->base_stat
[8] = c
;
495 unitp
->base_stat
[9] = d
;
496 unitp
->base_stat
[10] = e
;
497 unitp
->base_stat
[11] = f
;
498 } else printf("Skills must be in 1 2 3 4 5 6 format (six space-separated numbers)\n");
501 if (_eq("perception")) {
505 else if (_veq("smell")) {
508 else fprintf(stderr
, "Perception must be 'sight' or 'smell'\n");
512 if (_veq("none")) unitp
->modus
= MODUS_NONE
;
513 else if (_veq("worker")) unitp
->modus
= MODUS_WORKER
;
514 else if (_veq("hunter")) unitp
->modus
= MODUS_HUNTER
;
515 else if (_veq("soldier")) unitp
->modus
= MODUS_SOLDIER
;
516 else if (_veq("healer")) unitp
->modus
= MODUS_HEALER
;
517 else if (_veq("carrier")) unitp
->modus
= MODUS_CARRIER
;
518 else if (_veq("follower")) unitp
->modus
= MODUS_FOLLOWER
;
519 else if (_veq("buffer")) unitp
->modus
= MODUS_BUFFER
;
520 else if (_veq("debuffer")) unitp
->modus
= MODUS_DEBUFFER
;
521 else if (_veq("explorer")) unitp
->modus
= MODUS_EXPLORER
;
522 else fprintf(stderr
, "Unrecognized modus operandi '%s'. See 'ai.h' MODUS_ defines.\n", value
);
525 if (_eq("scent-human")) unitp
->base_scent
[SCENT_HUMAN
] = atoi(value
);
527 if (_eq("scent-animal")) unitp
->base_scent
[SCENT_ANIMAL
] = atoi(value
);
529 if (_eq("scent-magic")) unitp
->base_scent
[SCENT_MAGIC
] = atoi(value
);
531 if (!rcfg_apply_animation(&unitp
->body
, name
, value
)) {
535 if (_eq("animation-idle")) {
536 rcfg_parse_frames(&unitp
->body
, ANIM_IDLE
, value
);
539 if (_eq("animation-walk")) {
540 rcfg_parse_frames(&unitp
->body
, ANIM_WALK
, value
);
543 if (_eq("animation-carry")) {
544 rcfg_parse_frames(&unitp
->body
, ANIM_CARRY
, value
);
547 if (_eq("animation-attack")) {
548 rcfg_parse_frames(&unitp
->body
, ANIM_HIT
, value
);
551 if (_eq("animation-death")) {
552 rcfg_parse_frames(&unitp
->body
, ANIM_DEATH
, value
);
555 if (_eq("animation-face")) {
556 rcfg_parse_frames(&unitp
->body
, ANIM_FACE
, value
);
558 else printf(" Ignoring value %s = %s for unit %d %s (%s)\n", name
, value
, num
, unitp
->title
, unitp
->id
);
565 dom_iter rcfg_units_iterator
= {
582 dom_iter rcfg_house_iterator
= {
599 int cfg_load(const char *filename
) {
605 file
= SDL_RWFromFile(filename
, "rb");
606 if (file
== NULL
) return -1;
608 css_parser
*state
= css_parser_create();
613 n
= SDL_RWread(file
, buf
, sizeof(char), sizeof(buf
));
616 err
= css_parse(state
, buf
, n
);
622 sheet
= css_parser_done(state
);
623 if (sheet
== NULL
) return -1;
625 num_bunits
= MAX_BUNITS
;
626 num_bhouses
= MAX_BHOUSES
;
628 //css_fprintf(stdout, mainCSS);
629 css_cascade(&rcfg_units_iterator
, &bunits
, sheet
);
630 css_cascade(&rcfg_house_iterator
, &bhouses
, sheet
);
632 compute_units(&bunits
, num_bunits
);
633 compute_houses(&bhouses
, num_bhouses
);