Merge branch 'asmjit' into weapon_scriptification

# Conflicts:
#	src/gi.cpp
#	wadsrc/static/zscript/base.txt
This commit is contained in:
Christoph Oelckers 2018-11-26 00:14:44 +01:00
commit 47b1fa774d
51 changed files with 1825 additions and 1255 deletions

View file

@ -1150,6 +1150,7 @@ set (PCH_SOURCES
r_data/models/models_ue1.cpp
r_data/models/models_obj.cpp
scripting/symbols.cpp
scripting/vmthunks.cpp
scripting/types.cpp
scripting/thingdef.cpp
scripting/thingdef_data.cpp

View file

@ -749,7 +749,7 @@ static void (*MBFCodePointerFactories[])(FunctionCallEmitter&, int, int) =
void SetDehParams(FState *state, int codepointer)
{
static uint8_t regts[] = { REGT_POINTER, REGT_POINTER, REGT_POINTER };
static const uint8_t regts[] = { REGT_POINTER, REGT_POINTER, REGT_POINTER };
int value1 = state->GetMisc1();
int value2 = state->GetMisc2();
if (!(value1|value2)) return;

View file

@ -266,8 +266,6 @@ void PClass::StaticShutdown ()
// This flags DObject::Destroy not to call any scripted OnDestroy methods anymore.
bVMOperational = false;
// PendingWeapon must be cleared manually because it is not subjected to the GC if it contains WP_NOCHANGE, which is just RUNTIME_CLASS(AWWeapon).
// But that will get cleared here, confusing the GC if the value is left in.
for (auto &p : players)
{
p.PendingWeapon = nullptr;

View file

@ -38,6 +38,7 @@
#include <string.h>
#include <stdio.h>
#include <exception>
#include <stdexcept>
#define MAX_ERRORTEXT 1024
@ -70,7 +71,7 @@ public:
else
return NULL;
}
char const *what() const override
char const *what() const noexcept override
{
return m_Message;
}
@ -80,10 +81,10 @@ protected:
char m_Message[MAX_ERRORTEXT];
};
class CNoRunExit : public std::exception
class CNoRunExit : public std::runtime_error
{
public:
CNoRunExit() : std::exception("NoRunExit")
CNoRunExit() : std::runtime_error("NoRunExit")
{
}
};

View file

@ -735,7 +735,7 @@ void ProcessEDSector(sector_t *sec, int recordnum)
sec->terrainnum[sector_t::floor] = esec->floorterrain;
sec->terrainnum[sector_t::ceiling] = esec->ceilingterrain;
if (esec->colorSet) sec->SetColor(RPART(esec->color), GPART(esec->color), BPART(esec->color), 0);
if (esec->colorSet) sec->SetColor(esec->color, 0);
const uint32_t pflagmask = PLANEF_DISABLED | PLANEF_NORENDER | PLANEF_NOPASS | PLANEF_BLOCKSOUND | PLANEF_ADDITIVE;
for (int i = 0; i < 2; i++)

View file

@ -3833,7 +3833,7 @@ void FParser::SF_SetColor(void)
{
if (!DFraggleThinker::ActiveThinker->setcolormaterial)
{
level.sectors[i].SetColor(color.r, color.g, color.b, 0);
level.sectors[i].SetColor(color, 0);
}
else
{

View file

@ -61,10 +61,10 @@ DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, statusscreen_single)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, statusscreen_coop)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, statusscreen_dm)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, mSliderColor)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, defaultbloodcolor)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, telefogheight)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, defKickback)
const char *GameNames[17] =
{
NULL, "Doom", "Heretic", NULL, "Hexen", NULL, NULL, NULL, "Strife", NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Chex"

View file

@ -147,7 +147,7 @@ FModelVertexBuffer::FModelVertexBuffer(bool needindex, bool singleframe)
{ 1, VATTR_VERTEX2, VFmt_Float3, (int)myoffsetof(FModelVertex, x) },
{ 1, VATTR_NORMAL2, VFmt_Packed_A2R10G10B10, (int)myoffsetof(FModelVertex, packedNormal) }
};
mVertexBuffer->SetFormat(2, 4, sizeof(FModelVertex), format);
mVertexBuffer->SetFormat(2, 5, sizeof(FModelVertex), format);
}
//===========================================================================

View file

