ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/build_map.C
(Generate patch)

Comparing deliantra/server/server/build_map.C (file contents):
Revision 1.46 by root, Fri Nov 6 13:31:47 2009 UTC vs.
Revision 1.60 by root, Wed Apr 14 21:36:32 2010 UTC

1/* 1/*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2001,2007 Mark Wedel & Crossfire Development Team 5 * Copyright (©) 2001 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen 6 * Copyright (©) 1992 Frank Tore Johansen
7 * 7 *
8 * Deliantra is free software: you can redistribute it and/or modify it under 8 * Deliantra is free software: you can redistribute it and/or modify it under
9 * the terms of the Affero GNU General Public License as published by the 9 * the terms of the Affero GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your 10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version. 11 * option) any later version.
27#include <spells.h> 27#include <spells.h>
28#include <skills.h> 28#include <skills.h>
29#include <tod.h> 29#include <tod.h>
30#include <sproto.h> 30#include <sproto.h>
31 31
32// macro for this check, it had been inconsistent in this file.
33#define IS_FLOOR(x) x->flag [FLAG_IS_FLOOR]
34
32/** 35/**
33 * Check if objects on a square interfere with building 36 * Check if objects on a square interfere with building
34 */ 37 */
35static int 38static int
36can_build_over (maptile *map, object *tmp, int x, int y) 39can_build_over (maptile *map, object *tmp, int x, int y)
39 42
40 ob = GET_MAP_OB (map, x, y); 43 ob = GET_MAP_OB (map, x, y);
41 while (ob) 44 while (ob)
42 { 45 {
43 /* if ob is not a marking rune or floor, then check special cases */ 46 /* if ob is not a marking rune or floor, then check special cases */
44 if (ob->arch->archname != shstr_rune_mark && ob->type != FLOOR) 47 if (ob->arch->archname != shstr_rune_mark && !IS_FLOOR (ob))
45 { 48 {
46 switch (tmp->type) 49 switch (tmp->type)
47 { 50 {
48 case SIGN: 51 case SIGN:
49 case MAGIC_EAR: 52 case MAGIC_EAR:
64 } 67 }
65 } 68 }
66 69
67 ob = ob->above; 70 ob = ob->above;
68 } 71 }
72
69 return 1; 73 return 1;
70} 74}
71 75
72/** 76/**
73 * Erases marking runes at specified location 77 * Erases marking runes at specified location
341 */ 345 */
342 object::flags_t old_flags = wall->flag; // elmex: this is where C++ pays off 346 object::flags_t old_flags = wall->flag; // elmex: this is where C++ pays off
343 347
344 wall->destroy (); 348 wall->destroy ();
345 349
346 wall = arch_to_object (new_arch); 350 wall = new_arch->instance ();
347 wall->type = BUILDABLE_WALL; 351 wall->type = BUILDABLE_WALL;
348 insert_ob_in_map_at (wall, map, NULL, INS_ABOVE_FLOOR_ONLY, x, y); 352 insert_ob_in_map_at (wall, map, NULL, INS_ABOVE_FLOOR_ONLY, x, y);
349 wall->flag = old_flags; 353 wall->flag = old_flags;
350} 354}
351 355
389 /* There was a wall, remove it & keep its archetype to make new walls */ 393 /* There was a wall, remove it & keep its archetype to make new walls */
390 new_wall = tmp->arch; 394 new_wall = tmp->arch;
391 tmp->destroy (); 395 tmp->destroy ();
392 sprintf (message, "You destroy the wall and redo the floor."); 396 sprintf (message, "You destroy the wall and redo the floor.");
393 } 397 }
394 else if ((FLOOR == tmp->type) || (QUERY_FLAG (tmp, FLAG_IS_FLOOR))) 398 else if (IS_FLOOR (tmp))
395 { 399 {
396 tmp->destroy (); 400 tmp->destroy ();
397 floor_removed = 1; 401 floor_removed = 1;
398 } 402 }
399 else 403 else
417 /* Not found, log & bail out */ 421 /* Not found, log & bail out */
418 LOG (llevError, "apply_builder_floor: unable to find archetype %s.\n", &material->slaying); 422 LOG (llevError, "apply_builder_floor: unable to find archetype %s.\n", &material->slaying);
419 return; 423 return;
420 } 424 }
421 425
422 tmp = arch_to_object (new_floor); 426 tmp = new_floor->instance ();
423 SET_FLAG (tmp, FLAG_IS_BUILDABLE); 427 tmp->set_flag (FLAG_IS_BUILDABLE);
424 SET_FLAG (tmp, FLAG_UNIQUE); 428 tmp->set_flag (FLAG_UNIQUE);
425 SET_FLAG (tmp, FLAG_IS_FLOOR); 429 tmp->set_flag (FLAG_IS_FLOOR);
426 tmp->type = FLOOR; 430 //tmp->type = FLOOR;
427 insert_ob_in_map_at (tmp, pl->map, above_floor, above_floor ? INS_BELOW_ORIGINATOR : INS_ON_TOP, x, y); 431 insert_ob_in_map_at (tmp, pl->map, above_floor, above_floor ? INS_BELOW_ORIGINATOR : INS_ON_TOP, x, y);
428 432
429 /* 433 /*
430 * Next step: make sure there are either walls or floors around the new square 434 * Next step: make sure there are either walls or floors around the new square
431 * Since building, you can have: blocking view / floor / wall / nothing 435 * Since building, you can have: blocking view / floor / wall / nothing
436 yt = y + freearr_y[i]; 440 yt = y + freearr_y[i];
437 tmp = GET_MAP_OB (pl->map, xt, yt); 441 tmp = GET_MAP_OB (pl->map, xt, yt);
438 if (!tmp) 442 if (!tmp)
439 { 443 {
440 /* Must insert floor & wall */ 444 /* Must insert floor & wall */
441 tmp = arch_to_object (new_floor); 445 tmp = new_floor->instance ();
442 /* Better make the floor unique */ 446 /* Better make the floor unique */
443 SET_FLAG (tmp, FLAG_UNIQUE); 447 tmp->set_flag (FLAG_UNIQUE);
444 SET_FLAG (tmp, FLAG_IS_BUILDABLE); 448 tmp->set_flag (FLAG_IS_BUILDABLE);
445 tmp->type = FLOOR; 449 //tmp->type = FLOOR;
446 insert_ob_in_map_at (tmp, pl->map, 0, 0, xt, yt); 450 insert_ob_in_map_at (tmp, pl->map, 0, 0, xt, yt);
447 /* Insert wall if exists. Note: if it doesn't, the map is weird... */ 451 /* Insert wall if exists. Note: if it doesn't, the map is weird... */
448 if (new_wall) 452 if (new_wall)
449 { 453 {
450 tmp = arch_to_object (new_wall); 454 tmp = new_wall->instance ();
451 SET_FLAG (tmp, FLAG_IS_BUILDABLE); 455 tmp->set_flag (FLAG_IS_BUILDABLE);
452 tmp->type = BUILDABLE_WALL; 456 tmp->type = BUILDABLE_WALL;
453 insert_ob_in_map_at (tmp, pl->map, 0, 0, xt, yt); 457 insert_ob_in_map_at (tmp, pl->map, 0, 0, xt, yt);
454 } 458 }
455 } 459 }
456 } 460 }
509 { 513 {
510 LOG (llevError, "apply_builder_wall: unable to find archetype %s\n", &material->slaying); 514 LOG (llevError, "apply_builder_wall: unable to find archetype %s\n", &material->slaying);
511 return; 515 return;
512 } 516 }
513 517
514 tmp = arch_to_object (new_wall); 518 tmp = new_wall->instance ();
515 tmp->type = BUILDABLE_WALL; 519 tmp->type = BUILDABLE_WALL;
516 SET_FLAG (tmp, FLAG_IS_BUILDABLE); 520 tmp->set_flag (FLAG_IS_BUILDABLE);
517 insert_ob_in_map_at (tmp, pl->map, 0, INS_ABOVE_FLOOR_ONLY, x, y); 521 insert_ob_in_map_at (tmp, pl->map, 0, INS_ABOVE_FLOOR_ONLY, x, y);
518 522
519 /* If existing wall, remove it, no need to fix other walls */ 523 /* If existing wall, remove it, no need to fix other walls */
520 if (current_wall) 524 if (current_wall)
521 { 525 {
566 { 570 {
567 new_draw_info (NDI_UNIQUE, 0, pl, "Invalid square."); 571 new_draw_info (NDI_UNIQUE, 0, pl, "Invalid square.");
568 return; 572 return;
569 } 573 }
570 574
571 while (floor && (floor->type != FLOOR) && (!QUERY_FLAG (floor, FLAG_IS_FLOOR))) 575 while (floor && !IS_FLOOR (floor))
572 floor = floor->above; 576 floor = floor->above;
573 577
574 if (!floor) 578 if (!floor)
575 { 579 {
576 new_draw_info (NDI_UNIQUE, 0, pl, "This square has no floor, you can't build here."); 580 new_draw_info (NDI_UNIQUE, 0, pl, "This square has no floor, you can't build here.");
579 /* Create item, set flag, insert in map */ 583 /* Create item, set flag, insert in map */
580 arch = archetype::find (item->slaying); 584 arch = archetype::find (item->slaying);
581 if (!arch) 585 if (!arch)
582 return; 586 return;
583 587
584 tmp = arch_to_object (arch); 588 tmp = arch->instance ();
585 589
586 if (!floor->flag[FLAG_IS_BUILDABLE] || (floor->above) && (!can_build_over (pl->map, tmp, x, y))) 590 if (!floor->flag[FLAG_IS_BUILDABLE] || floor->above && !can_build_over (pl->map, tmp, x, y))
587 /* Floor has something on top that interferes with building */ 591 /* Floor has something on top that interferes with building */
588 { 592 {
589 new_draw_info (NDI_UNIQUE, 0, pl, "You can't build here."); 593 new_draw_info (NDI_UNIQUE, 0, pl, "You can't build here.");
590 return; 594 return;
591 } 595 }
592 596
593 SET_FLAG (tmp, FLAG_IS_BUILDABLE); 597 tmp->set_flag (FLAG_IS_BUILDABLE);
594 SET_FLAG (tmp, FLAG_NO_PICK); 598 tmp->set_flag (FLAG_NO_PICK);
595 599
596 /* 600 /*
597 * Str 1 is a flag that the item [pedestal] should go below the floor. 601 * Str 1 is a flag that the item [pedestal] should go below the floor.
598 * Items under the floor on non-unique maps will not be saved, 602 * Items under the floor on non-unique maps will not be saved,
599 * so make the item itself unique in this situation. 603 * so make the item itself unique in this situation.
600 */ 604 */
601 insert_flag = ( item->stats.Str == 1 ) ? INS_BELOW_ORIGINATOR : INS_ABOVE_FLOOR_ONLY; 605 insert_flag = item->stats.Str == 1 ? INS_BELOW_ORIGINATOR : INS_ABOVE_FLOOR_ONLY;
602 if (insert_flag == INS_BELOW_ORIGINATOR && !pl->map->no_reset) 606 if (insert_flag == INS_BELOW_ORIGINATOR && !pl->map->no_reset)
603 SET_FLAG (tmp, FLAG_UNIQUE); 607 tmp->set_flag (FLAG_UNIQUE);
604 608
605 shstr_tmp connected; 609 shstr_tmp connected;
606 610
607 switch (tmp->type) 611 switch (tmp->type)
608 { 612 {
670 new_draw_info (NDI_UNIQUE, 0, pl, "Invalid square."); 674 new_draw_info (NDI_UNIQUE, 0, pl, "Invalid square.");
671 LOG (llevError, "apply_builder_remove: (null) square at (%d, %d, %s)\n", x, y, &pl->map->path); 675 LOG (llevError, "apply_builder_remove: (null) square at (%d, %d, %s)\n", x, y, &pl->map->path);
672 return; 676 return;
673 } 677 }
674 678
675 if (item->type == FLOOR || QUERY_FLAG (item, FLAG_IS_FLOOR)) 679 if (IS_FLOOR (item))
676 item = item->above; 680 item = item->above;
677 681
678 if (!item) 682 if (!item)
679 new_draw_info (NDI_UNIQUE, 0, pl, "Nothing to remove."); 683 new_draw_info (NDI_UNIQUE, 0, pl, "Nothing to remove.");
680 else if (item->type == BUILDABLE_WALL) 684 else if (item->type == BUILDABLE_WALL)
695 * or remover object. 699 * or remover object.
696 */ 700 */
697void 701void
698apply_map_builder (object *pl, int dir) 702apply_map_builder (object *pl, int dir)
699{ 703{
700 object *builder;
701 object *tmp;
702 object *tmp2;
703 int x, y; 704 int x, y;
704 705
705 if (!pl->type == PLAYER) 706 if (!pl->type == PLAYER)
706 return; 707 return;
707 708
731 * The square must have only buildable items 732 * The square must have only buildable items
732 * Exception: marking runes are all right, 733 * Exception: marking runes are all right,
733 * since they are used for special things like connecting doors / buttons 734 * since they are used for special things like connecting doors / buttons
734 */ 735 */
735 736
736 tmp = GET_MAP_OB (pl->map, x, y); 737 object *tmp = GET_MAP_OB (pl->map, x, y);
737 if (!tmp) 738 if (!tmp)
738 { 739 {
739 /* Nothing, meaning player is standing next to an undefined square... */ 740 /* Nothing, meaning player is standing next to an undefined square... */
740 LOG (llevError, "apply_map_builder: undefined square at (%d, %d, %s)\n", x, y, &pl->map->path); 741 LOG (llevError, "apply_map_builder: undefined square at (%d, %d, %s)\n", x, y, &pl->map->path);
741 new_draw_info (NDI_UNIQUE, 0, pl, "You'd better not build here, it looks weird."); 742 new_draw_info (NDI_UNIQUE, 0, pl, "You'd better not build here, it looks weird.");
742 return; 743 return;
743 } 744 }
744 745
745 tmp2 = find_marked_object (pl); 746 object *builder = pl->contr->ranged_ob;
747
748 object *tmp2 = pl->mark ();
749
746 while (tmp) 750 while (tmp)
747 { 751 {
748 if (!QUERY_FLAG (tmp, FLAG_IS_BUILDABLE) && (tmp->type != SIGN || tmp->arch->archname != shstr_rune_mark)) 752 if (!tmp->flag [FLAG_IS_BUILDABLE] && (tmp->type != SIGN || tmp->arch->archname != shstr_rune_mark))
749 { 753 {
750 /* The item building function already has it's own special 754 /* The item building function already has it's own special
751 * checks for this 755 * checks for this
752 */ 756 */
753 if ((!tmp2) || (tmp2->subtype != ST_MAT_ITEM)) 757 if (!tmp2 || tmp2->subtype != ST_MAT_ITEM)
754 { 758 {
759 if (!INVOKE_PLAYER (BUILD, pl->contr, ARG_OBJECT (builder), ARG_MAP (pl->map), ARG_INT (x), ARG_INT (y), ARG_INT (0)))
755 new_draw_info (NDI_UNIQUE, 0, pl, "You can't build here."); 760 new_draw_info (NDI_UNIQUE, 0, pl, "You can't build here.");
761
756 return; 762 return;
757 } 763 }
758 } 764 }
765
759 tmp = tmp->above; 766 tmp = tmp->above;
760 } 767 }
761 768
762 /* Now we know the square is ok */ 769 /* Now we know the square is ok */
763 builder = pl->contr->ranged_ob; 770 if (INVOKE_PLAYER (BUILD, pl->contr, ARG_OBJECT (builder), ARG_MAP (pl->map), ARG_INT (x), ARG_INT (y), ARG_INT (1)))
771 return;
764 772
765 if (builder->subtype == ST_BD_REMOVE) 773 if (builder->subtype == ST_BD_REMOVE)
766 /* Remover -> call specific function and bail out */ 774 /* Remover -> call specific function and bail out */
767 { 775 {
768 apply_builder_remove (pl, dir); 776 apply_builder_remove (pl, dir);
788 return; 796 return;
789 } 797 }
790 798
791 switch (tmp->subtype) 799 switch (tmp->subtype)
792 { 800 {
793 case ST_MAT_FLOOR: 801 case ST_MAT_FLOOR:
794 apply_builder_floor (pl, tmp, x, y); 802 apply_builder_floor (pl, tmp, x, y);
795 return; 803 return;
796 804
797 case ST_MAT_WALL: 805 case ST_MAT_WALL:
798 apply_builder_wall (pl, tmp, x, y); 806 apply_builder_wall (pl, tmp, x, y);
799 return; 807 return;
800 808
801 case ST_MAT_ITEM: 809 case ST_MAT_ITEM:
802 apply_builder_item (pl, tmp, x, y); 810 apply_builder_item (pl, tmp, x, y);
803 return; 811 return;
804 812
805 default: 813 default:
806 new_draw_info (NDI_UNIQUE, 0, pl, "Don't know how to apply this material, sorry."); 814 new_draw_info (NDI_UNIQUE, 0, pl, "Don't know how to apply this material, sorry.");
807 LOG (llevError, "apply_map_builder: invalid material subtype %d\n", tmp->subtype); 815 LOG (llevError, "apply_map_builder: invalid material subtype %d\n", tmp->subtype);
808 return; 816 return;
809 } 817 }
810 } 818 }
811 819
812 /* Here, it means the builder has an invalid type */ 820 /* Here, it means the builder has an invalid type */
813 new_draw_info (NDI_UNIQUE, 0, pl, "Don't know how to apply this tool, sorry."); 821 new_draw_info (NDI_UNIQUE, 0, pl, "Don't know how to apply this tool, sorry.");

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines