Skip to content

Instantly share code, notes, and snippets.

@Yanrishatum
Created April 13, 2021 08:29
Show Gist options
  • Save Yanrishatum/72cd37714d3d3c371f382d4f0c09c07d to your computer and use it in GitHub Desktop.
Save Yanrishatum/72cd37714d3d3c371f382d4f0c09c07d to your computer and use it in GitHub Desktop.
Macro-powered tweak handler
import hxd.Res;
import core.util.IniFile;
typedef T = Tweaks;
class Tweaks {
// First part is category, i.e. PLAYER_, WORLD_, ENEMY_, etc.
// The rest it tweak name.
// Add @:name("something") to set the tweak name in the .ini file
// Add @:post(expr) to perform some action after the tweak was loaded.
public static var PLAYER_MAX_SPEED = 60.;
public static var PLAYER_SLOPE_ANGLE = .49;
public static var PLAYER_SPEED = 360.;
public static var PLAYER_COYOTE_FRAMES = 8;
public static var PLAYER_JUMP_FORCE = -160.;
public static var PLAYER_GRAVITY = 1.0;
public static var PLAYER_GRAVITY_APEX = 0.8;
public static var PLAYER_APEX_VELOCITY = 4.0;
@:post(if (stl.Stealer.INSTANCE != null) stl.Stealer.INSTANCE.phys.body.drag.x = Tweaks.PLAYER_DRAG_X)
@:name("drag.x") public static var PLAYER_DRAG_X = 300.;
// World
@:post(if (core.Game.i != null && core.Game.i.world != null) core.Game.i.world.gravity.y = Tweaks.WORLD_GRAVITY)
@:name("gravity.y") public static var WORLD_GRAVITY = 200.;
#if debug
static function saveTweaks() {
// IniFile is pretty simple parser of .ini files, and can be replaced with anything that have
// getFloat, setFloat, getInt, setInt, getBool, setBool and get, set methods.
// get should take category, name, and default value params.
// set should take category, name and value params.
// And obviously load/save methods.
var i = new IniFile();
i.load(Res.tweaks.entry.getText());
core.macro.TweakSaver.save();
sys.io.File.saveContent(Res.loader.getAbsPath(Res.tweaks.entry.path), i.save());
}
static function loadTweaks() {
var i = new IniFile();
i.load(Res.tweaks.entry.getText());
core.macro.TweakSaver.load();
}
#end
}
package core.macro;
import haxe.macro.Context;
using haxe.macro.Tools;
class TweakSaver {
public static macro function load() {
var res = [];
for (field in Context.getLocalClass().get().statics.get()) {
switch (field.kind) {
case FVar(read, write):
var name = field.name;
var category = name.substr(0, name.indexOf("_")).toLowerCase();
var iniName = name.substr(name.indexOf("_")+1).toLowerCase();
var tmp = field.meta.extract(":name");
if (tmp.length > 0) iniName = tmp[0].params[0].getValue();
var method = "getFloat";
switch (field.type) {
case TInst(_.get() => t, _):
if (t.name == "String") method = "get";
else throw "Unsupported type: " + field.type.toString();
case TAbstract(_.get() => t, _):
switch (t.name) {
case "Int": method = "getInt";
case "Bool": method = "getBool";
case "Float":
default: throw "Unsupported type: " + field.type.toString();
}
default: throw "Unsupported type: " + field.type.toString();
}
res.push(macro Tweaks.$name = i.$method($v{category}, $v{iniName}, Tweaks.$name));
tmp = field.meta.extract(":post");
for (e in tmp) for (p in e.params) res.push(p);
default:
}
}
return macro $b{res};
}
public static macro function save() {
var res = [];
for (field in Context.getLocalClass().get().statics.get()) {
switch (field.kind) {
case FVar(read, write):
var name = field.name;
var category = name.substr(0, name.indexOf("_")).toLowerCase();
var iniName = name.substr(name.indexOf("_")+1).toLowerCase();
var tmp = field.meta.extract(":name");
if (tmp.length > 0) iniName = tmp[0].params[0].getValue();
var method = "setFloat";
switch (field.type) {
case TInst(_.get() => t, _):
if (t.name == "String") method = "set";
else throw "Unsupported type: " + field.type.toString();
case TAbstract(_.get() => t, _):
switch (t.name) {
case "Int": method = "setInt";
case "Bool": method = "setBool";
case "Float":
default: throw "Unsupported type: " + field.type.toString();
}
default: throw "Unsupported type: " + field.type.toString();
}
res.push(macro i.$method($v{category}, $v{iniName}, Tweaks.$name));
tmp = field.meta.extract(":post");
for (e in tmp) for (p in e.params) res.push(p);
default:
}
}
return macro @:privateAccess $b{res};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment