Browse Source

TRN rewrite + bugfix (#4056)

* working new TRN system
* apply TRNs to all unique missiles
pull/4077/head
qndel 4 years ago committed by GitHub
parent
commit
9ba64ad08b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      Source/CMakeLists.txt
  2. 3
      Source/control.cpp
  3. 2
      Source/dead.cpp
  4. 3
      Source/engine/render/cel_render.cpp
  5. 4
      Source/engine/render/cl2_render.cpp
  6. 6
      Source/engine/render/cl2_render.hpp
  7. 10
      Source/engine/render/common_impl.h
  8. 25
      Source/engine/trn.cpp
  9. 14
      Source/engine/trn.hpp
  10. 3
      Source/lighting.h
  11. 8
      Source/missiles.cpp
  12. 6
      Source/monster.cpp
  13. 1
      Source/monster.h
  14. 24
      Source/scrollrt.cpp

1
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

3
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)

2
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;

3
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)

4
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)

6
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

10
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;

25
Source/engine/trn.cpp

@ -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

@ -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

3
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 {

8
Source/missiles.cpp

@ -2191,7 +2191,6 @@ void AddRhino(Missile &missile, const AddMissileParameter &parameter)
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

6
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<uint8_t>(filestr);
monster._uniqtrans = uniquetrans++;

1
Source/monster.h

@ -220,6 +220,7 @@ struct Monster { // note: missing field _mAFNum
const char *mName;
CMonster *MType;
const MonsterData *MData;
std::unique_ptr<uint8_t[]> uniqueTRN;
/**
* @brief Sets the current cell sprite to match the desired direction and animation sequence

24
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);
}

Loading…
Cancel
Save