@ -957,33 +957,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_CopyFriendliness)
//
//==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_PlaySound)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_SOUND (soundid);
PARAM_INT (channel);
PARAM_FLOAT (volume);
PARAM_BOOL (looping);
PARAM_FLOAT (attenuation);
PARAM_BOOL (local);
if (!looping)
{
if (!(channel & CHAN_NOSTOP) || !S_IsActorPlayingSomething(self, channel & 7, soundid))
{
S_PlaySound(self, channel, soundid, (float)volume, (float)attenuation, local);
}
}
else
{
if (!S_IsActorPlayingSomething (self, channel&7, soundid))
{
S_PlaySound(self, channel | CHAN_LOOP, soundid, (float)volume, (float)attenuation, local);
}
}
return 0;
}
DEFINE_ACTION_FUNCTION(AActor, A_StopSound)
{
PARAM_SELF_PROLOGUE(AActor);

View file

@ -368,13 +368,13 @@ bool P_CreateCeiling(sector_t *sec, DCeiling::ECeiling type, line_t *line, int t
break;
case DCeiling::ceilLowerByTexture:
targheight = sec->ceilingplane.ZatPoint (spot) - sec->FindShortestUpperAround ();
targheight = sec->ceilingplane.ZatPoint (spot) - FindShortestUpperAround (sec);
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
ceiling->m_Direction = -1;
break;
case DCeiling::ceilRaiseByTexture:
targheight = sec->ceilingplane.ZatPoint (spot) + sec->FindShortestUpperAround ();
targheight = sec->ceilingplane.ZatPoint (spot) + FindShortestUpperAround (sec);
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
ceiling->m_Direction = 1;
break;
@ -420,8 +420,8 @@ bool P_CreateCeiling(sector_t *sec, DCeiling::ECeiling type, line_t *line, int t
type == DCeiling::ceilRaiseToFloor ||
/*type == ceilLowerToHighest ||*/
type == DCeiling::ceilLowerToFloor) ?
sec->FindModelFloorSector (targheight) :
sec->FindModelCeilingSector (targheight);
FindModelFloorSector(sec, targheight) :
FindModelCeilingSector(sec, targheight);
if (modelsec != NULL)
{
ceiling->m_Texture = modelsec->GetTexture(sector_t::ceiling);

View file

@ -392,7 +392,7 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line,
case DFloor::floorLowerByTexture:
floor->m_Direction = -1;
newheight = sec->CenterFloor() - sec->FindShortestTextureAround();
newheight = sec->CenterFloor() - FindShortestTextureAround(sec);
floor->m_FloorDestDist = sec->floorplane.PointToDist(sec->centerspot, newheight);
break;
@ -409,7 +409,7 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line,
// since the code is identical to what was here. (Oddly
// enough, BOOM preserved the code here even though it
// also had this function.)
newheight = sec->CenterFloor() + sec->FindShortestTextureAround();
newheight = sec->CenterFloor() + FindShortestTextureAround(sec);
floor->m_FloorDestDist = sec->floorplane.PointToDist(sec->centerspot, newheight);
break;
@ -440,7 +440,7 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line,
//jff 5/23/98 use model subroutine to unify fixes and handling
sector_t *modelsec;
modelsec = sec->FindModelFloorSector(newheight);
modelsec = FindModelFloorSector(sec, newheight);
if (modelsec != NULL)
{
floor->m_Texture = modelsec->GetTexture(sector_t::floor);
@ -485,8 +485,8 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line,
floortype == DFloor::floorLowerToLowestCeiling ||
floortype == DFloor::floorRaiseToCeiling ||
floortype == DFloor::floorLowerToCeiling) ?
sec->FindModelCeilingSector(-floor->m_FloorDestDist) :
sec->FindModelFloorSector(-floor->m_FloorDestDist);
FindModelCeilingSector(sec, -floor->m_FloorDestDist) :
FindModelFloorSector(sec, -floor->m_FloorDestDist);
if (modelsec != NULL)
{
@ -1126,7 +1126,7 @@ bool EV_DoChange (line_t *line, EChange changetype, int tag)
}
break;
case numChangeOnly:
secm = sec->FindModelFloorSector (sec->CenterFloor());
secm = FindModelFloorSector(sec, sec->CenterFloor());
if (secm)
{ // if no model, no change
sec->SetTexture(sector_t::floor, secm->GetTexture(sector_t::floor));

View file

@ -2434,7 +2434,7 @@ FUNC(LS_Sector_SetColor)
int secnum;
while ((secnum = itr.Next()) >= 0)
{
level.sectors[secnum].SetColor(arg1, arg2, arg3, arg4);
level.sectors[secnum].SetColor(PalEntry(255, arg1, arg2, arg3), arg4);
}
return true;
@ -2447,7 +2447,7 @@ FUNC(LS_Sector_SetFade)
int secnum;
while ((secnum = itr.Next()) >= 0)
{
level.sectors[secnum].SetFade(arg1, arg2, arg3);
level.sectors[secnum].SetFade(PalEntry(255, arg1, arg2, arg3));
}
return true;
}

View file

@ -4508,7 +4508,7 @@ DEFINE_ACTION_FUNCTION(AActor, AimLineAttack)
PARAM_SELF_PROLOGUE(AActor);
PARAM_ANGLE(angle);
PARAM_FLOAT(distance);
PARAM_POINTER(pLineTarget, FTranslatedLineTarget);
PARAM_OUTPOINTER(pLineTarget, FTranslatedLineTarget);
PARAM_ANGLE(vrange);
PARAM_INT(flags);
PARAM_OBJECT(target, AActor);
@ -4920,7 +4920,7 @@ DEFINE_ACTION_FUNCTION(AActor, LineAttack)
PARAM_NAME(damageType);
PARAM_CLASS(puffType, AActor);
PARAM_INT(flags);
PARAM_POINTER(victim, FTranslatedLineTarget);
PARAM_OUTPOINTER(victim, FTranslatedLineTarget);
PARAM_FLOAT(offsetz);
PARAM_FLOAT(offsetforward);
PARAM_FLOAT(offsetside);
@ -5086,7 +5086,7 @@ DEFINE_ACTION_FUNCTION(AActor, LineTrace)
PARAM_FLOAT(offsetz);
PARAM_FLOAT(offsetforward);
PARAM_FLOAT(offsetside);
PARAM_POINTER(data, FLineTraceData);
PARAM_OUTPOINTER(data, FLineTraceData);
ACTION_RETURN_BOOL(P_LineTrace(self,angle,distance,pitch,flags,offsetz,offsetforward,offsetside,data));
}

View file

@ -7375,7 +7375,7 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnPlayerMissile)
PARAM_FLOAT(x);
PARAM_FLOAT(y);
PARAM_FLOAT(z);
PARAM_POINTER(lt, FTranslatedLineTarget);
PARAM_OUTPOINTER(lt, FTranslatedLineTarget);
PARAM_BOOL(nofreeaim);
PARAM_BOOL(noautoaim);
PARAM_INT(aimflags);

File diff suppressed because it is too large Load diff

View file

@ -556,17 +556,17 @@ static void GenericParse (FScanner &sc, FGenericParse *parser, const char **keyw
else
{
info = PClass::FindClass (sc.String);
if (!info->IsDescendantOf (RUNTIME_CLASS(AActor)))
if (info == NULL)
{
Printf ("Unknown actor %s in %s %s\n",
sc.String, type, name.GetChars());
}
else if (!info->IsDescendantOf (RUNTIME_CLASS(AActor)))
{
Printf ("%s is not an Actor (in %s %s)\n",
sc.String, type, name.GetChars());
info = NULL;
}
else if (info == NULL)
{
Printf ("Unknown actor %s in %s %s\n",
sc.String, type, name.GetChars());
}
}
SET_FIELD (const PClass *, info);
break;

View file

@ -77,6 +77,15 @@ public:
return clip_first_line + core_skip - first_line;
}
// Varyings
float worldposX[MAXWIDTH];
float worldposY[MAXWIDTH];
float worldposZ[MAXWIDTH];
uint32_t texel[MAXWIDTH];
int32_t texelV[MAXWIDTH];
fixed_t lightarray[MAXWIDTH];
uint32_t dynlights[MAXWIDTH];
static PolyTriangleThreadData *Get(DrawerThread *thread);
private:

View file

@ -227,7 +227,7 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat
if (x > xstart)
{
if (writeColor)
drawfunc(y, xstart, x, args);
drawfunc(y, xstart, x, args, thread);
if (writeStencil)
{
@ -379,29 +379,54 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat
}
template<typename ModeT, typename OptT>
void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread)
{
using namespace TriScreenDrawerModes;
uint32_t fixedlight;
uint32_t shade_fade_r, shade_fade_g, shade_fade_b, shade_light_r, shade_light_g, shade_light_b, desaturate, inv_desaturate;
fixed_t fuzzscale;
int _fuzzpos;
const uint32_t *texPixels, *translation;
int texWidth, texHeight;
uint32_t fillcolor;
int actoralpha;
float v1X, v1Y, v1W, v1U, v1V, v1WorldX, v1WorldY, v1WorldZ;
float startX, startY;
float stepW, stepU, stepV, stepWorldX, stepWorldY, stepWorldZ;
float posW, posU, posV, posWorldX, posWorldY, posWorldZ;
PolyLight *lights;
int num_lights;
float worldnormalX, worldnormalY, worldnormalZ;
uint32_t dynlightcolor;
const uint32_t *texPixels, *translation;
int texWidth, texHeight;
uint32_t fillcolor;
int alpha;
uint32_t light;
fixed_t shade, lightpos, lightstep;
uint32_t shade_fade_r, shade_fade_g, shade_fade_b, shade_light_r, shade_light_g, shade_light_b, desaturate, inv_desaturate;
int16_t dynlights_r[MAXWIDTH / 16], dynlights_g[MAXWIDTH / 16], dynlights_b[MAXWIDTH / 16];
int16_t posdynlight_r, posdynlight_g, posdynlight_b;
fixed_t lightarray[MAXWIDTH / 16];
float *worldposX = thread->worldposX;
float *worldposY = thread->worldposY;
float *worldposZ = thread->worldposZ;
uint32_t *texel = thread->texel;
int32_t *texelV = thread->texelV;
fixed_t *lightarray = thread->lightarray;
uint32_t *dynlights = thread->dynlights;
if (!(ModeT::SWFlags & SWSTYLEF_Fill) && !(ModeT::SWFlags & SWSTYLEF_FogBoundary))
{
texPixels = (const uint32_t*)args->uniforms->TexturePixels();
texWidth = args->uniforms->TextureWidth();
texHeight = args->uniforms->TextureHeight();
}
if (ModeT::SWFlags & SWSTYLEF_Translated)
{
translation = (const uint32_t*)args->uniforms->Translation();
}
if ((ModeT::SWFlags & SWSTYLEF_Fill) || (ModeT::SWFlags & SWSTYLEF_Skycap) || (ModeT::Flags & STYLEF_ColorIsFixed))
{
fillcolor = args->uniforms->Color();
}
if (!(ModeT::Flags & STYLEF_Alpha1))
{
actoralpha = args->uniforms->Alpha();
}
v1X = args->v1->x;
v1Y = args->v1->y;
@ -417,50 +442,6 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
posU = v1U + stepU * startX + args->gradientY.U * startY;
posV = v1V + stepV * startX + args->gradientY.V * startY;
texPixels = (const uint32_t*)args->uniforms->TexturePixels();
translation = (const uint32_t*)args->uniforms->Translation();
texWidth = args->uniforms->TextureWidth();
texHeight = args->uniforms->TextureHeight();
fillcolor = args->uniforms->Color();
alpha = args->uniforms->Alpha();
light = args->uniforms->Light();
if (OptT::Flags & SWOPT_FixedLight)
{
light += light >> 7; // 255 -> 256
}
else
{
float globVis = args->uniforms->GlobVis() * (1.0f / 32.0f);
shade = (fixed_t)((2.0f - (light + 12.0f) / 128.0f) * (float)FRACUNIT);
lightpos = (fixed_t)(globVis * posW * (float)FRACUNIT);
lightstep = (fixed_t)(globVis * stepW * (float)FRACUNIT);
int affineOffset = x0 / 16 * 16 - x0;
lightpos = lightpos + lightstep * affineOffset;
lightstep = lightstep * 16;
fixed_t maxvis = 24 * FRACUNIT / 32;
fixed_t maxlight = 31 * FRACUNIT / 32;
for (int x = x0 / 16; x <= x1 / 16 + 1; x++)
{
lightarray[x] = (FRACUNIT - clamp<fixed_t>(shade - MIN(maxvis, lightpos), 0, maxlight)) >> 8;
lightpos += lightstep;
}
int offset = x0 >> 4;
int t1 = x0 & 15;
int t0 = 16 - t1;
lightpos = (lightarray[offset] * t0 + lightarray[offset + 1] * t1);
for (int x = x0 / 16; x <= x1 / 16; x++)
{
lightarray[x] = lightarray[x + 1] - lightarray[x];
}
}
if (OptT::Flags & SWOPT_DynLights)
{
v1WorldX = args->v1->worldX * v1W;
@ -472,6 +453,61 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
posWorldX = v1WorldX + stepWorldX * startX + args->gradientY.WorldX * startY;
posWorldY = v1WorldY + stepWorldY * startX + args->gradientY.WorldY * startY;
posWorldZ = v1WorldZ + stepWorldZ * startX + args->gradientY.WorldZ * startY;
}
if (!(OptT::Flags & SWOPT_FixedLight))
{
float globVis = args->uniforms->GlobVis() * (1.0f / 32.0f);
light = args->uniforms->Light();
shade = (fixed_t)((2.0f - (light + 12.0f) / 128.0f) * (float)FRACUNIT);
lightpos = (fixed_t)(globVis * posW * (float)FRACUNIT);
lightstep = (fixed_t)(globVis * stepW * (float)FRACUNIT);
}
for (int x = x0; x < x1; x++)
{
if (OptT::Flags & SWOPT_DynLights)
{
float rcp_posW = 1.0f / posW;
worldposX[x] = posWorldX * rcp_posW;
worldposY[x] = posWorldY * rcp_posW;
worldposZ[x] = posWorldZ * rcp_posW;
posWorldX += stepWorldX;
posWorldY += stepWorldY;
posWorldZ += stepWorldZ;
}
if (!(OptT::Flags & SWOPT_FixedLight))
{
fixed_t maxvis = 24 * FRACUNIT / 32;
fixed_t maxlight = 31 * FRACUNIT / 32;
lightarray[x] = (FRACUNIT - clamp<fixed_t>(shade - MIN(maxvis, lightpos), 0, maxlight)) >> 8;
lightpos += lightstep;
}
if (!(ModeT::SWFlags & SWSTYLEF_Fill) && !(ModeT::SWFlags & SWSTYLEF_FogBoundary))
{
float rcpW = 0x01000000 / posW;
int32_t u = (int32_t)(posU * rcpW);
int32_t v = (int32_t)(posV * rcpW);
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
texel[x] = texelX * texHeight + texelY;
texelV[x] = v;
posU += stepU;
posV += stepV;
}
posW += stepW;
}
if (OptT::Flags & SWOPT_DynLights)
{
PolyLight *lights;
int num_lights;
float worldnormalX, worldnormalY, worldnormalZ;
uint32_t dynlightcolor;
lights = args->uniforms->Lights();
num_lights = args->uniforms->NumLights();
@ -503,26 +539,12 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
worldnormalZ *= rcplen;
}
int affineOffset = x0 / 16 * 16 - x0;
float posLightW = posW + stepW * affineOffset;
posWorldX = posWorldX + stepWorldX * affineOffset;
posWorldY = posWorldY + stepWorldY * affineOffset;
posWorldZ = posWorldZ + stepWorldZ * affineOffset;
float stepLightW = stepW * 16.0f;
stepWorldX *= 16.0f;
stepWorldY *= 16.0f;
stepWorldZ *= 16.0f;
for (int x = x0 / 16; x <= x1 / 16 + 1; x++)
for (int x = x0; x < x1; x++)
{
uint32_t lit_r = RPART(dynlightcolor);
uint32_t lit_g = GPART(dynlightcolor);
uint32_t lit_b = BPART(dynlightcolor);
float rcp_posW = 1.0f / posLightW;
float worldposX = posWorldX * rcp_posW;
float worldposY = posWorldY * rcp_posW;
float worldposZ = posWorldZ * rcp_posW;
for (int i = 0; i < num_lights; i++)
{
float lightposX = lights[i].x;
@ -538,9 +560,9 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
// L = light-pos
// dist = sqrt(dot(L, L))
// distance_attenuation = 1 - MIN(dist * (1/radius), 1)
float Lx = lightposX - worldposX;
float Ly = lightposY - worldposY;
float Lz = lightposZ - worldposZ;
float Lx = lightposX - worldposX[x];
float Ly = lightposY - worldposY[x];
float Lz = lightposZ - worldposZ[x];
float dist2 = Lx * Lx + Ly * Ly + Lz * Lz;
#ifdef NO_SSE
//float rcp_dist = 1.0f / sqrt(dist2);
@ -572,29 +594,14 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
lit_r = MIN<uint32_t>(lit_r, 255);
lit_g = MIN<uint32_t>(lit_g, 255);
lit_b = MIN<uint32_t>(lit_b, 255);
dynlights_r[x] = lit_r;
dynlights_g[x] = lit_g;
dynlights_b[x] = lit_b;
posLightW += stepLightW;
posWorldX += stepWorldX;
posWorldY += stepWorldY;
posWorldZ += stepWorldZ;
dynlights[x] = MAKEARGB(255, lit_r, lit_g, lit_b);
}
}
int offset = x0 >> 4;
int t1 = x0 & 15;
int t0 = 16 - t1;
posdynlight_r = (dynlights_r[offset] * t0 + dynlights_r[offset + 1] * t1);
posdynlight_g = (dynlights_g[offset] * t0 + dynlights_g[offset + 1] * t1);
posdynlight_b = (dynlights_b[offset] * t0 + dynlights_b[offset + 1] * t1);
for (int x = x0 / 16; x <= x1 / 16; x++)
{
dynlights_r[x] = dynlights_r[x + 1] - dynlights_r[x];
dynlights_g[x] = dynlights_g[x + 1] - dynlights_g[x];
dynlights_b[x] = dynlights_b[x + 1] - dynlights_b[x];
}
if (OptT::Flags & SWOPT_FixedLight)
{
fixedlight = args->uniforms->Light();
fixedlight += fixedlight >> 7; // 255 -> 256
}
if (OptT::Flags & SWOPT_ColoredFog)
@ -609,8 +616,6 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
inv_desaturate = 256 - desaturate;
}
fixed_t fuzzscale;
int _fuzzpos;
if (ModeT::BlendOp == STYLEOP_Fuzz)
{
fuzzscale = (200 << FRACBITS) / viewheight;
@ -620,19 +625,55 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
uint32_t *dest = (uint32_t*)args->dest;
uint32_t *destLine = dest + args->pitch * y;
int x = x0;
while (x < x1)
int sseend = x0;
#ifndef NO_SSE
if (ModeT::BlendOp == STYLEOP_Add &&
ModeT::BlendSrc == STYLEALPHA_One &&
ModeT::BlendDest == STYLEALPHA_Zero &&
(ModeT::Flags & STYLEF_Alpha1) &&
!(OptT::Flags & SWOPT_ColoredFog) &&
!(ModeT::Flags & STYLEF_RedIsAlpha) &&
!(ModeT::SWFlags & SWSTYLEF_Skycap) &&
!(ModeT::SWFlags & SWSTYLEF_FogBoundary) &&
!(ModeT::SWFlags & SWSTYLEF_Fill))
{
sseend += (x1 - x0) / 2 * 2;
__m128i mlightshade;
if (OptT::Flags & SWOPT_FixedLight)
mlightshade = _mm_set1_epi16(fixedlight);
__m128i alphamask = _mm_set1_epi32(0xff000000);
for (int x = x0; x < sseend; x += 2)
{
__m128i mfg = _mm_unpacklo_epi8(_mm_setr_epi32(texPixels[texel[x]], texPixels[texel[x + 1]], 0, 0), _mm_setzero_si128());
if (!(OptT::Flags & SWOPT_FixedLight))
mlightshade = _mm_shuffle_epi32(_mm_shufflelo_epi16(_mm_loadl_epi64((const __m128i*)&lightarray[x]), _MM_SHUFFLE(2, 2, 0, 0)), _MM_SHUFFLE(1, 1, 0, 0));
if (OptT::Flags & SWOPT_DynLights)
{
__m128i mdynlight = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i*)&dynlights[x]), _mm_setzero_si128());
mfg = _mm_srli_epi16(_mm_mullo_epi16(_mm_min_epi16(_mm_add_epi16(mdynlight, mlightshade), _mm_set1_epi16(256)), mfg), 8);
}
else
{
mfg = _mm_srli_epi16(_mm_mullo_epi16(mlightshade, mfg), 8);
}
_mm_storel_epi64((__m128i*)&destLine[x], _mm_or_si128(_mm_packus_epi16(mfg, _mm_setzero_si128()), alphamask));
}
}
#endif
for (int x = sseend; x < x1; x++)
{
if (ModeT::BlendOp == STYLEOP_Fuzz)
{
using namespace swrenderer;
float rcpW = 0x01000000 / posW;
int32_t u = (int32_t)(posU * rcpW);
int32_t v = (int32_t)(posV * rcpW);
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]);
unsigned int sampleshadeout = APART(texPixels[texel[x]]);
sampleshadeout += sampleshadeout >> 7; // 255 -> 256
int scaled_x = (x * fuzzscale) >> FRACBITS;
@ -654,14 +695,9 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
}
else if (ModeT::SWFlags & SWSTYLEF_Skycap)
{
float rcpW = 0x01000000 / posW;
int32_t u = (int32_t)(posU * rcpW);
int32_t v = (int32_t)(posV * rcpW);
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
uint32_t fg = texPixels[texelX * texHeight + texelY];
uint32_t fg = texPixels[texel[x]];
int v = texelV[x];
int start_fade = 2; // How fast it should fade out
int alpha_top = clamp(v >> (16 - start_fade), 0, 256);
int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256);
@ -695,11 +731,11 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
int lightshade;
if (OptT::Flags & SWOPT_FixedLight)
{
lightshade = light;
lightshade = fixedlight;
}
else
{
lightshade = lightpos >> 4;
lightshade = lightarray[x];
}
uint32_t shadedfg_r, shadedfg_g, shadedfg_b;
@ -731,26 +767,17 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
{
fg = fillcolor;
}
else if (ModeT::SWFlags & SWSTYLEF_Translated)
{
fg = translation[((const uint8_t*)texPixels)[texel[x]]];
}
else if (ModeT::Flags & STYLEF_RedIsAlpha)
{
fg = ((const uint8_t*)texPixels)[texel[x]];
}
else
{
float rcpW = 0x01000000 / posW;
int32_t u = (int32_t)(posU * rcpW);
int32_t v = (int32_t)(posV * rcpW);
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
if (ModeT::SWFlags & SWSTYLEF_Translated)
{
fg = translation[((const uint8_t*)texPixels)[texelX * texHeight + texelY]];
}
else if (ModeT::Flags & STYLEF_RedIsAlpha)
{
fg = ((const uint8_t*)texPixels)[texelX * texHeight + texelY];
}
else
{
fg = texPixels[texelX * texHeight + texelY];
}
fg = texPixels[texel[x]];
}
if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill))
@ -765,17 +792,17 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
if (!(ModeT::Flags & STYLEF_Alpha1))
{
fgalpha = (fgalpha * alpha) >> 8;
fgalpha = (fgalpha * actoralpha) >> 8;
}
int lightshade;
uint32_t lightshade;
if (OptT::Flags & SWOPT_FixedLight)
{
lightshade = light;
lightshade = fixedlight;
}
else
{
lightshade = lightpos >> 4;
lightshade = lightarray[x];
}
uint32_t shadedfg_r, shadedfg_g, shadedfg_b;
@ -792,24 +819,18 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
if (OptT::Flags & SWOPT_DynLights)
{
uint32_t lit_r = posdynlight_r >> 4;
uint32_t lit_g = posdynlight_g >> 4;
uint32_t lit_b = posdynlight_b >> 4;
shadedfg_r = MIN(shadedfg_r + ((fg_r * lit_r) >> 8), (uint32_t)255);
shadedfg_g = MIN(shadedfg_g + ((fg_g * lit_g) >> 8), (uint32_t)255);
shadedfg_b = MIN(shadedfg_b + ((fg_b * lit_b) >> 8), (uint32_t)255);
shadedfg_r = MIN(shadedfg_r + ((fg_r * RPART(dynlights[x])) >> 8), (uint32_t)255);
shadedfg_g = MIN(shadedfg_g + ((fg_g * GPART(dynlights[x])) >> 8), (uint32_t)255);
shadedfg_b = MIN(shadedfg_b + ((fg_b * BPART(dynlights[x])) >> 8), (uint32_t)255);
}
}
else
{
if (OptT::Flags & SWOPT_DynLights)
{
uint32_t lit_r = posdynlight_r >> 4;
uint32_t lit_g = posdynlight_g >> 4;
uint32_t lit_b = posdynlight_b >> 4;
shadedfg_r = (RPART(fg) * MIN(lightshade + lit_r, (uint32_t)256)) >> 8;
shadedfg_g = (GPART(fg) * MIN(lightshade + lit_g, (uint32_t)256)) >> 8;
shadedfg_b = (BPART(fg) * MIN(lightshade + lit_b, (uint32_t)256)) >> 8;
shadedfg_r = (RPART(fg) * MIN(lightshade + RPART(dynlights[x]), (uint32_t)256)) >> 8;
shadedfg_g = (GPART(fg) * MIN(lightshade + GPART(dynlights[x]), (uint32_t)256)) >> 8;
shadedfg_b = (BPART(fg) * MIN(lightshade + BPART(dynlights[x]), (uint32_t)256)) >> 8;
}
else
{
@ -927,24 +948,11 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
}
}
posW += stepW;
posU += stepU;
posV += stepV;
if (OptT::Flags & SWOPT_DynLights)
{
posdynlight_r += dynlights_r[x >> 4];
posdynlight_g += dynlights_g[x >> 4];
posdynlight_b += dynlights_b[x >> 4];
}
if (!(OptT::Flags & SWOPT_FixedLight))
lightpos += lightarray[x >> 4];
x++;
}
}
template<typename ModeT>
void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread)
{
using namespace TriScreenDrawerModes;
@ -953,16 +961,16 @@ void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
if (!args->uniforms->FixedLight())
{
if (args->uniforms->SimpleShade())
DrawSpanOpt32<ModeT, DrawerOpt>(y, x0, x1, args);
DrawSpanOpt32<ModeT, DrawerOpt>(y, x0, x1, args, thread);
else
DrawSpanOpt32<ModeT, DrawerOptC>(y, x0, x1, args);
DrawSpanOpt32<ModeT, DrawerOptC>(y, x0, x1, args, thread);
}
else
{
if (args->uniforms->SimpleShade())
DrawSpanOpt32<ModeT, DrawerOptF>(y, x0, x1, args);
DrawSpanOpt32<ModeT, DrawerOptF>(y, x0, x1, args, thread);
else
DrawSpanOpt32<ModeT, DrawerOptCF>(y, x0, x1, args);
DrawSpanOpt32<ModeT, DrawerOptCF>(y, x0, x1, args, thread);
}
}
else
@ -970,22 +978,22 @@ void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
if (!args->uniforms->FixedLight())
{
if (args->uniforms->SimpleShade())
DrawSpanOpt32<ModeT, DrawerOptL>(y, x0, x1, args);
DrawSpanOpt32<ModeT, DrawerOptL>(y, x0, x1, args, thread);
else
DrawSpanOpt32<ModeT, DrawerOptLC>(y, x0, x1, args);
DrawSpanOpt32<ModeT, DrawerOptLC>(y, x0, x1, args, thread);
}
else
{
if (args->uniforms->SimpleShade())
DrawSpanOpt32<ModeT, DrawerOptLF>(y, x0, x1, args);
DrawSpanOpt32<ModeT, DrawerOptLF>(y, x0, x1, args, thread);
else
DrawSpanOpt32<ModeT, DrawerOptLCF>(y, x0, x1, args);
DrawSpanOpt32<ModeT, DrawerOptLCF>(y, x0, x1, args, thread);
}
}
}
template<typename ModeT, typename OptT>
void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args)
void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread)
{
using namespace TriScreenDrawerModes;
@ -1501,23 +1509,23 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args)
}
template<typename ModeT>
void DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args)
void DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread)
{
using namespace TriScreenDrawerModes;
if (args->uniforms->NumLights() == 0 && args->uniforms->DynLightColor() == 0)
{
if (!args->uniforms->FixedLight())
DrawSpanOpt8<ModeT, DrawerOptC>(y, x0, x1, args);
DrawSpanOpt8<ModeT, DrawerOptC>(y, x0, x1, args, thread);
else
DrawSpanOpt8<ModeT, DrawerOptCF>(y, x0, x1, args);
DrawSpanOpt8<ModeT, DrawerOptCF>(y, x0, x1, args, thread);
}
else
{
if (!args->uniforms->FixedLight())
DrawSpanOpt8<ModeT, DrawerOptLC>(y, x0, x1, args);
DrawSpanOpt8<ModeT, DrawerOptLC>(y, x0, x1, args, thread);
else
DrawSpanOpt8<ModeT, DrawerOptLCF>(y, x0, x1, args);
DrawSpanOpt8<ModeT, DrawerOptLCF>(y, x0, x1, args, thread);
}
}
@ -2049,7 +2057,7 @@ void DrawRect32(const void *destOrg, int destWidth, int destHeight, int destPitc
DrawRectOpt32<ModeT, DrawerOptCF>(destOrg, destWidth, destHeight, destPitch, args, thread);
}
void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs *) =
void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs *, PolyTriangleThreadData *) =
{
&DrawSpan8<TriScreenDrawerModes::StyleOpaque>,
&DrawSpan8<TriScreenDrawerModes::StyleSkycap>,
@ -2081,7 +2089,7 @@ void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs *
&DrawSpan8<TriScreenDrawerModes::StyleAddShadedTranslated>
};
void(*ScreenTriangle::SpanDrawers32[])(int, int, int, const TriDrawTriangleArgs *) =
void(*ScreenTriangle::SpanDrawers32[])(int, int, int, const TriDrawTriangleArgs *, PolyTriangleThreadData *) =
{
&DrawSpan32<TriScreenDrawerModes::StyleOpaque>,
&DrawSpan32<TriScreenDrawerModes::StyleSkycap>,

View file

@ -142,8 +142,8 @@ class ScreenTriangle
public:
static void Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread);
static void(*SpanDrawers8[])(int y, int x0, int x1, const TriDrawTriangleArgs *args);
static void(*SpanDrawers32[])(int y, int x0, int x1, const TriDrawTriangleArgs *args);
static void(*SpanDrawers8[])(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread);
static void(*SpanDrawers32[])(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread);
static void(*RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *);
static void(*RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *);

