mahlendur/_work/Data/Scripts/Content/LeGo/FrameFunctions.d
Daniel Heße 96b7bfd52d Fixed some bugs, did some testing.
Everything should be working by now, up until final battle (still needs testing).

Updated LeGo to 2.8.0
2022-10-03 18:16:51 +02:00

337 lines
8.2 KiB
D

/***********************************\
FRAMEFUNCTIONS
\***********************************/
//========================================
// [intern] PM-Klasse
//========================================
class FFItem {
var int fncID;
var int next;
var int delay;
var int cycles;
var int data;
var int hasData;
var int gametime;
};
instance FFItem@(FFItem);
func void FFItem_Archiver(var FFItem this) {
PM_SaveFuncPtr("loop", this.fncID);
if(this.next) { PM_SaveInt("next", this.next); };
if(this.delay) { PM_SaveInt("delay", this.delay); };
if(this.cycles != -1) {
PM_SaveInt("cycles", this.cycles);
};
if (this.hasData) { PM_SaveInt("data", this.data); };
if (this.gametime) { PM_SaveInt("gametime", this.gametime); };
};
func void FFItem_Unarchiver(var FFItem this) {
this.fncID = PM_LoadFuncPtr("loop");
if(PM_Exists("next")) { this.next = PM_Load("next"); };
if(PM_Exists("delay")) { this.delay = PM_Load("delay"); };
if(PM_Exists("cycles")) {
this.cycles = PM_Load("cycles");
}
else {
this.cycles = -1;
};
if (PM_Exists("data")) {
this.data = PM_Load("data");
this.hasData = 1;
};
if (PM_Exists("gametime")) {
this.gametime = PM_Load("gametime");
};
// Fix function signature of invalid functions
if (this.fncID == MEM_GetFuncPtr(_PM_EmptyFunc_int)) && (!this.hasData) {
this.fncID = MEM_GetFuncPtr(_PM_EmptyFunc_void);
};
};
var int _FF_Symbol;
//========================================
// Funktion hinzufügen
//========================================
func void _FF_Create(var func function, var int delay, var int cycles, var int hasData, var int data, var int gametime) {
var int hndl; hndl = new(FFItem@);
var FFItem itm; itm = get(hndl);
itm.fncID = MEM_GetFuncPtr(function);
itm.cycles = cycles;
itm.delay = delay;
itm.data = data;
itm.hasData = hasData;
itm.gametime = gametime;
if (gametime) {
itm.next = TimerGT() + itm.delay;
} else {
itm.next = Timer() + itm.delay;
};
};
func void FF_ApplyExtData(var func function, var int delay, var int cycles, var int data) {
_FF_Create(function, delay, cycles, true, data, false);
};
func void FF_ApplyExt(var func function, var int delay, var int cycles) {
_FF_Create(function, delay, cycles, false, 0, false);
};
func void FF_ApplyExtDataGT(var func function, var int delay, var int cycles, var int data) {
_FF_Create(function, delay, cycles, true, data, true);
};
func void FF_ApplyExtGT(var func function, var int delay, var int cycles) {
_FF_Create(function, delay, cycles, false, 0, true);
};
//========================================
// Funktion prüfen
//========================================
func int FF_Active(var func function) {
_FF_Symbol = MEM_GetFuncPtr(function);
foreachHndl(FFItem@, _FF_Active);
return !_FF_Symbol;
};
func int _FF_Active(var int hndl) {
if(MEM_ReadInt(getPtr(hndl)) != _FF_Symbol) {
return continue;
};
_FF_Symbol = 0;
return break;
};
//========================================
// Funktion hinzufügen (vereinfacht)
//========================================
func void FF_Apply(var func function) {
FF_ApplyExt(function, 0, -1);
};
func void FF_ApplyGT(var func function) {
FF_ApplyExtGT(function, 0, -1);
};
//========================================
// Funktion einmalig hinzufügen
//========================================
func void FF_ApplyOnceExt(var func function, var int delay, var int cycles) {
if(FF_Active(function)) {
return;
};
FF_ApplyExt(function, delay, cycles);
};
func void FF_ApplyOnceExtGT(var func function, var int delay, var int cycles) {
if(FF_Active(function)) {
return;
};
FF_ApplyExtGT(function, delay, cycles);
};
//========================================
// Funktion einmalig hinzufügen (vereinfacht)
//========================================
func void FF_ApplyOnce(var func function) {
FF_ApplyOnceExt(function, 0, -1);
};
func void FF_ApplyOnceGT(var func function) {
FF_ApplyOnceExtGT(function, 0, -1);
};
//========================================
// Funktion entfernen
//========================================
func void FF_Remove(var func function) {
_FF_Symbol = MEM_GetFuncPtr(function);
foreachHndl(FFItem@, _FF_RemoveL);
};
func int _FF_RemoveL(var int hndl) {
if(MEM_ReadInt(getPtr(hndl)) != _FF_Symbol) {
return continue;
};
delete(hndl);
return break;
};
func void FF_RemoveAll(var func function) {
_FF_Symbol = MEM_GetFuncPtr(function);
foreachHndl(FFItem@, _FF_RemoveAllL);
};
func int _FF_RemoveAllL(var int hndl) {
if(MEM_ReadInt(getPtr(hndl)) != _FF_Symbol) {
return continue;
};
delete(hndl);
return continue;
};
//========================================
// [intern] Enginehook
//========================================
func void _FF_Hook() {
if(!Hlp_IsValidNpc(hero)) { return; };
foreachHndl(FFItem@, FrameFunctions);
};
func int FrameFunctions(var int hndl) {
var FFItem itm; itm = get(hndl);
var int timer;
var int t; t = Timer();
var int tgt; tgt = TimerGT();
if (itm.gametime) {
timer = tgt;
} else {
timer = t;
};
MEM_Label(0);
if(timer >= itm.next) {
// Backup data stack pointer
var int sptr; sptr = MEM_Parser.datastack_sptr;
// Call function
if (itm.hasData) {
itm.data;
};
MEM_CallByPtr(itm.fncID);
// Restore data stack pointer
MEM_Parser.datastack_sptr = sptr;
// If a FrameFunction removes itself while its delay is small enough s.t. MEM_Goto(0) is called below,
// the game crashes, because MEM_CallByPtr moves the stack pointer to an invalid position.
if (!Hlp_IsValidHandle(hndl)) {
return rContinue;
};
if(itm.cycles != -1) {
itm.cycles -= 1;
if(itm.cycles <= 0) {
delete(hndl);
return rContinue;
};
};
if(itm.delay) {
itm.next += itm.delay;
MEM_Goto(0);
} else {
// Minimally increase to prevent running during menu if PiM or GT, i.e. while timer will not increase, the
// above condition (timer >= itm.next) will always be satisfied.
itm.next = timer + 1;
};
};
return rContinue;
};
/***********************************\
The following code has been supplied by
Frank-95 (https://forum.worldofplayers.de/forum/members/148085-Frank-95)
\***********************************/
//========================================
// Remove FF with the specified data
//========================================
var int _FF_Data;
func int _FF_RemoveLData(var int hndl)
{
if(MEM_ReadInt(getPtr(hndl)) != _FF_Symbol)
{
return continue;
};
var FFItem itm; itm = get(hndl);
if(itm.data != _FF_Data)
{
return continue;
}
else
{
delete(hndl);
return break;
};
};
func void FF_RemoveData(var func function, var int data)
{
_FF_Data = data;
_FF_Symbol = MEM_GetFuncPtr(function);
foreachHndl(FFItem@, _FF_RemoveLData);
};
//=======================================================
// Check whether FF with the specified data is active
//=======================================================
func int _FF_ActiveData(var int hndl)
{
if(MEM_ReadInt(getPtr(hndl)) != _FF_Symbol)
{
return continue;
};
var FFItem itm; itm = get(hndl);
if(itm.data != _FF_Data)
{
return continue;
}
else
{
_FF_Symbol = 0;
return break;
};
};
func int FF_ActiveData(var func function, var int data)
{
_FF_Data = data;
_FF_Symbol = MEM_GetFuncPtr(function);
foreachHndl(FFItem@, _FF_ActiveData);
return !_FF_Symbol;
};
//========================================
// More FFdata functions
//========================================
func void FF_ApplyData(var func function, var int data)
{
FF_ApplyExtData(function, 0, -1, data);
};
func void FF_ApplyOnceExtData(var func function, var int delay, var int cycles, var int data)
{
if(FF_ActiveData(function,data))
{
return;
};
FF_ApplyExtData(function, delay, cycles, data);
};
func void FF_ApplyOnceData(var func function, var int data)
{
FF_ApplyOnceExtData(function, 0, -1, data);
};