-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Created example_mods w/ Gravity Manipulator script
- Loading branch information
1 parent
8ec1661
commit a5ff924
Showing
1 changed file
with
63 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import logging | ||
import ctypes | ||
from dataclasses import dataclass | ||
|
||
from pymhf.core.hooking import disable, on_key_pressed | ||
from pymhf.core.memutils import map_struct | ||
from pymhf.core.mod_loader import ModState | ||
from nmspy import NMSMod | ||
from pymhf.core.calling import call_function | ||
import pymhf.core.hooking | ||
from pymhf import FUNCDEF | ||
from pymhf.core.module_data import module_data | ||
from pymhf.gui import FLOAT | ||
|
||
# A quick mod used to change the gravity multiplier on all planets simultaneously, utilizing pyMHF's auto-gui. | ||
|
||
@dataclass | ||
class gravModState(ModState): #A special class inheriting from ModState which persists between mod Hot Reloads, allowing mod developers to cache pointers, values etc. | ||
Gravity: int = 1 | ||
planetAddresses= list() | ||
|
||
@disable | ||
class gravityManipulator(NMSMod): | ||
#General "Nice To Have"s | ||
__author__ = "ThatBomberBoi" | ||
__description__ = "Gravity Manipulator" | ||
__version__ = "0.1" | ||
__NMSPY_required_version__ = "0.7.0" | ||
|
||
#Create an instance of the persistant ModState Class in your mod class. | ||
state = gravModState() | ||
|
||
def __init__(self): | ||
super().__init__() | ||
self.should_print = False | ||
|
||
#Used to define a Float Type with a label in the Mod GUI, autogenerated by pyMHF. | ||
@property | ||
@FLOAT("Gravity Multiplier:") | ||
def gravMult(self): | ||
return self.state.Gravity | ||
|
||
#Used to actually update the persisted value with the one input by the user in the GUI. | ||
@gravMult.setter | ||
def gravMult(self, value): | ||
self.state.Gravity = value | ||
|
||
#Define the FUNCDEF for the function you want to hook, including the return-type and arguments as identified via decompilers (e.x. IDA). | ||
regionSetupFuncDef = FUNCDEF(restype=None, argtypes=[ctypes.c_ulonglong]) | ||
|
||
#The decorator used to tie a hook to a function. The tied function gets called whenever the in-game function is called. Requires a Function Signature as generated by plugins such as SigMakerEx for IDA. | ||
# If the function you're hooking hasn't changed since 4.13 - Fractals, you can use this lil trick I've done here, and save yourself having to manually write out a FUNCDEF. | ||
@pymhf.core.hooking.manual_hook(name="cGcPlanet::SetupRegionMap", pattern="48 89 5C 24 10 48 89 6C 24 18 56 57 41 56 48 83 EC 40 48 8B D9 8B", func_def=module_data.FUNC_CALL_SIGS["cGcPlanet::SetupRegionMap"], detour_time="after") | ||
def onRegionMap(self, this): #Include each in-game function's arguments seperately in the function, or use *args to inspect all arguments without knowing them prior. | ||
logging.info(f"Generated A Planet!") | ||
self.state.planetAddresses.append(this) | ||
logging.debug(f"Found {len(self.state.planetAddresses)} Planets So Far") | ||
|
||
@on_key_pressed("o") | ||
def modifyGravity(self): | ||
for i in self.state.planetAddresses: | ||
call_function("cGcPlanet::UpdateGravity", i, self.state.Gravity, pattern="40 53 48 83 EC 40 83 B9 78") #Used to call an in-game function directly from your mod code. You will need to provide the arguments for the in-game function, as well as the function signature. | ||
logging.info(f"Set Planetary Gravity Multiplier To {self.state.Gravity} For All Planets") |