View file

@ -265,11 +265,11 @@ int main (int argc, char **argv)
fprintf (stderr, "%s\n", error.what ());
#ifdef __APPLE__
Mac_I_FatalError(error.GetMessage());
Mac_I_FatalError(error.what());
#endif // __APPLE__
#ifdef __linux__
Linux_I_FatalError(error.GetMessage());
Linux_I_FatalError(error.what());
#endif // __linux__
exit (-1);

View file

@ -630,10 +630,6 @@ public:
double FindHighestCeilingSurrounding(vertex_t **v) const; // jff 2/04/98
double FindNextLowestCeiling(vertex_t **v) const; // jff 2/04/98
double FindNextHighestCeiling(vertex_t **v) const; // jff 2/04/98
double FindShortestTextureAround() const; // jff 2/04/98
double FindShortestUpperAround() const; // jff 2/04/98
sector_t *FindModelFloorSector(double floordestheight) const; // jff 2/04/98
sector_t *FindModelCeilingSector(double floordestheight) const; // jff 2/04/98
int FindMinSurroundingLight (int max) const;
sector_t *NextSpecialSector (int type, sector_t *prev) const; // [RH]
double FindLowestCeilingPoint(vertex_t **v) const;
@ -642,12 +638,13 @@ public:
int Index() const;
void AdjustFloorClip () const;
void SetColor(int r, int g, int b, int desat);
void SetFade(int r, int g, int b);
void SetColor(PalEntry pe, int desat);
void SetFade(PalEntry pe);
void SetFogDensity(int dens);
void ClosestPoint(const DVector2 &pos, DVector2 &out) const;
int GetFloorLight () const;
int GetCeilingLight () const;
int GetFloorLight() const;
int GetCeilingLight() const;
sector_t *GetHeightSec() const
{
@ -1585,6 +1582,11 @@ inline sector_t *P_PointInSector(double X, double Y)
return P_PointInSubsector(X, Y)->sector;
}
inline sector_t *P_PointInSectorXY(double X, double Y) // This is for the benefit of unambiguously looking up this function's address
{
return P_PointInSubsector(X, Y)->sector;
}
inline bool FBoundingBox::inRange(const line_t *ld) const
{
return Left() < ld->bbox[BOXRIGHT] &&
@ -1603,4 +1605,40 @@ inline void FColormap::CopyFrom3DLight(lightlist_t *light)
}
}
double FindShortestTextureAround(sector_t *sector); // jff 2/04/98
double FindShortestUpperAround(sector_t *sector); // jff 2/04/98
sector_t *FindModelFloorSector(sector_t *sec, double floordestheight); // jff 2/04/98
sector_t *FindModelCeilingSector(sector_t *sec, double floordestheight); // jff 2/04/98
// This setup is to allow the VM call directily into the implementation.
// With a member function this may be subject to OS implementation details, e.g. on Windows 32 bit members use a different calling convention than regular functions.
void RemoveForceField(sector_t *sec);
bool PlaneMoving(sector_t *sector, int pos);
void TransferSpecial(sector_t *self, sector_t *model);
void GetSpecial(sector_t *self, secspecial_t *spec);
void SetSpecial(sector_t *self, const secspecial_t *spec);
int GetTerrain(const sector_t *, int pos);
void CheckPortalPlane(sector_t *sector, int plane);
void AdjustFloorClip(const sector_t *sector);
void SetColor(sector_t *sector, int color, int desat);
void SetFade(sector_t *sector, int color);
int GetFloorLight(const sector_t *);
int GetCeilingLight(const sector_t *);
inline void sector_t::RemoveForceField() { return ::RemoveForceField(this); }
inline bool sector_t::PlaneMoving(int pos) { return ::PlaneMoving(this, pos); }
inline void sector_t::TransferSpecial(sector_t *model) { return ::TransferSpecial(this, model); }
inline void sector_t::GetSpecial(secspecial_t *spec) { ::GetSpecial(this, spec); }
inline void sector_t::SetSpecial(const secspecial_t *spec) { ::SetSpecial(this, spec); }
inline int sector_t::GetTerrain(int pos) const { return ::GetTerrain(this, pos); }
inline void sector_t::CheckPortalPlane(int plane) { return ::CheckPortalPlane(this, plane); }
inline void sector_t::AdjustFloorClip() const { ::AdjustFloorClip(this); }
inline void sector_t::SetColor(PalEntry pe, int desat) { ::SetColor(this, pe, desat); }
inline void sector_t::SetFade(PalEntry pe) { ::SetFade(this, pe); }
inline int sector_t::GetFloorLight() const { return ::GetFloorLight(this); }
inline int sector_t::GetCeilingLight() const { return ::GetCeilingLight(this); }
#endif

