2022-05-05 11:56:29 +02:00
|
|
|
#include "game/effects.h"
|
|
|
|
|
2022-05-14 22:38:03 +02:00
|
|
|
#include "game/output.h"
|
2023-01-20 09:55:04 -05:00
|
|
|
#include "game/room.h"
|
2022-05-13 00:24:21 +02:00
|
|
|
#include "global/const.h"
|
|
|
|
#include "global/types.h"
|
2022-05-05 11:56:29 +02:00
|
|
|
#include "global/vars.h"
|
2022-05-14 22:38:03 +02:00
|
|
|
#include "math/matrix.h"
|
2022-05-05 11:56:29 +02:00
|
|
|
|
2022-08-19 12:19:06 +02:00
|
|
|
#include <stddef.h>
|
|
|
|
|
2024-09-24 00:09:15 +02:00
|
|
|
FX *g_Effects = NULL;
|
2022-08-19 12:19:06 +02:00
|
|
|
int16_t g_NextFxActive = NO_ITEM;
|
|
|
|
|
|
|
|
static int16_t m_NextFxFree = NO_ITEM;
|
|
|
|
|
2022-05-05 11:56:29 +02:00
|
|
|
void Effect_InitialiseArray(void)
|
|
|
|
{
|
|
|
|
g_NextFxActive = NO_ITEM;
|
2022-08-19 12:19:06 +02:00
|
|
|
m_NextFxFree = 0;
|
2022-05-05 11:56:29 +02:00
|
|
|
for (int i = 0; i < NUM_EFFECTS - 1; i++) {
|
2023-08-31 17:43:45 +02:00
|
|
|
g_Effects[i].next_draw = i + 1;
|
|
|
|
g_Effects[i].next_free = i + 1;
|
2022-05-05 11:56:29 +02:00
|
|
|
}
|
2023-08-31 17:43:45 +02:00
|
|
|
g_Effects[NUM_EFFECTS - 1].next_draw = NO_ITEM;
|
|
|
|
g_Effects[NUM_EFFECTS - 1].next_free = NO_ITEM;
|
2022-05-05 11:56:29 +02:00
|
|
|
}
|
|
|
|
|
2022-08-19 12:19:06 +02:00
|
|
|
void Effect_Control(void)
|
|
|
|
{
|
|
|
|
int16_t fx_num = g_NextFxActive;
|
|
|
|
while (fx_num != NO_ITEM) {
|
2024-09-24 00:09:15 +02:00
|
|
|
FX *fx = &g_Effects[fx_num];
|
|
|
|
OBJECT *obj = &g_Objects[fx->object_id];
|
2022-08-19 12:19:06 +02:00
|
|
|
if (obj->control) {
|
|
|
|
obj->control(fx_num);
|
|
|
|
}
|
|
|
|
fx_num = fx->next_active;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-05 11:56:29 +02:00
|
|
|
int16_t Effect_Create(int16_t room_num)
|
|
|
|
{
|
2022-08-19 12:19:06 +02:00
|
|
|
int16_t fx_num = m_NextFxFree;
|
2022-05-05 11:56:29 +02:00
|
|
|
if (fx_num == NO_ITEM) {
|
|
|
|
return fx_num;
|
|
|
|
}
|
|
|
|
|
2024-09-24 00:09:15 +02:00
|
|
|
FX *fx = &g_Effects[fx_num];
|
2023-08-31 17:43:45 +02:00
|
|
|
m_NextFxFree = fx->next_free;
|
2022-05-05 11:56:29 +02:00
|
|
|
|
2024-09-24 00:09:15 +02:00
|
|
|
ROOM *r = &g_RoomInfo[room_num];
|
2024-09-06 10:03:51 +02:00
|
|
|
fx->room_num = room_num;
|
2024-09-06 10:07:10 +02:00
|
|
|
fx->next_draw = r->fx_num;
|
|
|
|
r->fx_num = fx_num;
|
2022-05-05 11:56:29 +02:00
|
|
|
|
|
|
|
fx->next_active = g_NextFxActive;
|
|
|
|
g_NextFxActive = fx_num;
|
|
|
|
|
|
|
|
return fx_num;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Effect_Kill(int16_t fx_num)
|
|
|
|
{
|
2024-09-24 00:09:15 +02:00
|
|
|
FX *fx = &g_Effects[fx_num];
|
2022-05-05 11:56:29 +02:00
|
|
|
|
2023-08-31 17:43:45 +02:00
|
|
|
if (g_NextFxActive == fx_num) {
|
2022-05-05 11:56:29 +02:00
|
|
|
g_NextFxActive = fx->next_active;
|
|
|
|
} else {
|
2023-08-31 17:43:45 +02:00
|
|
|
int16_t linknum = g_NextFxActive;
|
|
|
|
while (linknum != NO_ITEM) {
|
2024-09-24 00:09:15 +02:00
|
|
|
FX *fx_link = &g_Effects[linknum];
|
2023-08-31 17:43:45 +02:00
|
|
|
if (fx_link->next_active == fx_num) {
|
|
|
|
fx_link->next_active = fx->next_active;
|
2022-05-05 11:56:29 +02:00
|
|
|
}
|
2023-08-31 17:43:45 +02:00
|
|
|
linknum = fx_link->next_active;
|
2022-05-05 11:56:29 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-24 00:09:15 +02:00
|
|
|
ROOM *r = &g_RoomInfo[fx->room_num];
|
2024-09-06 10:07:10 +02:00
|
|
|
if (r->fx_num == fx_num) {
|
|
|
|
r->fx_num = fx->next_draw;
|
2022-05-05 11:56:29 +02:00
|
|
|
} else {
|
2024-09-06 10:07:10 +02:00
|
|
|
int16_t linknum = r->fx_num;
|
2023-08-31 17:43:45 +02:00
|
|
|
while (linknum != NO_ITEM) {
|
2024-09-24 00:09:15 +02:00
|
|
|
FX *fx_link = &g_Effects[linknum];
|
2023-08-31 17:43:45 +02:00
|
|
|
if (fx_link->next_draw == fx_num) {
|
|
|
|
fx_link->next_draw = fx->next_draw;
|
2022-05-05 11:56:29 +02:00
|
|
|
break;
|
|
|
|
}
|
2023-08-31 17:43:45 +02:00
|
|
|
linknum = fx_link->next_draw;
|
2022-05-05 11:56:29 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-31 17:43:45 +02:00
|
|
|
fx->next_free = m_NextFxFree;
|
2022-08-19 12:19:06 +02:00
|
|
|
m_NextFxFree = fx_num;
|
2022-05-05 11:56:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Effect_NewRoom(int16_t fx_num, int16_t room_num)
|
|
|
|
{
|
2024-09-24 00:09:15 +02:00
|
|
|
FX *fx = &g_Effects[fx_num];
|
|
|
|
ROOM *r = &g_RoomInfo[fx->room_num];
|
2022-05-05 11:56:29 +02:00
|
|
|
|
2024-09-06 10:07:10 +02:00
|
|
|
int16_t linknum = r->fx_num;
|
2022-05-05 11:56:29 +02:00
|
|
|
if (linknum == fx_num) {
|
2024-09-06 10:07:10 +02:00
|
|
|
r->fx_num = fx->next_draw;
|
2022-05-05 11:56:29 +02:00
|
|
|
} else {
|
2023-08-31 17:43:45 +02:00
|
|
|
for (; linknum != NO_ITEM; linknum = g_Effects[linknum].next_draw) {
|
|
|
|
if (g_Effects[linknum].next_draw == fx_num) {
|
|
|
|
g_Effects[linknum].next_draw = fx->next_draw;
|
2022-05-05 11:56:29 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
r = &g_RoomInfo[room_num];
|
2024-09-06 10:03:51 +02:00
|
|
|
fx->room_num = room_num;
|
2024-09-06 10:07:10 +02:00
|
|
|
fx->next_draw = r->fx_num;
|
|
|
|
r->fx_num = fx_num;
|
2022-05-05 11:56:29 +02:00
|
|
|
}
|
2022-05-14 22:38:03 +02:00
|
|
|
|
2024-04-22 09:35:24 +02:00
|
|
|
void Effect_Draw(const int16_t fxnum)
|
2022-05-14 22:38:03 +02:00
|
|
|
{
|
2024-09-24 00:09:15 +02:00
|
|
|
const FX *const fx = &g_Effects[fxnum];
|
|
|
|
const OBJECT *const object = &g_Objects[fx->object_id];
|
2022-05-14 22:38:03 +02:00
|
|
|
if (!object->loaded) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (object->nmeshes < 0) {
|
|
|
|
Output_DrawSprite(
|
2024-04-22 09:35:24 +02:00
|
|
|
fx->interp.result.pos.x, fx->interp.result.pos.y,
|
2024-09-21 12:04:30 +02:00
|
|
|
fx->interp.result.pos.z, object->mesh_idx - fx->frame_num, 4096);
|
2022-05-14 22:38:03 +02:00
|
|
|
} else {
|
|
|
|
Matrix_Push();
|
2024-04-22 09:35:24 +02:00
|
|
|
Matrix_TranslateAbs(
|
|
|
|
fx->interp.result.pos.x, fx->interp.result.pos.y,
|
|
|
|
fx->interp.result.pos.z);
|
2022-05-14 22:38:03 +02:00
|
|
|
if (g_MatrixPtr->_23 > Output_GetNearZ()
|
|
|
|
&& g_MatrixPtr->_23 < Output_GetFarZ()) {
|
2024-04-22 09:35:24 +02:00
|
|
|
Matrix_RotYXZ(
|
|
|
|
fx->interp.result.rot.y, fx->interp.result.rot.x,
|
|
|
|
fx->interp.result.rot.z);
|
2022-05-14 22:38:03 +02:00
|
|
|
if (object->nmeshes) {
|
|
|
|
Output_CalculateStaticLight(fx->shade);
|
2024-09-21 12:04:30 +02:00
|
|
|
Output_DrawPolygons(g_Meshes[object->mesh_idx], -1);
|
2022-05-14 22:38:03 +02:00
|
|
|
} else {
|
|
|
|
Output_CalculateLight(
|
2024-04-22 09:35:24 +02:00
|
|
|
fx->interp.result.pos.x, fx->interp.result.pos.y,
|
2024-09-06 10:03:51 +02:00
|
|
|
fx->interp.result.pos.z, fx->room_num);
|
2024-09-06 10:03:14 +02:00
|
|
|
Output_DrawPolygons(g_Meshes[fx->frame_num], -1);
|
2022-05-14 22:38:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Matrix_Pop();
|
|
|
|
}
|
|
|
|
}
|
2023-01-20 09:55:04 -05:00
|
|
|
|
|
|
|
void Effect_RunActiveFlipEffect(void)
|
|
|
|
{
|
|
|
|
// XXX: Some of the FX routines rely on the item to be not null!
|
|
|
|
if (g_FlipEffect != -1) {
|
|
|
|
g_EffectRoutines[g_FlipEffect](NULL);
|
|
|
|
}
|
|
|
|
}
|