mahlendur/_work/Data/Scripts/Content/neclib/Levitation.d
Daniel Heße 892a40ff0f Initial commit with Subversion-codebase from 13/05/2022.
Cleaned up the mess, at this time, only viable data get synced (_work directory for Gothic-data, miranda for mdc-scripts.
Need to symlink files to a working directory.
2022-05-13 17:38:52 +02:00

162 lines
No EOL
5.4 KiB
D

// public
// Note: You can change the variables values but do not change their names - they are partially needed by NEC library
const int LEVITATION_HOVER_DISTANCE = 50; // hover distance (in cm/s)
const int LEVITATION_SPEED_VERTICAL = 60; // up/down levitation speed (in cm/s)
const int LEVITATION_SPEED_FORWARD = 200; // forward levitation speed (in cm/s)
const int LEVITATION_SPEED_BACKWARD = 200; // backward levitation speed (in cm/s)
const int LEVITATION_SPEED_TURN = 90; // turn speed (in degree angles/s)
const int LEVITATION_MAX_LIFETIME = 30000; // maximum lifetime of the levitation state (in ms)
const int LEVITATION_GRAVITY = 10; // levitation gravity (in cm/s). Set it to 0 for no gravity.
const int LEVITATION_CONTINOUS_SUBSTRACTION_TIME = 120; // specifies the time (in seconds) it takes for the continous lifetime substraction
// to consume the whole levitation lifetime.
const string LEVITATION_OVERLAY = "Humans_Levitate.mds"; // levitation overlay
// user control
const int LEVITATION_CONTROL_FORWARD = KEY_UPARROW; // forward movement
const int LEVITATION_CONTROL_BACKWARD = KEY_DOWNARROW; // backward movement
const int LEVITATION_CONTROL_LEFT = KEY_LEFTARROW; // left turn
const int LEVITATION_CONTROL_RIGHT = KEY_RIGHTARROW; // right turn
const int LEVITATION_CONTROL_UP = KEY_A; // up movement
const int LEVITATION_CONTROL_DOWN = KEY_Z; // down movement
const int LEVITATION_CONTROL_TERMINATE = KEY_RETURN; // terminates levitation state
// private
var int _LEVITATION_barHandle; // lifetime bar of the levitation state
var int _LEVITATION_consumedLifetme; // spend lifetime of the levitation state (in ms)
var int _LEVITATION_IsActive; // indicates that the NEC library should activate levitation state for hero
/**
* Checks if the game is currently paused.
* @return : TRUE if the game is paused otherwise FALSE.
*/
func int LEVITATION_IsGamePaused() {
if (!(NEC_Init_Modules & NEC_LEVITATION)) {
MEM_Warn("neclib: LEVITATION_IsGamePaused: Levitation module isn't initialized!");
return FALSE;
};
const int call = 0;
var int ret;
if (CALL_Begin(call)) {
var int adr;
adr = GetProcAddress (LoadLibrary (NEC_relativeLibraryPath), "LEVITATION_IsGamePaused");
CALL_PutRetValTo(_@(ret));
CALL__cdecl(adr);
call = CALL_End();
};
return +ret;
};
/**
* Initializes the levitation module.
*/
func void LEVITATION_Init() {
if (!(NEC_Init_Modules & NEC_LEVITATION)) {
MEM_Warn("neclib: LEVITATION_Init: Levitation module isn't specified to be initialized!");
return;
};
if (!_LEVITATION_barHandle) {
_LEVITATION_barHandle = Bar_Create(GothicBar@);
Bar_Hide(_LEVITATION_barHandle);
MEM_Info("neclib: LEVITATION_Init: created lifetime bar.");
};
MEM_Info("neclib: LEVITATION_Init: done.");
};
/**
* Starts the levitation state.
*/
func void LEVITATION_Begin() {
if (!(NEC_Init_Modules & NEC_LEVITATION)) {
MEM_Warn("neclib: LEVITATION_Begin: Levitation module isn't initialized!");
return;
};
_LEVITATION_IsActive = TRUE;
Bar_Show(_LEVITATION_barHandle);
Bar_SetPromille(_LEVITATION_barHandle, 1000); // fill lifetime
Mdl_ApplyOverlayMds (hero, LEVITATION_OVERLAY);
_LEVITATION_consumedLifetme = FLOATNULL;
FF_ApplyOnce(LEVITATION_ConsumeLifetime);
MEM_Info("neclib: LEVITATION_Begin: begin levitation...");
};
/**
* Ends the levitation state.
*/
func void LEVITATION_End() {
if (!(NEC_Init_Modules & NEC_LEVITATION)) {
MEM_Warn("neclib: LEVITATION_End: Levitation module isn't initialized!");
return;
};
_LEVITATION_IsActive = FALSE;
Bar_Hide(_LEVITATION_barHandle);
Mdl_RemoveOverlayMDS(hero, "Humans_Levitate.mds");
FF_Remove(LEVITATION_ConsumeLifetime);
MEM_Info("neclib: LEVITATION_End: end levitation.");
};
/**
* Toggles the levitation state.
*/
func void LEVITATION_Toggle() {
if (!(NEC_Init_Modules & NEC_LEVITATION)) {
MEM_Warn("neclib: LEVITATION_Toggle: Levitation module isn't initialized!");
return;
};
if (_LEVITATION_IsActive) {
LEVITATION_End();
} else {
LEVITATION_Begin();
};
};
/**
* Updates levitation lifetime for the current frame.
*/
func void LEVITATION_ConsumeLifetime() {
// do nothing if game is currently paused.
if (LEVITATION_IsGamePaused()) {return;};
const int THOUSAND = 1000;
// we add 1/LEVITATION_CONTINOUS_SUBSTRACTION_TIME to the invested time as a continous contribution.
_LEVITATION_consumedLifetme = addf(_LEVITATION_consumedLifetme,
mulf(MEM_Timer.frameTimeFloat, fracf(LEVITATION_MAX_LIFETIME, LEVITATION_CONTINOUS_SUBSTRACTION_TIME * THOUSAND)));
// if levitation up movement is active we substract more lifetime.
if (MEM_KeyState(LEVITATION_CONTROL_UP) == KEY_HOLD) {
_LEVITATION_consumedLifetme = addf(_LEVITATION_consumedLifetme, MEM_Timer.frameTimeFloat);
};
// Update levitation lifetime bar
var int barPromille;
barPromille = subf(mkf(LEVITATION_MAX_LIFETIME), _LEVITATION_consumedLifetme);
barPromille = divf(barPromille, mkf(LEVITATION_MAX_LIFETIME));
barPromille = mulf(barPromille, mkf(THOUSAND));
barPromille = truncf(barPromille);
if (barPromille < 0) {
barPromille = 0;
};
Bar_SetPromille(_LEVITATION_barHandle, barPromille);
// end levitation state if lifetime is consumed or the user exits on purpose
if (MEM_KeyState(LEVITATION_CONTROL_TERMINATE) == KEY_PRESSED || barPromille == 0) {
LEVITATION_End();
};
};