Conversation
…o log all the properties and injections from the Game API
…ation about properties, operations, operationsgroups
…gic editor also now there is a MagicExporter class
| /// Gets the StaticActorInfo pointer for the player (Clive). | ||
| /// </summary> | ||
| /// <returns>StaticActorInfo pointer, or nint.Zero if not available.</returns> | ||
| nint GetPlayerStaticActorInfo(); |
There was a problem hiding this comment.
Don't return pointers in APIs, return specific interfaces.
| /// The game's targeting system already calculates the correct position. | ||
| /// </summary> | ||
| /// <returns>A copy of the game's TargetStruct with Type=1 forced, or null if no target.</returns> | ||
| TargetStruct? CopyGameTargetStruct(); |
There was a problem hiding this comment.
Same here, don't return structs. Wrap them in interfaces.
| /// Represents a single modification to a magic spell. | ||
| /// This is the public representation of modifications that will be applied. | ||
| /// </summary> | ||
| public record MagicModification |
| /// JSON-serializable format for magic spell modifications. | ||
| /// This structure is designed to be human-readable and easy to edit manually. | ||
| /// </summary> | ||
| public class MagicSpellConfig |
| /// <summary> | ||
| /// JSON-serializable format for a single modification. | ||
| /// </summary> | ||
| public class MagicModificationConfig |
| /// This enables mods to register their modifications once and have them automatically | ||
| /// applied whenever the game loads (or reloads) the magic files. | ||
| /// </summary> | ||
| public class MagicWriter : IMagicWriter, IDisposable |
There was a problem hiding this comment.
MagicWriterAPI (I'm adding the API to it's name) modifies the .magic file in memory using your FF16Tools.Files.Magic edit functions:
- Hooks into resource loading
- When a .magic file loads, applies all registered MagicBuilder modifications directly to the parsed file structure
- Changes happen before any magic execution
- Zero runtime cost when casting spells
It's the best for permanent modifications to spell behavior.
My idea is to add here the interface to add new MagicIds, the function will the return the ID assigned:
int CreateNewMagicID(string modID, IMagicBuilder builder, string characterId, string magicFileName=Null)
MagicAPI applies modifications at execution time:
- Intercepts magic casting calls
- Applies modifications on-the-fly during spell execution
- Has computational overhead per cast
It's the best for: dynamic modifications that change based on game state (e.g., different VFXs based on combo count, number of projectiles, casting Eid, etc.)
Why both exist:
With MagicWriter: permanent spell tweaks are "baked in" at load time.
With MagicAPI: add situational modifications are applied only when needed.
MagicBuilder is the shared component that defines what modifications to apply to a specific MagicID. Both MagicAPI and MagicWriterAPI consume it.
| public static void AddScan(this IStartupScanner scans, string pattern, Action<nint> action) | ||
| { | ||
| var baseAddress = Process.GetCurrentProcess().MainModule!.BaseAddress; | ||
| scans!.AddMainModuleScan(pattern, result => | ||
| { | ||
| if (!result.Found) | ||
| throw new Exception($"Scan unable to find pattern: {pattern}!"); | ||
| action(result.Offset + baseAddress); | ||
| }); | ||
| } |
There was a problem hiding this comment.
I will check how did you do the Scanning to do the same on my code.
| namespace FF16Framework.Services.GameApis.Magic; | ||
|
|
||
| /// <summary> | ||
| /// Handles magic file processing, property fuzzing, and injection logic. |
There was a problem hiding this comment.
It's a term used for automating injections or modification to data used by a piece of software. I will change it to terms like modification and injection.
There was a problem hiding this comment.
It is frequently used in the context of finding vulnerabilities in software
| _imGui.MenuItemBoolPtr("Property Logging"u8, ""u8, ref _frameworkConfig.GameApis.MagicApi.EnablePropertyLoggingField, true); | ||
| _imGui.MenuItemBoolPtr("Injection Logging"u8, ""u8, ref _frameworkConfig.GameApis.MagicApi.EnableInjectionLoggingField, true); |
There was a problem hiding this comment.
This needs to be made clearer, too vague otherwise
There was a problem hiding this comment.
Will do, I will change them to "Log all the properties from casted Magic" and "Log all the injections/modifications done to magic from the MagicAPI"
|
I left a good amount of comments but haven't tested the behavior yet, so consider it just a code quality review for now. My main issue with the code at the moment besides the reviews are the excessive amount of comments/docs that are pretty vague, I suspect you've used AI here and it has done a pretty poor job conveying the intent Can you make a quick summary of how the API(s) are meant to be used? Some parts of it seems pretty overengineered and I wonder how this looks like for any consumer. Furthermore since this is only really intended for FFXVI, service related code should probably go somewhere in |
|
I will add here how is the APIs used in tandem from the MagicAPI to the MagicWriterAPI: // =====================================================
// Simplified example of MagicAPI + MagicWriter usage
// Based on DiaModifications.json for Diara system
// =====================================================
// 1. Create a builder to modify Dia spell (ID=214)
var builder = _magicApi.CreateSpell(magicId: 214);
// 2. (Optional) Import from JSON to avoid steps 3, 4, 5
// builder.ImportFromFile("DiaModifications.json");
// 3. Remove the linear trajectory operation
// RemoveOperation(operationGroupId, operationId)
builder.RemoveOperation(4338, 1); // Remove Operation_1 (LinearHomingTrajectory)
// 4. Modify existing properties
// SetProperty(operationGroupId, operationId, propertyId, value)
builder.SetProperty(4338, 35, 35, 10.0f); // Duration = 10 seconds
// 5. Add parabolic trajectory operation with properties
// AddOperation(operationGroupId, operationId, propertyIds, values)
builder.AddOperation(
operationGroupId: 4338,
operationId: 2493, // ParabolaTrajectory
propertyIds: new[] { 187, 8, 2430, 2593 },
values: new object[]
{
2, // TrajectoryType
55.0f, // Speed
new Vector3(-90.0f, 0.0f, 0.0f), // TrajectoryRotation
2.0f // TrajectoryCurveStrength
}
);
// 6. Register to write changes to the .magic file
var handle = _magicWriter.Register(
modId: "truly.eikonic.spells",
builder: builder,
characterId: "c1001" // Clive
);
// 7. (Optional) Cast the modified Dia spell at runtime
_magicApi.Cast(magicId: 214);
// 8. Unregister when unloading the mod
_magicWriter.Unregister(handle);I will add examples onto the interfaces. |
Co-authored-by: Nenkai <Nenkai@users.noreply.github.com>
… added new interfaces to add and remove multiple properties at a time & improved export to JSON functionality to condense the JSON file size
…eceive a enum to choose source and target
…MagicBuilder, MagicWriter.
… the entire magicID before applying the modifications
Core Magic API
Magic Writer API
Magic Builder Enhancements
Magic Editor UI
Debugging & Configuration