From 9ba64ad08b2a56b3cf00b15b485997a0deec9dc2 Mon Sep 17 00:00:00 2001 From: qndel Date: Sun, 20 Feb 2022 14:28:51 +0100 Subject: [PATCH] TRN rewrite + bugfix (#4056) * working new TRN system * apply TRNs to all unique missiles --- Source/CMakeLists.txt | 1 + Source/control.cpp | 3 ++- Source/dead.cpp | 2 +- Source/engine/render/cel_render.cpp | 3 ++- Source/engine/render/cl2_render.cpp | 4 ++-- Source/engine/render/cl2_render.hpp | 6 +++--- Source/engine/render/common_impl.h | 10 ---------- Source/engine/trn.cpp | 25 +++++++++++++++++++++++++ Source/engine/trn.hpp | 14 ++++++++++++++ Source/lighting.h | 3 ++- Source/missiles.cpp | 8 +++++++- Source/monster.cpp | 6 +----- Source/monster.h | 1 + Source/scrollrt.cpp | 24 +++++++++++++----------- 14 files changed, 74 insertions(+), 36 deletions(-) create mode 100644 Source/engine/trn.cpp create mode 100644 Source/engine/trn.hpp diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 959a0f63e..195c6f04a 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -91,6 +91,7 @@ set(libdevilutionx_SRCS engine/render/dun_render.cpp engine/render/text_render.cpp engine/surface.cpp + engine/trn.cpp mpq/mpq_reader.cpp mpq/mpq_sdl_rwops.cpp mpq/mpq_writer.cpp diff --git a/Source/control.cpp b/Source/control.cpp index 1d344dba3..f3a6d392b 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -20,6 +20,7 @@ #include "engine/load_cel.hpp" #include "engine/render/cel_render.hpp" #include "engine/render/text_render.hpp" +#include "engine/trn.hpp" #include "error.h" #include "gamemenu.h" #include "init.h" @@ -1002,7 +1003,7 @@ void DrawDurIcon(const Surface &out) void RedBack(const Surface &out) { 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 w = gnScreenWidth; w != 0; w--) { if (leveltype != DTYPE_HELL || *dst >= 32) diff --git a/Source/dead.cpp b/Source/dead.cpp index ecdff0d5d..022b09a65 100644 --- a/Source/dead.cpp +++ b/Source/dead.cpp @@ -61,7 +61,7 @@ void InitCorpses() auto &monster = Monsters[ActiveMonsters[i]]; if (monster._uniqtype != 0) { InitDeadAnimationFromMonster(Corpses[nd], *monster.MType); - Corpses[nd].translationPaletteIndex = monster._uniqtrans + 4; + Corpses[nd].translationPaletteIndex = ActiveMonsters[i] + 1; nd++; monster._udeadval = nd; diff --git a/Source/engine/render/cel_render.cpp b/Source/engine/render/cel_render.cpp index db04ee030..63932db2d 100644 --- a/Source/engine/render/cel_render.cpp +++ b/Source/engine/render/cel_render.cpp @@ -10,6 +10,7 @@ #include "engine/cel_header.hpp" #include "engine/render/common_impl.h" +#include "engine/trn.hpp" #include "options.h" #include "palette.h" #include "scrollrt.h" @@ -620,7 +621,7 @@ void CelDrawLightRedTo(const Surface &out, Point position, const CelSprite &cel, { int 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) diff --git a/Source/engine/render/cl2_render.cpp b/Source/engine/render/cl2_render.cpp index 17a78e971..7c3fd4428 100644 --- a/Source/engine/render/cl2_render.cpp +++ b/Source/engine/render/cl2_render.cpp @@ -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); } -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); int 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) diff --git a/Source/engine/render/cl2_render.hpp b/Source/engine/render/cl2_render.hpp index f92f082c8..418133ad2 100644 --- a/Source/engine/render/cl2_render.hpp +++ b/Source/engine/render/cl2_render.hpp @@ -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); /** - * @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 sx Output buffer coordinate * @param sy Output buffer coordinate * @param pCelBuff CL2 buffer * @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 diff --git a/Source/engine/render/common_impl.h b/Source/engine/render/common_impl.h index d5b20c6c6..18cae6ba0 100644 --- a/Source/engine/render/common_impl.h +++ b/Source/engine/render/common_impl.h @@ -13,16 +13,6 @@ 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 { std::int_fast16_t left; std::int_fast16_t right; diff --git a/Source/engine/trn.cpp b/Source/engine/trn.cpp new file mode 100644 index 000000000..d33e6c069 --- /dev/null +++ b/Source/engine/trn.cpp @@ -0,0 +1,25 @@ +#include +#include + +#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 diff --git a/Source/engine/trn.hpp b/Source/engine/trn.hpp new file mode 100644 index 000000000..816459742 --- /dev/null +++ b/Source/engine/trn.hpp @@ -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 diff --git a/Source/lighting.h b/Source/lighting.h index 0697e8e72..daadbcccd 100644 --- a/Source/lighting.h +++ b/Source/lighting.h @@ -17,7 +17,8 @@ namespace devilution { #define MAXLIGHTS 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 struct LightPosition { diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 696b2ddb7..d284340df 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2191,7 +2191,6 @@ void AddRhino(Missile &missile, const AddMissileParameter ¶meter) if (monster.MType->mtype >= MT_NSNAKE && monster.MType->mtype <= MT_GSNAKE) missile._miAnimFrame = 7; if (monster._uniqtype != 0) { - missile._miUniqTrans = monster._uniqtrans + 1; missile._mlid = monster.mlid; } PutMissile(missile); @@ -2716,6 +2715,13 @@ Missile *AddMissile(Point src, Point dst, Direction midir, missile_id mitype, mi missile._mlid = NO_LIGHT; 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) SetMissDir(missile, 0); else diff --git a/Source/monster.cpp b/Source/monster.cpp index a1f00c8aa..f8f9b4ac5 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -376,10 +376,6 @@ void PlaceUniqueMonst(int uniqindex, int miniontype, int bosspacksize) auto &monster = Monsters[ActiveMonsterCount]; const auto &uniqueMonsterData = UniqueMonstersData[uniqindex]; - if ((uniquetrans + 19) * 256 >= LIGHTSIZE) { - return; - } - int uniqtype; for (uniqtype = 0; uniqtype < LevelMonsterTypeCount; uniqtype++) { if (LevelMonsterTypes[uniqtype].mtype == uniqueMonsterData.mtype) { @@ -552,7 +548,7 @@ void PlaceUniqueMonst(int uniqindex, int miniontype, int bosspacksize) char filestr[64]; sprintf(filestr, "Monsters\\Monsters\\%s.TRN", uniqueMonsterData.mTrnName); - LoadFileInMem(filestr, &LightTables[256 * (uniquetrans + 19)], 256); + monster.uniqueTRN = LoadFileInMem(filestr); monster._uniqtrans = uniquetrans++; diff --git a/Source/monster.h b/Source/monster.h index 57ba4f408..bce32c70e 100644 --- a/Source/monster.h +++ b/Source/monster.h @@ -220,6 +220,7 @@ struct Monster { // note: missing field _mAFNum const char *mName; CMonster *MType; const MonsterData *MData; + std::unique_ptr uniqueTRN; /** * @brief Sets the current cell sprite to match the desired direction and animation sequence diff --git a/Source/scrollrt.cpp b/Source/scrollrt.cpp index 46db4e321..070290426 100644 --- a/Source/scrollrt.cpp +++ b/Source/scrollrt.cpp @@ -16,6 +16,7 @@ #include "engine/render/cl2_render.hpp" #include "engine/render/dun_render.hpp" #include "engine/render/text_render.hpp" +#include "engine/trn.hpp" #include "error.h" #include "gmenu.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 } }; CelSprite cel { missile._miAnimData, missile._miAnimWidth }; 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) Cl2DrawLight(out, missileRenderPosition.x, missileRenderPosition.y, cel, missile._miAnimFrame); else @@ -432,18 +433,18 @@ void DrawMonster(const Surface &out, Point tilePosition, Point targetBufferPosit const auto &cel = *monster.AnimInfo.pCelSprite; if (!IsTileLit(tilePosition)) { - Cl2DrawLightTbl(out, targetBufferPosition.x, targetBufferPosition.y, cel, nCel, 1); + Cl2DrawTRN(out, targetBufferPosition.x, targetBufferPosition.y, cel, nCel, GetInfravisionTRN()); return; } - int trans = 0; + uint8_t *trn = nullptr; if (monster._uniqtype != 0) - trans = monster._uniqtrans + 4; + trn = monster.uniqueTRN.get(); if (monster._mmode == MonsterMode::Petrified) - trans = 2; + trn = GetStoneTRN(); if (Players[MyPlayerId]._pInfraFlag && LightTableIndex > 8) - trans = 1; - if (trans != 0) - Cl2DrawLightTbl(out, targetBufferPosition.x, targetBufferPosition.y, cel, nCel, trans); + trn = GetInfravisionTRN(); + if (trn != nullptr) + Cl2DrawTRN(out, targetBufferPosition.x, targetBufferPosition.y, cel, nCel, trn); else 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) { - Cl2DrawLightTbl(out, position.x, position.y, cel, 1, 1); + Cl2DrawTRN(out, position.x, position.y, cel, 1, GetInfravisionTRN()); return; } @@ -548,7 +549,7 @@ void DrawPlayer(const Surface &out, int pnum, Point tilePosition, Point targetBu } 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); return; } @@ -858,7 +859,8 @@ void DrawDungeon(const Surface &out, Point tilePosition, Point targetBufferPosit break; } 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 { Cl2DrawLight(out, px, targetBufferPosition.y, CelSprite(pCelBuff, pDeadGuy->width), nCel); }