1 | #!perl |
1 | #!perl |
2 | |
2 | |
3 | our %materials; |
3 | our %materials; |
|
|
4 | |
|
|
5 | our @CONNECTABLE = ( |
|
|
6 | cf::DOOR, |
|
|
7 | cf::GATE, |
|
|
8 | cf::BUTTON, |
|
|
9 | cf::DETECTOR, |
|
|
10 | cf::TIMED_GATE, |
|
|
11 | cf::PEDESTAL, |
|
|
12 | cf::CF_HANDLE, |
|
|
13 | cf::MAGIC_EAR |
|
|
14 | ); |
|
|
15 | our @READABLE = (cf::SIGN, cf::MAGIC_EAR); |
4 | |
16 | |
5 | $cf::CFG{"editor_builder_ui"} |
17 | $cf::CFG{"editor_builder_ui"} |
6 | or return; |
18 | or return; |
7 | |
19 | |
8 | cf::register_extcmd builder_player_items => sub { |
20 | cf::register_extcmd builder_player_items => sub { |
9 | my ($pl, $msg) = @_; |
21 | my ($pl, $msg) = @_; |
10 | |
22 | |
11 | # my @builditems = ext::reseller::find_rec ($pl->ob, sub { |
23 | (items => { |
12 | # my ($item) = @_; |
24 | map { |
13 | # return $item->type == cf::MATERIAL |
25 | my $arch = $_; |
14 | # }); |
26 | my $buildarch = cf::arch::find ($arch->clone->slaying); |
|
|
27 | my $h = { value => $arch->clone->value, build_arch_name => $buildarch->name }; |
15 | |
28 | |
16 | (items => { map { $_->name => { value => $_->clone->value } } values %materials }) |
29 | if (((grep { $buildarch->clone->type == $_ } @CONNECTABLE) > 0) |
|
|
30 | || ($buildarch->name eq 'magic_mouth' && $buildarch->clone->type == cf::SIGN)) { |
|
|
31 | $h->{has_connection} = 1; |
|
|
32 | } |
|
|
33 | |
|
|
34 | if (grep { $buildarch->clone->type == $_ } @READABLE) { |
|
|
35 | $h->{has_name} = 1; |
|
|
36 | $h->{has_text} = 1; |
|
|
37 | } |
|
|
38 | |
|
|
39 | $arch->name => $h |
|
|
40 | } values %materials |
|
|
41 | }) |
17 | }; |
42 | }; |
18 | |
43 | |
19 | cf::register_extcmd builder_build => sub { |
44 | cf::register_extcmd builder_build => sub { |
20 | my ($pl, $msg) = @_; |
45 | my ($pl, $msg) = @_; |
21 | my ($dx, $dy) = @$msg{qw(dx dy)}; |
46 | my ($dx, $dy) = @$msg{qw(dx dy)}; |
22 | my ($x, $y) = ($pl->ob->x + $dx, $pl->ob->y + $dy); |
47 | my ($x, $y) = ($pl->ob->x + $dx, $pl->ob->y + $dy); |
23 | |
48 | |
24 | my $near = (abs $dx) <= 2 && (abs $dy) <= 2; |
|
|
25 | |
|
|
26 | return unless $near; |
|
|
27 | |
|
|
28 | my $buildable = 0; |
49 | my $buildable = 0; |
29 | |
50 | |
|
|
51 | unless ($pl->ob->flag (cf::FLAG_WIZ)) { |
30 | for ($pl->ob->map->at ($x, $y)) { |
52 | for ($pl->ob->map->at ($x, $y)) { |
31 | unless ($_->flag (cf::FLAG_IS_BUILDABLE)) { |
53 | unless ($_->flag (cf::FLAG_IS_BUILDABLE)) { |
32 | return; |
54 | return; |
|
|
55 | } |
33 | } |
56 | } |
34 | } |
57 | } |
35 | |
58 | |
36 | if ($msg->{do_erase}) { |
59 | if ($msg->{do_erase}) { |
|
|
60 | if ($pl->ob->flag (cf::FLAG_WIZ)) { |
|
|
61 | my ($top) = reverse $pl->ob->map->at ($x, $y); |
|
|
62 | if ($top) { $top->remove; $top->free } |
|
|
63 | |
|
|
64 | } else { |
37 | for my $ob ($pl->ob->map->at ($x, $y)) { |
65 | for my $ob ($pl->ob->map->at ($x, $y)) { |
38 | unless ($ob->type == cf::WALL || $ob->type == cf::FLOOR || $ob->flag (cf::FLAG_IS_FLOOR)) { |
66 | unless ($ob->type == cf::WALL || $ob->type == cf::FLOOR || $ob->flag (cf::FLAG_IS_FLOOR)) { |
39 | $ob->remove; |
67 | $ob->remove; |
40 | $ob->free; |
68 | $ob->free; |
|
|
69 | } |
41 | } |
70 | } |
42 | } |
71 | } |
43 | } |
72 | } |
44 | |
73 | |
45 | return unless $msg->{item}; |
74 | return unless $msg->{item}; |
46 | |
75 | |
47 | if ($pl->cell_visible ($dx, $dy)) { |
76 | return unless $pl->cell_visible ($dx, $dy); |
48 | my $arch = cf::arch::find $msg->{item}; |
77 | my $arch = cf::arch::find $msg->{item}; |
49 | |
78 | |
50 | if ($arch->clone->subtype == cf::ST_MAT_FLOOR) { |
79 | if ($arch->clone->subtype == cf::ST_MAT_FLOOR) { |
51 | my $above_floor; |
80 | my $above_floor; |
52 | for my $ob ($pl->ob->map->at ($x, $y)) { |
81 | for my $ob ($pl->ob->map->at ($x, $y)) { |
53 | if ($ob->type == cf::WALL) { |
82 | if ($ob->type == cf::WALL) { |
54 | undef $above_floor if $above_floor == $ob; |
83 | undef $above_floor if $above_floor == $ob; |
55 | $ob->remove; |
84 | $ob->remove; |
56 | $ob->free; |
85 | $ob->free; |
57 | } elsif ($ob->type == cf::FLOOR || $ob->flag (cf::FLAG_IS_FLOOR)) { |
86 | } elsif ($ob->type == cf::FLOOR || $ob->flag (cf::FLAG_IS_FLOOR)) { |
58 | undef $above_floor if $above_floor == $ob; |
87 | undef $above_floor if $above_floor == $ob; |
59 | $above_floor = $ob->above; |
88 | $above_floor = $ob->above; |
60 | $ob->remove; |
89 | $ob->remove; |
61 | $ob->free; |
90 | $ob->free; |
62 | } |
|
|
63 | } |
91 | } |
|
|
92 | } |
64 | |
93 | |
65 | # my @obs = $pl->ob->map->at ($x, $y); |
94 | my $floor = cf::object::new $arch->clone->slaying; |
66 | # for (@obs) { $_->remove; $_->free } |
95 | $floor->flag (cf::FLAG_IS_BUILDABLE, 1); |
|
|
96 | $floor->flag (cf::FLAG_UNIQUE, 1); |
|
|
97 | $floor->flag (cf::FLAG_IS_FLOOR, 1); |
|
|
98 | $floor->type (cf::FLOOR); |
|
|
99 | $floor->insert_ob_in_map_at ($pl->ob->map, $above_floor, ($above_floor ? cf::INS_BELOW_ORIGINATOR : cf::INS_ON_TOP), $x, $y); |
67 | |
100 | |
68 | my $floor = cf::object::new $arch->clone->slaying; |
101 | $pl->ob->map->fix_walls_around ($x, $y); |
69 | $floor->flag (cf::FLAG_IS_BUILDABLE, 1); |
|
|
70 | $floor->flag (cf::FLAG_UNIQUE, 1); |
|
|
71 | $floor->flag (cf::FLAG_IS_FLOOR, 1); |
|
|
72 | $floor->type (cf::FLOOR); |
|
|
73 | $floor->insert_ob_in_map_at ($pl->ob->map, $above_floor, ($above_floor ? cf::INS_BELOW_ORIGINATOR : cf::INS_ON_TOP), $x, $y); |
|
|
74 | |
102 | |
75 | $pl->ob->map->fix_walls_around ($x, $y); |
103 | } elsif ($arch->clone->subtype == cf::ST_MAT_WALL) { |
|
|
104 | my @obs = $pl->ob->map->at ($x, $y); |
|
|
105 | my $prev_wall; |
|
|
106 | for (@obs) { |
|
|
107 | if ($_->type == cf::WALL) { |
|
|
108 | $prev_wall = $_; |
|
|
109 | last; |
|
|
110 | } |
|
|
111 | } |
76 | |
112 | |
77 | } elsif ($arch->clone->subtype == cf::ST_MAT_WALL) { |
113 | my ($floor) = |
|
|
114 | grep { $_->type == cf::FLOOR || $_->flag (cf::FLAG_IS_FLOOR) } |
78 | my @obs = $pl->ob->map->at ($x, $y); |
115 | $pl->ob->map->at ($x, $y); |
79 | my $prev_wall; |
|
|
80 | for (@obs) { |
|
|
81 | if ($_->type == cf::WALL) { |
|
|
82 | $prev_wall = $_; |
|
|
83 | last; |
|
|
84 | } |
|
|
85 | } |
|
|
86 | |
116 | |
87 | my ($floor) = |
117 | my $above_floor = $floor->above; |
88 | grep { $_->type == cf::FLOOR || $_->flag (cf::FLAG_IS_FLOOR) } |
118 | if ($above_floor) { |
89 | $pl->ob->map->at ($x, $y); |
119 | return; |
|
|
120 | } |
90 | |
121 | |
91 | my $above_floor = $floor->above; |
122 | my $wall = cf::object::new $arch->clone->slaying; |
92 | if ($above_floor) { |
123 | $wall->type (cf::WALL); |
93 | return; |
124 | $wall->flag (cf::FLAG_IS_BUILDABLE, 1); |
|
|
125 | $wall->insert_ob_in_map_at ($pl->ob->map, undef, cf::INS_ABOVE_FLOOR_ONLY, $x, $y); |
|
|
126 | if ($prev_wall) { |
|
|
127 | $prev_wall->remove; |
|
|
128 | $prev_wall->free; |
|
|
129 | $pl->ob->map->fix_walls ($pl->ob->x + $dx, $pl->ob->y + $dy); |
|
|
130 | } else { |
|
|
131 | $pl->ob->map->fix_walls_around ($pl->ob->x + $dx, $pl->ob->y + $dy); |
94 | } |
132 | } |
95 | |
133 | |
96 | my $wall = cf::object::new $arch->clone->slaying; |
134 | } elsif ($arch->clone->subtype == cf::ST_MAT_ITEM) { |
97 | $wall->type (cf::WALL); |
135 | my ($floor) = |
98 | $wall->flag (cf::FLAG_IS_BUILDABLE, 1); |
136 | grep { $_->type == cf::FLOOR || $_->flag (cf::FLAG_IS_FLOOR) } |
99 | $wall->insert_ob_in_map_at ($pl->ob->map, undef, cf::INS_ABOVE_FLOOR_ONLY, $x, $y); |
137 | $pl->ob->map->at ($x, $y); |
100 | if ($prev_wall) { |
|
|
101 | $prev_wall->remove; |
|
|
102 | $prev_wall->free; |
|
|
103 | $pl->ob->map->fix_walls ($pl->ob->x + $dx, $pl->ob->y + $dy); |
|
|
104 | } else { |
|
|
105 | $pl->ob->map->fix_walls_around ($pl->ob->x + $dx, $pl->ob->y + $dy); |
|
|
106 | } |
|
|
107 | |
138 | |
108 | } elsif ($arch->clone->subtype == cf::ST_MAT_ITEM) { |
139 | unless ($floor) { |
109 | my ($floor) = |
140 | return; |
110 | grep { $_->type == cf::FLOOR || $_->flag (cf::FLAG_IS_FLOOR) } |
141 | } |
111 | $pl->ob->map->at ($x, $y); |
|
|
112 | |
142 | |
113 | unless ($floor) { |
143 | if ($floor->above) { |
114 | return; |
144 | return; |
115 | } |
145 | } |
116 | |
146 | |
117 | my $above_floor = $floor->above; |
147 | my $ob = cf::object::new $arch->clone->slaying; |
118 | if ($above_floor) { |
148 | $ob->flag (cf::FLAG_IS_BUILDABLE, 1); |
119 | return; |
149 | $ob->flag (cf::FLAG_NO_PICK, 1); |
120 | } |
150 | $ob->insert_ob_in_map_at ($pl->ob->map, undef, cf::INS_ABOVE_FLOOR_ONLY, $x, $y); |
121 | |
151 | |
122 | my $ob = cf::object::new $arch->clone->slaying; |
152 | if (defined $msg->{connection}) { |
123 | $ob->flag (cf::FLAG_IS_BUILDABLE, 1); |
153 | $ob->add_button_link ($pl->ob->map, $msg->{connection}); |
124 | $ob->flag (cf::FLAG_NO_PICK, 1); |
154 | } |
125 | $ob->insert_ob_in_map_at ($pl->ob->map, undef, cf::INS_ABOVE_FLOOR_ONLY, $x, $y); |
155 | if (defined $msg->{text}) { |
|
|
156 | $ob->msg ($msg->{text}); |
|
|
157 | } |
|
|
158 | if (defined $msg->{name}) { |
|
|
159 | my $name = $msg->{name}; |
|
|
160 | $ob->name ($msg->{name}); |
|
|
161 | } |
|
|
162 | if ((grep { $ob->type == $_ } @READABLE) && $ob->invisible) { |
|
|
163 | $ob->name ("talking " . $ob->name); |
|
|
164 | $ob->invisible (0); |
126 | } |
165 | } |
127 | } |
166 | } |
128 | |
|
|
129 | # my $arch = cf::arch::find ($msg->{item}); |
|
|
130 | }; |
167 | }; |
131 | |
168 | |
132 | my $farch = cf::arch::first; |
169 | my $farch = cf::arch::first; |
133 | while ($farch) { |
170 | while ($farch) { |
134 | if ($farch->clone->type == cf::MATERIAL) { |
171 | if ($farch->clone->type == cf::MATERIAL) { |
|
|
172 | if (cf::arch::find $farch->clone->slaying) { |
135 | $materials{$farch->name} = $farch; |
173 | $materials{$farch->name} = $farch; |
|
|
174 | } else { |
|
|
175 | warn "Undefined build archetype '".($farch->clone->slaying)."' for build material '".($farch->name)."'\n"; |
|
|
176 | } |
136 | } |
177 | } |
137 | $farch = $farch->next; |
178 | $farch = $farch->next; |
138 | } |
179 | } |