Jump to content

Recommended Posts

Hello everyone,

 

I’m working on a DST mod (Client-only) where I have a custom component named aoespell,

and I want to override its CanCast method specifically for Willow’s Fire Ball in client-only mode, so that certain conditions can block the action.

 

However, my AddComponentPostInit("aoespell", …) hook never seems to execute, and aoespell never appears to be loaded or initialized as expected.

 

Below is the relevant snippet I placed in modmain.lua:

-- modmain.lua
-- ...
-- ...

AddComponentPostInit("aoespell", function(self)
    print("[SafeFireCaller] AddComponentPostInit for 'aoespell' executed on: "..tostring(self.inst.prefab))
    local OriginalCanCast = aoespell.CanCast
    aoespell.CanCast = function(self, doer, pos)
        print("[SafeFireCaller] OriginalCanCast called for aoespell on: " .. tostring(self.inst.prefab))
        
        if not doer or not pos then
            print("[SafeFireCaller] doer or pos is nil, returning false.")
            return false
        end

        if self.inst.components.spellbook and
            self.inst.components.spellbook.spell_name == GLOBAL.STRINGS.PYROMANCY.FIRE_BALL then
            print("[SafeFireCaller] Fire Ball spell detected. Checking ShouldBlockFireAction...")
            local fake_act = { doer = doer, invobject = self.inst, pos = pos }
            if ShouldBlockFireAction(fake_act) then
                print("[SafeFireCaller] Fire Ball action blocked by returning false.")
                return false
            end
        else
            print("[SafeFireCaller] Not a Fire Ball spell, proceeding with original CanCast logic.")
        end
        return OriginalCanCast(self, doer, pos)
    end
end)

 

What I expect:

  • When my player (or any entity with aoespell component) is initialized or when the component is added, the AddComponentPostInit("aoespell", …) should run and patch CanCast.

  • Later, when Willow attempts to cast Fire Ball (client-only), the overridden CanCast should check ShouldBlockFireAction(...) and block if needed.

What actually happens:

  • There is no print output from [SafeFireCaller] AddComponentPostInit for 'aoespell' executed on: ..., implying the hook never fires.

  • It seems aoespell component is not even being added or initialized, so the override never takes place.

 

Questions:

  1. How can I ensure my hook for aoespell fires reliably? Does the component need to be registered earlier or in a different way?

  2. Are there best practices for overriding a component’s method like CanCast in DST mods, especially when targeting client-only or server-only logic?

  3. Is there a more fundamental or built-in way in DST to conditionally block Willow’s skill (Fire Ball) before it executes, rather than relying solely on overriding CanCast in a custom component?

 

Thank you in advance for any guidance or examples.

I’d appreciate pointers on correct ordering, hooking patterns, or known pitfalls when overriding component methods in DST mods.

 

I also tried intercepting via DoAction (e.g., wrapping or overriding the relevant action), and it correctly recognizes Fire Ball as a spell.

local oldDoAction = self.DoAction
self.DoAction = function(self, action, ...)
    print("[SafeFireCaller] DoAction hook triggered.")

    if not action then
        print("[SafeFireCaller] Action is nil, calling original DoAction.")
        return oldDoAction(self, action, ...)
    end

    local action_id = action.action and action.action.id
    local doer = action.doer or self.inst

    print("[SafeFireCaller] Details - action_id: " .. tostring(action_id) .. ", doer: " .. tostring(doer and doer.prefab))

    local is_willow_action = GetModConfigData("enable_willow") and
                                doer and doer.prefab == "willow" and
                                action.invobject and action.invobject.prefab == "willow_ember"
    print("[SafeFireCaller] 'is_willow_action' check result: " .. tostring(is_willow_action))

    if is_willow_action then
        print("[SafeFireCaller] Action matched. Calling ShouldBlockFireAction...")
        action.doer = doer
        if ShouldBlockFireAction(action) then
            print("[SafeFireCaller] ShouldBlockFireAction returned true. ACTION BLOCKED by returning nil.")
            return
        else
            print("[SafeFireCaller] ShouldBlockFireAction returned false. Action allowed to proceed.")
        end
    else
            print("[SafeFireCaller] Action did not match protection criteria.")
    end

    print("[SafeFireCaller] Calling original DoAction.")
    return oldDoAction(self, action, ...)
end

 

However, even if I return false or block in that hook on the client, the skill still executes on the server.

My guess is that the client’s DoAction occurs, sends the request to the server immediately, and then my return only affects local logic after the packet is already sent.

 

 

 

Edited by PIGNOSE

Never mind, I've found the cause.

After reading the willow_ember prefab code in Don't Starve, I saw that the aoespell component is added on the server-side.

Therefore, after reading the detailed implementation of the PlayerController, I hooked the OnLeftClick function of that component. During AEOTargeting, I used the spell information from the component's reticule to attempt an action block, which allowed me to implement the desired behavior.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
  • Create New...