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/text_render.cpp
|
||||
engine/surface.cpp
|
||||
engine/trn.cpp
|
||||
mpq/mpq_reader.cpp
|
||||
mpq/mpq_sdl_rwops.cpp
|
||||
mpq/mpq_writer.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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
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 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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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…
Add table
Add a link
Reference in a new issue