mirror of
https://git.srhtnin.garden/sarah/srhtnin.github.io.git
synced 2026-10-14 02:38:12 +02:00
Added the actual functional effects, not just the base.
This commit is contained in:
1 parent
9de8af0d2b
commit
1452a4a96d
6 files changed
+1102
-88
No files matched your search
@@ -180,8 +180,40 @@ function GetResolvedFunctionalEffectCooldown(
|
||||
Effect,
|
||||
AtTime
|
||||
) {
|
||||
return GetFunctionalEffectCooldown(
|
||||
Effect
|
||||
const BaseCooldown =
|
||||
GetFunctionalEffectCooldown(
|
||||
Effect
|
||||
);
|
||||
|
||||
if (BaseCooldown <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Accelerator =
|
||||
GetStrongestFunctionalEffectAffectingPlot(
|
||||
SaveData,
|
||||
GardenIndex,
|
||||
PlotIndex,
|
||||
"CooldownReduction",
|
||||
AtTime
|
||||
);
|
||||
|
||||
const Reduction = Math.max(
|
||||
0,
|
||||
Math.min(
|
||||
1,
|
||||
GetFunctionalEffectAmount(
|
||||
Accelerator?.Effect
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
return Math.max(
|
||||
FunctionalEffectMinimumCooldown,
|
||||
Math.floor(
|
||||
BaseCooldown *
|
||||
(1 - Reduction)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1002,6 +1034,833 @@ function GetStrongestFunctionalEffectAffectingAnyPlot(
|
||||
}
|
||||
|
||||
|
||||
|
||||
function DoesFunctionalPlantHaveEffectType(
|
||||
Plant,
|
||||
Type
|
||||
) {
|
||||
return GetPlantFunctionalEffects(
|
||||
Plant
|
||||
).some(
|
||||
Effect =>
|
||||
String(Effect.Type) ===
|
||||
String(Type)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function CanFunctionalPlantUseAssignedSeed(
|
||||
Plant
|
||||
) {
|
||||
return DoesFunctionalPlantHaveEffectType(
|
||||
Plant,
|
||||
"Plant"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function GetFunctionalPercentageAmount(
|
||||
Effect,
|
||||
Fallback = 0
|
||||
) {
|
||||
return Math.max(
|
||||
0,
|
||||
Math.min(
|
||||
1,
|
||||
GetFunctionalEffectAmount(
|
||||
Effect,
|
||||
Fallback
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function GetFunctionalRandomItem(
|
||||
SaveData,
|
||||
Items
|
||||
) {
|
||||
if (!Array.isArray(Items) || Items.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Items.length === 1) {
|
||||
return Items[0];
|
||||
}
|
||||
|
||||
const Random =
|
||||
typeof GetSimulationRandom === "function"
|
||||
? GetSimulationRandom(
|
||||
SaveData
|
||||
)
|
||||
: Math.random();
|
||||
|
||||
return Items[
|
||||
Math.min(
|
||||
Items.length - 1,
|
||||
Math.floor(
|
||||
Random * Items.length
|
||||
)
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
function AddFunctionalCurrencyReward(
|
||||
SaveData,
|
||||
Currency,
|
||||
Amount
|
||||
) {
|
||||
const RewardAmount = Number(
|
||||
Amount
|
||||
);
|
||||
|
||||
if (
|
||||
!Number.isFinite(RewardAmount) ||
|
||||
RewardAmount <= 0
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SaveData.Currency ??= {};
|
||||
SaveData.Currency[Currency] ??= 0;
|
||||
SaveData.Currency[Currency] += RewardAmount;
|
||||
|
||||
SaveData.Statistics ??= {};
|
||||
SaveData.Statistics.CurrencyEarned ??= {};
|
||||
SaveData.Statistics.CurrencyEarned[
|
||||
Currency
|
||||
] ??= 0;
|
||||
SaveData.Statistics.CurrencyEarned[
|
||||
Currency
|
||||
] += RewardAmount;
|
||||
|
||||
return RewardAmount;
|
||||
}
|
||||
|
||||
|
||||
function IsGardenPlotHarvestDisabled(
|
||||
SaveData,
|
||||
GardenIndex,
|
||||
PlotIndex,
|
||||
AtTime
|
||||
) {
|
||||
return (
|
||||
GetStrongestFunctionalEffectAffectingPlot(
|
||||
SaveData,
|
||||
GardenIndex,
|
||||
PlotIndex,
|
||||
"DisableHarvest",
|
||||
AtTime
|
||||
) !== null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function IsGardenPlotMutationDisabled(
|
||||
SaveData,
|
||||
GardenIndex,
|
||||
PlotIndex,
|
||||
AtTime
|
||||
) {
|
||||
return (
|
||||
GetStrongestFunctionalEffectAffectingPlot(
|
||||
SaveData,
|
||||
GardenIndex,
|
||||
PlotIndex,
|
||||
"DisableMutation",
|
||||
AtTime
|
||||
) !== null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function DoesMutationPatternInvolveDisableMutation(
|
||||
SaveData,
|
||||
GardenIndex,
|
||||
OriginX,
|
||||
OriginY,
|
||||
Pattern
|
||||
) {
|
||||
const Garden =
|
||||
GetFunctionalGarden(
|
||||
SaveData,
|
||||
GardenIndex
|
||||
);
|
||||
|
||||
if (
|
||||
Garden === null ||
|
||||
!Array.isArray(Pattern)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (
|
||||
let LocalY = 0;
|
||||
LocalY < Pattern.length;
|
||||
LocalY++
|
||||
) {
|
||||
const Row = Pattern[LocalY];
|
||||
|
||||
if (!Array.isArray(Row)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (
|
||||
let LocalX = 0;
|
||||
LocalX < Row.length;
|
||||
LocalX++
|
||||
) {
|
||||
const Matcher = Row[LocalX];
|
||||
|
||||
if (
|
||||
Matcher === null ||
|
||||
Matcher === "Any" ||
|
||||
Matcher === "Empty"
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const PlotIndex =
|
||||
GetFunctionalPlotIndex(
|
||||
Garden,
|
||||
OriginX + LocalX,
|
||||
OriginY + LocalY
|
||||
);
|
||||
|
||||
if (PlotIndex === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Plot =
|
||||
Garden.Plots?.[PlotIndex] ?? null;
|
||||
|
||||
if (Plot === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Plant =
|
||||
Plants?.[Plot.Plant];
|
||||
|
||||
if (
|
||||
Plant !== undefined &&
|
||||
DoesFunctionalPlantHaveEffectType(
|
||||
Plant,
|
||||
"DisableMutation"
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function GetGardenPlotGrowthAdvance(
|
||||
SaveData,
|
||||
GardenIndex,
|
||||
PlotIndex,
|
||||
AtTime
|
||||
) {
|
||||
const Effect =
|
||||
GetStrongestFunctionalEffectAffectingPlot(
|
||||
SaveData,
|
||||
GardenIndex,
|
||||
PlotIndex,
|
||||
"GrowthAdvance",
|
||||
AtTime
|
||||
);
|
||||
|
||||
return GetFunctionalPercentageAmount(
|
||||
Effect?.Effect
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function GetGardenPlotHarvestYieldBonus(
|
||||
SaveData,
|
||||
GardenIndex,
|
||||
PlotIndex,
|
||||
AtTime
|
||||
) {
|
||||
const Effect =
|
||||
GetStrongestFunctionalEffectAffectingPlot(
|
||||
SaveData,
|
||||
GardenIndex,
|
||||
PlotIndex,
|
||||
"HarvestYieldBonus",
|
||||
AtTime
|
||||
);
|
||||
|
||||
return GetFunctionalPercentageAmount(
|
||||
Effect?.Effect
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function PlantGardenPlot(
|
||||
SaveData,
|
||||
GardenIndex,
|
||||
PlotIndex,
|
||||
PlantKey,
|
||||
AtTime,
|
||||
Options = {}
|
||||
) {
|
||||
const Garden =
|
||||
GetFunctionalGarden(
|
||||
SaveData,
|
||||
GardenIndex
|
||||
);
|
||||
|
||||
const Plant =
|
||||
Plants?.[PlantKey];
|
||||
|
||||
if (
|
||||
Garden === null ||
|
||||
Plant === undefined ||
|
||||
Garden.Plots?.[PlotIndex] !== null
|
||||
) {
|
||||
return {
|
||||
Changed: false,
|
||||
Planted: false
|
||||
};
|
||||
}
|
||||
|
||||
const ConsumeSeed =
|
||||
Options.ConsumeSeed === true;
|
||||
|
||||
if (ConsumeSeed) {
|
||||
if (
|
||||
typeof TakeSeed !== "function" ||
|
||||
!TakeSeed(
|
||||
SaveData,
|
||||
Plant.Id,
|
||||
1
|
||||
)
|
||||
) {
|
||||
return {
|
||||
Changed: false,
|
||||
Planted: false,
|
||||
MissingSeed: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const GrowthAdvance =
|
||||
Options.ApplyGrowthAdvance === false
|
||||
? 0
|
||||
: GetGardenPlotGrowthAdvance(
|
||||
SaveData,
|
||||
GardenIndex,
|
||||
PlotIndex,
|
||||
AtTime
|
||||
);
|
||||
|
||||
const GrowthTime = Math.max(
|
||||
0,
|
||||
Number(
|
||||
Plant.GrowthTime ?? 0
|
||||
) || 0
|
||||
);
|
||||
|
||||
const PlantedAt =
|
||||
Number(AtTime) -
|
||||
GrowthTime * GrowthAdvance;
|
||||
|
||||
const Rotation =
|
||||
FunctionalDirectionOffsets[
|
||||
Options.Rotation
|
||||
] !== undefined
|
||||
? Options.Rotation
|
||||
: "East";
|
||||
|
||||
Garden.Plots[PlotIndex] = {
|
||||
Plant: PlantKey,
|
||||
PlantedAt,
|
||||
Rotation
|
||||
};
|
||||
|
||||
return {
|
||||
Changed: true,
|
||||
Planted: true,
|
||||
PlantKey,
|
||||
PlotIndex,
|
||||
GrowthAdvance,
|
||||
PlantedAt
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function HarvestGardenPlot(
|
||||
SaveData,
|
||||
GardenIndex,
|
||||
PlotIndex,
|
||||
AtTime,
|
||||
Options = {}
|
||||
) {
|
||||
const Garden =
|
||||
GetFunctionalGarden(
|
||||
SaveData,
|
||||
GardenIndex
|
||||
);
|
||||
|
||||
const Plot =
|
||||
Garden?.Plots?.[PlotIndex] ?? null;
|
||||
|
||||
if (Plot === null) {
|
||||
return {
|
||||
Changed: false,
|
||||
Harvested: false
|
||||
};
|
||||
}
|
||||
|
||||
const Plant =
|
||||
Plants?.[Plot.Plant];
|
||||
|
||||
if (
|
||||
Plant === undefined ||
|
||||
!IsFunctionalPlantMatureAtTime(
|
||||
Plot,
|
||||
Plant,
|
||||
AtTime
|
||||
)
|
||||
) {
|
||||
return {
|
||||
Changed: false,
|
||||
Harvested: false,
|
||||
Immature: Plant !== undefined
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
Options.ExcludeFunctional === true &&
|
||||
IsFunctionalPlant(
|
||||
Plant
|
||||
)
|
||||
) {
|
||||
return {
|
||||
Changed: false,
|
||||
Harvested: false,
|
||||
Excluded: true
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
IsGardenPlotHarvestDisabled(
|
||||
SaveData,
|
||||
GardenIndex,
|
||||
PlotIndex,
|
||||
AtTime
|
||||
)
|
||||
) {
|
||||
return {
|
||||
Changed: false,
|
||||
Harvested: false,
|
||||
Disabled: true
|
||||
};
|
||||
}
|
||||
|
||||
const BaseReward =
|
||||
typeof GetPlantHarvestReward === "function"
|
||||
? GetPlantHarvestReward(
|
||||
SaveData,
|
||||
Plant.Id
|
||||
)
|
||||
: null;
|
||||
|
||||
if (BaseReward === null) {
|
||||
return {
|
||||
Changed: false,
|
||||
Harvested: false,
|
||||
RewardUnavailable: true
|
||||
};
|
||||
}
|
||||
|
||||
const YieldBonus =
|
||||
GetGardenPlotHarvestYieldBonus(
|
||||
SaveData,
|
||||
GardenIndex,
|
||||
PlotIndex,
|
||||
AtTime
|
||||
);
|
||||
|
||||
const RewardAmount = Math.ceil(
|
||||
BaseReward *
|
||||
(1 + YieldBonus)
|
||||
);
|
||||
|
||||
AddFunctionalCurrencyReward(
|
||||
SaveData,
|
||||
"Dew",
|
||||
RewardAmount
|
||||
);
|
||||
|
||||
Garden.Plots[PlotIndex] = null;
|
||||
|
||||
return {
|
||||
Changed: true,
|
||||
Harvested: true,
|
||||
Plant,
|
||||
PlantKey: Plot.Plant,
|
||||
Rotation:
|
||||
GetFunctionalPlotRotation(
|
||||
Plot
|
||||
),
|
||||
RewardAmount,
|
||||
YieldBonus
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function GetFunctionalEligibleSourceTargets(
|
||||
SaveData,
|
||||
Targets,
|
||||
AtTime,
|
||||
RequireMature = true
|
||||
) {
|
||||
return Targets.filter(
|
||||
Target => {
|
||||
const Plot = Target.Plot;
|
||||
|
||||
if (Plot === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Plant =
|
||||
Plants?.[Plot.Plant];
|
||||
|
||||
if (Plant === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
!RequireMature ||
|
||||
IsFunctionalPlantMatureAtTime(
|
||||
Plot,
|
||||
Plant,
|
||||
AtTime
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function SelectFunctionalTarget(
|
||||
SaveData,
|
||||
Targets,
|
||||
Random
|
||||
) {
|
||||
if (Targets.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Random === true
|
||||
? GetFunctionalRandomItem(
|
||||
SaveData,
|
||||
Targets
|
||||
)
|
||||
: Targets[0];
|
||||
}
|
||||
|
||||
|
||||
function HandleFunctionalHarvest(
|
||||
Context
|
||||
) {
|
||||
const Targets =
|
||||
Context.GetTargets();
|
||||
|
||||
let Changed = false;
|
||||
|
||||
for (const Target of Targets) {
|
||||
const Result =
|
||||
HarvestGardenPlot(
|
||||
Context.SaveData,
|
||||
Target.GardenIndex,
|
||||
Target.PlotIndex,
|
||||
Context.AtTime,
|
||||
{
|
||||
ExcludeFunctional:
|
||||
Context.Effect.ExcludeFunctional === true
|
||||
}
|
||||
);
|
||||
|
||||
Changed =
|
||||
Changed ||
|
||||
Result.Changed === true;
|
||||
}
|
||||
|
||||
return {Changed};
|
||||
}
|
||||
|
||||
|
||||
function HandleFunctionalDuplicate(
|
||||
Context
|
||||
) {
|
||||
const SourceArea =
|
||||
GetFunctionalEffectArea(
|
||||
Context.Effect,
|
||||
"Source",
|
||||
"Behind"
|
||||
);
|
||||
|
||||
const TargetArea =
|
||||
GetFunctionalEffectArea(
|
||||
Context.Effect,
|
||||
"Target",
|
||||
"Front"
|
||||
);
|
||||
|
||||
const Sources =
|
||||
GetFunctionalEligibleSourceTargets(
|
||||
Context.SaveData,
|
||||
GetFunctionalAreaTargets(
|
||||
Context.SaveData,
|
||||
Context.GardenIndex,
|
||||
Context.PlotIndex,
|
||||
SourceArea
|
||||
),
|
||||
Context.AtTime,
|
||||
Context.Effect.RequireMatureSource !== false
|
||||
);
|
||||
|
||||
const EmptyTargets =
|
||||
GetFunctionalAreaTargets(
|
||||
Context.SaveData,
|
||||
Context.GardenIndex,
|
||||
Context.PlotIndex,
|
||||
TargetArea
|
||||
).filter(
|
||||
Target => Target.Plot === null
|
||||
);
|
||||
|
||||
const Source =
|
||||
SelectFunctionalTarget(
|
||||
Context.SaveData,
|
||||
Sources,
|
||||
Context.Effect.RandomSource === true
|
||||
);
|
||||
|
||||
const Target =
|
||||
SelectFunctionalTarget(
|
||||
Context.SaveData,
|
||||
EmptyTargets,
|
||||
Context.Effect.RandomTarget === true
|
||||
);
|
||||
|
||||
if (
|
||||
Source === null ||
|
||||
Target === null
|
||||
) {
|
||||
return {Changed: false};
|
||||
}
|
||||
|
||||
return PlantGardenPlot(
|
||||
Context.SaveData,
|
||||
Context.GardenIndex,
|
||||
Target.PlotIndex,
|
||||
Source.Plot.Plant,
|
||||
Context.AtTime,
|
||||
{
|
||||
ConsumeSeed: false
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function HandleFunctionalPlant(
|
||||
Context
|
||||
) {
|
||||
const AssignedSeed =
|
||||
typeof Context.Plot.AssignedSeed === "string"
|
||||
? Context.Plot.AssignedSeed
|
||||
: null;
|
||||
|
||||
if (
|
||||
AssignedSeed === null ||
|
||||
Plants?.[AssignedSeed] === undefined
|
||||
) {
|
||||
return {Changed: false};
|
||||
}
|
||||
|
||||
const TargetArea =
|
||||
GetFunctionalEffectArea(
|
||||
Context.Effect,
|
||||
"Target",
|
||||
"Front"
|
||||
);
|
||||
|
||||
const EmptyTargets =
|
||||
GetFunctionalAreaTargets(
|
||||
Context.SaveData,
|
||||
Context.GardenIndex,
|
||||
Context.PlotIndex,
|
||||
TargetArea
|
||||
).filter(
|
||||
Target => Target.Plot === null
|
||||
);
|
||||
|
||||
const Target =
|
||||
SelectFunctionalTarget(
|
||||
Context.SaveData,
|
||||
EmptyTargets,
|
||||
Context.Effect.RandomTarget === true
|
||||
);
|
||||
|
||||
if (Target === null) {
|
||||
return {Changed: false};
|
||||
}
|
||||
|
||||
return PlantGardenPlot(
|
||||
Context.SaveData,
|
||||
Context.GardenIndex,
|
||||
Target.PlotIndex,
|
||||
AssignedSeed,
|
||||
Context.AtTime,
|
||||
{
|
||||
ConsumeSeed: true
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function HandleFunctionalReplant(
|
||||
Context
|
||||
) {
|
||||
const Targets =
|
||||
Context.GetTargets();
|
||||
|
||||
let Changed = false;
|
||||
|
||||
for (const Target of Targets) {
|
||||
const ExistingPlot = Target.Plot;
|
||||
|
||||
if (ExistingPlot === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const ExistingPlant =
|
||||
Plants?.[ExistingPlot.Plant];
|
||||
|
||||
if (ExistingPlant === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const ConsumeSeed =
|
||||
Context.Effect.ConsumeSeed !== false;
|
||||
|
||||
if (
|
||||
ConsumeSeed &&
|
||||
(
|
||||
typeof GetSeedCount !== "function" ||
|
||||
GetSeedCount(
|
||||
Context.SaveData,
|
||||
ExistingPlant.Id
|
||||
) < 1
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Rotation =
|
||||
GetFunctionalPlotRotation(
|
||||
ExistingPlot
|
||||
);
|
||||
|
||||
const HarvestResult =
|
||||
HarvestGardenPlot(
|
||||
Context.SaveData,
|
||||
Target.GardenIndex,
|
||||
Target.PlotIndex,
|
||||
Context.AtTime,
|
||||
{
|
||||
ExcludeFunctional:
|
||||
Context.Effect.ExcludeFunctional === true
|
||||
}
|
||||
);
|
||||
|
||||
if (!HarvestResult.Harvested) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const PlantResult =
|
||||
PlantGardenPlot(
|
||||
Context.SaveData,
|
||||
Target.GardenIndex,
|
||||
Target.PlotIndex,
|
||||
HarvestResult.PlantKey,
|
||||
Context.AtTime,
|
||||
{
|
||||
ConsumeSeed,
|
||||
Rotation
|
||||
}
|
||||
);
|
||||
|
||||
Changed =
|
||||
Changed ||
|
||||
HarvestResult.Changed === true ||
|
||||
PlantResult.Changed === true;
|
||||
}
|
||||
|
||||
return {Changed};
|
||||
}
|
||||
|
||||
|
||||
function SetFunctionalPlantAssignedSeed(
|
||||
Plot,
|
||||
PlantKey
|
||||
) {
|
||||
if (
|
||||
Plot === null ||
|
||||
typeof Plot !== "object" ||
|
||||
Plants?.[PlantKey] === undefined
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Plot.AssignedSeed = PlantKey;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function ClearFunctionalPlantAssignedSeed(
|
||||
Plot
|
||||
) {
|
||||
if (
|
||||
Plot === null ||
|
||||
typeof Plot !== "object"
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
delete Plot.AssignedSeed;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
RegisterFunctionalEffectHandler(
|
||||
"Harvest",
|
||||
HandleFunctionalHarvest
|
||||
);
|
||||
|
||||
RegisterFunctionalEffectHandler(
|
||||
"Duplicate",
|
||||
HandleFunctionalDuplicate
|
||||
);
|
||||
|
||||
RegisterFunctionalEffectHandler(
|
||||
"Plant",
|
||||
HandleFunctionalPlant
|
||||
);
|
||||
|
||||
RegisterFunctionalEffectHandler(
|
||||
"Replant",
|
||||
HandleFunctionalReplant
|
||||
);
|
||||
|
||||
|
||||
function CreateFunctionalProcessingResult() {
|
||||
return {
|
||||
Attempted: false,
|
||||
|
||||
Reference in new issue
Block a user