Files
gtav-src/tools_ng/script/coding/mod/RIM/Source/script.cpp
T
2025-09-29 00:52:08 +02:00

730 lines
20 KiB
C++
Executable File

#include "stdafx.h"
#include "ScriptEvents.h"
/*
THIS FILE IS A PART OF GTA V SCRIPT HOOK SDK
http://dev-c.com
(C) Alexander Blade 2015
*/
/*
F4 activate
NUM2/8/4/6 navigate thru the menus and lists (numlock must be on)
NUM5 select
NUM0/BACKSPACE/F4 back
W/S Key use vehicle boost when active
~ KEY use vehicle rockets when active
W + E key throw rpg knife
T KEY place blimp to teleport with t key on your keyboard
*/
#include "stdafx.h"
std::string statusText;
DWORD statusTextDrawTicksMax;
bool statusTextGxtEntry;
void update_status_text()
{
if (GetTickCount() < statusTextDrawTicksMax)
{
UI::SET_TEXT_FONT(7);
UI::SET_TEXT_SCALE(0.6f, 0.6f);
UI::SET_TEXT_COLOUR(255, 255, 255, 255);
UI::SET_TEXT_WRAP(0.0f, 1.0f);
UI::SET_TEXT_CENTRE(1);
UI::SET_TEXT_OUTLINE();
UI::SET_TEXT_DROPSHADOW(0, 0, 0, 0, 0);
UI::SET_TEXT_EDGE(1, 0, 0, 0, 205);
if (statusTextGxtEntry)
{
UI::_SET_TEXT_ENTRY((char *)statusText.c_str());
} else
{
UI::_SET_TEXT_ENTRY("STRING");
UI::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME((char *)statusText.c_str());
}
UI::_DRAW_TEXT(0.5, 0);
//UI::_DRAW_TEXT(0.6f, 0.6f);
}
}
void set_status_text(std::string str, DWORD time, bool isGxtEntry)
{
statusText = str;
statusTextDrawTicksMax = GetTickCount() + time;
statusTextGxtEntry = isGxtEntry;
}
void kill_pedestrians()
{
Player player = PLAYER::PLAYER_ID();
Ped playerPed = PLAYER::PLAYER_PED_ID();
BOOL bPlayerExists = ENTITY::DOES_ENTITY_EXIST(playerPed);
Ped pedestrian;
Vector3 position = ENTITY::GET_ENTITY_COORDS(playerPed, 1);
if (PED::GET_CLOSEST_PED(position.x, position.y, position.z, 999999999.f, 1, 0, &pedestrian, 1, 1, -1))
{
if (pedestrian)
ENTITY::SET_ENTITY_HEALTH(pedestrian, 0); // Crash at game_win64_bankrelease.exe!rage::fwScriptGuid::GetBaseFromGuid(Line 107)
else
DEBUGMSG("kill_pedestrians() could not find the closest ped.");
}
}
void clear_pedestrians() {
Player player = PLAYER::PLAYER_ID();
Ped playerPed = PLAYER::PLAYER_PED_ID();
BOOL bPlayerExists = ENTITY::DOES_ENTITY_EXIST(playerPed);
Vector3 position = ENTITY::GET_ENTITY_COORDS(playerPed, 1);
if (!bPlayerExists)
DEBUGMSG("clear_pedestrians() player doe snot exist!");
else
GAMEPLAY::CLEAR_AREA_OF_PEDS(position.x, position.y, position.z, 999999999.f, -1);
}
void clear_cop_pedestrians() {
Player player = PLAYER::PLAYER_ID();
Ped playerPed = PLAYER::PLAYER_PED_ID();
BOOL bPlayerExists = ENTITY::DOES_ENTITY_EXIST(playerPed);
Vector3 position = ENTITY::GET_ENTITY_COORDS(playerPed, 1);
if (!bPlayerExists)
DEBUGMSG("clear_cop_pedestrians() Player does not exist!");
else
GAMEPLAY::CLEAR_AREA_OF_COPS(position.x, position.y, position.z, 999999999.f, -1);
}
void clear_pedestrians_vehicles()
{
Player player = PLAYER::PLAYER_ID();
Ped playerPed = PLAYER::PLAYER_PED_ID();
Vector3 position = ENTITY::GET_ENTITY_COORDS(playerPed, 1);
GAMEPLAY::CLEAR_AREA_OF_VEHICLES(position.x, position.y, position.z, 999999999.f, 0, 0, 0, 0, 0);
}
/* Moneydrop code from GTA5, doesn't quite work this way in RDR3.
bool drop_money_on_me(int amount, DWORD hash = $("P_MONEYSTACK01X"))
{
Player player = PLAYER::PLAYER_ID();
Ped playerPed = PLAYER::PLAYER_PED_ID();
Vector3 pos = ENTITY::GET_ENTITY_COORDS(player, 1);
pos.z += 2.f;
Hash modelHash = hash; // amount > 2000 ? 0x113FD533U : hash; // 0x113FD533 = prop_money_bag_01 NEEDS UPDATING PROLLY
if (!STREAMING::IS_MODEL_IN_CDIMAGE(modelHash))
{
DEBUGMSG("Moneydrop: %x is not in CDIMAGE", modelHash);
return true;
}
STREAMING::REQUEST_MODEL(modelHash);
if (!STREAMING::HAS_MODEL_LOADED(modelHash))
{
DEBUGMSG("Moneydrop: %x model has not loaded.", modelHash);
return false;
}
OBJECT::CREATE_AMBIENT_PICKUP(90, pos.x, pos.y, pos.z, 0, amount, modelHash, false, true); // Not hashed yet
OBJECT::CREATE_AMBIENT_PICKUP(91, pos.x, pos.y, pos.z, 0, amount, modelHash, false, true); // Not hashed yet
OBJECT::CREATE_AMBIENT_PICKUP(92, pos.x, pos.y, pos.z, 0, amount, modelHash, false, true); // Not hashed yet
STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(modelHash);
return true;
}
*/
// This "works", though currently is missing script callbacks.
void loot_coins()
{
NetRPCGuid guid;
Award_Loot_Conditionals conditionals = {};
conditionals.iNumConditionals = 1;
conditionals.iConditionals = $("MULTIPLAYER_GAME");
NETWORK::NETWORK_REQUEST_CLAIM_LOOT($("REWARD_BILL"), &conditionals, &guid);
}
// Feature gvars (Maybe I should do this better...)
bool SuperjumpEnabled;
bool GodmodeEnabled;
bool Rankloop;
bool doTeleport; // Maybe not needed here?
float teleportTo[3]; //
bool AlwaysDay;
bool AlwaysNight;
bool Moneyloop;
int moneyCounter = 0;
// Updates all features that can be turned off by the game, being called each game frame
// Put any functions that should run every frame here.
void update_features()
{
update_status_text();
// wait until player is ready, basically to prevent using the trainer while player is dead or arrested
while (ENTITY::IS_ENTITY_DEAD(PLAYER::PLAYER_PED_ID()) || PLAYER::IS_PLAYER_BEING_ARRESTED(PLAYER::PLAYER_ID(), TRUE))
WAIT(0);
// common variables
Player player = PLAYER::PLAYER_ID();
Ped playerPed = PLAYER::PLAYER_PED_ID();
BOOL playerExists = ENTITY::DOES_ENTITY_EXIST(playerPed);
Vehicle playerVehicle = PED::GET_VEHICLE_PED_IS_USING(playerPed);
Vector3 playerCoords = ENTITY::GET_ENTITY_COORDS(playerPed, 1);
DWORD Model = ENTITY::GET_ENTITY_MODEL(playerVehicle);
if (AlwaysDay && AlwaysNight) // Both can't be active at once.
{
AlwaysNight = false;
AlwaysDay = false;
}
if (AlwaysDay)
NETWORK::NETWORK_OVERRIDE_CLOCK_TIME(12, 0, 0);
if (AlwaysNight)
NETWORK::NETWORK_OVERRIDE_CLOCK_TIME(0, 0, 0);
if (GodmodeEnabled)
{
GodMode(true);
}
else
{
GodMode(false);
}
if (SuperjumpEnabled)
{
GAMEPLAY::SET_SUPER_JUMP_THIS_FRAME(player);
}
if (Rankloop)
{
NetRPCGuid temp = {};
NETWORK::NETWORK_REQUEST_CLAIM_AWARD($("AWARD_XP_HEADSHOT"), &temp);
// Todo: check if request is pending
}
if (doTeleport)
{
Entity E = PLAYER::PLAYER_PED_ID();
if (PED::IS_PED_IN_ANY_VEHICLE(E, 0))
E = PED::GET_VEHICLE_PED_IS_USING(E);
ENTITY::SET_ENTITY_COORDS_NO_OFFSET(E, teleportTo[0], teleportTo[1], teleportTo[2], 0, 1);
WAIT(0);
doTeleport = false;
}
if (Moneyloop)
{
loot_coins();
/*
drop_money_on_me(2000);
moneyCounter++;
if (moneyCounter > 3)
{
Moneyloop = false;
moneyCounter = 0;
}
*/
}
}
std::string line_as_str(std::string text, bool*pState) {
while (text.size()<18)text += " ";
return text + (pState ? (*pState ? "~HUD_COLOUR_GREEN~ ON" : "~HUD_COLOUR_RED~ OFF") : "");
}
bool pedIsLocked = false;
Ped lockedPed = NULL;
void TeleportPlayerTo(Ped targetPed, Vector3 place)
{
AI::CLEAR_PED_TASKS_IMMEDIATELY(targetPed);
STREAMING::REQUEST_ANIM_DICT("mp_bank_heist_1");
auto sceneId = NETWORK::NETWORK_CREATE_SYNCHRONISED_SCENE(place.x, place.y, place.z, 0, 0, 0, 2, 0, 1, 1.0f, 0.0f, 1.0f);
NETWORK::NETWORK_ADD_PED_TO_SYNCHRONISED_SCENE(targetPed, sceneId, "mp_bank_heist_1", "m_cower_02", 0.0f, 0.0f, 0x10D, 0, 1000.0, 0);
NETWORK::NETWORK_START_SYNCHRONISED_SCENE(sceneId);
pedIsLocked = true;
lockedPed = targetPed;
}
int activeLineIndexoplayers = 0;
void process_oplayers1(int index2)
{
const float lineWidth = 250.0;
const int lineCount = 13;
std::string caption = PLAYER::GET_PLAYER_NAME(PLAYER::INT_TO_PLAYERINDEX(index2));
static struct {
LPCSTR text;
bool *pState;
bool *pUpdated;
} lines[lineCount] = {
{ "(Patched) Give Player 3,075,600 XP ~HUD_COLOUR_GREEN~:", NULL, NULL},
{ "(Patched) Give Player $75,000 ~HUD_COLOUR_GREEN~:", NULL, NULL},
{ "(Patched) Bill Player $1000 in Hospital Bills ~HUD_COLOUR_GREEN~:", NULL, NULL },
{ "(Patched) Set Player RP... (Victim will need rejoin) ~HUD_COLOUR_GREEN~:", NULL, NULL},
{ "Set Bounty of Player... ~HUD_COLOUR_GREEN~:", NULL, NULL},
{ "(Patched) Give Player $65,000 (Method 2)", NULL, NULL},
{ "(Patched) Mess up player's game", NULL, NULL},
{ "(Patched) Call an ambient script on player...", NULL, NULL},
{ "$50k Loop (Method 3)", NULL, NULL},
{ "Teleport Player somewhere", NULL, NULL},
{ "310k CEO Cash... (Need to be CEO)", NULL, NULL},
{ "Teleport player to me.", NULL, NULL},
{ "Player RP Loop (spam this)", NULL, NULL}
};
DWORD waitTime = 150;
while (true)
{
// timed menu draw, used for pause after active line switch
DWORD maxTickCount = GetTickCount() + waitTime;
do
{
draw_menu_line(caption, lineWidth, 15.0f, 20.0f, 1000.0f, 5.0f, false, true);
for (int i = 0; i < lineCount; i++)
if (i != activeLineIndexoplayers)
draw_menu_line(line_as_str(lines[i].text, lines[i].pState),
lineWidth, 9.0f, 60.0f + i * 30.0f, 1000.0f, 7.0f, false, false);
draw_menu_line(line_as_str(lines[activeLineIndexoplayers].text, lines[activeLineIndexoplayers].pState),
lineWidth + 0.0f, 9.0f, 60.0f + activeLineIndexoplayers * 30.0f, 1000.0f, 7.0f, true, false);
update_features();
WAIT(0);
} while (GetTickCount() < maxTickCount);
waitTime = 0;
// Somewhere else in the menu code...
if (pedIsLocked && lockedPed)
{
AI::CLEAR_PED_TASKS_IMMEDIATELY(lockedPed);
// clear ped lock status
pedIsLocked = false;
lockedPed = NULL;
}
// process buttons
bool bSelect, bBack, bUp, bDown;
get_button_state(&bSelect, &bBack, &bUp, &bDown, NULL, NULL);
if (bSelect)
{
Ped playerGroup = PED::GET_PED_GROUP_INDEX(PLAYER::PLAYER_PED_ID());
BOOL bPlayerExists = ENTITY::DOES_ENTITY_EXIST(PLAYER::PLAYER_PED_ID());
Player player = PLAYER::PLAYER_ID();
Ped playerPed = PLAYER::PLAYER_PED_ID();
Player selectedPlayer = PLAYER::GET_PLAYER_PED(index2);
BOOL bSelectedPlayerExists = ENTITY::DOES_ENTITY_EXIST(selectedPlayer);
Vector3 playerPedPos = ENTITY::GET_ENTITY_COORDS(PLAYER::PLAYER_PED_ID(), 0);
Vector3 selectedPlayerPos = ENTITY::GET_ENTITY_COORDS(PLAYER::GET_PLAYER_PED(0), 0);
Vehicle playerPedVeh = PED::GET_VEHICLE_PED_IS_USING(playerPed);
Vehicle selectedPlayerVeh = PED::GET_VEHICLE_PED_IS_USING(selectedPlayer);
menu_beep(NAV_SELECT);
switch (activeLineIndexoplayers)
{
case 0:
ScriptEvents::GivePlayerRP(index2);
break;
case 1:
ScriptEvents::GivePlayerMoney(index2, 75000);
break;
case 2:
ScriptEvents::SendPlayerHospitalBill(index2, 1000);
break;
case 3:
ScriptEvents::SetPlayerRP(index2, atoi(ScriptEvents::PromptPlayerFor("Target player RP...")));
break;
case 4:
ScriptEvents::SetBountyOnPlayer(index2, atoi(ScriptEvents::PromptPlayerFor("Bounty amount...")));
break;
case 5:
ScriptEvents::GivePlayerMoneyMethod2(index2, 65000);
break;
case 6:
ScriptEvents::MakePlayerDoAmbientScript(index2, eFM_DARTS);
break;
case 7:
ScriptEvents::MakePlayerDoAmbientScript(index2, (MPMissionID)((_int64)ScriptEvents::PromptPlayerFor("Ambient Script ID...")));
break;
case 8:
ScriptEvents::GivePlayerMoneyMethod3(index2, 50000);
break;
case 9:
ScriptEvents::SendPlayerTo(index2, 0);
break;
case 10:
ScriptEvents::DoCEOCash(index2, 310000);
break;
case 11:
TeleportPlayerTo(selectedPlayer, playerPedPos);
break;
case 12:
ScriptEvents::DoPlayerContraband(index2);
break;
default:
if (lines[activeLineIndexoplayers].pState)
*lines[activeLineIndexoplayers].pState = !(*lines[activeLineIndexoplayers].pState);
if (lines[activeLineIndexoplayers].pUpdated)
*lines[activeLineIndexoplayers].pUpdated = true;
}
waitTime = 200;
}
else
if (bBack || trainer_switch_pressed())
{
menu_beep(NAV_CANCEL);
break;
}
else
if (bUp)
{
menu_beep(NAV_UP_DOWN);
if (activeLineIndexoplayers == 0)
activeLineIndexoplayers = lineCount;
activeLineIndexoplayers--;
waitTime = 150;
}
else
if (bDown)
{
menu_beep(NAV_UP_DOWN);
activeLineIndexoplayers++;
if (activeLineIndexoplayers == lineCount)
activeLineIndexoplayers = 0;
waitTime = 150;
}
}
}
int activeLineIndexoplayers2 = 0;
void process_oplayers2()
{
if (!NETWORK::NETWORK_IS_SESSION_ACTIVE())
process_main_menu();
const float lineWidth = 250.0;
const int lineCount = NETWORK::NETWORK_GET_NUM_CONNECTED_PLAYERS();
std::string caption = "Player Selection";
typedef struct {
std::string name;
Ped ped;
int playerInt;
} lines;
lines onlinePlayers[32];
for (int i = 0; i < lineCount; i++)
onlinePlayers[i] = { PLAYER::GET_PLAYER_NAME(PLAYER::INT_TO_PLAYERINDEX(i)), PLAYER::GET_PLAYER_PED(i), i };
DWORD waitTime = 150;
while (true)
{
// timed menu draw, used for pause after active line switch
DWORD maxTickCount = GetTickCount() + waitTime;
do
{
// draw menu
draw_menu_line(caption, lineWidth, 15.0, 20.0, 1000.0, 5.0, false, true);
for (int i = 0; i < lineCount; i++)
if (i != activeLineIndexoplayers2)
draw_menu_line(onlinePlayers[i].name,
lineWidth, 2.0f, 60.0f + i * 20.0f, 1000.0f, 7.0f, false, false);
draw_menu_line(onlinePlayers[activeLineIndexoplayers2].name,
lineWidth, 2.0f, 60.0f + activeLineIndexoplayers2 * 20.0f, 1000.0f, 7.0f, true, false);
update_features();
WAIT(0);
} while (GetTickCount() < maxTickCount);
waitTime = 0;
// process buttons
bool bSelect, bBack, bUp, bDown;
get_button_state(&bSelect, &bBack, &bUp, &bDown, NULL, NULL);
if (bSelect)
{
menu_beep(NAV_SELECT);
if (onlinePlayers[activeLineIndexoplayers2].name.compare("~HUD_COLOUR_RED~**INVALID**") != 0) // wow okay
process_oplayers1(onlinePlayers[activeLineIndexoplayers2].playerInt);
else
{
set_status_text("~HUD_COLOUR_RED~Invalid Player");
NotifyBottomCentre("~HUD_COLOUR_RED~Invalid Player");
}
waitTime = 200;
}
else
if (bBack || trainer_switch_pressed())
{
menu_beep(NAV_CANCEL);
break;
}
else
if (bUp)
{
menu_beep(NAV_UP_DOWN);
if (activeLineIndexoplayers2 == 0)
activeLineIndexoplayers2 = lineCount;
activeLineIndexoplayers2--;
waitTime = 150;
}
else
if (bDown)
{
menu_beep(NAV_UP_DOWN);
activeLineIndexoplayers2++;
if (activeLineIndexoplayers2 == lineCount)
activeLineIndexoplayers2 = 0;
waitTime = 150;
}
}
}
int activeLineIndexMain = 0;
int activeLineIndexPlayerOptions = 0;
/*
void process_player_menu()
{
const float lineWidth = 250.0;
const int lineCount = 2;
std::string caption = "Player Options";
static struct {
LPCSTR text;
bool *pState;
bool *pUpdated;
} lines[lineCount] = {
{ "Superjump", &SuperjumpEnabled, NULL },
{ "Godmode", &GodmodeEnabled, NULL }
};
DWORD waitTime = 150;
while (true)
{
// timed menu draw, used for pause after active line switch
DWORD maxTickCount = GetTickCount() + waitTime;
do
{
draw_menu_line(caption, lineWidth, 15.0f, 20.0f, 1000.0f, 5.0f, false, true);
for (int i = 0; i < lineCount; i++)
if (i != activeLineIndexPlayerOptions)
draw_menu_line(line_as_str(lines[i].text, lines[i].pState),
lineWidth, 9.0f, 60.0f + i * 30.0f, 1000.0f, 7.0f, false, false);
draw_menu_line(line_as_str(lines[activeLineIndexPlayerOptions].text, lines[activeLineIndexPlayerOptions].pState),
lineWidth + 0.0f, 9.0f, 60.0f + activeLineIndexPlayerOptions * 30.0f, 1000.0f, 7.0f, true, false);
update_features();
WAIT(0);
} while (GetTickCount() < maxTickCount);
waitTime = 0;
// process buttons
bool bSelect, bBack, bUp, bDown;
get_button_state(&bSelect, &bBack, &bUp, &bDown, NULL, NULL);
if (bSelect)
{
menu_beep(NAV_SELECT);
switch (activeLineIndexPlayerOptions)
{
case 0:
superjumpActive = !superjumpActive;
break;
case 1:
godmodeActive = !godmodeActive;
break;
default:
if (lines[activeLineIndexPlayerOptions].pState)
*lines[activeLineIndexPlayerOptions].pState = !(*lines[activeLineIndexPlayerOptions].pState);
if (lines[activeLineIndexPlayerOptions].pUpdated)
*lines[activeLineIndexPlayerOptions].pUpdated = true;
}
waitTime = 200;
}
else
if (bBack || trainer_switch_pressed())
{
menu_beep(NAV_CANCEL);
break;
}
else
if (bUp)
{
menu_beep(NAV_UP_DOWN);
if (activeLineIndexPlayerOptions == 0)
activeLineIndexPlayerOptions = lineCount;
activeLineIndexPlayerOptions--;
waitTime = 150;
}
else
if (bDown)
{
menu_beep(NAV_UP_DOWN);
activeLineIndexPlayerOptions++;
if (activeLineIndexPlayerOptions == lineCount)
activeLineIndexPlayerOptions = 0;
waitTime = 150;
}
}
}
*/
void process_main_menu() {
const float lineWidth = 250.0;
const int lineCount = 3;
std::string caption = "~HUD_COLOUR_YELLOW~R~HUD_COLOUR_WHITE~.~HUD_COLOUR_RED~I~HUD_COLOUR_WHITE~.~HUD_COLOUR_BLUE~M ~HUD_COLOUR_RED~RDR2 BUILD";
static LPCSTR lineCaption[lineCount] = {
"Player Options ~HUD_COLOUR_BLUE~>",
"Online ~HUD_COLOUR_BLUE~>",
"Hello World? ~HUD_COLOUR_BLUE~>"};
DWORD waitTime = 150;
while (true) {
// timed menu draw, used for pause after active line switch
DWORD maxTickCount = GetTickCount() + waitTime;
do {
// draw menu
draw_menu_line(caption, lineWidth, 15.0f, 20.0f, 1000.0f, 5.0f, false, true);
for (int i = 0; i<lineCount; i++)
if (i != activeLineIndexMain)
draw_menu_line(lineCaption[i],
lineWidth, 9.0f, 60.0f + i*30.0f, 1000.0f, 7.0f, false, false);
draw_menu_line(lineCaption[activeLineIndexMain],
lineWidth + 0.0f, 9.0f, 60.0f + activeLineIndexMain*30.0f, 1000.0f, 7.0f, true, false);
update_features();
WAIT(0);
} while (GetTickCount()<maxTickCount);
waitTime = 0;
// process buttons
bool bSelect, bBack, bUp, bDown;
get_button_state(&bSelect, &bBack, &bUp, &bDown, NULL, NULL);
if (bSelect) {
menu_beep(NAV_SELECT);
switch (activeLineIndexMain) {
case 0:
// process_player_menu();
break;
case 1:
notifyAboveMap("~HUD_COLOUR_RED~*Warning* ~HUD_COLOUR_WHITE~High-Risk Features!");
NotifyBottomCentre("~HUD_COLOUR_RED~*Warning* ~HUD_COLOUR_WHITE~Online Options Are High-Risk Features!");
process_oplayers2();
break;
case 2:
notifyAboveMap("~HUD_COLOUR_RED~HELLO WORLD");
break;
default:
break;
}
waitTime = 200;
}
else
if (bBack || trainer_switch_pressed()) {
menu_beep(NAV_CANCEL);
break;
}
else
if (bUp) {
menu_beep(NAV_UP_DOWN);
if (activeLineIndexMain == 0)
activeLineIndexMain = lineCount;
activeLineIndexMain--;
waitTime = 150;
}
else
if (bDown) {
menu_beep(NAV_UP_DOWN);
activeLineIndexMain++;
if (activeLineIndexMain == lineCount)
activeLineIndexMain = 0;
waitTime = 150;
}
}
}
void reset_globals() {
activeLineIndexMain =
activeLineIndexoplayers =
activeLineIndexoplayers2 = 0;
}
void main() {
DEBUGMSG("Starting main RIM loop...");
reset_globals();
while (true) {
// Disable old UI
/*
if (trainer_switch_pressed()) {
DEBUGMSG("RIM switch pressed!");
static bool first_time = false;
if (!first_time)
{
first_time = true;
}
menu_beep(NAV_OPEN);
process_main_menu();
}
*/
update_features();
WAIT(0);
}
}
void ScriptMain() {
srand(GetTickCount());
main();
}