#!perl our %materials; our @CONNECTABLE = ( cf::DOOR, cf::GATE, cf::BUTTON, cf::DETECTOR, cf::TIMED_GATE, cf::PEDESTAL, cf::CF_HANDLE, cf::MAGIC_EAR ); our @READABLE = (cf::SIGN, cf::MAGIC_EAR); $cf::CFG{"editor_builder_ui"} or return; cf::register_extcmd builder_player_items => sub { my ($pl, $msg) = @_; (items => { map { my $arch = $_; my $buildarch = cf::arch::find ($arch->clone->slaying); my $h = { value => $arch->clone->value, build_arch_name => $buildarch->name }; if (((grep { $buildarch->clone->type == $_ } @CONNECTABLE) > 0) || ($buildarch->name eq 'magic_mouth' && $buildarch->clone->type == cf::SIGN)) { $h->{has_connection} = 1; } if (grep { $buildarch->clone->type == $_ } @READABLE) { $h->{has_name} = 1; $h->{has_text} = 1; } $arch->name => $h } values %materials }) }; cf::register_extcmd builder_build => sub { my ($pl, $msg) = @_; my ($dx, $dy) = @$msg{qw(dx dy)}; my ($x, $y) = ($pl->ob->x + $dx, $pl->ob->y + $dy); my $buildable = 0; unless ($pl->ob->flag (cf::FLAG_WIZ)) { for ($pl->ob->map->at ($x, $y)) { unless ($_->flag (cf::FLAG_IS_BUILDABLE)) { return; } } } if ($msg->{do_erase}) { if ($pl->ob->flag (cf::FLAG_WIZ)) { my ($top) = reverse $pl->ob->map->at ($x, $y); $top->destroy if $top; } else { for my $ob ($pl->ob->map->at ($x, $y)) { unless ($ob->type == cf::WALL || $ob->type == cf::FLOOR || $ob->flag (cf::FLAG_IS_FLOOR)) { $ob->destroy; } } } } return unless $msg->{item}; return unless $pl->cell_visible ($dx, $dy); my $arch = cf::arch::find $msg->{item}; if ($arch->clone->subtype == cf::ST_MAT_FLOOR) { my $above_floor; for my $ob ($pl->ob->map->at ($x, $y)) { if ($ob->type == cf::WALL) { undef $above_floor if $above_floor == $ob; $ob->destroy; } elsif ($ob->type == cf::FLOOR || $ob->flag (cf::FLAG_IS_FLOOR)) { undef $above_floor if $above_floor == $ob; $above_floor = $ob->above; $ob->destroy; } } my $floor = cf::object::new $arch->clone->slaying; $floor->flag (cf::FLAG_IS_BUILDABLE, 1); $floor->flag (cf::FLAG_UNIQUE, 1); $floor->flag (cf::FLAG_IS_FLOOR, 1); $floor->type (cf::FLOOR); $floor->insert_ob_in_map_at ($pl->ob->map, $above_floor, ($above_floor ? cf::INS_BELOW_ORIGINATOR : cf::INS_ON_TOP), $x, $y); $pl->ob->map->fix_walls_around ($x, $y); } elsif ($arch->clone->subtype == cf::ST_MAT_WALL) { my @obs = $pl->ob->map->at ($x, $y); my $prev_wall; for (@obs) { if ($_->type == cf::WALL) { $prev_wall = $_; last; } } my ($floor) = grep { $_->type == cf::FLOOR || $_->flag (cf::FLAG_IS_FLOOR) } $pl->ob->map->at ($x, $y); my $above_floor = $floor->above; if ($above_floor) { return; } my $wall = cf::object::new $arch->clone->slaying; $wall->type (cf::WALL); $wall->flag (cf::FLAG_IS_BUILDABLE, 1); $wall->insert_ob_in_map_at ($pl->ob->map, undef, cf::INS_ABOVE_FLOOR_ONLY, $x, $y); if ($prev_wall) { $prev_wall->destroy; $pl->ob->map->fix_walls ($pl->ob->x + $dx, $pl->ob->y + $dy); } else { $pl->ob->map->fix_walls_around ($pl->ob->x + $dx, $pl->ob->y + $dy); } } elsif ($arch->clone->subtype == cf::ST_MAT_ITEM) { my ($floor) = grep { $_->type == cf::FLOOR || $_->flag (cf::FLAG_IS_FLOOR) } $pl->ob->map->at ($x, $y); unless ($floor) { return; } if ($floor->above) { return; } my $ob = cf::object::new $arch->clone->slaying; $ob->flag (cf::FLAG_IS_BUILDABLE, 1); $ob->flag (cf::FLAG_NO_PICK, 1); $ob->insert_ob_in_map_at ($pl->ob->map, undef, cf::INS_ABOVE_FLOOR_ONLY, $x, $y); if (defined $msg->{connection}) { $ob->add_button_link ($pl->ob->map, $msg->{connection}); } if (defined $msg->{text}) { $ob->msg ($msg->{text}); } if (defined $msg->{name}) { my $name = $msg->{name}; $ob->name ($msg->{name}); } if ((grep { $ob->type == $_ } @READABLE) && $ob->invisible) { $ob->name ("talking " . $ob->name); $ob->invisible (0); } } }; my $farch = cf::arch::first; while ($farch) { if ($farch->clone->type == cf::MATERIAL) { if (cf::arch::find $farch->clone->slaying) { $materials{$farch->name} = $farch; } else { warn "Undefined build archetype '".($farch->clone->slaying)."' for build material '".($farch->name)."'\n"; } } $farch = $farch->next; }