TRN rewrite + bugfix (#4056)
* working new TRN system * apply TRNs to all unique missiles
This commit is contained in:
parent
1f7b0607a6
commit
9ba64ad08b
14 changed files with 74 additions and 36 deletions
|
|
@ -91,6 +91,7 @@ set(libdevilutionx_SRCS
|
||||||
engine/render/dun_render.cpp
|
engine/render/dun_render.cpp
|
||||||
engine/render/text_render.cpp
|
engine/render/text_render.cpp
|
||||||
engine/surface.cpp
|
engine/surface.cpp
|
||||||
|
engine/trn.cpp
|
||||||
mpq/mpq_reader.cpp
|
mpq/mpq_reader.cpp
|
||||||
mpq/mpq_sdl_rwops.cpp
|
mpq/mpq_sdl_rwops.cpp
|
||||||
mpq/mpq_writer.cpp
|
mpq/mpq_writer.cpp
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#include "engine/load_cel.hpp"
|
#include "engine/load_cel.hpp"
|
||||||
#include "engine/render/cel_render.hpp"
|
#include "engine/render/cel_render.hpp"
|
||||||
#include "engine/render/text_render.hpp"
|
#include "engine/render/text_render.hpp"
|
||||||
|
#include "engine/trn.hpp"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "gamemenu.h"
|
#include "gamemenu.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
|
|
@ -1002,7 +1003,7 @@ void DrawDurIcon(const Surface &out)
|
||||||
void RedBack(const Surface &out)
|
void RedBack(const Surface &out)
|
||||||
{
|
{
|
||||||
uint8_t *dst = out.begin();
|
uint8_t *dst = out.begin();
|
||||||
uint8_t *tbl = &LightTables[4608];
|
uint8_t *tbl = GetPauseTRN();
|
||||||
for (int h = gnViewportHeight; h != 0; h--, dst += out.pitch() - gnScreenWidth) {
|
for (int h = gnViewportHeight; h != 0; h--, dst += out.pitch() - gnScreenWidth) {
|
||||||
for (int w = gnScreenWidth; w != 0; w--) {
|
for (int w = gnScreenWidth; w != 0; w--) {
|
||||||
if (leveltype != DTYPE_HELL || *dst >= 32)
|
if (leveltype != DTYPE_HELL || *dst >= 32)
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ void InitCorpses()
|
||||||
auto &monster = Monsters[ActiveMonsters[i]];
|
auto &monster = Monsters[ActiveMonsters[i]];
|
||||||
if (monster._uniqtype != 0) {
|
if (monster._uniqtype != 0) {
|
||||||
InitDeadAnimationFromMonster(Corpses[nd], *monster.MType);
|
InitDeadAnimationFromMonster(Corpses[nd], *monster.MType);
|
||||||
Corpses[nd].translationPaletteIndex = monster._uniqtrans + 4;
|
Corpses[nd].translationPaletteIndex = ActiveMonsters[i] + 1;
|
||||||
nd++;
|
nd++;
|
||||||
|
|
||||||
monster._udeadval = nd;
|
monster._udeadval = nd;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include "engine/cel_header.hpp"
|
#include "engine/cel_header.hpp"
|
||||||
#include "engine/render/common_impl.h"
|
#include "engine/render/common_impl.h"
|
||||||
|
#include "engine/trn.hpp"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "palette.h"
|
#include "palette.h"
|
||||||
#include "scrollrt.h"
|
#include "scrollrt.h"
|
||||||
|
|
@ -620,7 +621,7 @@ void CelDrawLightRedTo(const Surface &out, Point position, const CelSprite &cel,
|
||||||
{
|
{
|
||||||
int nDataSize;
|
int nDataSize;
|
||||||
const auto *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize);
|
const auto *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize);
|
||||||
RenderCelWithLightTable(out, position, pRLEBytes, nDataSize, cel.Width(frame), GetLightTable(1));
|
RenderCelWithLightTable(out, position, pRLEBytes, nDataSize, cel.Width(frame), GetInfravisionTRN());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CelDrawItem(const Item &item, const Surface &out, Point position, const CelSprite &cel, int frame)
|
void CelDrawItem(const Item &item, const Surface &out, Point position, const CelSprite &cel, int frame)
|
||||||
|
|
|
||||||
|
|
@ -783,13 +783,13 @@ void Cl2DrawOutline(const Surface &out, uint8_t col, int sx, int sy, const CelSp
|
||||||
RenderCl2Outline(out, { sx, sy }, pRLEBytes, nDataSize, cel.Width(frame), col);
|
RenderCl2Outline(out, { sx, sy }, pRLEBytes, nDataSize, cel.Width(frame), col);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cl2DrawLightTbl(const Surface &out, int sx, int sy, const CelSprite &cel, int frame, char light)
|
void Cl2DrawTRN(const Surface &out, int sx, int sy, const CelSprite &cel, int frame, uint8_t *trn)
|
||||||
{
|
{
|
||||||
assert(frame > 0);
|
assert(frame > 0);
|
||||||
|
|
||||||
int nDataSize;
|
int nDataSize;
|
||||||
const byte *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize);
|
const byte *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize);
|
||||||
Cl2BlitLightSafe(out, sx, sy, pRLEBytes, nDataSize, cel.Width(frame), GetLightTable(light));
|
Cl2BlitLightSafe(out, sx, sy, pRLEBytes, nDataSize, cel.Width(frame), trn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cl2DrawLight(const Surface &out, int sx, int sy, const CelSprite &cel, int frame)
|
void Cl2DrawLight(const Surface &out, int sx, int sy, const CelSprite &cel, int frame)
|
||||||
|
|
|
||||||
|
|
@ -44,15 +44,15 @@ void Cl2Draw(const Surface &out, int sx, int sy, const CelSprite &cel, int frame
|
||||||
void Cl2DrawOutline(const Surface &out, uint8_t col, int sx, int sy, const CelSprite &cel, int frame);
|
void Cl2DrawOutline(const Surface &out, uint8_t col, int sx, int sy, const CelSprite &cel, int frame);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Blit CL2 sprite, and apply a given lighting, to the given buffer at the given coordianates
|
* @brief Blit CL2 sprite, and apply given TRN to the given buffer at the given coordinates
|
||||||
* @param out Output buffer
|
* @param out Output buffer
|
||||||
* @param sx Output buffer coordinate
|
* @param sx Output buffer coordinate
|
||||||
* @param sy Output buffer coordinate
|
* @param sy Output buffer coordinate
|
||||||
* @param pCelBuff CL2 buffer
|
* @param pCelBuff CL2 buffer
|
||||||
* @param nCel CL2 frame number
|
* @param nCel CL2 frame number
|
||||||
* @param light Light shade to use
|
* @param TRN to use
|
||||||
*/
|
*/
|
||||||
void Cl2DrawLightTbl(const Surface &out, int sx, int sy, const CelSprite &cel, int frame, char light);
|
void Cl2DrawTRN(const Surface &out, int sx, int sy, const CelSprite &cel, int frame, uint8_t *trn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Blit CL2 sprite, and apply lighting, to the given buffer at the given coordinates
|
* @brief Blit CL2 sprite, and apply lighting, to the given buffer at the given coordinates
|
||||||
|
|
|
||||||
|
|
@ -13,16 +13,6 @@
|
||||||
|
|
||||||
namespace devilution {
|
namespace devilution {
|
||||||
|
|
||||||
inline std::uint8_t *GetLightTable(char light)
|
|
||||||
{
|
|
||||||
int idx = 4096;
|
|
||||||
if (light == 2)
|
|
||||||
idx += 256; // gray colors
|
|
||||||
if (light >= 4)
|
|
||||||
idx += (light - 1) << 8;
|
|
||||||
return &LightTables[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ClipX {
|
struct ClipX {
|
||||||
std::int_fast16_t left;
|
std::int_fast16_t left;
|
||||||
std::int_fast16_t right;
|
std::int_fast16_t right;
|
||||||
|
|
|
||||||
25
Source/engine/trn.cpp
Normal file
25
Source/engine/trn.cpp
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "engine/load_file.hpp"
|
||||||
|
#include "engine/trn.hpp"
|
||||||
|
#include "lighting.h"
|
||||||
|
|
||||||
|
namespace devilution {
|
||||||
|
|
||||||
|
uint8_t *GetInfravisionTRN()
|
||||||
|
{
|
||||||
|
return &LightTables[16 * 256];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *GetStoneTRN()
|
||||||
|
{
|
||||||
|
return &LightTables[17 * 256];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *GetPauseTRN()
|
||||||
|
{
|
||||||
|
return &LightTables[18 * 256];
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace devilution
|
||||||
14
Source/engine/trn.hpp
Normal file
14
Source/engine/trn.hpp
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
/**
|
||||||
|
* @file trn.h
|
||||||
|
*
|
||||||
|
* Contains most of trn logic
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace devilution {
|
||||||
|
|
||||||
|
uint8_t *GetInfravisionTRN();
|
||||||
|
uint8_t *GetStoneTRN();
|
||||||
|
uint8_t *GetPauseTRN();
|
||||||
|
|
||||||
|
} // namespace devilution
|
||||||
|
|
@ -17,7 +17,8 @@ namespace devilution {
|
||||||
|
|
||||||
#define MAXLIGHTS 32
|
#define MAXLIGHTS 32
|
||||||
#define MAXVISION 32
|
#define MAXVISION 32
|
||||||
#define LIGHTSIZE (27 * 256)
|
/** 16 light levels + infravision + stone curse + red for pause/death screen */
|
||||||
|
#define LIGHTSIZE (19 * 256)
|
||||||
#define NO_LIGHT -1
|
#define NO_LIGHT -1
|
||||||
|
|
||||||
struct LightPosition {
|
struct LightPosition {
|
||||||
|
|
|
||||||
|
|
@ -2191,7 +2191,6 @@ void AddRhino(Missile &missile, const AddMissileParameter ¶meter)
|
||||||
if (monster.MType->mtype >= MT_NSNAKE && monster.MType->mtype <= MT_GSNAKE)
|
if (monster.MType->mtype >= MT_NSNAKE && monster.MType->mtype <= MT_GSNAKE)
|
||||||
missile._miAnimFrame = 7;
|
missile._miAnimFrame = 7;
|
||||||
if (monster._uniqtype != 0) {
|
if (monster._uniqtype != 0) {
|
||||||
missile._miUniqTrans = monster._uniqtrans + 1;
|
|
||||||
missile._mlid = monster.mlid;
|
missile._mlid = monster.mlid;
|
||||||
}
|
}
|
||||||
PutMissile(missile);
|
PutMissile(missile);
|
||||||
|
|
@ -2716,6 +2715,13 @@ Missile *AddMissile(Point src, Point dst, Direction midir, missile_id mitype, mi
|
||||||
missile._mlid = NO_LIGHT;
|
missile._mlid = NO_LIGHT;
|
||||||
missile.lastCollisionTargetHash = 0;
|
missile.lastCollisionTargetHash = 0;
|
||||||
|
|
||||||
|
if (micaster == TARGET_PLAYERS) {
|
||||||
|
Monster &monster = Monsters[id];
|
||||||
|
if (monster._uniqtype != 0) {
|
||||||
|
missile._miUniqTrans = monster._uniqtrans + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (missile._miAnimType == MFILE_NONE || MissileSpriteData[missile._miAnimType].animFAmt < 8)
|
if (missile._miAnimType == MFILE_NONE || MissileSpriteData[missile._miAnimType].animFAmt < 8)
|
||||||
SetMissDir(missile, 0);
|
SetMissDir(missile, 0);
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -376,10 +376,6 @@ void PlaceUniqueMonst(int uniqindex, int miniontype, int bosspacksize)
|
||||||
auto &monster = Monsters[ActiveMonsterCount];
|
auto &monster = Monsters[ActiveMonsterCount];
|
||||||
const auto &uniqueMonsterData = UniqueMonstersData[uniqindex];
|
const auto &uniqueMonsterData = UniqueMonstersData[uniqindex];
|
||||||
|
|
||||||
if ((uniquetrans + 19) * 256 >= LIGHTSIZE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int uniqtype;
|
int uniqtype;
|
||||||
for (uniqtype = 0; uniqtype < LevelMonsterTypeCount; uniqtype++) {
|
for (uniqtype = 0; uniqtype < LevelMonsterTypeCount; uniqtype++) {
|
||||||
if (LevelMonsterTypes[uniqtype].mtype == uniqueMonsterData.mtype) {
|
if (LevelMonsterTypes[uniqtype].mtype == uniqueMonsterData.mtype) {
|
||||||
|
|
@ -552,7 +548,7 @@ void PlaceUniqueMonst(int uniqindex, int miniontype, int bosspacksize)
|
||||||
|
|
||||||
char filestr[64];
|
char filestr[64];
|
||||||
sprintf(filestr, "Monsters\\Monsters\\%s.TRN", uniqueMonsterData.mTrnName);
|
sprintf(filestr, "Monsters\\Monsters\\%s.TRN", uniqueMonsterData.mTrnName);
|
||||||
LoadFileInMem(filestr, &LightTables[256 * (uniquetrans + 19)], 256);
|
monster.uniqueTRN = LoadFileInMem<uint8_t>(filestr);
|
||||||
|
|
||||||
monster._uniqtrans = uniquetrans++;
|
monster._uniqtrans = uniquetrans++;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -220,6 +220,7 @@ struct Monster { // note: missing field _mAFNum
|
||||||
const char *mName;
|
const char *mName;
|
||||||
CMonster *MType;
|
CMonster *MType;
|
||||||
const MonsterData *MData;
|
const MonsterData *MData;
|
||||||
|
std::unique_ptr<uint8_t[]> uniqueTRN;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the current cell sprite to match the desired direction and animation sequence
|
* @brief Sets the current cell sprite to match the desired direction and animation sequence
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
#include "engine/render/cl2_render.hpp"
|
#include "engine/render/cl2_render.hpp"
|
||||||
#include "engine/render/dun_render.hpp"
|
#include "engine/render/dun_render.hpp"
|
||||||
#include "engine/render/text_render.hpp"
|
#include "engine/render/text_render.hpp"
|
||||||
|
#include "engine/trn.hpp"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "gmenu.h"
|
#include "gmenu.h"
|
||||||
#include "help.h"
|
#include "help.h"
|
||||||
|
|
@ -319,7 +320,7 @@ void DrawMissilePrivate(const Surface &out, const Missile &missile, Point target
|
||||||
const Point missileRenderPosition { targetBufferPosition + missile.position.offsetForRendering - Displacement { missile._miAnimWidth2, 0 } };
|
const Point missileRenderPosition { targetBufferPosition + missile.position.offsetForRendering - Displacement { missile._miAnimWidth2, 0 } };
|
||||||
CelSprite cel { missile._miAnimData, missile._miAnimWidth };
|
CelSprite cel { missile._miAnimData, missile._miAnimWidth };
|
||||||
if (missile._miUniqTrans != 0)
|
if (missile._miUniqTrans != 0)
|
||||||
Cl2DrawLightTbl(out, missileRenderPosition.x, missileRenderPosition.y, cel, missile._miAnimFrame, missile._miUniqTrans + 3);
|
Cl2DrawTRN(out, missileRenderPosition.x, missileRenderPosition.y, cel, missile._miAnimFrame, Monsters[missile._misource].uniqueTRN.get());
|
||||||
else if (missile._miLightFlag)
|
else if (missile._miLightFlag)
|
||||||
Cl2DrawLight(out, missileRenderPosition.x, missileRenderPosition.y, cel, missile._miAnimFrame);
|
Cl2DrawLight(out, missileRenderPosition.x, missileRenderPosition.y, cel, missile._miAnimFrame);
|
||||||
else
|
else
|
||||||
|
|
@ -432,18 +433,18 @@ void DrawMonster(const Surface &out, Point tilePosition, Point targetBufferPosit
|
||||||
const auto &cel = *monster.AnimInfo.pCelSprite;
|
const auto &cel = *monster.AnimInfo.pCelSprite;
|
||||||
|
|
||||||
if (!IsTileLit(tilePosition)) {
|
if (!IsTileLit(tilePosition)) {
|
||||||
Cl2DrawLightTbl(out, targetBufferPosition.x, targetBufferPosition.y, cel, nCel, 1);
|
Cl2DrawTRN(out, targetBufferPosition.x, targetBufferPosition.y, cel, nCel, GetInfravisionTRN());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int trans = 0;
|
uint8_t *trn = nullptr;
|
||||||
if (monster._uniqtype != 0)
|
if (monster._uniqtype != 0)
|
||||||
trans = monster._uniqtrans + 4;
|
trn = monster.uniqueTRN.get();
|
||||||
if (monster._mmode == MonsterMode::Petrified)
|
if (monster._mmode == MonsterMode::Petrified)
|
||||||
trans = 2;
|
trn = GetStoneTRN();
|
||||||
if (Players[MyPlayerId]._pInfraFlag && LightTableIndex > 8)
|
if (Players[MyPlayerId]._pInfraFlag && LightTableIndex > 8)
|
||||||
trans = 1;
|
trn = GetInfravisionTRN();
|
||||||
if (trans != 0)
|
if (trn != nullptr)
|
||||||
Cl2DrawLightTbl(out, targetBufferPosition.x, targetBufferPosition.y, cel, nCel, trans);
|
Cl2DrawTRN(out, targetBufferPosition.x, targetBufferPosition.y, cel, nCel, trn);
|
||||||
else
|
else
|
||||||
Cl2DrawLight(out, targetBufferPosition.x, targetBufferPosition.y, cel, nCel);
|
Cl2DrawLight(out, targetBufferPosition.x, targetBufferPosition.y, cel, nCel);
|
||||||
}
|
}
|
||||||
|
|
@ -466,7 +467,7 @@ void DrawPlayerIconHelper(const Surface &out, int pnum, missile_graphic_id missi
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lighting) {
|
if (lighting) {
|
||||||
Cl2DrawLightTbl(out, position.x, position.y, cel, 1, 1);
|
Cl2DrawTRN(out, position.x, position.y, cel, 1, GetInfravisionTRN());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -548,7 +549,7 @@ void DrawPlayer(const Surface &out, int pnum, Point tilePosition, Point targetBu
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsTileLit(tilePosition) || (Players[MyPlayerId]._pInfraFlag && LightTableIndex > 8)) {
|
if (!IsTileLit(tilePosition) || (Players[MyPlayerId]._pInfraFlag && LightTableIndex > 8)) {
|
||||||
Cl2DrawLightTbl(out, targetBufferPosition.x, targetBufferPosition.y, *pCelSprite, nCel, 1);
|
Cl2DrawTRN(out, targetBufferPosition.x, targetBufferPosition.y, *pCelSprite, nCel, GetInfravisionTRN());
|
||||||
DrawPlayerIcons(out, pnum, targetBufferPosition, true);
|
DrawPlayerIcons(out, pnum, targetBufferPosition, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -858,7 +859,8 @@ void DrawDungeon(const Surface &out, Point tilePosition, Point targetBufferPosit
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (pDeadGuy->translationPaletteIndex != 0) {
|
if (pDeadGuy->translationPaletteIndex != 0) {
|
||||||
Cl2DrawLightTbl(out, px, targetBufferPosition.y, CelSprite(pCelBuff, pDeadGuy->width), nCel, pDeadGuy->translationPaletteIndex);
|
uint8_t *trn = Monsters[pDeadGuy->translationPaletteIndex - 1].uniqueTRN.get();
|
||||||
|
Cl2DrawTRN(out, px, targetBufferPosition.y, CelSprite(pCelBuff, pDeadGuy->width), nCel, trn);
|
||||||
} else {
|
} else {
|
||||||
Cl2DrawLight(out, px, targetBufferPosition.y, CelSprite(pCelBuff, pDeadGuy->width), nCel);
|
Cl2DrawLight(out, px, targetBufferPosition.y, CelSprite(pCelBuff, pDeadGuy->width), nCel);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue