1 | %{ |
1 | %{ |
2 | /* |
2 | /* |
3 | * static char *rcsid_object_c = |
3 | * static char *rcsid_object_c = |
4 | * "$Id: loader.l,v 1.18 2006/08/31 17:54:14 root Exp $"; |
4 | * "$Id: loader.l,v 1.19 2006/09/03 00:18:40 root Exp $"; |
5 | */ |
5 | */ |
6 | |
6 | |
7 | /* |
7 | /* |
8 | CrossFire, A Multiplayer game for X-windows |
8 | CrossFire, A Multiplayer game for X-windows |
9 | |
9 | |
… | |
… | |
270 | }; |
270 | }; |
271 | |
271 | |
272 | #define SET_OR_CLEAR_FLAG(op, flag, val) \ |
272 | #define SET_OR_CLEAR_FLAG(op, flag, val) \ |
273 | { if (val) SET_FLAG(op, flag); else CLEAR_FLAG(op, flag); } |
273 | { if (val) SET_FLAG(op, flag); else CLEAR_FLAG(op, flag); } |
274 | |
274 | |
275 | /* SET_RESIST is really only really needed for transition code. We normally |
|
|
276 | * don't care about multiple values overwriting each other, but this is |
|
|
277 | * to catch items that have multiple protection/immune/vulnerable. |
|
|
278 | * This can be simplified later on to just do the set after all the archs |
|
|
279 | * and maps have been updated. |
|
|
280 | * We always keep the last value because otherwise the value from the |
|
|
281 | * arch may take precedence. |
|
|
282 | * Unfortunately, we will report warnings here simply because an object has |
|
|
283 | * been modified from the arch. |
|
|
284 | */ |
|
|
285 | #if 0 /* #if's don't work in #define macros */ |
|
|
286 | #define SET_RESIST(op, type, val) \ |
|
|
287 | {if (op->resist[type]!=0) { \ |
|
|
288 | LOG(llevInfo, "object %s having multiple resistances set, type=%s, old=%d, new=%d\n", \ |
|
|
289 | op->name?op->name:(op->arch?op->arch->name:"unknown"), \ |
|
|
290 | resist_plus[type], op->resist[type], val); \ |
|
|
291 | } op->resist[type] = val; } |
|
|
292 | #else |
|
|
293 | #define SET_RESIST(op, type, val) op->resist[type] = val; |
275 | #define SET_RESIST(op, type, val) op->resist[type] = val; |
294 | #endif |
|
|
295 | |
276 | |
296 | #define IVAL atoi(yval()) |
277 | #define IVAL atoi(yval()) |
297 | #define FVAL atof(yval()) |
278 | #define FVAL atof(yval()) |
298 | extern int arch_init; |
279 | extern int arch_init; |
299 | |
280 | |
… | |
… | |
372 | * also have to catch is if this object is not using the normal name for |
353 | * also have to catch is if this object is not using the normal name for |
373 | * the object. In that case, we also want to use the loaded name. |
354 | * the object. In that case, we also want to use the loaded name. |
374 | * Otherwise, what happens is that the the plural name will lose |
355 | * Otherwise, what happens is that the the plural name will lose |
375 | * information (appear as just 'hearts' and not 'goblins heart') |
356 | * information (appear as just 'hearts' and not 'goblins heart') |
376 | */ |
357 | */ |
377 | if (op->arch && op->name != op->arch->clone.name && op->name_pl == op->arch->clone.name_pl) { |
358 | if (op->arch && op->name != op->arch->clone.name && op->name_pl == op->arch->clone.name_pl) |
378 | if (op->name_pl) free_string(op->name_pl); |
|
|
379 | op->name_pl = NULL; |
359 | op->name_pl = NULL; |
380 | } |
360 | |
381 | if (!op->name_pl) op->name_pl = add_string(op->name); |
361 | if (!op->name_pl) op->name_pl = op->name; |
382 | |
362 | |
383 | /* objects now have a materialname. try to patch it in */ |
363 | /* objects now have a materialname. try to patch it in */ |
384 | if (!(IS_WEAPON(op) && op->level > 0)) { |
364 | if (!(IS_WEAPON(op) && op->level > 0)) { |
385 | if (op->map != NULL) |
365 | if (op->map != NULL) |
386 | set_materialname(op, op->map->difficulty, NULL); |
366 | set_materialname(op, op->map->difficulty, NULL); |
… | |
… | |
396 | if (!op->skill) { |
376 | if (!op->skill) { |
397 | LOG(llevError,"Weapon %s lacks a skill.\n", op_debug_info (op)); |
377 | LOG(llevError,"Weapon %s lacks a skill.\n", op_debug_info (op)); |
398 | } else if ((!strcmp(op->skill,"one handed weapons") && op->body_info[1] != -1) || |
378 | } else if ((!strcmp(op->skill,"one handed weapons") && op->body_info[1] != -1) || |
399 | (!strcmp(op->skill,"two handed weapons") && op->body_info[1] != -2)) { |
379 | (!strcmp(op->skill,"two handed weapons") && op->body_info[1] != -2)) { |
400 | LOG(llevError,"weapon %s arm usage does not match skill: %d, %s\n", |
380 | LOG(llevError,"weapon %s arm usage does not match skill: %d, %s\n", |
401 | op_debug_info (op), op->body_info[1], op->skill); |
381 | op_debug_info (op), op->body_info[1], &op->skill); |
402 | } |
382 | } |
403 | } |
383 | } |
404 | |
384 | |
405 | /* We changed last_heal to gen_sp_armour, which is what it |
385 | /* We changed last_heal to gen_sp_armour, which is what it |
406 | * really does for many objects. Need to catch any in maps |
386 | * really does for many objects. Need to catch any in maps |
… | |
… | |
649 | * about not overflowing the buffer. |
629 | * about not overflowing the buffer. |
650 | */ |
630 | */ |
651 | if (strlen(msgbuf) >= HUGE_BUF) |
631 | if (strlen(msgbuf) >= HUGE_BUF) |
652 | { |
632 | { |
653 | LOG(llevDebug, "\n\tError message length >= %d: %d\n>%.80s<\n", |
633 | LOG(llevDebug, "\n\tError message length >= %d: %d\n>%.80s<\n", |
654 | HUGE_BUF, strlen(op->msg),op->msg); |
634 | HUGE_BUF, strlen(op->msg), &op->msg); |
655 | op->msg = add_string ("ERROR, please report: string too long, winged.\n"); |
635 | op->msg = "ERROR, please report: string too long, winged.\n"; |
656 | } |
636 | } |
657 | else |
637 | else |
658 | op->msg = add_string (msgbuf); |
638 | op->msg = msgbuf; |
659 | } |
639 | } |
660 | <MESSAGE>.* {strcat(msgbuf, yytext); strcat(msgbuf,"\n"); } |
640 | <MESSAGE>.* {strcat(msgbuf, yytext); strcat(msgbuf,"\n"); } |
661 | |
641 | |
662 | ^lore{WS}$ { BEGIN( LORE ); lorebuf[0]='\0'; } |
642 | ^lore{WS}$ { BEGIN( LORE ); lorebuf[0]='\0'; } |
663 | <LORE>^endlore{WS}$ { BEGIN( INITIAL ); |
643 | <LORE>^endlore{WS}$ { BEGIN( INITIAL ); |
664 | op->lore=add_string(lorebuf); |
644 | op->lore=lorebuf; |
665 | /* Just print a warning so we can be reasonably safe |
645 | /* Just print a warning so we can be reasonably safe |
666 | * about not overflowing the buffer. |
646 | * about not overflowing the buffer. |
667 | */ |
647 | */ |
668 | if (strlen(op->lore) > (HUGE_BUF/2)) |
648 | if (strlen(op->lore) > (HUGE_BUF/2)) |
669 | LOG(llevDebug, "\n\tWarning lore length > %d (max allowed=%d): %d\n>%.80s<\n", |
649 | LOG(llevDebug, "\n\tWarning lore length > %d (max allowed=%d): %d\n>%.80s<\n", |
670 | HUGE_BUF/2, HUGE_BUF, strlen(op->lore),op->lore); |
650 | HUGE_BUF/2, HUGE_BUF, strlen(op->lore), &op->lore); |
671 | } |
651 | } |
672 | <LORE>.* {strcat(lorebuf, yytext); strcat(lorebuf,"\n"); } |
652 | <LORE>.* {strcat(lorebuf, yytext); strcat(lorebuf,"\n"); } |
673 | |
653 | |
674 | ^object{S} { char *yv=yval(); |
654 | ^object{S} { char *yv=yval(); |
675 | |
655 | |
… | |
… | |
678 | return LL_IGNORED; |
658 | return LL_IGNORED; |
679 | } |
659 | } |
680 | if (!arch_init) { |
660 | if (!arch_init) { |
681 | LOG(llevError,"Got object info when not in arch_init (%s)?\n", yv); |
661 | LOG(llevError,"Got object info when not in arch_init (%s)?\n", yv); |
682 | } else { |
662 | } else { |
683 | if (op->arch!=NULL) op->arch->name=add_string(yv); |
663 | if (op->arch!=NULL) op->arch->name=yv; |
684 | op->name = add_string(yv); |
664 | op->name = yv; |
685 | } |
665 | } |
686 | } |
666 | } |
687 | |
667 | |
688 | ^name{S} { char *yv=yval(); |
668 | ^name{S} { char *yv=yval(); |
689 | |
669 | |
690 | if (*yv=='\0') LOG(llevError,"Name without val\n"); |
670 | if (*yv=='\0') LOG(llevError,"Name without val\n"); |
691 | else FREE_AND_COPY(op->name, yv); |
671 | else op->name = yv; |
692 | } |
672 | } |
693 | ^name_pl{S} { char *yv=yval(); |
673 | ^name_pl{S} { char *yv=yval(); |
694 | |
674 | |
695 | if (*yv=='\0') LOG(llevError,"Name without val\n"); |
675 | if (*yv=='\0') LOG(llevError,"Name without val\n"); |
696 | else FREE_AND_COPY(op->name_pl, yv); |
676 | else op->name_pl = yv; |
697 | } |
|
|
698 | ^attach{S} { char *yv=yval(); |
|
|
699 | if (*yv) |
677 | } |
700 | op->attach = add_string (yv); |
678 | ^attach{S} op->attach = yval (); |
701 | } |
|
|
702 | ^skill{S} FREE_AND_COPY(op->skill,yval()); |
679 | ^skill{S} op->skill = yval(); |
703 | ^custom_name{S} { char *yv=yval(); |
680 | ^custom_name{S} { char *yv=yval(); |
704 | |
681 | |
705 | if (*yv=='\0') LOG(llevError,"Custom name without val\n"); |
682 | if (*yv=='\0') LOG(llevError,"Custom name without val\n"); |
706 | else FREE_AND_COPY(op->custom_name, yv); |
683 | else op->custom_name = yv; |
707 | } |
684 | } |
708 | ^race{S} FREE_AND_COPY(op->race,yval()); |
685 | ^race{S} op->race = yval(); |
709 | ^slaying{S} FREE_AND_COPY(op->slaying, yval()); |
686 | ^slaying{S} op->slaying = yval(); |
710 | ^inventory.*$ LOG(llevError,"Got depreciated Inventory command?\n"); |
687 | ^inventory.*$ LOG(llevError,"Got depreciated Inventory command?\n"); |
711 | |
688 | |
712 | |
689 | |
713 | ^arch{S} { /* If op->arch has been set, then this new object |
690 | ^arch{S} { /* If op->arch has been set, then this new object |
714 | * must be part of the inventory. So process |
691 | * must be part of the inventory. So process |
… | |
… | |
721 | archetype *arch = find_archetype(yv); |
698 | archetype *arch = find_archetype(yv); |
722 | if (arch!=NULL) |
699 | if (arch!=NULL) |
723 | tmp = arch_to_object (arch); |
700 | tmp = arch_to_object (arch); |
724 | else { |
701 | else { |
725 | tmp = get_object (); |
702 | tmp = get_object (); |
726 | if (tmp->name) free_string(tmp->name); |
|
|
727 | /* record the name of the broken object */ |
703 | /* record the name of the broken object */ |
728 | tmp->name = add_string(yv); |
704 | tmp->name = yv; |
729 | } |
705 | } |
730 | strcpy(msgbuf, ""); |
706 | strcpy(msgbuf, ""); |
731 | strcpy(lorebuf, ""); |
707 | strcpy(lorebuf, ""); |
732 | lex_load(tmp, thawer, map_flags); |
708 | lex_load(tmp, thawer, map_flags); |
733 | if (tmp->arch) { |
709 | if (tmp->arch) { |
… | |
… | |
744 | |
720 | |
745 | op->arch=find_archetype(yv); |
721 | op->arch=find_archetype(yv); |
746 | if (op->arch!=NULL) { |
722 | if (op->arch!=NULL) { |
747 | copy_object(&op->arch->clone,op); |
723 | copy_object(&op->arch->clone,op); |
748 | } else if (!arch_init) { |
724 | } else if (!arch_init) { |
749 | if (op->name) free_string(op->name); |
|
|
750 | /* record the name of the broken object */ |
725 | /* record the name of the broken object */ |
751 | op->name = add_string(yv); |
726 | op->name = yv; |
752 | } |
727 | } |
753 | } |
728 | } |
754 | } |
729 | } |
755 | |
730 | |
756 | ^other_arch{S} op->other_arch=find_archetype(yval()); |
731 | ^other_arch{S} op->other_arch=find_archetype(yval()); |
… | |
… | |
794 | ^slow_move{S} { op->move_slow |= MOVE_WALK; |
769 | ^slow_move{S} { op->move_slow |= MOVE_WALK; |
795 | op->move_slow_penalty = FVAL; |
770 | op->move_slow_penalty = FVAL; |
796 | } |
771 | } |
797 | ^title{S} { char *y=yval(); |
772 | ^title{S} { char *y=yval(); |
798 | if (*y=='\0') LOG(llevError,"Title without value.\n"); |
773 | if (*y=='\0') LOG(llevError,"Title without value.\n"); |
799 | else FREE_AND_COPY(op->title, y); |
774 | else op->title = y; |
800 | } |
775 | } |
801 | |
776 | |
802 | ^face{S} op->face = &new_faces[FindFace(yval(), 0)]; |
777 | ^face{S} op->face = &new_faces[FindFace(yval(), 0)]; |
803 | ^str{S} op->stats.Str = IVAL; |
778 | ^str{S} op->stats.Str = IVAL; |
804 | ^dex{S} op->stats.Dex = IVAL; |
779 | ^dex{S} op->stats.Dex = IVAL; |
… | |
… | |
829 | ^material{S} op->material = IVAL; |
804 | ^material{S} op->material = IVAL; |
830 | ^materialname{S} { char *yv=yval(); |
805 | ^materialname{S} { char *yv=yval(); |
831 | if (*yv=='\0') |
806 | if (*yv=='\0') |
832 | LOG(llevError,"Materialname without val\n"); |
807 | LOG(llevError,"Materialname without val\n"); |
833 | else |
808 | else |
834 | FREE_AND_COPY(op->materialname, yv); |
809 | op->materialname = yv; |
835 | } |
810 | } |
836 | |
811 | |
837 | ^value{S} op->value = IVAL; |
812 | ^value{S} op->value = IVAL; |
838 | ^weight{S} op->weight = atol(yval()); |
813 | ^weight{S} op->weight = atol(yval()); |
839 | ^carrying{S} op->carrying = atol(yval()); |
814 | ^carrying{S} op->carrying = atol(yval()); |
… | |
… | |
1272 | if (all_count <=1) return retbuf_all+1; |
1247 | if (all_count <=1) return retbuf_all+1; |
1273 | else return retbuf+1; |
1248 | else return retbuf+1; |
1274 | } |
1249 | } |
1275 | |
1250 | |
1276 | |
1251 | |
1277 | /* |
|
|
1278 | * Returns a pointer to a static string which contains all variables |
|
|
1279 | * which are different in the two given objects. op is the what object |
|
|
1280 | * the different values will be taken from. This function is |
|
|
1281 | * typically used to dump objects (op2=empty object), or to save objects |
|
|
1282 | * (op2 is the objects original archetype) |
|
|
1283 | * Note by MSW 2003-09-22: It's a bug that we need to pass entrysize - |
|
|
1284 | * we should use strlen entryname instead. Any smart compiler should |
|
|
1285 | * optimize that out. |
|
|
1286 | */ |
|
|
1287 | |
|
|
1288 | |
|
|
1289 | #define ADD_STRINGLINE_ENTRY(buf__,entryname__,entryvalue__,entrysize__){\ |
|
|
1290 | FAST_STRNCAT(buf__,entryname__,entrysize__);\ |
|
|
1291 | FAST_STRCAT(buf__,entryvalue__);\ |
|
|
1292 | FAST_STRNCAT(buf__,"\n",1);} |
|
|
1293 | #define FAST_SAVE_LONG(buf__,entryname__,entryvalue__,entrysize__) \ |
|
|
1294 | ADD_STRINGLINE_ENTRY(buf__,entryname__,ltostr10(entryvalue__),entrysize__) |
|
|
1295 | #define FAST_SAVE_DOUBLE(buf__,entryname__,entryvalue__,entrysize__) \ |
|
|
1296 | ADD_STRINGLINE_ENTRY(buf__,entryname__,doubletostr10(entryvalue__),entrysize__) |
|
|
1297 | |
|
|
1298 | |
|
|
1299 | |
|
|
1300 | // compare *op against *tmp and output differences |
1252 | // compare *op against *tmp and output differences |
1301 | void |
1253 | void |
1302 | put (object_freezer &f, object *op, object *tmp) |
1254 | put (object_freezer &f, object *op, object *tmp) |
1303 | { |
1255 | { |
1304 | int i; |
1256 | int i; |
… | |
… | |
1511 | |
1463 | |
1512 | fp.put (op); |
1464 | fp.put (op); |
1513 | fprintf (fp, "end\n"); |
1465 | fprintf (fp, "end\n"); |
1514 | } |
1466 | } |
1515 | |
1467 | |
1516 | event * |
|
|
1517 | find_event (object *op, int etype) |
|
|
1518 | { |
|
|
1519 | for (event *found = op->events; found != NULL; found = found->next) |
|
|
1520 | if (found->type == etype) |
|
|
1521 | return found; |
|
|
1522 | |
|
|
1523 | return NULL; |
|
|
1524 | } |
|
|