RPG courses and Design questions

Hi

I’m working on the two RPG courses. First of all, are there plans for another course in the series, and if so, what will they cover and when will they be released?
Secondly, I’m working on extending the project. Currently working on abilities. I’m making the abilities inherit from ActionItem. However, I’m not sure that would work with what I have in mind.
I want to set the abilities’ properties (range, damage, etc.) at runtime. AFAIK scriptable objects are not persistent on the one hand, but I can’t use the save system on them either. I guess I can make some monobehavior that would initialize them on load with values that I can save with the save system. Alternatively, I can set base values in the SO and pass it through a monobehavior that contains modifiers when they’re being used. Is there a better way that doesn’t occur to me?

yea currently doing the same thing, my approach was going to be similar to what we have done with weapons except it would have an array of damage ( it increase at it goes up ) and the modifier would be from my character stat (ie int & accesories & gears used). However i do believe you can change the value of SO on runtime and it will persist without even saving it. i found this out as a bug when i was playing around with persisting cooldown for my potions

Did you change itthrough the editor at runtime? Because that does persist. But I don’t think changes made through code are supposed to. I’ll test that and see, I guess. Thanks

so what i had on my previous potion SO was its currentimer(to be used to calculate how much left on cd)
and it would updated code wise with a simple += deltatime.
so i monitored the bug closely and can confirm data stored at runtime will safe it on SO even after you exit the play through.

That’s interesting. Did you try it in a build outside of the editor?

Found this in the documentation:
When you use the Editor, you can save data to ScriptableObjects while editing and at run time because ScriptableObjects use the Editor namespace and Editor scripting. In a deployed build, however, you can’t use ScriptableObjects to save data, but you can use the saved data from the ScriptableObject Assets that you set up during development.

Data that you save from Editor Tools to ScriptableObjects as an asset is written to disk and is therefore persistent between sessions.

well i did try both [serialzefield] and just a normal private and on both instance there was still data being stored on the SO even in private. cause the remaining cd would persist even after the play enviroment has ended.

Yes, it should. But it would only work that way while running the game in the editor. If you build the game for running outside of the editor, it wouldn’t work like that anymore .

herm perhaps build a progression for all skills and just have it pull its value on runtime then i suppose.
the modifiers could be added after collecting its base damage. cause i assume you’re planning to scale the damage as the character progresses. Btw seeing as we’re on the same boat atm. have you figured out the way to animate it? so on like a keydown would it reattach a new animoverride on top of what could be the previous animoverride(weapon)

I’m still figuring my approach to this, i haven’t gotten close to thinking about the animation yet. However, I’m not implementing progression on my abilities and I’m not creating any weapons per se. My plan is to let the player design the ability by assigning points to different attributes (range, damage, area of effect, etc.). The same plan goes for weapons, so I’d basically have some sort of forging system. The number of points the player would have to allocate would depend on the player’s level somehow. Currently I’m thinking there would be a small drop chance of a scroll that let’s them create an ability.
As for your issue, I guess you mean different skills with the weapon? like different hits? Why would you have to override the animator? you can have different animations in the same animator , so you just have to add animations to the overriding animator. If you mean using skills that are unrelated to the weapon, why not implement a sheath/unsheath mechanism? It wouldn’t look good to use a casting animation with the sword in hand anyway.

Well cause i still want characters to be able to holding whatever gears they have and each gears have different animation. but skills should just override skills animation. currently the design of the game is each weapon is already an AnimOverride so what happens when you override and override what happens. just wondering if thats the direction im heading

I know that. They override unarmed with sword for instance. I’m talking about the override of the override. What is that supposed to serve? Do you want different hits with the same weapon? That can be implemented in the same animator (of the character with the sword, the one overriding unarmed), AFAIK.

So lets say i have these sets of animations
move(forward,back etc)
Attack(weapon default attack)
skill 1
skill 2

So default animation is unarmed
a player then equip a sword so swordAnimOver used which populates movements and attack
then a player press skill at slot1 which then uses the skillAnimOver which populates only skill1 and skill 2
will that then wipe the previous swordAnimOver which had the attack and movement populated

The override contains the animations that the original animator had. They can be overridden or not, but the list of animations remains the same. I guess you would have to have animations for the skills for every weapon the player may hold. I own the full version of the animations asset they use here, and indeed it contains a different version for every weapon type and unarmed. So in the original unarmed you need to have the unarmed version of the skill, even if you can’t use that skill when unarmed, and then override it where you need . That’s the extent of my understanding of the matter, which may very well be less than yours.

yea so i tried playing around with the idea, and found out nope you cant override and overrideAnimCon.
guess have to find a different approach to doing this, Now im thinking perhaps on casting spell temporarily remove the overrideAnim(and hide the weapon it is holding) and fall back to unarmed and override attach the override briefly before removing it and reattaching the previous weapon override

My approach to dealing with modifying InventoryItems (and ActionItems at their core are just InventoryItems) is to give them the ability to save themselves in the SavingSystem.
The first thing you need to do is to Instantiate the InventoryItem and make your modifications on the copy of the SO, not the original SO itself. When you CaptureState your Inventory/Actionbar/etc, save the UUID of the ScriptableObject, and Capture the state from the instantiated SO. when you restore, instantiate the SO and Restore it’s state.

Where do I put the saveable entity ? I can’t attach it to a SO, so how can it have a uuid?

Your SO actually has a UUID so that you can save a reference to it in InventoryItem. In each of the stores (Inventory, ActionBar, Equipment, ItemDropper) you have the SaveableEntity. These are the objects responsible for saving the reference to SO so that you can capture/restore their existence.
In the SO itself, you don’t need a SaveableEntity (that won’t even make sense), but you can implement the ISaveable interface with them…

In the backing stores, you’ll need to save a bit more than the ID… you’ll also need to run CaptureState on the ScriptableObject you’re saving and get it’s information.

I added CaptureState/RestoreState to InventoryItem, but I made them abstract, so that each of the things that overrides them must implement their own CaptureState/RestoreState as override.

Then in the structures for saving in each of the stores, I added a public object state
Here’s an example in Inventory:

[System.Serializeable]
private struct InventorySlotRecord
{
    public string itemID;
    public int number;
    public object state;
}

object ISaveable.CaptureState()
        {
            var slotStrings = new InventorySlotRecord[inventorySize];
            for (int i = 0; i < inventorySize; i++)
            {
                if (slots[i].item != null)
                {
                    slotStrings[i].itemID = slots[i].item.GetItemID();
                    slotStrings[i].number = slots[i].number;
                    slotStrings[i].state = slots[i].item.CaptureState();
                }
            }
            return slotStrings;
        }

        void ISaveable.RestoreState(object state)
        {
            var slotStrings = (InventorySlotRecord[])state;
            for (int i = 0; i < inventorySize; i++)
            {
                slots[i].item = Instantiate(InventoryItem.GetFromID(slotStrings[i].itemID));
                slots[i].number = slotStrings[i].number;
                slots[i].item.RestoreState(slotStrings[i].state;
            }
            if (inventoryUpdated != null)
            {
                inventoryUpdated();
            }
        }