View file

@ -1438,6 +1438,24 @@ void S_PlaySound(AActor *a, int chan, FSoundID sid, float vol, float atten, bool
}
}
void A_PlaySound(AActor *self, int soundid, int channel, double volume, int looping, double attenuation, int local)
{
if (!looping)
{
if (!(channel & CHAN_NOSTOP) || !S_IsActorPlayingSomething(self, channel & 7, soundid))
{
S_PlaySound(self, channel, soundid, (float)volume, (float)attenuation, local);
}
}
else
{
if (!S_IsActorPlayingSomething(self, channel & 7, soundid))
{
S_PlaySound(self, channel | CHAN_LOOP, soundid, (float)volume, (float)attenuation, local);
}
}
}
//==========================================================================
//
// S_LoadSound

View file

@ -371,6 +371,7 @@ sfxinfo_t *S_LoadSound(sfxinfo_t *sfx, FSoundLoadBuffer *pBuffer = nullptr);
unsigned int S_GetMSLength(FSoundID sound);
void S_ParseMusInfo();
bool S_ParseTimeTag(const char *tag, bool *as_samples, unsigned int *time);
void A_PlaySound(AActor *self, int soundid, int channel, double volume, int looping, double attenuation, int local);
// [RH] Prints sound debug info to the screen.
// Modelled after Hexen's noise cheat.

