diff options
| author | Magnus Auvinen <magnus.auvinen@gmail.com> | 2008-02-02 12:38:36 +0000 |
|---|---|---|
| committer | Magnus Auvinen <magnus.auvinen@gmail.com> | 2008-02-02 12:38:36 +0000 |
| commit | 1fe3202f0b7e2f52e50c430caa744b029fd5bcef (patch) | |
| tree | e238b0f211badb35fecdc3f87fe32978fd512b5e /src/game | |
| parent | 307c2cfae8fd678b10235bdc0c1a8cfc7da6adae (diff) | |
| download | zcatch-1fe3202f0b7e2f52e50c430caa744b029fd5bcef.tar.gz zcatch-1fe3202f0b7e2f52e50c430caa744b029fd5bcef.zip | |
cleaned up the console code. added the ability to tune the game in runtime.
Diffstat (limited to 'src/game')
| -rw-r--r-- | src/game/client/gc_client.cpp | 77 | ||||
| -rw-r--r-- | src/game/client/gc_client.h | 1 | ||||
| -rw-r--r-- | src/game/client/gc_console.cpp | 26 | ||||
| -rw-r--r-- | src/game/client/gc_hooks.cpp | 11 | ||||
| -rw-r--r-- | src/game/editor/ed_editor.hpp | 1 | ||||
| -rw-r--r-- | src/game/g_game.cpp | 79 | ||||
| -rw-r--r-- | src/game/g_game.h | 30 | ||||
| -rw-r--r-- | src/game/g_mapitems.h | 5 | ||||
| -rw-r--r-- | src/game/g_math.h | 26 | ||||
| -rw-r--r-- | src/game/g_protocol.h | 22 | ||||
| -rw-r--r-- | src/game/g_tuning.h | 17 | ||||
| -rw-r--r-- | src/game/g_variables.h | 4 | ||||
| -rw-r--r-- | src/game/server/gs_common.h | 2 | ||||
| -rw-r--r-- | src/game/server/gs_game_ctf.cpp | 2 | ||||
| -rw-r--r-- | src/game/server/gs_server.cpp | 71 |
15 files changed, 295 insertions, 79 deletions
diff --git a/src/game/client/gc_client.cpp b/src/game/client/gc_client.cpp index 27021c1f..c092ca73 100644 --- a/src/game/client/gc_client.cpp +++ b/src/game/client/gc_client.cpp @@ -35,6 +35,7 @@ bool menu_active = false; bool menu_game_active = false; static bool emoticon_selector_active = false; +tuning_params tuning; vec2 mouse_pos; vec2 local_character_pos; @@ -1439,14 +1440,6 @@ void render_game() } } - if(client_connection_problems()) - { - gfx_mapscreen(0, 0, 300*gfx_screenaspect(), 300); - const char *text = "Connection Problems..."; - float w = gfx_text_width(0, 24, text, -1); - gfx_text(0, 150*gfx_screenaspect()-w/2, 50, 24, text, -1); - } - if(config.debug && local_character && local_prev_character) { gfx_mapscreen(0, 0, 300*gfx_screenaspect(), 300); @@ -1496,5 +1489,73 @@ void render_game() render_goals(width/2-w/2, 150+750+25, w); render_spectators(width/2-w/2, 150+750+25+50+25, w); } + + + + { + gfx_mapscreen(0, 0, 300*gfx_screenaspect(), 300); + + if(client_connection_problems()) + { + const char *text = "Connection Problems..."; + float w = gfx_text_width(0, 24, text, -1); + gfx_text(0, 150*gfx_screenaspect()-w/2, 50, 24, text, -1); + } + + tuning_params standard_tuning; + + // render warning about non standard tuning + bool flash = time_get()/(time_freq()/2)%2 == 0; + if(config.cl_warning_tuning && memcmp(&standard_tuning, &tuning, sizeof(tuning_params)) != 0) + { + const char *text = "Warning! Server is running non-standard tuning."; + if(flash) + gfx_text_color(1,0.4f,0.4f,1.0f); + else + gfx_text_color(0.75f,0.2f,0.2f,1.0f); + gfx_text(0x0, 5, 40, 6, text, -1); + gfx_text_color(1,1,1,1); + } + + // render tuning debugging + if(config.dbg_tuning) + { + float y = 50.0f; + int count = 0; + for(int i = 0; i < tuning.num(); i++) + { + char buf[128]; + float current, standard; + tuning.get(i, ¤t); + standard_tuning.get(i, &standard); + + if(standard == current) + gfx_text_color(1,1,1,1.0f); + else + gfx_text_color(1,0.25f,0.25f,1.0f); + + float w; + float x = 5.0f; + + sprintf(buf, "%.2f", standard); + x += 20.0f; + w = gfx_text_width(0, 5, buf, -1); + gfx_text(0x0, x-w, y+count*6, 5, buf, -1); + + sprintf(buf, "%.2f", current); + x += 20.0f; + w = gfx_text_width(0, 5, buf, -1); + gfx_text(0x0, x-w, y+count*6, 5, buf, -1); + + x += 5.0f; + gfx_text(0x0, x, y+count*6, 5, tuning.names[i], -1); + + count++; + } + } + + gfx_text_color(1,1,1,1); + } + } diff --git a/src/game/client/gc_client.h b/src/game/client/gc_client.h index def3cad8..63c74d77 100644 --- a/src/game/client/gc_client.h +++ b/src/game/client/gc_client.h @@ -25,6 +25,7 @@ extern const obj_player_character *local_prev_character; extern const obj_player_info *local_info; extern const obj_flag *flags[2]; extern const obj_game *gameobj; +extern tuning_params tuning; // predicted players extern player_core predicted_prev_player; diff --git a/src/game/client/gc_console.cpp b/src/game/client/gc_console.cpp index b8f090ea..d462156b 100644 --- a/src/game/client/gc_console.cpp +++ b/src/game/client/gc_console.cpp @@ -39,6 +39,8 @@ static float time_now() return float(time_get()-time_start)/float(time_freq()); } + + static void client_console_print(const char *str) { int len = strlen(str); @@ -66,39 +68,21 @@ static void client_console_print(const char *str) //dbg_msg("console", "FROM CLIENT!! %s", str); } -static void connect_command(struct lexer_result *result, void *user_data) -{ - const char *address; - extract_result_string(result, 1, &address); - client_connect(address); -} -static void disconnect_command(struct lexer_result *result, void *user_data) -{ - client_disconnect(); -} - -static void quit_command(struct lexer_result *result, void *user_data) -{ - client_quit(); -} - -static void con_team(struct lexer_result *result, void *user_data) +static void con_team(void *result, void *user_data) { int new_team; - extract_result_int(result, 1, &new_team); + console_result_int(result, 1, &new_team); send_switch_team(new_team); } void client_console_init() { console_register_print_callback(client_console_print); - MACRO_REGISTER_COMMAND("quit", "", quit_command, 0x0); - MACRO_REGISTER_COMMAND("connect", "s", connect_command, 0x0); - MACRO_REGISTER_COMMAND("disconnect", "", disconnect_command, 0x0); MACRO_REGISTER_COMMAND("team", "i", con_team, 0x0); } + void console_handle_input() { int was_active = console_active(); diff --git a/src/game/client/gc_hooks.cpp b/src/game/client/gc_hooks.cpp index 3c8d801d..0acd1c41 100644 --- a/src/game/client/gc_hooks.cpp +++ b/src/game/client/gc_hooks.cpp @@ -5,6 +5,7 @@ extern "C" { #include <engine/e_config.h> #include <engine/client/ec_font.h> + #include <engine/e_console.h> }; #include <game/generated/gc_data.h> @@ -25,7 +26,7 @@ extern void menu_init(); extern bool menu_active; extern bool menu_game_active; -extern "C" void modc_preinit() +extern "C" void modc_console_init() { client_console_init(); } @@ -109,6 +110,7 @@ extern "C" void modc_predict() // repredict player world_core world; + world.tuning = tuning; int local_cid = -1; // search for players @@ -437,10 +439,15 @@ extern "C" void modc_message(int msg) client_datas[cid].update_render_info(); } + else if(msg == MSG_TUNE_PARAMS) + { + int *params = (int *)&tuning; + for(unsigned i = 0; i < sizeof(tuning_params)/sizeof(int); i++) + params[i] = msg_unpack_int(); + } else if(msg == MSG_WEAPON_PICKUP) { int weapon = msg_unpack_int(); - picked_up_weapon = weapon+1; } else if(msg == MSG_READY_TO_ENTER) diff --git a/src/game/editor/ed_editor.hpp b/src/game/editor/ed_editor.hpp index 80ca42d5..2bbc4e08 100644 --- a/src/game/editor/ed_editor.hpp +++ b/src/game/editor/ed_editor.hpp @@ -4,6 +4,7 @@ #include <math.h> #include "array.h" #include "../g_mapitems.h" +#include "../g_math.h" #include "../client/gc_render.h" extern "C" { diff --git a/src/game/g_game.cpp b/src/game/g_game.cpp index 98ae8c47..74b9aed4 100644 --- a/src/game/g_game.cpp +++ b/src/game/g_game.cpp @@ -1,6 +1,50 @@ /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ +#include <string.h> #include "g_game.h" +const char *tuning_params::names[] = +{ + #define MACRO_TUNING_PARAM(name,value) #name, + #include "g_tuning.h" + #undef MACRO_TUNING_PARAM +}; + + +bool tuning_params::set(int index, float value) +{ + if(index < 0 || index >= num()) + return false; + ((tune_param *)this)[index] = value; + return true; +} + +bool tuning_params::get(int index, float *value) +{ + if(index < 0 || index >= num()) + return false; + *value = (float)((tune_param *)this)[index]; + return true; +} + +bool tuning_params::set(const char *name, float value) +{ + for(int i = 0; i < num(); i++) + if(strcmp(name, names[i]) == 0) + return set(i, value); + return false; +} + +bool tuning_params::get(const char *name, float *value) +{ + for(int i = 0; i < num(); i++) + if(strcmp(name, names[i]) == 0) + return get(i, value); + + return false; +} + + + // TODO: OPT: rewrite this smarter! void move_point(vec2 *inout_pos, vec2 *inout_vel, float elasticity, int *bounces) { @@ -125,11 +169,11 @@ void player_core::tick() vec2 direction = normalize(vec2(input.target_x, input.target_y)); - vel.y += gravity; + vel.y += world->tuning.gravity; - float max_speed = grounded ? ground_control_speed : air_control_speed; - float accel = grounded ? ground_control_accel : air_control_accel; - float friction = grounded ? ground_friction : air_friction; + float max_speed = grounded ? world->tuning.ground_control_speed : world->tuning.air_control_speed; + float accel = grounded ? world->tuning.ground_control_accel : world->tuning.air_control_accel; + float friction = grounded ? world->tuning.ground_friction : world->tuning.air_friction; // handle movement if(input.left) @@ -153,13 +197,13 @@ void player_core::tick() if(grounded) { triggered_events |= COREEVENT_GROUND_JUMP; - vel.y = -ground_jump_speed; + vel.y = -world->tuning.ground_jump_impulse; jumped |= 1; } else if(!(jumped&2)) { triggered_events |= COREEVENT_AIR_JUMP; - vel.y = -ground_air_speed; + vel.y = -world->tuning.air_jump_impulse; jumped |= 3; } } @@ -181,7 +225,7 @@ void player_core::tick() } else if(hook_state == HOOK_FLYING) { - vec2 new_pos = hook_pos+hook_dir*hook_fire_speed; + vec2 new_pos = hook_pos+hook_dir*world->tuning.hook_fire_speed; // Check against other players first for(int i = 0; i < MAX_CLIENTS; i++) @@ -223,7 +267,7 @@ void player_core::tick() hook_state = HOOK_GRABBED; hook_pos = new_pos; } - else if(distance(pos, new_pos) > hook_length) + else if(distance(pos, new_pos) > world->tuning.hook_length) { triggered_events |= COREEVENT_HOOK_RETRACT; hook_state = HOOK_RETRACTED; @@ -270,7 +314,7 @@ void player_core::tick() // don't do this hook rutine when we are hook to a player if(hooked_player == -1 && distance(hook_pos, pos) > 46.0f) { - vec2 hookvel = normalize(hook_pos-pos)*hook_drag_accel; + vec2 hookvel = normalize(hook_pos-pos)*world->tuning.hook_drag_accel; // the hook as more power to drag you up then down. // this makes it easier to get on top of an platform if(hookvel.y > 0) @@ -286,7 +330,7 @@ void player_core::tick() vec2 new_vel = vel+hookvel; // check if we are under the legal limit for the hook - if(length(new_vel) < hook_drag_speed || length(new_vel) < length(vel)) + if(length(new_vel) < world->tuning.hook_drag_speed || length(new_vel) < length(vel)) vel = new_vel; // no problem. apply } @@ -333,23 +377,24 @@ void player_core::tick() { if(d > phys_size*1.50f) // TODO: fix tweakable variable { - float accel = hook_drag_accel * (d/hook_length); + float accel = world->tuning.hook_drag_accel * (d/world->tuning.hook_length); + float drag_speed = world->tuning.hook_drag_speed; // add force to the hooked player - p->vel.x = saturated_add(-hook_drag_speed, hook_drag_speed, p->vel.x, accel*dir.x*1.5f); - p->vel.y = saturated_add(-hook_drag_speed, hook_drag_speed, p->vel.y, accel*dir.y*1.5f); + p->vel.x = saturated_add(-drag_speed, drag_speed, p->vel.x, accel*dir.x*1.5f); + p->vel.y = saturated_add(-drag_speed, drag_speed, p->vel.y, accel*dir.y*1.5f); // add a little bit force to the guy who has the grip - vel.x = saturated_add(-hook_drag_speed, hook_drag_speed, vel.x, -accel*dir.x*0.25f); - vel.y = saturated_add(-hook_drag_speed, hook_drag_speed, vel.y, -accel*dir.y*0.25f); + vel.x = saturated_add(-drag_speed, drag_speed, vel.x, -accel*dir.x*0.25f); + vel.y = saturated_add(-drag_speed, drag_speed, vel.y, -accel*dir.y*0.25f); } } } } // clamp the velocity to something sane - if(length(vel) > terminal_velocity) - vel = normalize(vel) * terminal_velocity; + if(length(vel) > world->tuning.terminal_velocity) + vel = normalize(vel) * world->tuning.terminal_velocity; } void player_core::move() diff --git a/src/game/g_game.h b/src/game/g_game.h index 5cece9d9..a9fddde7 100644 --- a/src/game/g_game.h +++ b/src/game/g_game.h @@ -4,12 +4,35 @@ #include <engine/e_system.h> #include <engine/e_common_interface.h> -#include <game/g_math.h> #include <math.h> +#include "g_math.h" #include "g_collision.h" - #include "g_protocol.h" +struct tuning_params +{ + tuning_params() + { + const float ticks_per_second = 50.0f; + #define MACRO_TUNING_PARAM(name,value) name = value; + #include "g_tuning.h" + #undef MACRO_TUNING_PARAM + } + + static const char *names[]; + + #define MACRO_TUNING_PARAM(name,value) tune_param name; + #include "g_tuning.h" + #undef MACRO_TUNING_PARAM + + static int num() { return sizeof(tuning_params)/sizeof(int); } + bool set(int index, float value); + bool set(const char *name, float value); + bool get(int index, float *value); + bool get(const char *name, float *value); +}; + + inline vec2 get_direction(int angle) { float a = angle/256.0f; @@ -90,7 +113,8 @@ public: { mem_zero(players, sizeof(players)); } - + + tuning_params tuning; class player_core *players[MAX_CLIENTS]; }; diff --git a/src/game/g_mapitems.h b/src/game/g_mapitems.h index 8b4455ec..53561beb 100644 --- a/src/game/g_mapitems.h +++ b/src/game/g_mapitems.h @@ -158,9 +158,4 @@ typedef struct int name; } MAPITEM_ENVELOPE; -// float to fixed -inline int f2fx(float v) { return (int)(v*(float)(1<<10)); } -inline float fx2f(int v) { return v*(1.0f/(1<<10)); } - - #endif diff --git a/src/game/g_math.h b/src/game/g_math.h index 54c23ac9..5e3f7ede 100644 --- a/src/game/g_math.h +++ b/src/game/g_math.h @@ -27,6 +27,32 @@ inline T mix(const T a, const T b, TB amount) inline float frandom() { return rand()/(float)(RAND_MAX); } +// float to fixed +inline int f2fx(float v) { return (int)(v*(float)(1<<10)); } +inline float fx2f(int v) { return v*(1.0f/(1<<10)); } + +class fxp +{ + int value; +public: + void set(int v) { value = v; } + int get() const { return value; } + fxp &operator = (int v) { value = v<<10; return *this; } + fxp &operator = (float v) { value = (int)(v*(float)(1<<10)); return *this; } + operator float() const { return value/(float)(1<<10); } +}; + +class tune_param +{ + int value; +public: + void set(int v) { value = v; } + int get() const { return value; } + tune_param &operator = (int v) { value = (int)(v*100.0f); return *this; } + tune_param &operator = (float v) { value = (int)(v*100.0f); return *this; } + operator float() const { return value/100.0f; } +}; + const float pi = 3.1415926535897932384626433f; template <typename T> inline T min(T a, T b) { return a<b?a:b; } diff --git a/src/game/g_protocol.h b/src/game/g_protocol.h index e63da143..b0d84916 100644 --- a/src/game/g_protocol.h +++ b/src/game/g_protocol.h @@ -4,27 +4,6 @@ #ifndef GAME_PROTOCOL_H #define GAME_PROTOCOL_H -// --------- PHYSICS TWEAK! -------- -const float ticks_per_second = 50.0f; -const float ground_control_speed = 350.0f / ticks_per_second; -const float ground_control_accel = 100.0f / ticks_per_second; -const float ground_friction = 0.5f; -const float ground_jump_speed = 12.6f; -const float ground_air_speed = 11.5f; -const float air_control_speed = 250.0f / ticks_per_second; -const float air_control_accel = 1.5f; -const float air_friction = 0.95f; -const float hook_length = 34*10.0f; -const float hook_fire_speed = 45.0f; -const float hook_drag_accel = 3.0f; -const float hook_drag_speed = 15.0f; -const float gravity = 0.5f; -const float terminal_velocity = 20.0f; - -const float wall_friction = 0.80f; -const float wall_jump_speed_up = ground_jump_speed*0.8f; -const float wall_jump_speed_out = ground_jump_speed*0.8f; - // Network stuff enum { @@ -62,6 +41,7 @@ enum MSG_READY_TO_ENTER, // server -> client MSG_WEAPON_PICKUP, MSG_SOUND_GLOBAL, + MSG_TUNE_PARAMS, }; enum diff --git a/src/game/g_tuning.h b/src/game/g_tuning.h new file mode 100644 index 00000000..9f7ffb80 --- /dev/null +++ b/src/game/g_tuning.h @@ -0,0 +1,17 @@ +/* physics tuning */ +MACRO_TUNING_PARAM(ground_control_speed, 350.0f / ticks_per_second) +MACRO_TUNING_PARAM(ground_control_accel, 100.0f / ticks_per_second) +MACRO_TUNING_PARAM(ground_friction, 0.5f) +MACRO_TUNING_PARAM(ground_jump_impulse, 12.6f) +MACRO_TUNING_PARAM(air_jump_impulse, 11.5f) +MACRO_TUNING_PARAM(air_control_speed, 250.0f / ticks_per_second) +MACRO_TUNING_PARAM(air_control_accel, 1.5f) +MACRO_TUNING_PARAM(air_friction, 0.95f) +MACRO_TUNING_PARAM(hook_length, 34*10.0f) +MACRO_TUNING_PARAM(hook_fire_speed, 45.0f) +MACRO_TUNING_PARAM(hook_drag_accel, 3.0f) +MACRO_TUNING_PARAM(hook_drag_speed, 15.0f) +MACRO_TUNING_PARAM(gravity, 0.5f) +MACRO_TUNING_PARAM(terminal_velocity, 1000.0f / ticks_per_second) + +/* weapon tuning */ diff --git a/src/game/g_variables.h b/src/game/g_variables.h index 9e4d1c7c..d7848629 100644 --- a/src/game/g_variables.h +++ b/src/game/g_variables.h @@ -34,6 +34,9 @@ MACRO_CONFIG_INT(cl_autoswitch_weapons, 0, 0, 1) MACRO_CONFIG_INT(cl_show_player_ids, 0, 0, 1) +MACRO_CONFIG_INT(cl_warning_tuning, 1, 0, 1) + + MACRO_CONFIG_INT(cl_flow, 0, 0, 1) MACRO_CONFIG_INT(cl_show_welcome, 1, 0, 1) @@ -46,6 +49,7 @@ MACRO_CONFIG_STR(player_skin, 64, "default") MACRO_CONFIG_INT(dbg_bots, 0, 0, 11) MACRO_CONFIG_INT(dbg_firedelay, 0, 0, 1) MACRO_CONFIG_INT(dbg_flow, 0, 0, 1) +MACRO_CONFIG_INT(dbg_tuning, 0, 0, 1) MACRO_CONFIG_INT(ui_page, 1, 0, 5) MACRO_CONFIG_STR(ui_server_address, 128, "localhost:8303") diff --git a/src/game/server/gs_common.h b/src/game/server/gs_common.h index 8c4509a2..4519cf37 100644 --- a/src/game/server/gs_common.h +++ b/src/game/server/gs_common.h @@ -3,6 +3,8 @@ #include "../generated/gs_data.h" +extern tuning_params tuning; + void create_sound_global(int sound, int target=-1); inline int cmask_all() { return -1; } diff --git a/src/game/server/gs_game_ctf.cpp b/src/game/server/gs_game_ctf.cpp index 0c54d1c5..37e2baba 100644 --- a/src/game/server/gs_game_ctf.cpp +++ b/src/game/server/gs_game_ctf.cpp @@ -151,7 +151,7 @@ void gameobject_ctf::tick() } else { - f->vel.y += gravity; + f->vel.y += world->core.tuning.gravity; move_box(&f->pos, &f->vel, vec2(f->phys_size, f->phys_size), 0.5f); } } diff --git a/src/game/server/gs_server.cpp b/src/game/server/gs_server.cpp index c1f5e130..0416c808 100644 --- a/src/game/server/gs_server.cpp +++ b/src/game/server/gs_server.cpp @@ -14,6 +14,8 @@ data_container *data = 0x0; +tuning_params tuning; + class player* get_player(int index); void create_damageind(vec2 p, float angle_mod, int amount); void create_explosion(vec2 p, int owner, int weapon, bool bnodamage); @@ -58,6 +60,16 @@ void send_chat(int cid, int team, const char *msg) } +void send_tuning_params(int cid) +{ + msg_pack_start(MSG_TUNE_PARAMS, MSGFLAG_VITAL); + int *params = (int *)&tuning; + for(unsigned i = 0; i < sizeof(tuning_params)/sizeof(int); i++) + msg_pack_int(params[i]); + msg_pack_end(); + server_send_msg(cid); +} + ////////////////////////////////////////////////// // Event handler ////////////////////////////////////////////////// @@ -1670,7 +1682,7 @@ player* intersect_player(vec2 pos0, vec2 pos1, vec2& new_pos, entity* notthis) // Server hooks void mods_tick() { - // clear all events + world->core.tuning = tuning; world->tick(); if(world->paused) // make sure that the game object always updates @@ -1858,13 +1870,19 @@ void mods_message(int msg, int client_id) if(msg == MSG_STARTINFO) { + // a client that connected! + // send all info to this client for(int i = 0; i < MAX_CLIENTS; i++) { if(players[i].client_id != -1) send_info(i, client_id); } + + // send tuning parameters to client + send_tuning_params(client_id); + // msg_pack_start(MSG_READY_TO_ENTER, MSGFLAG_VITAL); msg_pack_end(); server_send_msg(client_id); @@ -1881,6 +1899,57 @@ void mods_message(int msg, int client_id) extern unsigned char internal_data[]; + +static void con_tune_param(void *result, void *user_data) +{ + const char *param_name; + float new_value; + + if(console_result_string(result, 1, ¶m_name) == 0) + { + if(console_result_float(result, 2, &new_value) == 0) + { + if(tuning.set(param_name, new_value)) + { + dbg_msg("tuning", "%s changed to %.2f", param_name, new_value); + send_tuning_params(-1); + } + else + console_print("No such tuning parameter"); + } + else + { + //console_print(""); + } + } +} + +static void con_tune_reset(void *result, void *user_data) +{ + tuning_params p; + tuning = p; + send_tuning_params(-1); + console_print("tuning reset"); +} + +static void con_tune_dump(void *result, void *user_data) +{ + for(int i = 0; i < tuning.num(); i++) + { + float v; + tuning.get(i, &v); + dbg_msg("tuning", "%s %.2f", tuning.names[i], v); + } +} + + +void mods_console_init() +{ + MACRO_REGISTER_COMMAND("tune", "s?i", con_tune_param, 0); + MACRO_REGISTER_COMMAND("tune_reset", "", con_tune_reset, 0); + MACRO_REGISTER_COMMAND("tune_dump", "", con_tune_dump, 0); +} + void mods_init() { if(!data) /* only load once */ |