00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00037 #include <global.h>
00038 #include <living.h>
00039 #include <spells.h>
00040 #include <skills.h>
00041 #include <tod.h>
00042 #include <sproto.h>
00043
00057 static int can_build_over(struct mapdef *map, object *new_item, short x, short y) {
00058 object *ob;
00059
00060 for (ob = GET_MAP_OB(map, x, y); ob; ob = ob->above) {
00061 if (strcmp(ob->arch->name, "rune_mark") == 0)
00062
00063 continue;
00064
00065 if ((ob->head && QUERY_FLAG(ob->head, FLAG_IS_BUILDABLE)) || (!ob->head && QUERY_FLAG(ob, FLAG_IS_BUILDABLE)))
00066
00067
00068
00069 continue;
00070
00071 switch (new_item->type) {
00072 case SIGN:
00073 case MAGIC_EAR:
00074
00075 if (ob->type != BOOK)
00076 return 0;
00077 break;
00078
00079 case BUTTON:
00080 case DETECTOR:
00081 case PEDESTAL:
00082 case CF_HANDLE:
00083
00084 if (ob->type != GATE && ob->type != DOOR)
00085 return 0;
00086 break;
00087
00088 default:
00089 return 0;
00090 }
00091 }
00092
00093
00094 if (new_item->more)
00095 return can_build_over(map, new_item->more, x+new_item->more->arch->clone.x-new_item->arch->clone.x, y+new_item->more->arch->clone.y-new_item->arch->clone.y);
00096
00097 return 1;
00098 }
00099
00111 static object *get_connection_rune(object *pl, short x, short y) {
00112 object *rune;
00113
00114 rune = GET_MAP_OB(pl->map, x, y);
00115 while (rune && ((rune->type != SIGN) || (strcmp(rune->arch->name, "rune_mark"))))
00116 rune = rune->above;
00117 return rune;
00118 }
00119
00131 static object *get_msg_book(object *pl, short x, short y) {
00132 object *book;
00133
00134 book = GET_MAP_OB(pl->map, x, y);
00135 while (book && (book->type != BOOK))
00136 book = book->above;
00137 return book;
00138 }
00139
00152 static object *get_wall(struct mapdef *map, int x, int y) {
00153 object *wall;
00154
00155 wall = GET_MAP_OB(map, x, y);
00156 while (wall && (wall->type != WALL))
00157 wall = wall->above;
00158
00159 return wall;
00160 }
00161
00170 static void remove_marking_runes(struct mapdef *map, short x, short y) {
00171 object *rune;
00172 object *next;
00173
00174 rune = GET_MAP_OB(map, x, y);
00175 while (rune) {
00176 next = rune->above;
00177 if ((rune->type == SIGN) && (!strcmp(rune->arch->name, "rune_mark"))) {
00178 remove_ob(rune);
00179 free_object(rune);
00180 }
00181 rune = next;
00182 }
00183 }
00184
00202 static int adjust_sign_msg(object *pl, short x, short y, object *tmp) {
00203 object *book;
00204 char buf[MAX_BUF];
00205 char buf2[MAX_BUF];
00206
00207 book = get_msg_book(pl, x, y);
00208 if (!book) {
00209 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
00210 "You need to put a book or scroll with the message.", NULL);
00211 return -1;
00212 }
00213
00214 tmp->msg = book->msg;
00215 add_refcount(tmp->msg);
00216
00217 if (tmp->invisible) {
00218 if (book->custom_name != NULL) {
00219 snprintf(buf, sizeof(buf), "talking %s", book->custom_name);
00220 } else {
00221 snprintf(buf, sizeof(buf), "talking %s", book->name);
00222 }
00223 if (tmp->name)
00224 free_string(tmp->name);
00225 tmp->name = add_string(buf);
00226
00227 if (book->name_pl != NULL) {
00228 snprintf(buf2, sizeof(buf2), "talking %s", book->name_pl);
00229 if (tmp->name_pl)
00230 free_string(tmp->name_pl);
00231 tmp->name_pl = add_string(buf2);
00232 }
00233
00234 tmp->face = book->face;
00235 tmp->invisible = 0;
00236 }
00237 remove_ob(book);
00238 free_object(book);
00239 return 0;
00240 }
00241
00252 static int find_unused_connected_value(struct mapdef *map) {
00253 int connected = 0;
00254 int itest = 0;
00255 oblinkpt *obp;
00256
00257 while (itest++ < 1000) {
00258 connected = 1+rand()%20000;
00259 for (obp = map->buttons; obp && (obp->value != connected); obp = obp->next)
00260 ;
00261
00262 if (!obp)
00263 return connected;
00264 }
00265
00266 return -1;
00267 }
00268
00269
00290 static int find_or_create_connection_for_map(object *pl, short x, short y, object *rune) {
00291 object *force;
00292 int connected;
00293
00294 if (!rune)
00295 rune = get_connection_rune(pl, x, y);
00296
00297 if (!rune || !rune->msg) {
00298 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
00299 "You need to put a marking rune with the group name.", NULL);
00300 return -1;
00301 }
00302
00303
00304 force = pl->inv;
00305 while (force && ((force->type != FORCE) || (!force->slaying) || (strcmp(force->slaying, pl->map->path)) || (!force->msg) || (strcmp(force->msg, rune->msg))))
00306 force = force->below;
00307
00308 if (!force) {
00309
00310
00311 connected = find_unused_connected_value(pl->map);
00312 if (connected == -1) {
00313 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
00314 "Could not create more groups.", NULL);
00315 return -1;
00316 }
00317
00318 force = create_archetype(FORCE_NAME);
00319 force->speed = 0;
00320 update_ob_speed(force);
00321 force->slaying = add_string(pl->map->path);
00322 force->msg = add_string(rune->msg);
00323 force->path_attuned = connected;
00324 insert_ob_in_ob(force, pl);
00325
00326 return connected;
00327 }
00328
00329
00330 return force->path_attuned;
00331 }
00332
00348 static void fix_walls(struct mapdef *map, int x, int y) {
00349 int connect;
00350 object *wall;
00351 char archetype[MAX_BUF];
00352 char *underscore;
00353 uint32 old_flags[4];
00354 struct archt *new_arch;
00355 int flag;
00356 int len;
00357 int has_window;
00358
00359
00360 wall = get_wall(map, x, y);
00361 if (!wall)
00362
00363 return;
00364
00365
00366 strncpy(archetype, wall->arch->name, sizeof(archetype));
00367 archetype[sizeof(archetype)-1] = '\0';
00368 underscore = strchr(archetype, '_');
00369 if (!underscore)
00370
00371 return;
00372 has_window = 0;
00373 if (!strcmp(underscore+1, "win1"))
00374 has_window = 1;
00375 else if (!strcmp(underscore+1, "win2"))
00376 has_window = 1;
00377 else if (!isdigit(*(underscore+1)))
00378 return;
00379
00380 underscore++;
00381 *underscore = '\0';
00382 len = sizeof(archetype)-strlen(archetype)-2;
00383
00384 connect = 0;
00385
00386 if ((x > 0) && get_wall(map, x-1, y))
00387 connect |= 1;
00388 if ((x < MAP_WIDTH(map)-1) && get_wall(map, x+1, y))
00389 connect |= 2;
00390 if ((y > 0) && get_wall(map, x, y-1))
00391 connect |= 4;
00392 if ((y < MAP_HEIGHT(map)-1) && get_wall(map, x, y+1))
00393 connect |= 8;
00394
00395 switch (connect) {
00396 case 0:
00397 strncat(archetype, "0", len);
00398 break;
00399
00400 case 1:
00401 strncat(archetype, "1_3", len);
00402 break;
00403
00404 case 2:
00405 strncat(archetype, "1_4", len);
00406 break;
00407
00408 case 3:
00409 if (has_window) {
00410 strncat(archetype, "win2", len);
00411 } else {
00412 strncat(archetype, "2_1_2", len);
00413 }
00414 break;
00415
00416 case 4:
00417 strncat(archetype, "1_2", len);
00418 break;
00419
00420 case 5:
00421 strncat(archetype, "2_2_4", len);
00422 break;
00423
00424 case 6:
00425 strncat(archetype, "2_2_1", len);
00426 break;
00427
00428 case 7:
00429 strncat(archetype, "3_1", len);
00430 break;
00431
00432 case 8:
00433 strncat(archetype, "1_1", len);
00434 break;
00435
00436 case 9:
00437 strncat(archetype, "2_2_3", len);
00438 break;
00439
00440 case 10:
00441 strncat(archetype, "2_2_2", len);
00442 break;
00443
00444 case 11:
00445 strncat(archetype, "3_3", len);
00446 break;
00447
00448 case 12:
00449 if (has_window) {
00450 strncat(archetype, "win1", len);
00451 } else {
00452 strncat(archetype, "2_1_1", len);
00453 }
00454 break;
00455
00456 case 13:
00457 strncat(archetype, "3_4", len);
00458 break;
00459
00460 case 14:
00461 strncat(archetype, "3_2", len);
00462 break;
00463
00464 case 15:
00465 strncat(archetype, "4", len);
00466 break;
00467 }
00468
00469
00470
00471
00472 if (!strncmp(archetype, wall->arch->name, sizeof(archetype)))
00473 return;
00474
00475
00476
00477
00478
00479 new_arch = find_archetype(archetype);
00480 if (!new_arch)
00481 return;
00482
00483
00484
00485
00486 for (flag = 0; flag < 4; flag++)
00487 old_flags[flag] = wall->flags[flag];
00488 remove_ob(wall);
00489 free_object(wall);
00490
00491 wall = arch_to_object(new_arch);
00492 wall->type = WALL;
00493 insert_ob_in_map_at(wall, map, NULL, INS_ABOVE_FLOOR_ONLY, x, y);
00494 for (flag = 0; flag < 4; flag++)
00495 wall->flags[flag] = old_flags[flag];
00496 }
00497
00519 static int apply_builder_floor(object *pl, object *new_floor, short x, short y) {
00520 object *tmp;
00521 object *above_floor;
00522 object *floor;
00523 struct archt *new_wall;
00524 int i, xt, yt, wall_removed;
00525 char message[MAX_BUF];
00526
00527 snprintf(message, sizeof(message), "You change the floor to better suit your tastes.");
00528
00529
00530
00531
00532
00533 above_floor = NULL;
00534 floor = NULL;
00535 new_wall = NULL;
00536 wall_removed = 0;
00537 tmp = GET_MAP_OB(pl->map, x, y);
00538 while (tmp) {
00539 object *above;
00540
00541 above = tmp->above;
00542 if (WALL == tmp->type) {
00543
00544 new_wall = tmp->arch;
00545 remove_ob(tmp);
00546 free_object(tmp);
00547 snprintf(message, sizeof(message), "You destroy the wall and redo the floor.");
00548 wall_removed = 1;
00549 if (floor != NULL) {
00550 remove_ob(floor);
00551 free_object(floor);
00552 floor = NULL;
00553 }
00554 } else if ((FLOOR == tmp->type) || (QUERY_FLAG(tmp, FLAG_IS_FLOOR))) {
00555 floor = tmp;
00556 } else {
00557 if (floor != NULL)
00558 above_floor = tmp;
00559 }
00560
00561 tmp = above;
00562 }
00563
00564 if (wall_removed == 0 && floor != NULL) {
00565 if (floor->arch == new_floor->arch) {
00566 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD, "You feel too lazy to redo the exact same floor.", NULL);
00567 free_object(new_floor);
00568 return 0;
00569 }
00570 }
00571
00572 SET_FLAG(new_floor, FLAG_UNIQUE);
00573 SET_FLAG(new_floor, FLAG_IS_FLOOR);
00574 new_floor->type = FLOOR;
00575 insert_ob_in_map_at(new_floor, pl->map, above_floor, above_floor ? INS_BELOW_ORIGINATOR : INS_ON_TOP, x, y);
00576
00577
00578 if (floor) {
00579 remove_ob(floor);
00580 free_object(floor);
00581 floor = NULL;
00582 }
00583
00584
00585
00586
00587
00588 for (i = 1; i <= 8; i++) {
00589 xt = x+freearr_x[i];
00590 yt = y+freearr_y[i];
00591 tmp = GET_MAP_OB(pl->map, xt, yt);
00592 if (!tmp) {
00593
00594
00595 tmp = arch_to_object(new_floor->arch);
00596
00597 SET_FLAG(tmp, FLAG_UNIQUE);
00598 SET_FLAG(tmp, FLAG_IS_BUILDABLE);
00599 tmp->type = FLOOR;
00600 insert_ob_in_map_at(tmp, pl->map, NULL, 0, xt, yt);
00601
00602 if (new_wall) {
00603 tmp = arch_to_object(new_wall);
00604 SET_FLAG(tmp, FLAG_IS_BUILDABLE);
00605 tmp->type = WALL;
00606 insert_ob_in_map_at(tmp, pl->map, NULL, 0, xt, yt);
00607 }
00608 }
00609 }
00610
00611
00612
00613
00614
00615
00616 for (xt = x-2; xt <= x+2; xt++)
00617 for (yt = y-2; yt <= y+2; yt++) {
00618 if (!OUT_OF_REAL_MAP(pl->map, xt, yt))
00619 fix_walls(pl->map, xt, yt);
00620 }
00621
00622
00623 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD, message, NULL);
00624 return 1;
00625 }
00626
00644 static int apply_builder_wall(object *pl, object *new_wall, short x, short y) {
00645 object *current_wall;
00646 char message[MAX_BUF];
00647
00648 remove_marking_runes(pl->map, x, y);
00649
00650 current_wall = get_wall(pl->map, x, y);
00651
00652 if (current_wall) {
00653 char current_basename[MAX_BUF];
00654 char new_basename[MAX_BUF];
00655 char *underscore;
00656
00657
00658 strncpy(current_basename, current_wall->arch->name, sizeof(current_basename));
00659 current_basename[sizeof(current_basename)-1] = '\0';
00660 underscore = strchr(current_basename, '_');
00661 if (underscore && isdigit(*(underscore+1))) {
00662 underscore++;
00663 *underscore = '\0';
00664 }
00665 strncpy(new_basename, new_wall->arch->name, sizeof(new_basename));
00666 new_basename[sizeof(new_basename)-1] = '\0';
00667 underscore = strchr(new_basename, '_');
00668 if (underscore && isdigit(*(underscore+1))) {
00669 underscore++;
00670 *underscore = '\0';
00671 }
00672 if (!strncmp(current_basename, new_basename, sizeof(new_basename))) {
00673 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD, "You feel too lazy to redo the exact same wall.", NULL);
00674 free_object(new_wall);
00675 return 0;
00676 }
00677 }
00678
00679 snprintf(message, sizeof(message), "You build a wall.");
00680 new_wall->type = WALL;
00681
00682 if (current_wall) {
00683
00684 remove_ob(current_wall);
00685 free_object(current_wall);
00686 insert_ob_in_map_at(new_wall, pl->map, NULL, INS_ABOVE_FLOOR_ONLY, x, y);
00687 fix_walls(pl->map, x, y);
00688 snprintf(message, sizeof(message), "You redecorate the wall to better suit your tastes.");
00689 } else {
00690 int xt, yt;
00691
00692
00693 insert_ob_in_map_at(new_wall, pl->map, NULL, INS_ABOVE_FLOOR_ONLY, x, y);
00694 for (xt = x-1; xt <= x+1; xt++)
00695 for (yt = y-1; yt <= y+1; yt++) {
00696 if (OUT_OF_REAL_MAP(pl->map, xt, yt))
00697 continue;
00698
00699 fix_walls(pl->map, xt, yt);
00700 }
00701 }
00702
00703
00704 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD, message, NULL);
00705 return 1;
00706 }
00707
00724 static int apply_builder_window(object *pl, object *new_wall_win, short x, short y) {
00725 object *current_wall;
00726 char archetype[MAX_BUF];
00727 struct archt *new_arch;
00728 object *window;
00729 uint32 old_flags[4];
00730 int flag;
00731
00732
00733 free_object(new_wall_win);
00734
00735 current_wall = get_wall(pl->map, x, y);
00736
00737 if (current_wall) {
00738 char *underscore;
00739
00740 strncpy(archetype, current_wall->arch->name, sizeof(archetype));
00741 archetype[sizeof(archetype)-1] = '\0';
00742 underscore = strchr(archetype, '_');
00743 if (underscore) {
00744 underscore++;
00745
00746 if (!strcmp(underscore, "win1")
00747 || !strcmp(underscore, "win2")) {
00748 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD, "You feel too lazy to redo the window.", NULL);
00749 return 0;
00750 }
00751 if (!strcmp(underscore, "2_1_1"))
00752 strcpy(underscore, "win1");
00753 else if (!strcmp(underscore, "2_1_2"))
00754 strcpy(underscore, "win2");
00755 else {
00756
00757 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD, "You cannot build a window in that wall.", NULL);
00758 return 0;
00759 }
00760 }
00761 } else {
00762 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
00763 "There is no wall there.", NULL);
00764 return 0;
00765 }
00766
00767 new_arch = find_archetype(archetype);
00768 if (!new_arch) {
00769
00770 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD, "You cannot build a window in that wall.", NULL);
00771 return 0;
00772 }
00773
00774
00775
00776
00777 for (flag = 0; flag < 4; flag++)
00778 old_flags[flag] = current_wall->flags[flag];
00779 remove_ob(current_wall);
00780 free_object(current_wall);
00781
00782 window = arch_to_object(new_arch);
00783 window->type = WALL;
00784 insert_ob_in_map_at(window, pl->map, NULL, INS_ABOVE_FLOOR_ONLY, x, y);
00785 for (flag = 0; flag < 4; flag++)
00786 window->flags[flag] = old_flags[flag];
00787
00788
00789 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD, "You build a window in the wall.", NULL);
00790 return 1;
00791 }
00792
00814 static int apply_builder_item(object *pl, object *new_item, short x, short y) {
00815 int insert_flag;
00816 object *floor;
00817 object *con_rune;
00818 int connected;
00819 char name[MAX_BUF];
00820
00821
00822 floor = GET_MAP_OB(pl->map, x, y);
00823 if (!floor) {
00824 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD, "Invalid square.", NULL);
00825 free_object(new_item);
00826 return 0;
00827 }
00828
00829 while (floor && (floor->type != FLOOR) && (!QUERY_FLAG(floor, FLAG_IS_FLOOR)))
00830 floor = floor->above;
00831
00832 if (!floor) {
00833 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
00834 "This square has no floor, you can't build here.", NULL);
00835 free_object(new_item);
00836 return 0;
00837 }
00838
00839 SET_FLAG(new_item, FLAG_NO_PICK);
00840
00841
00842
00843
00844
00845 insert_flag = INS_ABOVE_FLOOR_ONLY;
00846
00847 connected = 0;
00848 con_rune = NULL;
00849 switch (new_item->type) {
00850 case DOOR:
00851 case GATE:
00852 case BUTTON:
00853 case DETECTOR:
00854 case TIMED_GATE:
00855 case PEDESTAL:
00856 case CF_HANDLE:
00857 case MAGIC_EAR:
00858 case SIGN:
00859
00860 if (new_item->type == SIGN && strcmp(new_item->arch->name, "magic_mouth"))
00861 break;
00862 con_rune = get_connection_rune(pl, x, y);
00863 connected = find_or_create_connection_for_map(pl, x, y, con_rune);
00864 if (connected == -1) {
00865
00866 free_object(new_item);
00867 return 0;
00868 }
00869 }
00870
00871
00872 if ((new_item->type == SIGN) || (new_item->type == MAGIC_EAR)) {
00873 if (adjust_sign_msg(pl, x, y, new_item) == -1) {
00874 free_object(new_item);
00875 return 0;
00876 }
00877 }
00878
00879 if (con_rune != NULL) {
00880
00881 remove_ob(con_rune);
00882 free_object(con_rune);
00883 }
00884
00885 insert_ob_in_map_at(new_item, pl->map, floor, insert_flag, x, y);
00886 if (connected != 0)
00887 add_button_link(new_item, pl->map, connected);
00888
00889 query_name(new_item, name, MAX_BUF);
00890 draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
00891 "You build the %s",
00892 "You build the %s",
00893 name);
00894 return 1;
00895 }
00896
00907 void apply_builder_remove(object *pl, int dir) {
00908 object *item;
00909 short x, y;
00910 char name[MAX_BUF];
00911
00912 x = pl->x+freearr_x[dir];
00913 y = pl->y+freearr_y[dir];
00914
00915
00916 item = GET_MAP_OB(pl->map, x, y);
00917 if (!item) {
00918
00919 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
00920 "Invalid square.", NULL);
00921 LOG(llevError, "apply_builder_remove: (null) square at (%d, %d, %s)\n", x, y, pl->map->path);
00922 return;
00923 }
00924
00925 if (item->type == FLOOR || QUERY_FLAG(item, FLAG_IS_FLOOR))
00926 item = item->above;
00927
00928 if (!item) {
00929 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
00930 "Nothing to remove.", NULL);
00931 return;
00932 }
00933
00934
00935 switch (item->type) {
00936 case WALL:
00937 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
00938 "Can't remove a wall with that, build a floor.", NULL);
00939 return;
00940
00941 case DOOR:
00942 case BUTTON:
00943 case GATE:
00944 case TIMED_GATE:
00945 case DETECTOR:
00946 case PEDESTAL:
00947 case CF_HANDLE:
00948 case MAGIC_EAR:
00949 case SIGN:
00950
00951 if (QUERY_FLAG(item, FLAG_IS_LINKED))
00952 remove_button_link(item);
00953
00954
00955 default:
00956
00957 query_name(item, name, MAX_BUF);
00958 draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
00959 "You remove the %s",
00960 "You remove the %s",
00961 name);
00962 remove_ob(item);
00963 free_object(item);
00964 }
00965 }
00966
00978 void apply_map_builder(object *pl, int dir) {
00979 object *builder;
00980 object *tmp;
00981 short x, y;
00982
00983 if (!pl->type == PLAYER)
00984 return;
00985
00986 if (dir == 0) {
00987 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
00988 "You can't build or destroy under yourself.", NULL);
00989 return;
00990 }
00991
00992 x = pl->x+freearr_x[dir];
00993 y = pl->y+freearr_y[dir];
00994
00995 if ((1 > x) || (1 > y)
00996 || ((MAP_WIDTH(pl->map)-2) < x) || ((MAP_HEIGHT(pl->map)-2) < y)) {
00997 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
00998 "Can't build on map edge.", NULL);
00999 return;
01000 }
01001
01002
01003
01004
01005
01006
01007
01008
01009 tmp = GET_MAP_OB(pl->map, x, y);
01010 if (!tmp) {
01011
01012 LOG(llevError, "apply_map_builder: undefined square at (%d, %d, %s)\n", x, y, pl->map->path);
01013 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
01014 "You'd better not build here, it looks weird.", NULL);
01015 return;
01016 }
01017
01018 builder = pl->contr->ranges[range_builder];
01019
01020 if (builder->subtype != ST_BD_BUILD) {
01021 while (tmp) {
01022 if (!QUERY_FLAG(tmp, FLAG_IS_BUILDABLE)
01023 && ((tmp->type != SIGN) || (strcmp(tmp->arch->name, "rune_mark")))) {
01024 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
01025 "You can't build here.", NULL);
01026 return;
01027 }
01028 tmp = tmp->above;
01029 }
01030 }
01031
01032
01033
01034 if (builder->subtype == ST_BD_REMOVE) {
01035
01036 apply_builder_remove(pl, dir);
01037 return;
01038 }
01039
01040 if (builder->subtype == ST_BD_BUILD) {
01041 object *material;
01042 struct archt *new_arch;
01043 object *new_item;
01044 int built = 0;
01045
01046
01047
01048 material = find_marked_object(pl);
01049 if (!material) {
01050 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
01051 "You need to mark raw materials to use.", NULL);
01052 return;
01053 }
01054
01055 if (material->type != MATERIAL) {
01056 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
01057 "You can't use the marked item to build.", NULL);
01058 return;
01059 }
01060
01061
01062 new_arch = find_archetype(material->slaying);
01063 if (!new_arch) {
01064 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
01065 "You can't use this strange material.", NULL);
01066 LOG(llevError, "apply_map_builder: unable to find archetype %s\n", material->slaying);
01067 return;
01068 }
01069 new_item = object_create_arch(new_arch);
01070 SET_FLAG(new_item, FLAG_IS_BUILDABLE);
01071
01072 if (!can_build_over(pl->map, new_item, x, y)) {
01073 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
01074 "You can't build here.", NULL);
01075 return;
01076 }
01077
01078
01079 switch (material->subtype) {
01080 case ST_MAT_FLOOR:
01081 built = apply_builder_floor(pl, new_item, x, y);
01082 break;
01083
01084 case ST_MAT_WALL:
01085 built = apply_builder_wall(pl, new_item, x, y);
01086 break;
01087
01088 case ST_MAT_ITEM:
01089 built = apply_builder_item(pl, new_item, x, y);
01090 break;
01091
01092 case ST_MAT_WINDOW:
01093 built = apply_builder_window(pl, new_item, x, y);
01094 break;
01095
01096 default:
01097 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
01098 "Don't know how to apply this material, sorry.", NULL);
01099 LOG(llevError, "apply_map_builder: invalid material subtype %d\n", material->subtype);
01100 break;
01101 }
01102 if (built)
01103 decrease_ob(material);
01104 return;
01105 }
01106
01107
01108 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
01109 "Don't know how to apply this tool, sorry.", NULL);
01110 LOG(llevError, "apply_map_builder: invalid builder subtype %d\n", builder->subtype);
01111 }