View file

@ -259,20 +259,9 @@ void ExpEmit::Reuse(VMFunctionBuilder *build)
//
//==========================================================================
static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCallType func, const uint8_t *reginfo)
static PFunction *FindBuiltinFunction(FName funcname)
{
PSymbol *sym = Namespaces.GlobalNamespace->Symbols.FindSymbol(funcname, false);
if (sym == nullptr)
{
PSymbolVMFunction *symfunc = Create<PSymbolVMFunction>(funcname);
VMNativeFunction *calldec = new VMNativeFunction(func, funcname);
calldec->PrintableName = funcname.GetChars();
calldec->RegTypes = reginfo;
symfunc->Function = calldec;
sym = symfunc;
Namespaces.GlobalNamespace->Symbols.AddSymbol(sym);
}
return sym;
return dyn_cast<PFunction>(RUNTIME_CLASS(DObject)->FindSymbol(funcname, true));
}
//==========================================================================
@ -5471,33 +5460,35 @@ FxExpression *FxRandom::Resolve(FCompileContext &ctx)
//
//==========================================================================
int BuiltinRandom(VM_ARGS)
static int NativeRandom(FRandom *rng, int min, int max)
{
if (max < min)
{
std::swap(max, min);
}
return (*rng)(max - min + 1) + min;
}
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinRandom, NativeRandom)
{
PARAM_PROLOGUE;
PARAM_POINTER(rng, FRandom);
PARAM_INT(min);
PARAM_INT(max);
if (max < min)
{
std::swap(max, min);
}
ACTION_RETURN_INT((*rng)(max - min + 1) + min);
ACTION_RETURN_INT(NativeRandom(rng, min, max));
}
ExpEmit FxRandom::Emit(VMFunctionBuilder *build)
{
// Call DecoRandom to generate a random number.
VMFunction *callfunc;
static const uint8_t reginfo[] = { REGT_POINTER, REGT_INT, REGT_INT };
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom, reginfo);
auto sym = FindBuiltinFunction(NAME_BuiltinRandom);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
assert(sym);
callfunc = sym->Variants[0].Implementation;
assert(min && max);
callfunc = ((PSymbolVMFunction *)sym)->Function;
FunctionCallEmitter emitters(callfunc);
emitters.AddParameterPointerConst(rng);
emitters.AddParameter(build, min);
emitters.AddParameter(build, max);
@ -5596,12 +5587,10 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
// Call BuiltinRandom to generate a random number.
VMFunction *callfunc;
static const uint8_t reginfo[] = { REGT_POINTER, REGT_INT, REGT_INT };
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom, reginfo);
auto sym = FindBuiltinFunction(NAME_BuiltinRandom);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
callfunc = ((PSymbolVMFunction *)sym)->Function;
assert(sym);
callfunc = sym->Variants[0].Implementation;
FunctionCallEmitter emitters(callfunc);
emitters.AddParameterPointerConst(rng);
@ -5694,13 +5683,8 @@ FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScri
//
//==========================================================================
int BuiltinFRandom(VM_ARGS)
static double NativeFRandom(FRandom *rng, double min, double max)
{
PARAM_PROLOGUE;
PARAM_POINTER(rng, FRandom);
PARAM_FLOAT(min);
PARAM_FLOAT(max);
int random = (*rng)(0x40000000);
double frandom = random / double(0x40000000);
@ -5708,20 +5692,29 @@ int BuiltinFRandom(VM_ARGS)
{
std::swap(max, min);
}
ACTION_RETURN_FLOAT(frandom * (max - min) + min);
return frandom * (max - min) + min;
}
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinFRandom, NativeFRandom)
{
PARAM_PROLOGUE;
PARAM_POINTER(rng, FRandom);
PARAM_FLOAT(min);
PARAM_FLOAT(max);
ACTION_RETURN_FLOAT(NativeFRandom(rng, min, max));
}
ExpEmit FxFRandom::Emit(VMFunctionBuilder *build)
{
// Call the BuiltinFRandom function to generate a floating point random number..
VMFunction *callfunc;
static uint8_t reginfo[] = { REGT_POINTER, REGT_FLOAT, REGT_FLOAT };
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinFRandom, BuiltinFRandom, reginfo);
auto sym = FindBuiltinFunction(NAME_BuiltinFRandom);
assert(sym);
callfunc = sym->Variants[0].Implementation;
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
assert(min && max);
callfunc = ((PSymbolVMFunction *)sym)->Function;
FunctionCallEmitter emitters(callfunc);
emitters.AddParameterPointerConst(rng);
@ -5776,7 +5769,12 @@ FxExpression *FxRandom2::Resolve(FCompileContext &ctx)
//
//==========================================================================
int BuiltinRandom2(VM_ARGS)
static int NativeRandom2(FRandom *rng, int maskval)
{
return rng->Random2(maskval);
}
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinRandom2, NativeRandom2)
{
PARAM_PROLOGUE;
PARAM_POINTER(rng, FRandom);
@ -5794,12 +5792,10 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build)
{
// Call the BuiltinRandom function to generate the random number.
VMFunction *callfunc;
static uint8_t reginfo[] = { REGT_POINTER, REGT_INT };
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom2, BuiltinRandom2, reginfo);
auto sym = FindBuiltinFunction(NAME_BuiltinRandom2);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
callfunc = ((PSymbolVMFunction *)sym)->Function;
assert(sym);
callfunc = sym->Variants[0].Implementation;
FunctionCallEmitter emitters(callfunc);
@ -5853,7 +5849,12 @@ FxExpression *FxRandomSeed::Resolve(FCompileContext &ctx)
//
//==========================================================================
int BuiltinRandomSeed(VM_ARGS)
static void NativeRandomSeed(FRandom *rng, int seed)
{
rng->Init(seed);
}
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinRandomSeed, NativeRandomSeed)
{
PARAM_PROLOGUE;
PARAM_POINTER(rng, FRandom)
@ -5866,12 +5867,10 @@ ExpEmit FxRandomSeed::Emit(VMFunctionBuilder *build)
{
// Call DecoRandom to generate a random number.
VMFunction *callfunc;
static uint8_t reginfo[] = { REGT_POINTER, REGT_INT };
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandomSeed, BuiltinRandomSeed, reginfo);
auto sym = FindBuiltinFunction(NAME_BuiltinRandomSeed);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
callfunc = ((PSymbolVMFunction *)sym)->Function;
assert(sym);
callfunc = sym->Variants[0].Implementation;
FunctionCallEmitter emitters(callfunc);
emitters.AddParameterPointerConst(rng);
@ -8525,7 +8524,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx)
//
//==========================================================================
int BuiltinCallLineSpecial(VM_ARGS)
DEFINE_ACTION_FUNCTION(DObject, BuiltinCallLineSpecial)
{
PARAM_PROLOGUE;
PARAM_INT(special);
@ -8545,11 +8544,10 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
// Call the BuiltinCallLineSpecial function to perform the desired special.
static uint8_t reginfo[] = { REGT_INT, REGT_POINTER, REGT_INT, REGT_INT, REGT_INT, REGT_INT, REGT_INT };
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinCallLineSpecial, BuiltinCallLineSpecial, reginfo);
auto sym = FindBuiltinFunction(NAME_BuiltinCallLineSpecial);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
VMFunction *callfunc = ((PSymbolVMFunction *)sym)->Function;
assert(sym);
auto callfunc = sym->Variants[0].Implementation;
FunctionCallEmitter emitters(callfunc);
@ -10749,23 +10747,29 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
//
//==========================================================================
int BuiltinNameToClass(VM_ARGS)
static PClass *NativeNameToClass(int _clsname, PClass *desttype)
{
PARAM_PROLOGUE;
PARAM_NAME(clsname);
PARAM_CLASS(desttype, DObject);
PClass *cls = nullptr;
FName clsname = ENamedName(_clsname);
if (clsname != NAME_None)
{
cls = PClass::FindClass(clsname);
if (cls != nullptr && (cls->VMType == nullptr || !cls->IsDescendantOf(desttype)))
{
// does not match required parameters or is invalid.
cls = nullptr;
return nullptr;
}
}
ACTION_RETURN_POINTER(cls);
return cls;
}
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinNameToClass, NativeNameToClass)
{
PARAM_PROLOGUE;
PARAM_NAME(clsname);
PARAM_CLASS(desttype, DObject);
ACTION_RETURN_POINTER(NativeNameToClass(clsname, desttype));
}
ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
@ -10777,12 +10781,10 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
// Call the BuiltinNameToClass function to convert from 'name' to class.
VMFunction *callfunc;
static uint8_t reginfo[] = { REGT_INT, REGT_POINTER };
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinNameToClass, BuiltinNameToClass, reginfo);
auto sym = FindBuiltinFunction(NAME_BuiltinNameToClass);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
callfunc = ((PSymbolVMFunction *)sym)->Function;
assert(sym);
callfunc = sym->Variants[0].Implementation;
FunctionCallEmitter emitters(callfunc);
emitters.AddParameter(build, basex);
@ -10871,12 +10873,17 @@ FxExpression *FxClassPtrCast::Resolve(FCompileContext &ctx)
//
//==========================================================================
int BuiltinClassCast(VM_ARGS)
static PClass *NativeClassCast(PClass *from, PClass *to)
{
return from && to && from->IsDescendantOf(to) ? from : nullptr;
}
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinClassCast, NativeClassCast)
{
PARAM_PROLOGUE;
PARAM_CLASS(from, DObject);
PARAM_CLASS(to, DObject);
ACTION_RETURN_POINTER(from && to && from->IsDescendantOf(to) ? from : nullptr);
ACTION_RETURN_POINTER(NativeClassCast(from, to));
}
ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
@ -10884,12 +10891,10 @@ ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
ExpEmit clsname = basex->Emit(build);
VMFunction *callfunc;
static uint8_t reginfo[] = { REGT_POINTER, REGT_POINTER };
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinClassCast, BuiltinClassCast, reginfo);
auto sym = FindBuiltinFunction(NAME_BuiltinClassCast);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
callfunc = ((PSymbolVMFunction *)sym)->Function;
assert(sym);
callfunc = sym->Variants[0].Implementation;
FunctionCallEmitter emitters(callfunc);
emitters.AddParameter(clsname, false);

