summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2014-05-25 14:53:28 -0400
committerJesse Luehrs <doy@tozt.net>2014-05-25 14:53:28 -0400
commitab47ed016d0444707f5441b63db2ca89b8585201 (patch)
treef1f43250b5a56d6636b07382cf61aad60e828acf
parent2b7eb6c2cbb67cc07e2ffef0ba80dc8bbdd4b537 (diff)
downloadgames-smtnocturne-demons-ab47ed016d0444707f5441b63db2ca89b8585201.tar.gz
games-smtnocturne-demons-ab47ed016d0444707f5441b63db2ca89b8585201.zip
implement special fusions
fusions_for doesn't support them yet
-rw-r--r--lib/Games/SMTNocturne/Demons.pm43
-rw-r--r--lib/Games/SMTNocturne/Demons/FusionChart.pm73
2 files changed, 109 insertions, 7 deletions
diff --git a/lib/Games/SMTNocturne/Demons.pm b/lib/Games/SMTNocturne/Demons.pm
index dab637b..6a06272 100644
--- a/lib/Games/SMTNocturne/Demons.pm
+++ b/lib/Games/SMTNocturne/Demons.pm
@@ -7,11 +7,26 @@ use Games::SMTNocturne::Demons::FusionChart;
sub fuse {
my ($demon1, $demon2, $options) = @_;
+ $options = { %$options };
$demon1 = Games::SMTNocturne::Demons::Demon->from_name($demon1)
unless ref($demon1);
$demon2 = Games::SMTNocturne::Demons::Demon->from_name($demon2)
unless ref($demon2);
+ if ($options->{sacrifice}) {
+ $options->{sacrifice} = Games::SMTNocturne::Demons::Demon->from_name(
+ $options->{sacrifice}
+ ) unless ref($options->{sacrifice});
+ }
+
+ if (!$options->{basic}) {
+ if (my $demon = _try_special_fusion($demon1, $demon2, $options)) {
+ return $demon;
+ }
+ else {
+ $options->{fusion_type} = 'normal';
+ }
+ }
if ($demon1->type eq 'Element' && $demon2->type eq 'Element') {
return _fuse_mitama($demon1, $demon2, $options);
@@ -63,6 +78,22 @@ sub fusions_for {
return @fusions;
}
+sub _try_special_fusion {
+ my ($demon1, $demon2, $options) = @_;
+
+ my $fused = Games::SMTNocturne::Demons::FusionChart::special_fusion(
+ $demon1, $demon2, $options
+ );
+ return unless $fused;
+
+ my $demon = Games::SMTNocturne::Demons::Demon->from_name($fused);
+
+ my %bosses = map { $_ => 1 } @{ $options->{bosses} || [] };
+ return if $demon->boss && !$bosses{$demon->name};
+
+ return $demon;
+}
+
sub _fuse_mitama {
my ($element1, $element2) = @_;
@@ -82,10 +113,9 @@ sub _element_fusion {
return unless $direction;
return Games::SMTNocturne::Demons::Demon->from_fusion_stats({
- type => $demon->type,
- level => $demon->level,
- fusion_type => 'normal',
- offset => $direction,
+ type => $demon->type,
+ level => $demon->level,
+ offset => $direction,
%{ $options || {} },
});
}
@@ -117,9 +147,8 @@ sub _normal_fusion {
my $new_level = ($demon1->level + $demon2->level) / 2 + 1;
return Games::SMTNocturne::Demons::Demon->from_fusion_stats({
- type => $new_type,
- level => $new_level,
- fusion_type => 'normal',
+ type => $new_type,
+ level => $new_level,
%{ $options || {} },
});
}
diff --git a/lib/Games/SMTNocturne/Demons/FusionChart.pm b/lib/Games/SMTNocturne/Demons/FusionChart.pm
index cbc56eb..94e5a29 100644
--- a/lib/Games/SMTNocturne/Demons/FusionChart.pm
+++ b/lib/Games/SMTNocturne/Demons/FusionChart.pm
@@ -75,6 +75,79 @@ sub fuse_mitama {
return $mitama_fusions{$element1}{$element2};
}
+sub special_fusion {
+ my ($demon1, $demon2, $options) = @_;
+
+ my $find = sub {
+ my ($need, @have) = @_;
+
+ if (my $name = $need->{name}) {
+ return (grep { $_->name eq $name } @have)[0];
+ }
+ elsif (my $type = $need->{type}) {
+ my @types = ref($need->{type}) ? @$type : ($type);
+ return (
+ grep { my $d = $_; grep { $d->type eq $_ } @types } @have
+ )[0];
+ }
+ else {
+ return undef;
+ }
+ };
+
+ DEMON: for my $demon (keys %SPECIAL) {
+ my $conditions = $SPECIAL{$demon};
+
+ if ($conditions->{deathstone}) {
+ next unless $options->{deathstone};
+ }
+
+ if (my $phases = $conditions->{kagatsuchi}) {
+ next unless defined $options->{kagatsuchi}
+ && grep { $_ == $options->{kagatsuchi} } @$phases;
+ }
+
+ if (my $sacrifice = $conditions->{sacrifice}) {
+ next unless $find->(
+ $sacrifice,
+ ($options->{sacrifice} ? ($options->{sacrifice}) : ())
+ );
+ }
+
+ if (my $target = $conditions->{target}) {
+ if (my $type = $target->{type}) {
+ next unless fuse($demon1->type, $demon2->type) eq $type;
+ }
+ elsif (my $name = $target->{name}) {
+ require Games::SMTNocturne::Demons;
+ my $fused = Games::SMTNocturne::Demons::fuse(
+ $demon1, $demon2, { %$options, basic => 1 }
+ );
+ next unless $fused && $fused->name eq $name;
+ }
+ else {
+ next;
+ }
+ }
+
+ my @have = ($demon1, $demon2);
+ push @have, $options->{sacrifice}
+ if $conditions->{demon3} && $options->{sacrifice};
+
+ for my $key (qw(demon1 demon2 demon3)) {
+ if ($conditions->{$key}) {
+ my $found = $find->($conditions->{$key}, @have);
+ next DEMON unless $found;
+ @have = grep { $_ ne $found } @have;
+ }
+ }
+
+ return $demon;
+ }
+
+ return;
+}
+
1;
__DATA__