Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 70c43240bc |
@@ -358,7 +358,7 @@ keyboard (there is no hold behavior).
|
||||
- `keypad 0`-`keypad 9`: a controller button per digit is not useful; use the
|
||||
on-screen keyboard.
|
||||
- `toggle_freelook` (F): the free-view actions cover mouse look.
|
||||
- The 4 `cheat_*` entries: debug cheats.
|
||||
- The 4 `cheat_*` entries: debug cheats. They are on the menu's Cheats tab instead.
|
||||
- `mac_help` (disabled) and `audiolog_cancel` (its build flag is not
|
||||
defined): they are not real hotkeys in this build.
|
||||
- `toggle_opengl` (Ctrl+G): the Video Options tab's Renderer buttons already
|
||||
|
||||
@@ -1250,6 +1250,7 @@ static Uint32 s_begin_control_capture_event_type;
|
||||
static Uint32 s_cancel_control_capture_event_type;
|
||||
static Uint32 s_reset_player_controls_event_type;
|
||||
static Uint32 s_menu_visibility_event_type;
|
||||
static Uint32 s_cheat_event_type;
|
||||
|
||||
void qs_config_load_startup(void) {
|
||||
// Registers the custom SDL event types qs_config_request_save()/_load()/
|
||||
@@ -1260,7 +1261,7 @@ void qs_config_load_startup(void) {
|
||||
// exist yet, rather than lazily from those functions themselves (which
|
||||
// run on Android's UI thread and could otherwise race each other doing
|
||||
// this lazily).
|
||||
Uint32 base = SDL_RegisterEvents(14);
|
||||
Uint32 base = SDL_RegisterEvents(15);
|
||||
s_save_event_type = base;
|
||||
s_load_event_type = base + 1;
|
||||
s_set_renderer_event_type = base + 2;
|
||||
@@ -1275,6 +1276,7 @@ void qs_config_load_startup(void) {
|
||||
s_cancel_control_capture_event_type = base + 11;
|
||||
s_reset_player_controls_event_type = base + 12;
|
||||
s_menu_visibility_event_type = base + 13;
|
||||
s_cheat_event_type = base + 14;
|
||||
|
||||
QsParsedConfig parsed;
|
||||
bool haveConfig = qs_config_read_file(&parsed);
|
||||
@@ -1407,6 +1409,14 @@ void qs_config_request_cancel_control_capture(void) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
void qs_config_request_cheat(int cheat_id) {
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
event.type = s_cheat_event_type;
|
||||
event.user.code = cheat_id;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
void qs_config_notify_menu_visibility(bool visible) {
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
@@ -1449,6 +1459,77 @@ static void qs_apply_menu_pause(bool menu_visible) {
|
||||
}
|
||||
}
|
||||
|
||||
// hkeyfunc.c - the engine's own cheat hotkey handlers, and the refill added by
|
||||
// android/engine-patches/26-android-cheat-refill.patch.
|
||||
extern uchar toggle_giveall_func(ushort keycode, uint32_t context, intptr_t data);
|
||||
extern uchar toggle_physics_func(ushort keycode, uint32_t context, intptr_t data);
|
||||
extern uchar toggle_up_level_func(ushort keycode, uint32_t context, intptr_t data);
|
||||
extern uchar toggle_down_level_func(ushort keycode, uint32_t context, intptr_t data);
|
||||
extern void qs_cheat_refill(int what);
|
||||
extern uchar physics_running;
|
||||
|
||||
#define QS_CHEAT_GIVE_ALL 0
|
||||
#define QS_CHEAT_PHYSICS 1
|
||||
#define QS_CHEAT_LEVEL_UP 2
|
||||
#define QS_CHEAT_LEVEL_DOWN 3
|
||||
#define QS_CHEAT_UNLIMITED_HEALTH 4
|
||||
#define QS_CHEAT_UNLIMITED_ENERGY 5
|
||||
#define QS_CHEAT_UNLIMITED_AMMO 6
|
||||
#define QS_CHEAT_UNLIMITED_ITEMS 7
|
||||
|
||||
// Bits of s_cheat_unlimited; the values match qs_cheat_refill() in patch 26.
|
||||
#define QS_CHEAT_MASK_HEALTH 1
|
||||
#define QS_CHEAT_MASK_ENERGY 2
|
||||
#define QS_CHEAT_MASK_AMMO 4
|
||||
#define QS_CHEAT_MASK_ITEMS 8
|
||||
|
||||
static int s_cheat_unlimited = 0;
|
||||
|
||||
int qs_config_cheat_unlimited_mask(void) { return s_cheat_unlimited; }
|
||||
bool qs_config_cheat_physics_running(void) { return physics_running != 0; }
|
||||
|
||||
void qs_config_frame_tick(void) {
|
||||
if (s_cheat_unlimited && s_screen_profile_is_game)
|
||||
qs_cheat_refill(s_cheat_unlimited);
|
||||
}
|
||||
|
||||
static void qs_apply_cheat(int cheat_id) {
|
||||
if (cheat_id >= QS_CHEAT_UNLIMITED_HEALTH && cheat_id <= QS_CHEAT_UNLIMITED_ITEMS) {
|
||||
static const struct {
|
||||
int mask;
|
||||
const char *on, *off;
|
||||
} kUnlimited[] = {
|
||||
{QS_CHEAT_MASK_HEALTH, "Unlimited health on", "Unlimited health off"},
|
||||
{QS_CHEAT_MASK_ENERGY, "Unlimited energy on", "Unlimited energy off"},
|
||||
{QS_CHEAT_MASK_AMMO, "Unlimited ammo on", "Unlimited ammo off"},
|
||||
{QS_CHEAT_MASK_ITEMS, "Unlimited items on", "Unlimited items off"},
|
||||
};
|
||||
const int i = cheat_id - QS_CHEAT_UNLIMITED_HEALTH;
|
||||
s_cheat_unlimited ^= kUnlimited[i].mask;
|
||||
message_info((s_cheat_unlimited & kUnlimited[i].mask) ? kUnlimited[i].on : kUnlimited[i].off);
|
||||
return;
|
||||
}
|
||||
// The engine's own handlers assume a running game (player state, levels).
|
||||
if (!s_screen_profile_is_game) {
|
||||
message_info("Cheats need a running game");
|
||||
return;
|
||||
}
|
||||
switch (cheat_id) {
|
||||
case QS_CHEAT_GIVE_ALL:
|
||||
toggle_giveall_func(0, 0, 0);
|
||||
break;
|
||||
case QS_CHEAT_PHYSICS:
|
||||
toggle_physics_func(0, 0, 0);
|
||||
break;
|
||||
case QS_CHEAT_LEVEL_UP:
|
||||
toggle_up_level_func(0, 0, 0);
|
||||
break;
|
||||
case QS_CHEAT_LEVEL_DOWN:
|
||||
toggle_down_level_func(0, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool qs_config_handle_event(const SDL_Event *event) {
|
||||
if (event->type == s_save_event_type) {
|
||||
if (qs_config_write_file())
|
||||
@@ -1531,6 +1612,10 @@ bool qs_config_handle_event(const SDL_Event *event) {
|
||||
xr_input_capture_cancel();
|
||||
return true;
|
||||
}
|
||||
if (event->type == s_cheat_event_type) {
|
||||
qs_apply_cheat(event->user.code);
|
||||
return true;
|
||||
}
|
||||
if (event->type == s_menu_visibility_event_type) {
|
||||
qs_apply_menu_pause(event->user.code != 0);
|
||||
return true;
|
||||
|
||||
@@ -104,6 +104,20 @@ void qs_config_notify_control_capture_result(int action_index, const char *raw_n
|
||||
// engine's thread at pump_events() time.
|
||||
void qs_config_notify_menu_visibility(bool visible);
|
||||
|
||||
// Cheats tab (MenuOverlay.java). Same enqueue-only requests as above; the work
|
||||
// runs on the engine's thread. cheat_id: 0 give everything, 1 toggle physics,
|
||||
// 2 next level, 3 previous level, 4-7 toggle unlimited health, energy, ammo,
|
||||
// items (grenades and drugs). Cheats need a running game (the unlimited
|
||||
// switches can be set anywhere). The getters are plain scalar reads, safe from
|
||||
// the UI thread; the unlimited mask has bit 0 health, 1 energy, 2 ammo, 3 items.
|
||||
void qs_config_request_cheat(int cheat_id);
|
||||
int qs_config_cheat_unlimited_mask(void);
|
||||
bool qs_config_cheat_physics_running(void);
|
||||
|
||||
// Called once per frame from xr_input.c on the engine's thread; applies the
|
||||
// unlimited-resource cheats that are switched on.
|
||||
void qs_config_frame_tick(void);
|
||||
|
||||
// Called from xr_input.c's xr_input_suggest_bindings() when the OpenXR runtime
|
||||
// rejects a supported interaction profile's suggested bindings at startup.
|
||||
// That is an app bug, not a config problem, so it shows
|
||||
|
||||
@@ -270,3 +270,19 @@ Java_de_ladkau_questshock_MenuOverlay_nativeSetControllerOptionsTabOpen(JNIEnv *
|
||||
jboolean open) {
|
||||
xr_input_set_controller_options_tab_open(open == JNI_TRUE);
|
||||
}
|
||||
|
||||
// Cheats tab: same enqueue-only pattern as the other requests.
|
||||
JNIEXPORT void JNICALL
|
||||
Java_de_ladkau_questshock_MenuOverlay_nativeRequestCheat(JNIEnv *env, jclass clazz, jint cheatId) {
|
||||
qs_config_request_cheat(cheatId);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_de_ladkau_questshock_MenuOverlay_nativeGetCheatUnlimitedMask(JNIEnv *env, jclass clazz) {
|
||||
return qs_config_cheat_unlimited_mask();
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_de_ladkau_questshock_MenuOverlay_nativeGetCheatPhysicsRunning(JNIEnv *env, jclass clazz) {
|
||||
return qs_config_cheat_physics_running();
|
||||
}
|
||||
|
||||
@@ -2000,6 +2000,7 @@ void xr_input_sync_and_draw(XrSpace baseSpace, XrTime time, bool draw) {
|
||||
(menuVisible || freeView[xr_input_raw_input_hand(raw)])) &&
|
||||
g_raw_down[raw];
|
||||
}
|
||||
qs_config_frame_tick();
|
||||
xr_input_update_cyber_scales(wantDown);
|
||||
xr_input_apply_free_view(freeView);
|
||||
for (size_t i = 0; i < QS_NUM_KEY_ACTIONS; i++) {
|
||||
|
||||
@@ -143,14 +143,27 @@ public class MenuOverlay extends OverlayPanel {
|
||||
private TextView statsView;
|
||||
|
||||
// Content area (tabs) - only one of mainMenuTab/videoOptionsTab/
|
||||
// controllerOptionsTab is VISIBLE at a time; currentTab tracks which.
|
||||
// controllerOptionsTab/cheatsTab is VISIBLE at a time; currentTab tracks which.
|
||||
private View mainMenuTab;
|
||||
private View videoOptionsTab;
|
||||
private View controllerOptionsTab;
|
||||
private View cheatsTab;
|
||||
private View currentTab;
|
||||
private Button mainMenuTabButton;
|
||||
private Button videoOptionsTabButton;
|
||||
private Button controllerOptionsTabButton;
|
||||
private Button cheatsTabButton;
|
||||
|
||||
// Cheats tab
|
||||
private TextView cheatsNoteView;
|
||||
private Button giveAllButton;
|
||||
private Button physicsButton;
|
||||
private Button levelUpButton;
|
||||
private Button levelDownButton;
|
||||
private Button unlimitedHealthButton;
|
||||
private Button unlimitedEnergyButton;
|
||||
private Button unlimitedAmmoButton;
|
||||
private Button unlimitedItemsButton;
|
||||
|
||||
// Main Menu tab's own two states (only one VISIBLE at a time, within
|
||||
// mainMenuTab) - mainMenuContent is the normal state (button row +
|
||||
@@ -251,14 +264,18 @@ public class MenuOverlay extends OverlayPanel {
|
||||
mainMenuTab = buildMainMenuTab();
|
||||
videoOptionsTab = buildVideoOptionsTab();
|
||||
controllerOptionsTab = buildControllerOptionsTab();
|
||||
cheatsTab = buildCheatsTab();
|
||||
content.addView(mainMenuTab, new FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
|
||||
content.addView(videoOptionsTab, new FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
|
||||
content.addView(controllerOptionsTab, new FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
|
||||
content.addView(cheatsTab, new FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
|
||||
videoOptionsTab.setVisibility(View.GONE);
|
||||
controllerOptionsTab.setVisibility(View.GONE);
|
||||
cheatsTab.setVisibility(View.GONE);
|
||||
currentTab = mainMenuTab;
|
||||
panel.addView(content, new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, 0, 1f));
|
||||
@@ -923,6 +940,86 @@ public class MenuOverlay extends OverlayPanel {
|
||||
return profile.image;
|
||||
}
|
||||
|
||||
// Cheats tab: the engine's own cheat functions as buttons, plus four switches
|
||||
// for unlimited health, energy, ammo and items. The physics and unlimited
|
||||
// buttons show their state through the selected highlight.
|
||||
private static final int CHEAT_GIVE_ALL = 0;
|
||||
private static final int CHEAT_PHYSICS = 1;
|
||||
private static final int CHEAT_LEVEL_UP = 2;
|
||||
private static final int CHEAT_LEVEL_DOWN = 3;
|
||||
private static final int CHEAT_UNLIMITED_HEALTH = 4;
|
||||
private static final int CHEAT_UNLIMITED_ENERGY = 5;
|
||||
private static final int CHEAT_UNLIMITED_AMMO = 6;
|
||||
private static final int CHEAT_UNLIMITED_ITEMS = 7;
|
||||
|
||||
private View buildCheatsTab() {
|
||||
LinearLayout tab = new LinearLayout(activity);
|
||||
tab.setOrientation(LinearLayout.VERTICAL);
|
||||
tab.setGravity(Gravity.CENTER);
|
||||
tab.setPadding(24, 16, 24, 16);
|
||||
|
||||
cheatsNoteView = new TextView(activity);
|
||||
cheatsNoteView.setTextColor(0xFFFFD060);
|
||||
cheatsNoteView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 15);
|
||||
cheatsNoteView.setGravity(Gravity.CENTER);
|
||||
cheatsNoteView.setPadding(0, 0, 0, 16);
|
||||
cheatsNoteView.setText(Strings.get("cheats_note", currentLanguage));
|
||||
tab.addView(cheatsNoteView);
|
||||
|
||||
LinearLayout firstRow = new LinearLayout(activity);
|
||||
firstRow.setOrientation(LinearLayout.HORIZONTAL);
|
||||
giveAllButton = addSelectableButton(firstRow, Strings.get("cheat_give_all", currentLanguage),
|
||||
v -> nativeRequestCheat(CHEAT_GIVE_ALL));
|
||||
physicsButton = addSelectableButton(firstRow, Strings.get("cheat_physics", currentLanguage),
|
||||
v -> {
|
||||
nativeRequestCheat(CHEAT_PHYSICS);
|
||||
refreshCheatsSelection();
|
||||
});
|
||||
tab.addView(firstRow);
|
||||
|
||||
LinearLayout secondRow = new LinearLayout(activity);
|
||||
secondRow.setOrientation(LinearLayout.HORIZONTAL);
|
||||
levelUpButton = addSelectableButton(secondRow, Strings.get("cheat_level_up", currentLanguage),
|
||||
v -> nativeRequestCheat(CHEAT_LEVEL_UP));
|
||||
levelDownButton = addSelectableButton(secondRow, Strings.get("cheat_level_down", currentLanguage),
|
||||
v -> nativeRequestCheat(CHEAT_LEVEL_DOWN));
|
||||
tab.addView(secondRow);
|
||||
|
||||
LinearLayout thirdRow = new LinearLayout(activity);
|
||||
thirdRow.setOrientation(LinearLayout.HORIZONTAL);
|
||||
unlimitedHealthButton = addSelectableButton(thirdRow,
|
||||
Strings.get("cheat_unlimited_health", currentLanguage), v -> toggleUnlimited(CHEAT_UNLIMITED_HEALTH));
|
||||
unlimitedEnergyButton = addSelectableButton(thirdRow,
|
||||
Strings.get("cheat_unlimited_energy", currentLanguage), v -> toggleUnlimited(CHEAT_UNLIMITED_ENERGY));
|
||||
tab.addView(thirdRow);
|
||||
|
||||
LinearLayout fourthRow = new LinearLayout(activity);
|
||||
fourthRow.setOrientation(LinearLayout.HORIZONTAL);
|
||||
unlimitedAmmoButton = addSelectableButton(fourthRow,
|
||||
Strings.get("cheat_unlimited_ammo", currentLanguage), v -> toggleUnlimited(CHEAT_UNLIMITED_AMMO));
|
||||
unlimitedItemsButton = addSelectableButton(fourthRow,
|
||||
Strings.get("cheat_unlimited_items", currentLanguage), v -> toggleUnlimited(CHEAT_UNLIMITED_ITEMS));
|
||||
tab.addView(fourthRow);
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
// The requests run on the engine's thread a frame later, so the physics
|
||||
// and unlimited highlights catch up on the next periodic refresh.
|
||||
private void refreshCheatsSelection() {
|
||||
physicsButton.setSelected(nativeGetCheatPhysicsRunning());
|
||||
int mask = nativeGetCheatUnlimitedMask();
|
||||
unlimitedHealthButton.setSelected((mask & 1) != 0);
|
||||
unlimitedEnergyButton.setSelected((mask & 2) != 0);
|
||||
unlimitedAmmoButton.setSelected((mask & 4) != 0);
|
||||
unlimitedItemsButton.setSelected((mask & 8) != 0);
|
||||
}
|
||||
|
||||
private void toggleUnlimited(int cheatId) {
|
||||
nativeRequestCheat(cheatId);
|
||||
refreshCheatsSelection();
|
||||
}
|
||||
|
||||
private View buildTabBar() {
|
||||
LinearLayout tabBar = new LinearLayout(activity);
|
||||
tabBar.setOrientation(LinearLayout.HORIZONTAL);
|
||||
@@ -969,7 +1066,21 @@ public class MenuOverlay extends OverlayPanel {
|
||||
controllerOptionsTabButton.setOnTouchListener(CLICK_ON_TOUCH_UP);
|
||||
registerHoverable(controllerOptionsTabButton);
|
||||
tabBar.addView(controllerOptionsTabButton,
|
||||
new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1f));
|
||||
new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1.3f));
|
||||
|
||||
View separator3 = new View(activity);
|
||||
separator3.setBackgroundColor(0xFFFFFFFF);
|
||||
tabBar.addView(separator3, new LinearLayout.LayoutParams(2, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
|
||||
cheatsTabButton = new Button(activity);
|
||||
cheatsTabButton.setText(Strings.get("cheats", currentLanguage));
|
||||
cheatsTabButton.setBackground(selectableButtonBackground());
|
||||
cheatsTabButton.setTextColor(buttonTextColors());
|
||||
cheatsTabButton.setOnClickListener(v -> switchTab(cheatsTab));
|
||||
cheatsTabButton.setOnTouchListener(CLICK_ON_TOUCH_UP);
|
||||
registerHoverable(cheatsTabButton);
|
||||
tabBar.addView(cheatsTabButton,
|
||||
new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 0.7f));
|
||||
|
||||
return tabBar;
|
||||
}
|
||||
@@ -992,6 +1103,7 @@ public class MenuOverlay extends OverlayPanel {
|
||||
mainMenuTabButton.setSelected(tab == mainMenuTab);
|
||||
videoOptionsTabButton.setSelected(tab == videoOptionsTab);
|
||||
controllerOptionsTabButton.setSelected(tab == controllerOptionsTab);
|
||||
cheatsTabButton.setSelected(tab == cheatsTab);
|
||||
nativeSetControllerOptionsTabOpen(tab == controllerOptionsTab);
|
||||
resetHover();
|
||||
if (tab == videoOptionsTab) {
|
||||
@@ -1007,6 +1119,8 @@ public class MenuOverlay extends OverlayPanel {
|
||||
controllerScrollView.scrollTo(0, 0);
|
||||
controllerScrollBar.setFraction(0f);
|
||||
refreshControllerOptionsSelection();
|
||||
} else if (tab == cheatsTab) {
|
||||
refreshCheatsSelection();
|
||||
}
|
||||
relayoutAndRedraw();
|
||||
}
|
||||
@@ -1172,6 +1286,8 @@ public class MenuOverlay extends OverlayPanel {
|
||||
refreshLanguageSelection();
|
||||
} else if (currentTab == controllerOptionsTab) {
|
||||
refreshControllerOptionsSelection();
|
||||
} else if (currentTab == cheatsTab) {
|
||||
refreshCheatsSelection();
|
||||
}
|
||||
|
||||
// The stats text's width changes every tick (digit count, "ms"
|
||||
@@ -1227,6 +1343,16 @@ public class MenuOverlay extends OverlayPanel {
|
||||
gameScreenDistanceLabel.setText(Strings.get("distance", currentLanguage));
|
||||
|
||||
controllerOptionsTabButton.setText(Strings.get("controller_options", currentLanguage));
|
||||
cheatsTabButton.setText(Strings.get("cheats", currentLanguage));
|
||||
cheatsNoteView.setText(Strings.get("cheats_note", currentLanguage));
|
||||
giveAllButton.setText(Strings.get("cheat_give_all", currentLanguage));
|
||||
physicsButton.setText(Strings.get("cheat_physics", currentLanguage));
|
||||
levelUpButton.setText(Strings.get("cheat_level_up", currentLanguage));
|
||||
levelDownButton.setText(Strings.get("cheat_level_down", currentLanguage));
|
||||
unlimitedHealthButton.setText(Strings.get("cheat_unlimited_health", currentLanguage));
|
||||
unlimitedEnergyButton.setText(Strings.get("cheat_unlimited_energy", currentLanguage));
|
||||
unlimitedAmmoButton.setText(Strings.get("cheat_unlimited_ammo", currentLanguage));
|
||||
unlimitedItemsButton.setText(Strings.get("cheat_unlimited_items", currentLanguage));
|
||||
controllerGenericNoteView.setText(Strings.get("generic_profile_note", currentLanguage));
|
||||
controlResetButton.setText(Strings.get("reset_to_defaults", currentLanguage));
|
||||
for (int i = 0; i < ACTION_KEYS.length; i++) {
|
||||
@@ -1351,6 +1477,12 @@ public class MenuOverlay extends OverlayPanel {
|
||||
// or reassigned - see switchTab().
|
||||
private static native void nativeSetControllerOptionsTabOpen(boolean open);
|
||||
|
||||
// Cheats tab - see qs_config.h. cheatId: 0 give all, 1 toggle physics, 2 next level,
|
||||
// 3 previous level, 4-7 toggle unlimited health/energy/ammo/items.
|
||||
private static native void nativeRequestCheat(int cheatId);
|
||||
private static native int nativeGetCheatUnlimitedMask();
|
||||
private static native boolean nativeGetCheatPhysicsRunning();
|
||||
|
||||
// Called from xr_overlay.c's xr_overlay_init_jni(), on the render
|
||||
// thread, right after it resolves this class via the activity's own
|
||||
// ClassLoader (plain FindClass() can't see app classes from a thread
|
||||
|
||||
@@ -119,6 +119,19 @@ final class Strings {
|
||||
put("action_mfd_right_4", "Right MFD: Target", "MFD droit : cible", "Rechtes MFD: Ziel");
|
||||
put("action_mfd_right_5", "Right MFD: Info", "MFD droit : info", "Rechtes MFD: Info");
|
||||
put("action_fire_weapon", "Fire Weapon", "Tirer", "Waffe abfeuern");
|
||||
// Cheats tab.
|
||||
put("cheats", "Cheats", "Triches", "Cheats");
|
||||
put("cheats_note", "Cheats need a running game.", "Les triches nécessitent une partie en cours.",
|
||||
"Cheats benötigen ein laufendes Spiel.");
|
||||
put("cheat_give_all", "Give All Items & Weapons", "Tout obtenir", "Alles erhalten");
|
||||
put("cheat_physics", "Physics", "Physique", "Physik");
|
||||
put("cheat_level_up", "Next Level", "Niveau suivant", "Nächstes Level");
|
||||
put("cheat_level_down", "Previous Level", "Niveau précédent", "Vorheriges Level");
|
||||
put("cheat_unlimited_health", "Unlimited Health", "Santé illimitée", "Unbegrenzt Leben");
|
||||
put("cheat_unlimited_energy", "Unlimited Energy", "Énergie illimitée", "Unbegrenzt Energie");
|
||||
put("cheat_unlimited_ammo", "Unlimited Ammo", "Munitions illimitées", "Unbegrenzt Munition");
|
||||
put("cheat_unlimited_items", "Unlimited Items", "Objets illimités", "Unbegrenzt Items");
|
||||
|
||||
put("action_free_left_thumbstick_view", "Free View (Left Stick)",
|
||||
"Vue libre (stick gauche)", "Freie Ansicht (linker Stick)");
|
||||
put("action_free_right_thumbstick_view", "Free View (Right Stick)",
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
--- a/src/GameSrc/hkeyfunc.c
|
||||
+++ b/src/GameSrc/hkeyfunc.c
|
||||
@@ -1465,3 +1465,71 @@
|
||||
#pragma enable_message(202)
|
||||
|
||||
#endif // NOT_YET
|
||||
+
|
||||
+#ifdef __ANDROID__
|
||||
+// Tops up parts of the player's state; android/app/src/main/cpp/qs_config.c
|
||||
+// calls it once per frame with the "unlimited" cheats that are switched on.
|
||||
+// `what` is a bitmask: 1 health, 2 energy, 4 ammo, 8 items (the same values as
|
||||
+// QS_CHEAT_MASK_* in qs_config.c). Only conventional guns use ammo: beam and
|
||||
+// melee weapons keep heat in the same field, so they are left alone (beams draw
|
||||
+// on energy). Spare ammo clips, grenades and drugs are only refilled for kinds
|
||||
+// the player already holds, so the cheat never creates items.
|
||||
+void qs_cheat_refill(int what) {
|
||||
+ const int kAmmoFloor = 99;
|
||||
+ const int kItemFloor = 99;
|
||||
+ uchar vitalsChanged = FALSE;
|
||||
+ uchar inventoryChanged = FALSE;
|
||||
+
|
||||
+ if (player_struct.dead)
|
||||
+ return;
|
||||
+ if ((what & 1) && player_struct.hit_points < PLAYER_MAX_HP) {
|
||||
+ player_struct.hit_points = PLAYER_MAX_HP;
|
||||
+ vitalsChanged = TRUE;
|
||||
+ }
|
||||
+ if ((what & 1) && player_struct.cspace_hp < PLAYER_MAX_HP) {
|
||||
+ player_struct.cspace_hp = PLAYER_MAX_HP;
|
||||
+ vitalsChanged = TRUE;
|
||||
+ }
|
||||
+ if ((what & 2) && player_struct.energy < 255) {
|
||||
+ player_struct.energy = 255;
|
||||
+ vitalsChanged = TRUE;
|
||||
+ }
|
||||
+ if (vitalsChanged)
|
||||
+ chg_set_flg(VITALS_UPDATE);
|
||||
+
|
||||
+ if (what & 4) {
|
||||
+ for (int i = 0; i < NUM_WEAPON_SLOTS; i++) {
|
||||
+ weapon_slot *slot = &player_struct.weapons[i];
|
||||
+ if (slot->type != EMPTY_WEAPON_SLOT && slot->type <= GUN_SUBCLASS_SPECIAL &&
|
||||
+ slot->ammo < kAmmoFloor) {
|
||||
+ slot->ammo = kAmmoFloor;
|
||||
+ inventoryChanged = TRUE;
|
||||
+ }
|
||||
+ }
|
||||
+ for (int i = 0; i < NUM_AMMO_TYPES; i++) {
|
||||
+ if (player_struct.cartridges[i] > 0 && player_struct.cartridges[i] < kItemFloor) {
|
||||
+ player_struct.cartridges[i] = kItemFloor;
|
||||
+ inventoryChanged = TRUE;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ if (what & 8) {
|
||||
+ for (int i = 0; i < NUM_GRENADEZ; i++) {
|
||||
+ if (player_struct.grenades[i] > 0 && player_struct.grenades[i] < kItemFloor) {
|
||||
+ player_struct.grenades[i] = kItemFloor;
|
||||
+ inventoryChanged = TRUE;
|
||||
+ }
|
||||
+ }
|
||||
+ for (int i = 0; i < NUM_DRUGZ; i++) {
|
||||
+ if (player_struct.drugs[i] > 0 && player_struct.drugs[i] < kItemFloor) {
|
||||
+ player_struct.drugs[i] = kItemFloor;
|
||||
+ inventoryChanged = TRUE;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ if (inventoryChanged) {
|
||||
+ chg_set_flg(INVENTORY_UPDATE);
|
||||
+ mfd_force_update();
|
||||
+ }
|
||||
+}
|
||||
+#endif
|
||||
Reference in New Issue
Block a user