View file

@ -52,7 +52,6 @@ IMPLEMENT_CLASS(PSymbolConstNumeric, false, false);
IMPLEMENT_CLASS(PSymbolConstString, false, false);
IMPLEMENT_CLASS(PSymbolTreeNode, false, false)
IMPLEMENT_CLASS(PSymbolType, false, false)
IMPLEMENT_CLASS(PSymbolVMFunction, false, false)
IMPLEMENT_CLASS(PFunction, false, false)
//==========================================================================

View file

@ -37,16 +37,6 @@ protected:
// A VM function ------------------------------------------------------------
class PSymbolVMFunction : public PSymbol
{
DECLARE_CLASS(PSymbolVMFunction, PSymbol);
public:
VMFunction *Function;
PSymbolVMFunction(FName name) : PSymbol(name) {}
PSymbolVMFunction() : PSymbol(NAME_None) {}
};
// A symbol for a type ------------------------------------------------------
class PSymbolType : public PSymbol

View file

@ -944,6 +944,7 @@ void InitThingdef()
assert(afunc->VMPointer != NULL);
*(afunc->VMPointer) = new VMNativeFunction(afunc->Function, afunc->FuncName);
(*(afunc->VMPointer))->PrintableName.Format("%s.%s [Native]", afunc->ClassName+1, afunc->FuncName);
(*(afunc->VMPointer))->DirectNativeCall = afunc->DirectNative;
AFTable.Push(*afunc);
}
AFTable.ShrinkToFit();

