Skip to content

Contributing New Effects

milkytoasto edited this page Mar 11, 2023 · 2 revisions

Summary

Every new effect should contain implementations of the _on_start and _on_stop functions, as well as have a field for name and config_alias. The config_alias should match what you decide to name the effect in the corresponding game configuration file.

Calls will be made to the inherited class's start method which will make calls to _on_start. Likewise for stop and _on_stop.

For more advanced functionality, there is also the _on_tick method which will get called each time a second passes. This can be used to have an effect that does different things over a period of time.

Example (Dark Souls Remastered's Big Head Effect)

class BigHead(DSREffect):
    name = "Big Head Mode"
    config_alias = "big_head"

    async def _set_head_size(self, size):
        BaseB = BaseAddress.BaseB(self.pm, self.module)
        head_pointer = Pointer.Player.Body.head_size(self.pm, BaseB)
        memory.write_float(self.pm.process_handle, head_pointer, size)

    async def _on_start(self):
        await self._set_head_size(20)
        await self.tick(self.seconds)

    async def _on_stop(self):
        await self._set_head_size(0)

As you can see here, the big head effect relies on the base address BaseB as well as a pointer to the player's head size. This information has been grabbed from using cheat engine to discover these pointers as well as base addresses.

If we look at the pointer file, with the irrelevant parts excluded...

def _get_pointer(pm, base, offsets=False):
    addr = pm.read_ulonglong(base)

    if not offsets:  # No offsets, return address
        return addr

    for i in offsets[:-1]:  # Loop over all but the last
        addr = pm.read_ulonglong(addr + i)
    return addr + offsets[-1]


class PointerOffsets:
    class Player:
        class Body:
            HEAD_SIZE = [0x10, 0x388]

class Pointer:
    class Player:
        class Body:
            def head_size(pm, BaseB):
                return _get_pointer(pm, BaseB, PointerOffsets.Player.Body.HEAD_SIZE)

You can see that the PlayerHeadSize pointer is obtained by using the BaseB parameter as well as using offsets provided from PointerOffsets. The corresponding pointer offsets are [0x10, 0x388].

Using this information, we can see that this corresponds pretty closely to how the attribute is access in a fairly popular cheat engine table for Dark Souls Remastered, with a base address labelled BaseB and offsets [0x10, 0x388].

All of the effects for the chaos mod have been obtained using cheat engine to find the necessary values to make the changes we want. Therefore, a firm understanding of how to edit values using cheat engine as well as find them is greatly recommended.

It's worth noting that at the time of this writing, integrity checks haven't been handled properly with the current implementation of this mod. This means certain effects such as mob vacuum, noclip, etc. likely will not work if you try to implement them.

Clone this wiki locally