View file

@ -9,6 +9,7 @@ extern PStruct *TypeVector3;
static void OutputJitLog(const asmjit::StringLogger &logger);
static TArray<uint8_t*> JitBlocks;
static TArray<uint8_t*> JitFrames;
static size_t JitBlockPos = 0;
static size_t JitBlockSize = 0;
@ -61,6 +62,25 @@ static void *AllocJitMemory(size_t size)
#define UWOP_SAVE_XMM128_FAR 9
#define UWOP_PUSH_MACHFRAME 10
void JitRelease()
{
#ifdef _WIN64
for (auto p : JitFrames)
{
RtlDeleteFunctionTable((PRUNTIME_FUNCTION)p);
}
#endif
for (auto p : JitBlocks)
{
asmjit::OSUtils::releaseVirtualMemory(p, 1024 * 1024);
}
JitFrames.Clear();
JitBlocks.Clear();
JitBlockPos = 0;
JitBlockSize = 0;
}
static TArray<uint16_t> CreateUnwindInfo(asmjit::CCFunc *func)
{
using namespace asmjit;
@ -276,6 +296,7 @@ static void *AddJitFunction(asmjit::CodeHolder* code, asmjit::CCFunc *func)
table[0].EndAddress = (DWORD)(ptrdiff_t)(endaddr - baseaddr);
table[0].UnwindInfoAddress = (DWORD)(ptrdiff_t)(unwindptr - baseaddr);
BOOLEAN result = RtlAddFunctionTable(table, 1, (DWORD64)baseaddr);
JitFrames.Push((uint8_t*)table);
if (result == 0)
I_FatalError("RtlAddFunctionTable failed");
#endif

View file

@ -317,13 +317,16 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target)
{
using namespace asmjit;
auto call = cc.call(imm_ptr(target->DirectNativeCall), CreateFuncSignature(target));
if ((pc - 1)->op == OP_VTBL)
{
I_FatalError("Native direct member function calls not implemented\n");
}
asmjit::CBNode *cursorBefore = cc.getCursor();
auto call = cc.call(imm_ptr(target->DirectNativeCall), CreateFuncSignature(target));
asmjit::CBNode *cursorAfter = cc.getCursor();
cc.setCursor(cursorBefore);
X86Gp tmp;
X86Xmm tmp2;
@ -398,6 +401,8 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target)
}
}
cc.setCursor(cursorAfter);
if (numparams != B)
I_FatalError("OP_CALL parameter count does not match the number of preceding OP_PARAM instructions\n");
@ -461,7 +466,7 @@ asmjit::FuncSignature JitCompiler::CreateFuncSignature(VMFunction *func)
for (unsigned int i = 0; i < func->Proto->ArgumentTypes.Size(); i++)
{
const PType *type = func->Proto->ArgumentTypes[i];
if (func->ArgFlags[i] & (VARF_Out | VARF_Ref))
if (func->ArgFlags.Size() && func->ArgFlags[i] & (VARF_Out | VARF_Ref))
{
args.Push(TypeIdOf<void*>::kTypeId);
key += "v";

View file

@ -53,6 +53,8 @@ extern FMemArena ClassDataAllocator;
#define MAX_RETURNS 8 // Maximum number of results a function called by script code can return
#define MAX_TRY_DEPTH 8 // Maximum number of nested TRYs in a single function
void JitRelease();
typedef unsigned char VM_UBYTE;
typedef signed char VM_SBYTE;
@ -432,6 +434,8 @@ public:
f->~VMFunction();
}
AllFunctions.Clear();
// also release any JIT data
JitRelease();
}
static void CreateRegUseInfo()
{
@ -511,6 +515,7 @@ bool AssertObject(void * ob);
#define PARAM_STATE_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); FState *x = (FState *)StateLabels.GetState(param[p].i, self->GetClass());
#define PARAM_STATE_ACTION_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); FState *x = (FState *)StateLabels.GetState(param[p].i, stateowner->GetClass());
#define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(reginfo[p] == REGT_POINTER); type *x = (type *)param[p].a;
#define PARAM_OUTPOINTER_AT(p,x,type) assert((p) < numparam); type *x = (type *)param[p].a;
#define PARAM_POINTERTYPE_AT(p,x,type) assert((p) < numparam); assert(reginfo[p] == REGT_POINTER); type x = (type )param[p].a;
#define PARAM_OBJECT_AT(p,x,type) assert((p) < numparam); assert(reginfo[p] == REGT_POINTER && AssertObject(param[p].a)); type *x = (type *)param[p].a; assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type)));
#define PARAM_CLASS_AT(p,x,base) assert((p) < numparam); assert(reginfo[p] == REGT_POINTER); base::MetaClass *x = (base::MetaClass *)param[p].a; assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base)));
@ -534,6 +539,7 @@ bool AssertObject(void * ob);
#define PARAM_STATE(x) ++paramnum; PARAM_STATE_AT(paramnum,x)
#define PARAM_STATE_ACTION(x) ++paramnum; PARAM_STATE_ACTION_AT(paramnum,x)
#define PARAM_POINTER(x,type) ++paramnum; PARAM_POINTER_AT(paramnum,x,type)
#define PARAM_OUTPOINTER(x,type) ++paramnum; PARAM_OUTPOINTER_AT(paramnum,x,type)
#define PARAM_POINTERTYPE(x,type) ++paramnum; PARAM_POINTERTYPE_AT(paramnum,x,type)
#define PARAM_OBJECT(x,type) ++paramnum; PARAM_OBJECT_AT(paramnum,x,type)
#define PARAM_CLASS(x,base) ++paramnum; PARAM_CLASS_AT(paramnum,x,base)
@ -559,6 +565,7 @@ struct AFuncDesc
const char *FuncName;
actionf_p Function;
VMNativeFunction **VMPointer;
void *DirectNative;
};
#if defined(_MSC_VER)
@ -579,10 +586,19 @@ struct AFuncDesc
// Macros to handle action functions. These are here so that I don't have to
// change every single use in case the parameters change.
#define DEFINE_ACTION_FUNCTION_NATIVE(cls, name, native) \
static int AF_##cls##_##name(VM_ARGS); \
VMNativeFunction *cls##_##name##_VMPtr; \
static const AFuncDesc cls##_##name##_Hook = { #cls, #name, AF_##cls##_##name, &cls##_##name##_VMPtr, reinterpret_cast<void*>(native) }; \
extern AFuncDesc const *const cls##_##name##_HookPtr; \
MSVC_ASEG AFuncDesc const *const cls##_##name##_HookPtr GCC_ASEG = &cls##_##name##_Hook; \
static int AF_##cls##_##name(VM_ARGS)
//#define DEFINE_ACTION_FUNCTION(cls, name) DEFINE_ACTION_FUNCTION_NATIVE(cls, name, nullptr)
#define DEFINE_ACTION_FUNCTION(cls, name) \
static int AF_##cls##_##name(VM_ARGS); \
VMNativeFunction *cls##_##name##_VMPtr; \
static const AFuncDesc cls##_##name##_Hook = { #cls, #name, AF_##cls##_##name, &cls##_##name##_VMPtr }; \
static const AFuncDesc cls##_##name##_Hook = { #cls, #name, AF_##cls##_##name, &cls##_##name##_VMPtr, nullptr }; \
extern AFuncDesc const *const cls##_##name##_HookPtr; \
MSVC_ASEG AFuncDesc const *const cls##_##name##_HookPtr GCC_ASEG = &cls##_##name##_Hook; \
static int AF_##cls##_##name(VM_ARGS)

View file

@ -80,6 +80,7 @@ void VMFunction::CreateRegUse()
return;
}
assert(Proto->isPrototype());
for (auto arg : Proto->ArgumentTypes)
{
count += arg? arg->GetRegCount() : 1;
@ -87,14 +88,20 @@ void VMFunction::CreateRegUse()
uint8_t *regp;
RegTypes = regp = (uint8_t*)ClassDataAllocator.Alloc(count);
count = 0;
for (auto arg : Proto->ArgumentTypes)
for (unsigned i = 0; i < Proto->ArgumentTypes.Size(); i++)
{
auto arg = Proto->ArgumentTypes[i];
auto flg = ArgFlags.Size() > i ? ArgFlags[i] : 0;
if (arg == nullptr)
{
// Marker for start of varargs.
*regp++ = REGT_NIL;
}
else for (int i = 0; i < arg->GetRegCount(); i++)
else if ((flg & VARF_Out) && !arg->isPointer())
{
*regp++ = REGT_POINTER;
}
else for (int j = 0; j < arg->GetRegCount(); j++)
{
*regp++ = arg->GetRegType();
}

1267
src/scripting/vmthunks.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -1586,17 +1586,13 @@ FSerializer &Serialize(FSerializer &arc, const char *key, DObject *&value, DObje
if (retcode) *retcode = true;
if (arc.isWriting())
{
if (value != nullptr)
if (value != nullptr && !(value->ObjectFlags & (OF_EuthanizeMe | OF_Transient)))
{
int ndx;
if (value == WP_NOCHANGE)
{
ndx = -1;
}
else if (value->ObjectFlags & (OF_EuthanizeMe | OF_Transient))
{
return arc;
}
else
{
int *pndx = arc.w->mObjectMap.CheckKey(value);

View file

@ -1423,6 +1423,24 @@ TXT_QUIETUS_PIECE = "SEGMENT OF QUIETUS";
TXT_WRAITHVERGE_PIECE = "SEGMENT OF WRAITHVERGE";
TXT_BLOODSCOURGE_PIECE = "SEGMENT OF BLOODSCOURGE";
// Friendly names
FN_FIREDEMON = "Afrit";
FN_DEMON1 = "Serpent";
FN_ETTIN = "Ettin";
FN_CENTAUR = "Centaur";
FN_SLAUGHTAUR = "Slaughtaur";
FN_BISHOP = "Bishop";
FN_ICEGUY = "Wendigo";
FN_SERPENT = "Stalker";
FN_WRAITH = "Reiver";
FN_DRAGON = "Death Wyvern";
FN_KORAX = "Korax";
FN_FBOSS = "Zedek";
FN_MBOSS = "Menelkir";
FN_CBOSS = "Traductus";
FN_HERESIARCH = "Heresiarch";
// Strife locks
TXT_NEEDKEY = "You don't have the key";

View file

@ -366,6 +366,7 @@ struct GameInfoStruct native
native double gibfactor;
native bool intermissioncounter;
native Name mSliderColor;
native Color defaultbloodcolor;
native double telefogheight;
native int defKickback;
}
@ -374,6 +375,15 @@ class Object native
{
native bool bDestroyed;
// These must be defined in some class, so that the compiler can find them. Object is just fine, as long as they are private to external code.
private native static int BuiltinRandom(voidptr rng, int min, int max);
private native static double BuiltinFRandom(voidptr rng, double min, double max);
private native static int BuiltinRandom2(voidptr rng, int mask);
private native static void BuiltinRandomSeed(voidptr rng, int seed);
private native static int BuiltinCallLineSpecial(int special, Actor activator, int arg1, int arg2, int arg3, int arg4, int arg5);
private native static Class<Object> BuiltinNameToClass(Name nm, Class<Object> filter);
private native static Object BuiltinClassCast(Object inptr, Class<Object> test);
// These really should be global functions...
native static String G_SkillName();
native static int G_SkillPropertyInt(int p);

View file

@ -24,6 +24,7 @@ class Bishop : Actor
DeathSound "BishopDeath";
ActiveSound "BishopActiveSounds";
Obituary"$OB_BISHOP";
Tag "$FN_BISHOP";
}
States

View file

@ -21,6 +21,7 @@ class Centaur : Actor
HowlSound "PuppyBeat";
Obituary "$OB_CENTAUR";
DamageFactor "Electric", 3;
Tag "$FN_CENTAUR";
}
States
{
@ -107,6 +108,7 @@ class CentaurLeader : Centaur
Speed 10;
Obituary "$OB_SLAUGHTAUR";
HitObituary "$OB_SLAUGHTAURHIT";
Tag "$FN_SLAUGHTAUR";
}
States
{

View file

@ -15,7 +15,8 @@ class ClericBoss : Actor
+DONTMORPH
PainSound "PlayerClericPain";
DeathSound "PlayerClericCrazyDeath";
Obituary "$OBCBOSS";
Obituary "$OB_CBOSS";
Tag "$FN_CBOSS";
}
States

View file

@ -20,6 +20,7 @@ class Demon1 : Actor
DeathSound "DemonDeath";
ActiveSound "DemonActive";
Obituary "$OB_DEMON1";
Tag "$FN_DEMON1";
}
const ChunkFlags = SXF_TRANSFERTRANSLATION | SXF_ABSOLUTEVELOCITY;

View file

@ -19,6 +19,7 @@ class Dragon : Actor
DeathSound "DragonDeath";
ActiveSound "DragonActive";
Obituary "$OB_DRAGON";
Tag "$FN_DRAGON";
}
States

View file

@ -22,6 +22,7 @@ class Ettin : Actor
ActiveSound "EttinActive";
HowlSound "PuppyBeat";
Obituary "$OB_ETTIN";
Tag "$FN_ETTIN";
}
States
{

View file

@ -17,6 +17,7 @@ class FighterBoss : Actor
PainSound "PlayerFighterPain";
DeathSound "PlayerFighterCrazyDeath";
Obituary "$OB_FBOSS";
Tag "$FN_FBOSS";
}
States

View file

@ -24,6 +24,7 @@ class FireDemon : Actor
DeathSound "FireDemonDeath";
ActiveSound "FireDemonActive";
Obituary "$OB_FIREDEMON";
Tag "$FN_FIREDEMON";
}
States

View file

@ -70,6 +70,7 @@ class Heresiarch : Actor
DeathSound "SorcererDeathScream";
ActiveSound "SorcererActive";
Obituary "$OB_HERESIARCH";
Tag "$FN_HERESIARCH";
}
States

View file

@ -65,6 +65,7 @@ class ZRock4 : Actor
{
Radius 20;
Height 16;
+SOLID
}
States
{

View file

@ -20,6 +20,7 @@ class IceGuy : Actor
AttackSound "IceGuyAttack";
ActiveSound "IceGuyActive";
Obituary "$OB_ICEGUY";
Tag "$FN_ICEGUY";
}

View file

@ -60,6 +60,7 @@ class Korax : Actor
DeathSound "KoraxDeath";
ActiveSound "KoraxActive";
Obituary "$OB_KORAX";
Tag "$FN_KORAX";
}
States

View file

@ -16,6 +16,7 @@ class MageBoss : Actor
PainSound "PlayerMagePain";
DeathSound "PlayerMageCrazyDeath";
Obituary "$OB_MBOSS";
Tag "$FN_MBOSS";
}
States

View file

@ -22,6 +22,7 @@ class Serpent : Actor
PainSound "SerpentPain";
DeathSound "SerpentDeath";
HitObituary "$OB_SERPENTHIT";
Tag "$FN_SERPENT";
}
States

View file

@ -21,6 +21,7 @@ class Wraith : Actor
ActiveSound "WraithActive";
HitObituary "$OB_WRAITHHIT";
Obituary "$OB_WRAITH";
Tag "$FN_WRAITH";
}
States