Merge remote-tracking branch 'gzdoom/master' into asmjit

This commit is contained in:
Magnus Norddahl 2018-09-02 03:46:06 +02:00
commit 55955b9c22
36 changed files with 1227 additions and 482 deletions

View file

@ -1154,6 +1154,7 @@ set (PCH_SOURCES
r_data/models/models_md2.cpp
r_data/models/models_voxel.cpp
r_data/models/models_ue1.cpp
r_data/models/models_obj.cpp
scripting/symbols.cpp
scripting/types.cpp
scripting/thingdef.cpp

View file

@ -38,6 +38,7 @@
#include "doomtype.h"
#include "configfile.h"
#include "files.h"
#include "m_random.h"
#define READBUFFERSIZE 256
@ -601,17 +602,16 @@ FConfigFile::FConfigEntry *FConfigFile::NewConfigEntry (
void FConfigFile::LoadConfigFile ()
{
FILE *file = fopen (PathName, "r");
FileReader file;
bool succ;
FileExisted = false;
if (file == NULL)
if (!file.OpenFile (PathName))
{
return;
}
succ = ReadConfig (file);
fclose (file);
succ = ReadConfig (&file);
FileExisted = succ;
}
@ -787,7 +787,7 @@ FConfigFile::FConfigEntry *FConfigFile::ReadMultiLineValue(void *file, FConfigSe
char *FConfigFile::ReadLine (char *string, int n, void *file) const
{
return fgets (string, n, (FILE *)file);
return ((FileReader *)file)->Gets (string, n);
}
//====================================================================
@ -805,7 +805,7 @@ bool FConfigFile::WriteConfigFile () const
return true;
}
FILE *file = fopen (PathName, "w");
FileWriter *file = FileWriter::Open (PathName);
FConfigSection *section;
FConfigEntry *entry;
@ -820,27 +820,27 @@ bool FConfigFile::WriteConfigFile () const
entry = section->RootEntry;
if (section->Note.IsNotEmpty())
{
fputs (section->Note.GetChars(), file);
file->Write (section->Note.GetChars(), section->Note.Len());
}
fprintf (file, "[%s]\n", section->SectionName.GetChars());
file->Printf ("[%s]\n", section->SectionName.GetChars());
while (entry != NULL)
{
if (strpbrk(entry->Value, "\r\n") == NULL)
{ // Single-line value
fprintf (file, "%s=%s\n", entry->Key, entry->Value);
file->Printf ("%s=%s\n", entry->Key, entry->Value);
}
else
{ // Multi-line value
const char *endtag = GenerateEndTag(entry->Value);
fprintf (file, "%s=<<<%s\n%s\n>>>%s\n", entry->Key,
file->Printf ("%s=<<<%s\n%s\n>>>%s\n", entry->Key,
endtag, entry->Value, endtag);
}
entry = entry->Next;
}
section = section->Next;
fputs ("\n", file);
file->Write ("\n", 1);
}
fclose (file);
delete file;
return true;
}
@ -890,7 +890,7 @@ const char *FConfigFile::GenerateEndTag(const char *value)
//
//====================================================================
void FConfigFile::WriteCommentHeader (FILE *file) const
void FConfigFile::WriteCommentHeader (FileWriter *file) const
{
}

View file

@ -35,6 +35,7 @@
#define __CONFIGFILE_H__
#include <stdio.h>
#include "files.h"
#include "zstring.h"
class FConfigFile
@ -73,7 +74,7 @@ public:
bool WriteConfigFile () const;
protected:
virtual void WriteCommentHeader (FILE *file) const;
virtual void WriteCommentHeader (FileWriter *file) const;
virtual char *ReadLine (char *string, int n, void *file) const;
bool ReadConfig (void *file);

View file

@ -468,7 +468,7 @@ public:
TObjPtr<AActor*> MUSINFOactor = nullptr; // For MUSINFO purposes
int8_t MUSINFOtics = 0;
bool settings_controller = false; // Player can control game settings.
bool settings_controller = true; // Player can control game settings.
int8_t crouching = 0;
int8_t crouchdir = 0;

View file

@ -167,22 +167,19 @@ class TObjPtr
DObject *o;
};
public:
TObjPtr() throw()
{
}
TObjPtr() = default;
TObjPtr(const TObjPtr<T> &q) = default;
TObjPtr(T q) throw()
: pp(q)
{
}
TObjPtr(const TObjPtr<T> &q) throw()
: pp(q.pp)
T operator=(T q)
{
pp = q;
return *this;
}
T operator=(T q) throw()
{
return pp = q;
// The caller must now perform a write barrier.
}
operator T() throw()
{
return GC::ReadBarrier(pp);

View file

@ -103,7 +103,7 @@ enum
struct PalEntry
{
PalEntry () {}
PalEntry() = default;
PalEntry (uint32_t argb) { d = argb; }
operator uint32_t () const { return d; }
void SetRGB(PalEntry other)
@ -146,6 +146,7 @@ struct PalEntry
{
return (d & 0xffffff) == 0xffffff;
}
PalEntry &operator= (const PalEntry &other) = default;
PalEntry &operator= (uint32_t other) { d = other; return *this; }
PalEntry InverseColor() const { PalEntry nc; nc.a = a; nc.r = 255 - r; nc.g = 255 - g; nc.b = 255 - b; return nc; }
#ifdef __BIG_ENDIAN__
@ -205,7 +206,7 @@ class FTextureID
friend void R_InitSpriteDefs();
public:
FTextureID() throw() {}
FTextureID() = default;
bool isNull() const { return texnum == 0; }
bool isValid() const { return texnum > 0; }
bool Exists() const { return texnum >= 0; }

View file

@ -167,9 +167,9 @@ FGameConfigFile::~FGameConfigFile ()
{
}
void FGameConfigFile::WriteCommentHeader (FILE *file) const
void FGameConfigFile::WriteCommentHeader (FileWriter *file) const
{
fprintf (file, "# This file was generated by " GAMENAME " %s on %s\n", GetVersionString(), myasctime());
file->Printf ("# This file was generated by " GAMENAME " %s on %s\n", GetVersionString(), myasctime());
}
void FGameConfigFile::DoAutoloadSetup (FIWadManager *iwad_man)

View file

@ -58,7 +58,7 @@ public:
void ReadNetVars ();
protected:
void WriteCommentHeader (FILE *file) const;
void WriteCommentHeader (FileWriter *file) const;
void CreateStandardAutoExec (const char *section, bool start);
private:

View file

@ -399,7 +399,6 @@ void GLHorizonPortal::DrawContents(HWDrawInfo *hwdi)
Clocker c(PortalAll);
FMaterial * gltexture;
PalEntry color;
player_t * player=&players[consoleplayer];
GLSectorPlane * sp = &origin->plane;
auto &vp = di->Viewpoint;

View file

@ -228,7 +228,6 @@ int LevelAABBTree::GenerateTreeNode(int *lines, int num_lines, const FVector2 *c
// Try sort at longest axis, then if that fails then the other one.
// We place the sorted lines into work_buffer and then move the result back to the lines list when done.
int left_count, right_count;
FVector2 axis;
for (int attempt = 0; attempt < 2; attempt++)
{
// Find the sort plane for axis

View file

@ -319,7 +319,6 @@ void FMaterial::SetSpriteRect()
bool FMaterial::TrimBorders(uint16_t *rect)
{
PalEntry col;
int w;
int h;

View file

@ -46,7 +46,7 @@ class FString;
class FName
{
public:
FName() = default;// : Index(0) {}
FName() = default;
FName (const char *text) { Index = NameData.FindName (text, false); }
FName (const char *text, bool noCreate) { Index = NameData.FindName (text, noCreate); }
FName (const char *text, size_t textlen, bool noCreate) { Index = NameData.FindName (text, textlen, noCreate); }
@ -63,7 +63,7 @@ public:
FName &operator = (const char *text) { Index = NameData.FindName (text, false); return *this; }
FName &operator = (const FString &text);
FName &operator = (const FName &other) { Index = other.Index; return *this; }
FName &operator = (const FName &other) = default;
FName &operator = (ENamedName index) { Index = index; return *this; }
int SetName (const char *text, bool noCreate=false) { return Index = NameData.FindName (text, noCreate); }

View file

@ -2345,7 +2345,6 @@ double P_XYMovement (AActor *mo, DVector2 scroll)
{
static int pushtime = 0;
bool bForceSlide = !scroll.isZero();
DAngle Angle;
DVector2 ptry;
player_t *player;
DVector2 move;

View file

@ -306,7 +306,7 @@ static void P_SetSlopesFromVertexHeights(FMapThing *firstmt, FMapThing *lastmt,
{
if (sec.Lines.Size() != 3) continue; // only works with triangular sectors
DVector3 vt1, vt2, vt3, cross;
DVector3 vt1, vt2, vt3;
DVector3 vec1, vec2;
int vi1, vi2, vi3;

View file

@ -153,13 +153,13 @@ static struct SteamAppInfo
const int AppID;
} AppInfo[] =
{
/*{"doom 2/base", 2300},
{"final doom/base", 2290},
{"heretic shadow of the serpent riders/base", 2390},
{"hexen/base", 2360},
{"hexen deathkings of the dark citadel/base", 2370},
{"ultimate doom/base", 2280},
{"DOOM 3 BFG Edition/base/wads", 208200},*/
{"Doom 2/base", 2300},
{"Final Doom/base", 2290},
{"Heretic Shadow of the Serpent Riders/base", 2390},
{"Hexen/base", 2360},
{"Hexen Deathkings of the Dark Citadel/base", 2370},
{"Ultimate Doom/base", 2280},
{"DOOM 3 BFG Edition/base/wads", 208200},
{"Strife", 317040}
};
@ -190,7 +190,13 @@ TArray<FString> I_GetSteamPath()
if(home != NULL && *home != '\0')
{
FString regPath;
regPath.Format("%s/.steam/config/config.vdf", home);
// [BL] The config seems to have moved from the more modern .local to
// .steam at some point. Not sure if it's just my setup so I guess we
// can fall back on it?
if(!FileExists(regPath))
regPath.Format("%s/.local/share/Steam/config/config.vdf", home);
try
{
SteamInstallFolders = ParseSteamRegistry(regPath);

View file

@ -40,6 +40,7 @@
#include "r_utility.h"
#include "r_data/models/models.h"
#include "r_data/models/models_ue1.h"
#include "r_data/models/models_obj.h"
#include "i_time.h"
#ifdef _MSC_VER
@ -419,7 +420,7 @@ static unsigned FindModel(const char * path, const char * modelfile)
FMemLump lumpd = Wads.ReadLump(lump);
char * buffer = (char*)lumpd.GetMem();
if ( (size_t)fullname.IndexOf("_d.3d") == fullname.Len()-5 )
if ( (size_t)fullname.LastIndexOf("_d.3d") == fullname.Len()-5 )
{
FString anivfile = fullname.GetChars();
anivfile.Substitute("_d.3d","_a.3d");
@ -428,7 +429,7 @@ static unsigned FindModel(const char * path, const char * modelfile)
model = new FUE1Model;
}
}
else if ( (size_t)fullname.IndexOf("_a.3d") == fullname.Len()-5 )
else if ( (size_t)fullname.LastIndexOf("_a.3d") == fullname.Len()-5 )
{
FString datafile = fullname.GetChars();
datafile.Substitute("_a.3d","_d.3d");
@ -437,6 +438,10 @@ static unsigned FindModel(const char * path, const char * modelfile)
model = new FUE1Model;
}
}
else if ( (size_t)fullname.LastIndexOf(".obj") == fullname.Len() - 4 )
{
model = new FOBJModel;
}
else if (!memcmp(buffer, "DMDM", 4))
{
model = new FDMDModel;

View file

@ -0,0 +1,588 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2018 Kevin Caccamo
// All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//--------------------------------------------------------------------------
#include "w_wad.h"
#include "r_data/models/models_obj.h"
/**
* Load an OBJ model
*
* @param fn The path to the model file
* @param lumpnum The lump index in the wad collection
* @param buffer The contents of the model file
* @param length The size of the model file
* @return Whether or not the model was parsed successfully
*/
bool FOBJModel::Load(const char* fn, int lumpnum, const char* buffer, int length)
{
FString objName = Wads.GetLumpFullPath(lumpnum);
FString objBuf(buffer, length);
// Do some replacements before we parse the OBJ string
{
// Ensure usemtl statements remain intact
TArray<FString> mtlUsages;
TArray<long> mtlUsageIdxs;
long bpos = 0, nlpos = 0, slashpos = 0;
while (1)
{
bpos = objBuf.IndexOf("\nusemtl", bpos);
if (bpos == -1) break;
slashpos = objBuf.IndexOf('/', bpos);
nlpos = objBuf.IndexOf('\n', ++bpos);
if (slashpos > nlpos || slashpos == -1)
{
continue;
}
if (nlpos == -1)
{
nlpos = objBuf.Len();
}
FString lineStr(objBuf.GetChars() + bpos, nlpos - bpos);
mtlUsages.Push(lineStr);
mtlUsageIdxs.Push(bpos);
}
// Replace forward slashes with percent signs so they aren't parsed as line comments
objBuf.ReplaceChars('/', *newSideSep);
char* wObjBuf = objBuf.LockBuffer();
// Substitute broken usemtl statements with old ones
for (size_t i = 0; i < mtlUsages.Size(); i++)
{
bpos = mtlUsageIdxs[i];
nlpos = objBuf.IndexOf('\n', bpos);
if (nlpos == -1)
{
nlpos = objBuf.Len();
}
memcpy(wObjBuf + bpos, mtlUsages[i].GetChars(), nlpos - bpos);
}
bpos = 0;
// Find each OBJ line comment, and convert each to a C-style line comment
while (1)
{
bpos = objBuf.IndexOf('#', bpos);
if (bpos == -1) break;
if (objBuf[(unsigned int)bpos + 1] == '\n')
{
wObjBuf[bpos] = ' ';
}
else
{
wObjBuf[bpos] = '/';
wObjBuf[bpos+1] = '/';
}
bpos += 1;
}
wObjBuf = nullptr;
objBuf.UnlockBuffer();
}
sc.OpenString(objName, objBuf);
FTextureID curMtl = FNullTextureID();
OBJSurface *curSurface = nullptr;
int aggSurfFaceCount = 0;
int curSurfFaceCount = 0;
while(sc.GetString())
{
if (sc.Compare("v")) // Vertex
{
ParseVector<FVector3, 3>(this->verts);
}
else if (sc.Compare("vn")) // Vertex normal
{
ParseVector<FVector3, 3>(this->norms);
}
else if (sc.Compare("vt")) // UV Coordinates
{
ParseVector<FVector2, 2>(this->uvs);
}
else if (sc.Compare("usemtl"))
{
// Get material name and try to load it
sc.MustGetString();
curMtl = LoadSkin("", sc.String);
if (!curMtl.isValid())
{
// Relative to model file path?
curMtl = LoadSkin(fn, sc.String);
}
if (!curMtl.isValid())
{
sc.ScriptMessage("Material %s (#%u) not found.", sc.String, surfaces.Size());
}
// Build surface...
if (curSurface == nullptr)
{
// First surface
curSurface = new OBJSurface(curMtl);
}
else
{
if (curSurfFaceCount > 0)
{
// Add previous surface
curSurface->numFaces = curSurfFaceCount;
curSurface->faceStart = aggSurfFaceCount;
surfaces.Push(*curSurface);
delete curSurface;
// Go to next surface
curSurface = new OBJSurface(curMtl);
aggSurfFaceCount += curSurfFaceCount;
}
else
{
curSurface->skin = curMtl;
}
}
curSurfFaceCount = 0;
}
else if (sc.Compare("f"))
{
FString sides[4];
OBJFace face;
for (int i = 0; i < 3; i++)
{
// A face must have at least 3 sides
sc.MustGetString();
sides[i] = sc.String;
if (!ParseFaceSide(sides[i], face, i)) return false;
}
face.sideCount = 3;
if (sc.GetString())
{
if (!sc.Compare("f") && FString(sc.String).IndexOfAny("-0123456789") == 0)
{
sides[3] = sc.String;
face.sideCount += 1;
if (!ParseFaceSide(sides[3], face, 3)) return false;
}
else
{
sc.UnGet(); // No 4th side, move back
}
}
faces.Push(face);
curSurfFaceCount += 1;
}
}
sc.Close();
if (curSurface == nullptr)
{ // No valid materials detected
FTextureID dummyMtl = LoadSkin("", "-NOFLAT-"); // Built-in to GZDoom
curSurface = new OBJSurface(dummyMtl);
}
curSurface->numFaces = curSurfFaceCount;
curSurface->faceStart = aggSurfFaceCount;
surfaces.Push(*curSurface);
delete curSurface;
if (uvs.Size() == 0)
{ // Needed so that OBJs without UVs can work
uvs.Push(FVector2(0.0, 0.0));
}
return true;
}
/**
* Parse an x-Dimensional vector
*
* @tparam T A subclass of TVector2 to be used
* @tparam L The length of the vector to parse
* @param[out] array The array to append the parsed vector to
*/
template<typename T, size_t L> void FOBJModel::ParseVector(TArray<T> &array)
{
float *coord = new float[L];
for (size_t axis = 0; axis < L; axis++)
{
sc.MustGetFloat();
coord[axis] = (float)sc.Float;
}
T vec(coord);
array.Push(vec);
delete[] coord;
}
/**
* Parse a side of a face
*
* @param[in] sideStr The side definition string
* @param[out] face The face to assign the parsed side data to
* @param sidx The 0-based index of the side
* @return Whether or not the face side was parsed successfully
*/
bool FOBJModel::ParseFaceSide(const FString &sideStr, OBJFace &face, int sidx)
{
OBJFaceSide side;
int origIdx;
if (sideStr.IndexOf(newSideSep) >= 0)
{
TArray<FString> sides = sideStr.Split(newSideSep, FString::TOK_KEEPEMPTY);
if (sides[0].Len() > 0)
{
origIdx = atoi(sides[0].GetChars());
side.vertref = ResolveIndex(origIdx, FaceElement::VertexIndex);
}
else
{
sc.ScriptError("Vertex reference is not optional!");
return false;
}
if (sides[1].Len() > 0)
{
origIdx = atoi(sides[1].GetChars());
side.uvref = ResolveIndex(origIdx, FaceElement::UVIndex);
}
else
{
side.uvref = -1;
}
if (sides.Size() > 2)
{
if (sides[2].Len() > 0)
{
origIdx = atoi(sides[2].GetChars());
side.normref = ResolveIndex(origIdx, FaceElement::VNormalIndex);
}
else
{
side.normref = -1;
}
}
else
{
side.normref = -1;
}
}
else
{
origIdx = atoi(sideStr.GetChars());
side.vertref = ResolveIndex(origIdx, FaceElement::VertexIndex);
side.normref = -1;
side.uvref = -1;
}
face.sides[sidx] = side;
return true;
}
/**
* Resolve an OBJ index to an absolute index
*
* OBJ indices are 1-based, and can also be negative
*
* @param origIndex The original OBJ index to resolve
* @param el What type of element the index references
* @return The absolute index of the element
*/
int FOBJModel::ResolveIndex(int origIndex, FaceElement el)
{
if (origIndex > 0)
{
return origIndex - 1; // OBJ indices start at 1
}
else if (origIndex < 0)
{
if (el == FaceElement::VertexIndex)
{
return verts.Size() + origIndex; // origIndex is negative
}
else if (el == FaceElement::UVIndex)
{
return uvs.Size() + origIndex;
}
else if (el == FaceElement::VNormalIndex)
{
return norms.Size() + origIndex;
}
}
return -1;
}
/**
* Construct the vertex buffer for this model
*
* @param renderer A pointer to the model renderer. Used to allocate the vertex buffer.
*/
void FOBJModel::BuildVertexBuffer(FModelRenderer *renderer)
{
if (GetVertexBuffer(renderer))
{
return;
}
unsigned int vbufsize = 0;
for (size_t i = 0; i < surfaces.Size(); i++)
{
ConstructSurfaceTris(surfaces[i]);
surfaces[i].vbStart = vbufsize;
vbufsize += surfaces[i].numTris * 3;
}
auto vbuf = renderer->CreateVertexBuffer(false,true);
SetVertexBuffer(renderer, vbuf);
FModelVertex *vertptr = vbuf->LockVertexBuffer(vbufsize);
for (size_t i = 0; i < surfaces.Size(); i++)
{
for (size_t j = 0; j < surfaces[i].numTris; j++)
{
for (size_t side = 0; side < 3; side++)
{
FModelVertex *mdv = vertptr +
side + j * 3 + // Current surface and previous triangles
surfaces[i].vbStart; // Previous surfaces
OBJFaceSide &curSide = surfaces[i].tris[j].sides[side];
int vidx = curSide.vertref;
int uvidx = (curSide.uvref >= 0 && (unsigned int)curSide.uvref < uvs.Size()) ? curSide.uvref : 0;
int nidx = curSide.normref;
FVector3 curVvec = RealignVector(verts[vidx]);
FVector2 curUvec = FixUV(uvs[uvidx]);
FVector3 *nvec = nullptr;
mdv->Set(curVvec.X, curVvec.Y, curVvec.Z, curUvec.X, curUvec.Y);
if (nidx >= 0 && (unsigned int)nidx < norms.Size())
{
nvec = new FVector3(RealignVector(norms[nidx]));
}
else
{
// https://www.khronos.org/opengl/wiki/Calculating_a_Surface_Normal
// Find other sides of triangle
int nextSidx = side + 2;
if (nextSidx >= 3) nextSidx -= 3;
int lastSidx = side + 1;
if (lastSidx >= 3) lastSidx -= 3;
OBJFaceSide &nextSide = surfaces[i].tris[j].sides[nextSidx];
OBJFaceSide &lastSide = surfaces[i].tris[j].sides[lastSidx];
// Cross-multiply the U-vector and V-vector
FVector3 uvec = RealignVector(verts[nextSide.vertref]) - curVvec;
FVector3 vvec = RealignVector(verts[lastSide.vertref]) - curVvec;
nvec = new FVector3(uvec ^ vvec);
}
mdv->SetNormal(nvec->X, nvec->Y, nvec->Z);
delete nvec;
}
}
delete[] surfaces[i].tris;
}
vbuf->UnlockVertexBuffer();
}
/**
* Fill in the triangle data for a surface
*
* @param[in,out] surf The surface to fill in the triangle data for
*/
void FOBJModel::ConstructSurfaceTris(OBJSurface &surf)
{
unsigned int triCount = 0;
size_t start = surf.faceStart;
size_t end = start + surf.numFaces;
for (size_t i = start; i < end; i++)
{
triCount += faces[i].sideCount - 2;
}
surf.numTris = triCount;
surf.tris = new OBJFace[triCount];
for (size_t i = start, triIdx = 0; i < end; i++, triIdx++)
{
surf.tris[triIdx].sideCount = 3;
if (faces[i].sideCount == 3)
{
memcpy(surf.tris[triIdx].sides, faces[i].sides, sizeof(OBJFaceSide) * 3);
}
else if (faces[i].sideCount == 4) // Triangulate face
{
OBJFace *triangulated = new OBJFace[2];
TriangulateQuad(faces[i], triangulated);
memcpy(surf.tris[triIdx].sides, triangulated[0].sides, sizeof(OBJFaceSide) * 3);
memcpy(surf.tris[triIdx+1].sides, triangulated[1].sides, sizeof(OBJFaceSide) * 3);
delete[] triangulated;
triIdx += 1; // Filling out two faces
}
}
}
/**
* Triangulate a 4-sided face
*
* @param[in] quad The 4-sided face to triangulate
* @param[out] tris The resultant triangle data
*/
void FOBJModel::TriangulateQuad(const OBJFace &quad, OBJFace *tris)
{
tris[0].sideCount = 3;
tris[1].sideCount = 3;
int tsidx[2][3] = {{0, 1, 3}, {1, 2, 3}};
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 2; j++)
{
tris[j].sides[i].vertref = quad.sides[tsidx[j][i]].vertref;
tris[j].sides[i].uvref = quad.sides[tsidx[j][i]].uvref;
tris[j].sides[i].normref = quad.sides[tsidx[j][i]].normref;
}
}
}
/**
* Re-align a vector to match MD3 alignment
*
* @param vecToRealign The vector to re-align
* @return The re-aligned vector
*/
inline FVector3 FOBJModel::RealignVector(FVector3 vecToRealign)
{
vecToRealign.Z *= -1;
return vecToRealign;
}
/**
* Fix UV coordinates of a UV vector
*
* @param vecToRealign The vector to fix
* @return The fixed UV coordinate vector
*/
inline FVector2 FOBJModel::FixUV(FVector2 vecToRealign)
{
vecToRealign.Y *= -1;
return vecToRealign;
}
/**
* Find the index of the frame with the given name
*
* OBJ models are not animated, so this always returns 0
*
* @param name The name of the frame
* @return The index of the frame
*/
int FOBJModel::FindFrame(const char* name)
{
return 0; // OBJs are not animated.
}
/**
* Render the model
*
* @param renderer The model renderer
* @param skin The loaded skin for the surface
* @param frameno Unused
* @param frameno2 Unused
* @param inter Unused
* @param translation The translation for the skin
*/
void FOBJModel::RenderFrame(FModelRenderer *renderer, FTexture * skin, int frameno, int frameno2, double inter, int translation)
{
for (unsigned int i = 0; i < surfaces.Size(); i++)
{
OBJSurface *surf = &surfaces[i];
FTexture *userSkin = skin;
if (!userSkin)
{
if (i < MD3_MAX_SURFACES && curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].isValid())
{
userSkin = TexMan(curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i]);
}
else if (surf->skin.isValid())
{
userSkin = TexMan(surf->skin);
}
}
// Still no skin after checking for one?
if (!userSkin)
{
continue;
}
renderer->SetMaterial(userSkin, false, translation);
GetVertexBuffer(renderer)->SetupFrame(renderer, surf->vbStart, surf->vbStart, surf->numTris * 3);
renderer->DrawArrays(0, surf->numTris * 3);
}
}
/**
* Pre-cache skins for the model
*
* @param hitlist The list of textures
*/
void FOBJModel::AddSkins(uint8_t* hitlist)
{
for (size_t i = 0; i < surfaces.Size(); i++)
{
if (i < MD3_MAX_SURFACES && curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].isValid())
{
// Precache skins manually reassigned by the user.
// On OBJs with lots of skins, such as Doom map OBJs exported from GZDB,
// there may be too many skins for the user to manually change, unless
// the limit is bumped or surfaceskinIDs is changed to a TArray<FTextureID>.
hitlist[curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].GetIndex()] |= FTextureManager::HIT_Flat;
return; // No need to precache skin that was replaced
}
OBJSurface * surf = &surfaces[i];
if (surf->skin.isValid())
{
hitlist[surf->skin.GetIndex()] |= FTextureManager::HIT_Flat;
}
}
}
/**
* Remove the data that was loaded
*/
FOBJModel::~FOBJModel()
{
verts.Clear();
norms.Clear();
uvs.Clear();
faces.Clear();
surfaces.Clear();
}

View file

@ -0,0 +1,87 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2018 Kevin Caccamo
// All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//--------------------------------------------------------------------------
//
#ifndef __GL_MODELS_OBJ_H__
#define __GL_MODELS_OBJ_H__
#include "models.h"
#include "sc_man.h"
class FOBJModel : public FModel
{
private:
const char *newSideSep = "$"; // OBJ side separator is /, which is parsed as a line comment by FScanner if two of them are next to each other.
enum class FaceElement
{
VertexIndex,
UVIndex,
VNormalIndex
};
struct OBJFaceSide
{
int vertref;
int normref;
int uvref;
};
struct OBJFace
{
unsigned int sideCount;
OBJFaceSide sides[4];
};
struct OBJSurface // 1 surface per 'usemtl'
{
unsigned int numTris; // Number of triangulated faces
unsigned int numFaces; // Number of faces
unsigned int vbStart; // First index in vertex buffer
unsigned int faceStart; // Index of first face in faces array
OBJFace* tris; // Triangles
FTextureID skin;
OBJSurface(FTextureID skin): numTris(0), numFaces(0), vbStart(0), faceStart(0), tris(nullptr), skin(skin) {}
};
TArray<FVector3> verts;
TArray<FVector3> norms;
TArray<FVector2> uvs;
TArray<OBJFace> faces;
TArray<OBJSurface> surfaces;
FScanner sc;
template<typename T, size_t L> void ParseVector(TArray<T> &array);
bool ParseFaceSide(const FString &side, OBJFace &face, int sidx);
void ConstructSurfaceTris(OBJSurface &surf);
int ResolveIndex(int origIndex, FaceElement el);
void TriangulateQuad(const OBJFace &quad, OBJFace *tris);
FVector3 RealignVector(FVector3 vecToRealign);
FVector2 FixUV(FVector2 vecToRealign);
public:
FOBJModel() {}
~FOBJModel();
bool Load(const char* fn, int lumpnum, const char* buffer, int length) override;
int FindFrame(const char* name) override;
void RenderFrame(FModelRenderer* renderer, FTexture* skin, int frame, int frame2, double inter, int translation=0) override;
void BuildVertexBuffer(FModelRenderer* renderer) override;
void AddSkins(uint8_t* hitlist) override;
};
#endif

View file

@ -776,8 +776,8 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector,
{
DVector2 disp = level.Displacements.getOffset(pgroup, poly->CenterSubsector->sector->PortalGroup);
CalcPolyobjSoundOrg(listenpos + disp, poly, *pos);
pos->X += (float)disp.X;
pos->Z += (float)disp.Y;
pos->X -= (float)disp.X;
pos->Z -= (float)disp.Y;
}
break;
}

View file

@ -114,15 +114,8 @@ public:
{
ID = S_FindSound(name.GetChars());
}
FSoundID(const FSoundID &other)
{
ID = other.ID;
}
FSoundID &operator=(const FSoundID &other)
{
ID = other.ID;
return *this;
}
FSoundID(const FSoundID &other) = default;
FSoundID &operator=(const FSoundID &other) = default;
FSoundID &operator=(const char *name)
{
ID = S_FindSound(name);
@ -168,19 +161,7 @@ class FSoundIDNoInit : public FSoundID
{
public:
FSoundIDNoInit() : FSoundID(NoInit) {}
FSoundID &operator=(const FSoundID &other)
{
return FSoundID::operator=(other);
}
FSoundID &operator=(const char *name)
{
return FSoundID::operator=(name);
}
FSoundID &operator=(const FString &name)
{
return FSoundID::operator=(name);
}
using FSoundID::operator=;
};
extern FRolloffInfo S_Rolloff;

View file

@ -1266,6 +1266,14 @@ DEFINE_ACTION_FUNCTION(FStringStruct, IndexOf)
}
DEFINE_ACTION_FUNCTION(FStringStruct, LastIndexOf)
{
PARAM_SELF_STRUCT_PROLOGUE(FString);
PARAM_STRING(substr);
PARAM_INT_DEF(endIndex);
ACTION_RETURN_INT(self->LastIndexOfBroken(substr, endIndex));
}
DEFINE_ACTION_FUNCTION(FStringStruct, RightIndexOf)
{
PARAM_SELF_STRUCT_PROLOGUE(FString);
PARAM_STRING(substr);

View file

@ -57,12 +57,6 @@ public:
class cycle_t
{
public:
cycle_t &operator= (const cycle_t &o)
{
Sec = o.Sec;
return *this;
}
void Reset()
{
Sec = 0;
@ -153,12 +147,6 @@ inline uint64_t rdtsc()
class cycle_t
{
public:
cycle_t &operator= (const cycle_t &o)
{
Counter = o.Counter;
return *this;
}
void Reset()
{
Counter = 0;

View file

@ -961,8 +961,6 @@ PalEntry FTexture::averageColor(const uint32_t *data, int size, int maxout)
PalEntry FTexture::GetSkyCapColor(bool bottom)
{
PalEntry col;
if (!bSWSkyColorDone)
{
bSWSkyColorDone = true;

View file

@ -594,6 +594,46 @@ void F2DDrawer::AddLine(int x1, int y1, int x2, int y2, int palcolor, uint32_t c
//
//==========================================================================
void F2DDrawer::AddThickLine(int x1, int y1, int x2, int y2, double thickness, uint32_t color)
{
PalEntry p = (PalEntry)color;
DVector2 point0(x1, y1);
DVector2 point1(x2, y2);
DVector2 delta = point1 - point0;
DVector2 perp(-delta.Y, delta.X);
perp.MakeUnit();
perp *= thickness / 2;
DVector2 corner0 = point0 + perp;
DVector2 corner1 = point0 - perp;
DVector2 corner2 = point1 + perp;
DVector2 corner3 = point1 - perp;
RenderCommand dg;
dg.mType = DrawTypeTriangles;
dg.mVertCount = 4;
dg.mVertIndex = (int)mVertices.Reserve(4);
dg.mRenderStyle = LegacyRenderStyles[STYLE_Translucent];
auto ptr = &mVertices[dg.mVertIndex];
ptr->Set(corner0.X, corner0.Y, 0, 0, 0, p); ptr++;
ptr->Set(corner1.X, corner1.Y, 0, 0, 0, p); ptr++;
ptr->Set(corner2.X, corner2.Y, 0, 0, 0, p); ptr++;
ptr->Set(corner3.X, corner3.Y, 0, 0, 0, p); ptr++;
dg.mIndexIndex = mIndices.Size();
dg.mIndexCount += 6;
AddIndices(dg.mVertIndex, 6, 0, 1, 2, 1, 3, 2);
AddCommand(&dg);
}
//==========================================================================
//
//
//
//==========================================================================
void F2DDrawer::AddPixel(int x1, int y1, int palcolor, uint32_t color)
{
PalEntry p = color ? (PalEntry)color : GPalette.BaseColors[palcolor];

View file

@ -149,6 +149,7 @@ public:
void AddLine(int x1, int y1, int x2, int y2, int palcolor, uint32_t color);
void AddThickLine(int x1, int y1, int x2, int y2, double thickness, uint32_t color);
void AddPixel(int x1, int y1, int palcolor, uint32_t color);
void Clear();

View file

@ -1088,6 +1088,24 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawLine)
return 0;
}
void DFrameBuffer::DrawThickLine(int x0, int y0, int x1, int y1, double thickness, uint32_t realcolor) {
m2DDrawer.AddThickLine(x0, y0, x1, y1, thickness, realcolor);
}
DEFINE_ACTION_FUNCTION(_Screen, DrawThickLine)
{
PARAM_PROLOGUE;
PARAM_INT(x0);
PARAM_INT(y0);
PARAM_INT(x1);
PARAM_INT(y1);
PARAM_FLOAT(thickness);
PARAM_INT(color);
if (!screen->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function");
screen->DrawThickLine(x0, y0, x1, y1, thickness, color);
return 0;
}
//==========================================================================
//
// Draw a single pixel

View file

@ -1995,7 +1995,14 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
FixXMoves();
if (!noTranslate) LoadTranslations();
if (noTranslate)
{
ActiveColors = 0;
}
else
{
LoadTranslations();
}
delete[] charlumps;
}

View file

@ -498,6 +498,9 @@ public:
// Draws a line
void DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor);
// Draws a line with thickness
void DrawThickLine(int x0, int y0, int x1, int y1, double thickness, uint32_t realcolor);
// Draws a single pixel
void DrawPixel(int x, int y, int palcolor, uint32_t rgbcolor);

View file

@ -66,19 +66,14 @@ struct TVector2
{
vec_t X, Y;
TVector2 ()
{
}
TVector2() = default;
TVector2 (vec_t a, vec_t b)
: X(a), Y(b)
{
}
TVector2 (const TVector2 &other)
: X(other.X), Y(other.Y)
{
}
TVector2(const TVector2 &other) = default;
TVector2 (const TVector3<vec_t> &other) // Copy the X and Y from the 3D vector and discard the Z
: X(other.X), Y(other.Y)
@ -95,18 +90,7 @@ struct TVector2
return X == 0 && Y == 0;
}
TVector2 &operator= (const TVector2 &other)
{
// This might seem backwards, but this helps produce smaller code when a newly
// created vector is assigned, because the components can just be popped off
// the FPU stack in order without the need for fxch. For platforms with a
// more sensible registered-based FPU, of course, the order doesn't matter.
// (And, yes, I know fxch can improve performance in the right circumstances,
// but this isn't one of those times. Here, it's little more than a no-op that
// makes the exe 2 bytes larger whenever you assign one vector to another.)
Y = other.Y, X = other.X;
return *this;
}
TVector2 &operator= (const TVector2 &other) = default;
// Access X and Y as an array
vec_t &operator[] (int index)
@ -317,9 +301,7 @@ struct TVector3
vec_t X, Y, Z;
TVector3 ()
{
}
TVector3() = default;
TVector3 (vec_t a, vec_t b, vec_t c)
: X(a), Y(b), Z(c)
@ -331,10 +313,7 @@ struct TVector3
{
}
TVector3 (const TVector3 &other)
: X(other.X), Y(other.Y), Z(other.Z)
{
}
TVector3(const TVector3 &other) = default;
TVector3 (const Vector2 &xy, vec_t z)
: X(xy.X), Y(xy.Y), Z(z)
@ -353,11 +332,7 @@ struct TVector3
return X == 0 && Y == 0 && Z == 0;
}
TVector3 &operator= (const TVector3 &other)
{
Z = other.Z, Y = other.Y, X = other.X;
return *this;
}
TVector3 &operator= (const TVector3 &other) = default;
// Access X and Y and Z as an array
vec_t &operator[] (int index)
@ -546,13 +521,12 @@ struct TVector3
{
right = { 0.f, 0.f, 1.f };
}
if (major == 1 || (major == 2 && n[2] > 0.f))
else if (major == 1 || (major == 2 && n[2] > 0.f))
{
right = { 1.f, 0.f, 0.f };
}
if (major == 2 && n[2] < 0.0f)
// Unconditional to ease static analysis
else // major == 2 && n[2] <= 0.0f
{
right = { -1.f, 0.f, 0.f };
}
@ -662,9 +636,7 @@ struct TVector4
vec_t X, Y, Z, W;
TVector4()
{
}
TVector4() = default;
TVector4(vec_t a, vec_t b, vec_t c, vec_t d)
: X(a), Y(b), Z(c), W(d)
@ -676,10 +648,7 @@ struct TVector4
{
}
TVector4(const TVector4 &other)
: X(other.X), Y(other.Y), Z(other.Z), W(other.W)
{
}
TVector4(const TVector4 &other) = default;
TVector4(const Vector3 &xyz, vec_t w)
: X(xyz.X), Y(xyz.Y), Z(xyz.Z), W(w)
@ -696,11 +665,7 @@ struct TVector4
return X == 0 && Y == 0 && Z == 0 && W == 0;
}
TVector4 &operator= (const TVector4 &other)
{
W = other.W, Z = other.Z, Y = other.Y, X = other.X;
return *this;
}
TVector4 &operator= (const TVector4 &other) = default;
// Access X and Y and Z as an array
vec_t &operator[] (int index)
@ -939,16 +904,8 @@ struct TMatrix3x3
vec_t Cells[3][3];
TMatrix3x3()
{
}
TMatrix3x3(const TMatrix3x3 &other)
{
(*this)[0] = other[0];
(*this)[1] = other[1];
(*this)[2] = other[2];
}
TMatrix3x3() = default;
TMatrix3x3(const TMatrix3x3 &other) = default;
TMatrix3x3(const Vector3 &row1, const Vector3 &row2, const Vector3 &row3)
{
@ -1151,32 +1108,15 @@ struct TAngle
TAngle &operator= (long other) = delete;
TAngle &operator= (unsigned long other) = delete;
TAngle ()
{
}
TAngle() = default;
TAngle (vec_t amt)
: Degrees(amt)
{
}
/*
TAngle (int amt)
: Degrees(vec_t(amt))
{
}
*/
TAngle (const TAngle &other)
: Degrees(other.Degrees)
{
}
TAngle &operator= (const TAngle &other)
{
Degrees = other.Degrees;
return *this;
}
TAngle(const TAngle &other) = default;
TAngle &operator= (const TAngle &other) = default;
TAngle &operator= (double other)
{
@ -1491,25 +1431,15 @@ struct TRotator
Angle Roll; // rotation about the forward axis.
Angle CamRoll; // Roll specific to actor cameras. Used by quakes.
TRotator ()
{
}
TRotator() = default;
TRotator (const Angle &p, const Angle &y, const Angle &r)
: Pitch(p), Yaw(y), Roll(r)
{
}
TRotator (const TRotator &other)
: Pitch(other.Pitch), Yaw(other.Yaw), Roll(other.Roll)
{
}
TRotator &operator= (const TRotator &other)
{
Roll = other.Roll, Yaw = other.Yaw, Pitch = other.Pitch;
return *this;
}
TRotator(const TRotator &other) = default;
TRotator &operator= (const TRotator &other) = default;
// Access angles as an array
Angle &operator[] (int index)

View file

@ -55,9 +55,9 @@ const char *GetVersionString();
#define RC_FILEVERSION 3,5,9999,0
#define RC_PRODUCTVERSION 3,5,9999,0
#define RC_PRODUCTVERSION2 VERSIONSTR
// These are for content versioning. The current state is '3.5'.
// These are for content versioning.
#define VER_MAJOR 3
#define VER_MINOR 5
#define VER_MINOR 6
#define VER_REVISION 0
// Version identifier for network games.

View file

@ -507,31 +507,11 @@ long FString::IndexOfAny (const char *charset, long startIndex) const
return long(brk - Chars);
}
long FString::LastIndexOf (const FString &substr) const
{
return LastIndexOf (substr.Chars, long(Len()), substr.Len());
}
long FString::LastIndexOf (const char *substr) const
{
return LastIndexOf (substr, long(Len()), strlen(substr));
}
long FString::LastIndexOf (char subchar) const
{
return LastIndexOf (subchar, long(Len()));
}
long FString::LastIndexOf (const FString &substr, long endIndex) const
{
return LastIndexOf (substr.Chars, endIndex, substr.Len());
}
long FString::LastIndexOf (const char *substr, long endIndex) const
{
return LastIndexOf (substr, endIndex, strlen(substr));
}
long FString::LastIndexOf (char subchar, long endIndex) const
{
if ((size_t)endIndex > Len())
@ -548,8 +528,10 @@ long FString::LastIndexOf (char subchar, long endIndex) const
return -1;
}
long FString::LastIndexOf (const char *substr, long endIndex, size_t substrlen) const
long FString::LastIndexOfBroken (const FString &_substr, long endIndex) const
{
const char *substr = _substr.GetChars();
size_t substrlen = _substr.Len();
if ((size_t)endIndex > Len())
{
endIndex = long(Len());
@ -596,6 +578,43 @@ long FString::LastIndexOfAny (const char *charset, long endIndex) const
return -1;
}
long FString::LastIndexOf (const FString &substr) const
{
return LastIndexOf(substr.Chars, long(Len() - substr.Len()), substr.Len());
}
long FString::LastIndexOf (const FString &substr, long endIndex) const
{
return LastIndexOf(substr.Chars, endIndex, substr.Len());
}
long FString::LastIndexOf (const char *substr) const
{
return LastIndexOf(substr, long(Len() - strlen(substr)), strlen(substr));
}
long FString::LastIndexOf (const char *substr, long endIndex) const
{
return LastIndexOf(substr, endIndex, strlen(substr));
}
long FString::LastIndexOf (const char *substr, long endIndex, size_t substrlen) const
{
if ((size_t)endIndex + substrlen > Len())
{
endIndex = long(Len() - substrlen);
}
while (endIndex >= 0)
{
if (strncmp (substr, Chars + endIndex, substrlen) == 0)
{
return endIndex;
}
endIndex--;
}
return -1;
}
void FString::ToUpper ()
{
LockBuffer();
@ -1003,7 +1022,7 @@ void FString::Substitute (const char *oldstr, const char *newstr, size_t oldstrl
bool FString::IsInt () const
{
// String must match: [whitespace] [{+ | }] [0 [{ x | X }]] [digits] [whitespace]
// String must match: [whitespace] [{+ | <EFBFBD>}] [0 [{ x | X }]] [digits] [whitespace]
/* This state machine is based on a simplification of re2c's output for this input:
digits = [0-9];

View file

@ -201,19 +201,22 @@ public:
long IndexOfAny (const FString &charset, long startIndex=0) const;
long IndexOfAny (const char *charset, long startIndex=0) const;
long LastIndexOf (const FString &substr) const;
long LastIndexOf (const char *substr) const;
// This is only kept for backwards compatibility with old ZScript versions that used this function and depend on its bug.
long LastIndexOf (char subchar) const;
long LastIndexOf (const FString &substr, long endIndex) const;
long LastIndexOf (const char *substr, long endIndex) const;
long LastIndexOfBroken (const FString &substr, long endIndex) const;
long LastIndexOf (char subchar, long endIndex) const;
long LastIndexOf (const char *substr, long endIndex, size_t substrlen) const;
long LastIndexOfAny (const FString &charset) const;
long LastIndexOfAny (const char *charset) const;
long LastIndexOfAny (const FString &charset, long endIndex) const;
long LastIndexOfAny (const char *charset, long endIndex) const;
long LastIndexOf (const FString &substr) const;
long LastIndexOf (const FString &substr, long endIndex) const;
long LastIndexOf (const char *substr) const;
long LastIndexOf (const char *substr, long endIndex) const;
long LastIndexOf (const char *substr, long endIndex, size_t substrlen) const;
void ToUpper ();
void ToLower ();
void SwapCase ();
@ -463,4 +466,3 @@ template<> struct THashTraits<FString>
// Compares two keys, returning zero if they are the same.
int Compare(const FString &left, const FString &right) { return left.Compare(right); }
};

View file

@ -2820,6 +2820,8 @@ GLPREFMNU_DITHER = "Dither output";
GLPREFMNU_PALTONEMAPORDER = "Tonemap Palette Order";
GLPREFMNU_PALTONEMAPPOWER = "Tonemap Palette Exponent";
GLPREFMNU_SWLMBANDED = "Banded SW Lightmode";
GLPREFMNU_VRIPD = "Distance Between Your Eyes";
GLPREFMNU_VRSCREENDIST = "Distance From Your Screen";
// Option Values
OPTVAL_SMART = "Smart";

View file

@ -34,7 +34,7 @@ QUITMSG10 = "Tirez vous de là et retournez\nà vos programmes ennuyeux.";
QUITMSG11 = "Si j'étais votre patron, je vous\n collerai un Deathmatch dans la minute!";
QUITMSG12 = "Regardez l'ami. Vous partez maintenant\net vous pouvez oublier votre score!";
QUITMSG13 = "Allez, partez. Quand vous reviendrez\nje vous attendrai avec une batte.";
QUITMSG14 = "Vous êtes chanceux que je ne vous \ncolle pas une parce que vous pensez partir.";
QUITMSG14 = "Vous êtes chanceux que je ne vous en \ncolle pas une parce que vous pensez partir.";
// Quit Strife messages
QUITMSG15 = "Où allez vous?\nQue va devenir la rébellion?";
@ -206,7 +206,7 @@ HUSTR_23 = "NIVEAU 23: Une Tonne-eau de plaisir";
HUSTR_24 = "NIVEAU 24: Le Gouffre";
HUSTR_25 = "NIVEAU 25: Chutes de Sang";
HUSTR_26 = "NIVEAU 26: Les Mines Abandonnées";
HUSTR_27 = "NIVEAU 27: Monstrueuse Résiden,ce";
HUSTR_27 = "NIVEAU 27: Monstrueuse Résidence";
HUSTR_28 = "NIVEAU 28: Le Monde Spirituel";
HUSTR_29 = "NIVEAU 29: La Limite";
HUSTR_30 = "NIVEAU 30: L'Icône du Péché";
@ -257,7 +257,7 @@ PHUSTR_26 = "NIVEAU 26: Bunker";
PHUSTR_27 = "NIVEAU 27: Anti-Christ";
PHUSTR_28 = "NIVEAU 28: Les Egouts";
PHUSTR_29 = "NIVEAU 29: Odysée de Bruits";
PHUSTR_30 = "NIVEAU 30: La Porte des Enferts";
PHUSTR_30 = "NIVEAU 30: La Porte des Enfers";
PHUSTR_31 = "NIVEAU 31: Cyber-Antre";
PHUSTR_32 = "NIVEAU 32: GO 2 IT";
@ -348,7 +348,7 @@ TXT_DEFAULTPICKUPMSG = "Quelque chose récupéré.";
// F_Finale.C
//
E1TEXT =
"APRES AVOIR VAINCU LES GROS MECHANTS\n"
"APRES AVOIR VAINCU CES SALES PESTES\n"
"ET NETTOYE LA BASE LUNAIRE, VOUS AVEZ\n"
"GAGNE, NON? PAS VRAI? OU EST DONC VOTRE\n"
"RECOMPENSE ET VOTRE BILLET DE\n"
@ -381,7 +381,7 @@ E2TEXT =
"LA SURFACE DE L'ENFER.\n"
"\n"
"VOICI MAINTENANT LE CHAPITRE FINAL DE\n"
"DOOM! -- L'ENFER.";
"DOOM! -- INFERNO.";
E3TEXT =
"LE DEMON ARACHNEEN ET REPUGNANT\n"
@ -399,28 +399,28 @@ E3TEXT =
"VOUS VOUS DEMANDEZ CE QUI S'EST PASSE\n"
"SUR TERRE PENDANT QUE VOUS AVEZ\n"
"COMBATTU LE DEMON. HEUREUSEMENT,\n"
"AUCUN GERME DU MAL N'A FRANCHI\n"
"QU'AUCUN GERME DU MAL N'A FRANCHI\n"
"CETTE PORTE AVEC VOUS...";
E4TEXT =
"l'araignee cerveau doit avoir envoye\n"
"ses legions de creatures de l' enfer \n"
"l'araignee cerveau doit avoir envoyé\n"
"ses légions de créatures de l'enfer \n"
"avant votre confrontation finale avec\n"
"cette terrible bete de l'enfer.\n"
"cette terrible bête infernale.\n"
"Mais vous avancez et mettez de suite\n"
"la damnation eternelle et souffrances\n"
"a la meute comme un hero le fairait\n"
"face de quelque chose de si malefique.\n"
"a la meute comme un héros le fairait\n"
"face à quelque chose de si maléfique.\n"
"D'ailleurs, quelqu'un va devoir payer \n"
"pour ce qui est arrive a margherite, \n"
"pour ce qui est arrivé a Daisy, \n"
"votre lapin domestique.\n"
"\n"
"mais maintenant, vous voyez devant vous \n"
"encore plus de nouvelles souffrances \n"
"potencielles et de chairs broyees\n"
"comme une horde de demons devunus \n"
"vindicatifs parmi nos villes.\n\n"
"prochain arret,l'enfer sur terre!";
"potentielles et de chairs broyees\n"
"comme une horde de demons déversant \n"
"la mort parmi nos villes.\n\n"
"prochain arrêt, l'enfer sur terre!";
// after level 6, put this:
@ -479,7 +479,7 @@ C4TEXT =
"TAILLE INCROYABLE S'EFFONDRE DEVANT\n"
"VOUS LORSQUE VOUS TIREZ UNE SALVE DE\n"
"ROQUETTES DANS SON CERVEAU. LE MONSTRE\n"
"SE RATATINE, SES MEMBRES DECHIQUETES\n"
"S'ECRASE, SES MEMBRES DECHIQUETES\n"
"SE REPANDANT SUR DES CENTAINES DE\n"
"KILOMETRES A LA SURFACE DE L'ENFER.\n"
"\n"
@ -508,151 +508,170 @@ C6TEXT =
"MIEUX DE FONCER DANS CELUI-LA!\n";
P1TEXT =
"Vous jubilez sur la carcass brulante \n"
"du Guardien. Avec sa mort, vous avez \n"
"arrache l'accelerateur des griffes \n"
"fetides de l'enfer. Vous vous reposez \n"
"et regardez aux alentours de l'endroit. \n"
"Mince! Il etait suppose qu'il y ait\n"
"au mois un prototype fonctionnant, \n"
"mais vous ne le voyez pas. les demons \n"
"l'on surement pris. \n\n"
"Vous jubilez sur la carcasse brûlante \n"
"du Gardien. Avec sa mort, vous avez \n"
"arraché l'accélerateur des griffes \n"
"fétides de l'enfer. Vous vous reposez \n"
"et regardez aux alentours du lieu. \n"
"Mince! Il était supposé qu'il y ait\n"
"au mois un prototype en fonctionnement, \n"
"mais vous ne le trouvez pas. les démons \n"
"l'on sûrement pris avec eux. \n\n"
"Vous devez trouver le prototype, ou \n"
"tous vos combats auront ete vains. \n"
"continez a avancer, vous battre, tuer. \n"
"Oh oui ,a vivre ,aussi.";
"tous vos combats auront été vains. \n"
"continez à avancer, à vous battre, à tuer. \n"
"Oh oui, à vivre, aussi.";
P2TEXT =
"Meme le labyrinthe mortifere des \n"
"archi-infames ne vous arreta pas,\n"
"et vous arrivez au prototype \n"
"d'accelerateur qui est proche \n"
"desactive efficacement et pour toujours.\n"
"Même le labyrinthe mortifère des \n"
"arche-viles ne vous a pas arrêté,\n"
"et vous obtenez le prototype \n"
"d'accelerateur et parvenez à le \n"
"désactiver efficacement et pour toujours.\n"
"\n"
"Vous etes doue pour ces choses la.";
"Vous êtes doué pour ces choses là.";
P3TEXT =
"Vous vous etes fraye votre chemin a \n"
"Vous vous êtes frayé votre chemin à \n"
"travers le coeur d'une ruche de \n"
"diables. Il est temps pour une mission\n"
"de recherche et destruction visant le \n"
"guardien de la porte ,avec sa \n"
"progeniture repugnante descendant en \n"
"gardien de la porte, avec sa \n"
"progéniture répugnante descendant en \n"
"cascade sur terre. Oui ,il est cruel. \n"
"Mais vous savez qui est pire!\n\n"
"Sourriant malefiquement, vous verifiez \n"
"l'equipement et vous vous preparez a\n"
"Souriant malicieusement, vous vérifiez \n"
"l'equipement et vous vous préparez a\n"
"faire voir a ce fumier un petit enfer\n"
"fait de votre propre main!";
"fait de vos propres mains!";
P4TEXT =
"La face malefique du gardien de la porte \n"
"est eparpillee aux alentours. Comme son \n"
"La face maléfique du gardien de la porte \n"
"est éparpillee aux alentours. Comme son \n"
"corps en lambeaux vacille, un portail \n"
"inverse se forme et aspire les eclat du \n"
"dernier prototype d'accelerateur, sans \n"
"inverse se forme et aspire les éclats du \n"
"dernier prototype d'accélerateur, sans \n"
"parler des quelques demons restants.\n"
"Vous avez termine. L'enfer a fini de\n"
"liberer des mort-vivants au lieu de \n"
"Vous avez gagné. L'enfer a fini de\n"
"libérer des mort-vivants au lieu de \n"
"gens bien vivants.\n"
"Souvenez vous de dire a vos enfants de\n"
"mettre un lance-roquette dans votre\n"
"cercueil. Si vous allez en enfer,\n"
"quand vous serez mort, vous en aurez \n"
"besoin ,pour un nettoyage definitif...";
"besoin, pour un nettoyage définitif...";
P5TEXT =
"Vous avez trouver notre second niveau\n"
"Vous avez trouvé le deuxième niveau\n"
"le plus difficile que nous avons.\n"
"J'espere que vous avez sauvegarde\n"
"au deux precendants.\n"
"Sinon, soyez prets a mourrir souvent.\n"
"Pour maitre marine seulement.";
"J'espère que vous avez sauvegardé\n"
"lors du précédant...\n"
"Sinon, soyez prêt a mourir souvent.\n"
"Pour les pros seulement.";
P6TEXT =
"peut etre, vous demandiez vous quel\n"
"ETAIT le niveau le plus dure, que nous\n"
"avions prepare pour vous? Maintenant,\n"
"Alors, vous vous demandiez quel\n"
"était le niveau le plus dur que nous\n"
"avions préparé pour vous? Maintenant,\n"
"vous savez. Nul n'en sortira vivant.\n";
T1TEXT =
"Vous vous etes fraye un chemin vers la\n"
"sortie des labos experimentaux infestes.\n"
"Il semble que l'UAC les a encore vides. \n"
"Avec leur chiffres d'affaires eleve,\n"
"ca doit etre dur pour la pauvre vieille\n"
"Vous vous êtes frayé un chemin vers la\n"
"sortie des labos expérimentaux infestés.\n"
"Il semble que l'UAC les a encore vidés. \n"
"Avec leur chiffres d'affaires élevé,\n"
"ca doit etre dûr pour la pauvre vieille\n"
"UAC d'acheter des societes \n"
"d'assurance vie ,de nos jours...\n"
"d'assurance vie de nos jours...\n"
"\n"
"Vous avez devant vous le complexe \n"
"militaire, cela grouille d'horreurs \n"
"morbides pres a vous enfoncer leur dents.\n"
"morbides prètes a vous estropier.\n"
"Avec un peu de chance, le complexe a \n"
"encore quelques munitions de guerre,\n"
"encore quelques munitions de guerre\n"
"reposant autour.";
T2TEXT =
"Vous entendez le grincement d'une grosse\n"
"machinerie devant. Vous esperez surement\n"
"qu'ils ne sont pas en train de fabriquer\n"
"de nouvelles creatures de l'enfer,\n"
"mais vous etes pret a balayer tout\n"
"mais vous etes prêt a balayer tout\n"
"un troupeau si vous le deviez.\n"
"Ils pourraient etre en train de preparer\n"
"Ils pourraient etre en train de préparer\n"
"un festin de sang, mais vous vous sentez\n"
"pareil a deux milliers de fous dans le \n"
"corps d'un seul et meme tueur\n"
"corps d'un seul et même tueur.\n"
"\n"
"Vous ne pensez pas tomber si facilement.";
"Vous ne pensez pas mourir si facilement.";
T3TEXT =
"La vue s'ouvrant devant vous semble \n"
"sacrement ,diablement ,familiere.\n"
"Les odeurs familieres, trop -- comme\n"
"des excrements frits. Vous n'aimiez \n"
"sacrément, diablement familière.\n"
"Les odeurs familières, trop -- comme\n"
"des excrèments frits. Vous n'aimiez \n"
"pas cet endroit avant, et vous etes \n"
"terriblement sur de ne pas envisager\n"
"terriblement sûr de ne pas envisager\n"
"l'aimer maintenant.\n"
"Plus vous pensiez a cette idee ,\n"
"plus vous sombriez dans la folie.\n"
"Plus vous pensiez a cette idée,\n"
"plus vous sombrez dans la folie.\n"
"Saisissant votre arme, un sourrire\n"
"malefique apparait sur votre visage.\n"
"Il est temps de prendre quelques noms.";
"maléfique apparait sur votre visage.\n"
"Il est l'heure de buter du démon....";
T4TEXT =
"Tout a coup, tout est silencieux ,\n"
"d'un horizon a l'autre.\n"
"L'echo agonisant de l'enfer s'estompe,\n"
"L'écho agonisant de l'enfer s'estompe,\n"
"le ciel cauchemardeque tourne au bleu,\n"
"les tas de cadavres de monstres \n"
"commencent a s'evaporer avec une puanteur\n"
"nauseabonde qui remplissait l'air.\n"
"Doux jesus ,peut etre l'avez vous fait.\n"
"Avez vous reellement gagne?\n\n"
"commencent a s'évaporer avec une puanteur\n"
"nauséabonde qui remplit l'air.\n"
"Doux jésus, peut être l'avez vous fait.\n"
"Avez vous réellement gagné?\n\n"
"quelque chose gronde au loin.\n"
"une lumiere bleue a commence a luire\n"
"dans le crane defonce du demon\n"
"une lumière bleue a commence a luire\n"
"dans le crâne défonce du démon\n"
"cracheur.";
T5TEXT =
"Maintenant quoi? Cela semble \n"
"completement different.\n"
"Une Sorte de lottissement du\n"
"roi Tut.\n"
"Bon, rien ne peut-etre pire\n"
"complètement different.\n"
"Une sorte de lotissement au\n"
"bon vieux Toutankhamon.\n"
"Bon, rien ne peut être pire\n"
"que d'habitude. N'est-ce pas?\n"
"Ou peut etre est ce mieux\n"
"Ou peut être est ce mieux\n"
"de laisser dormir les dieux,\n"
"la ou ils reposent\n"
"la ou ils reposent..\n"
T6TEXT =
"Vous avez besoin de vacances.\n"
"Vous avez eclates les entrailles\n"
"de l'enfer et pour sur vous etes \n"
"pres pour une pause.\n"
"Vous marmonner a vous meme:\n"
"peut-etre quelqu'un pourrait botter\n"
"Vous aviez besoin de vacances.\n"
"Vous avez éclaté les entrailles\n"
"de l'enfer et pour sûr vous êtes \n"
"prét pour une pause.\n"
"Vous marmonnez à vous même:\n"
"Peut-etre quelqu'un pourrait botter\n"
"le cul de l'enfer a votre place,\n"
"la prochaine fois.\n"
"Une ville tranquille reside devant, \n"
"Une ville tranquille réside devant, \n"
"avec le flot paisible de l'eau,\n"
"les batiments pittoresques, et\n"
"probablement plus de creatures\n"
"probablement plus de créatures\n"
"de l'enfer.\n"
"Quand vous descendez au dehors du \n"
"transport, vous entendez le bruit \n"
"du sabot d'acier d'un \n"
"demon-cybernetique.";
"Cyberdémon.";
NERVETEXT =
"Quelqu'un avait décidé de foutre le bordel\n"
"sur votre lieu de vacances préféré: L'Enfer.\n"
"Un cyberdémon à la noix avait décidé d'en\n"
"faire son parc d'attraction, et la terre\n"
"son petit guichet.\n"
"\n"
"Cet abruti méchanique ne s'attendait pas\n"
"à ce que vous visitiez son chantier,\n"
"rien de mieux qu'un stand de tir plein de\n"
"démons pour faire chauffer l'ambiance..\n"
"\n"
"Maintenant que le cadavre croulant du démon\n"
"résonne en s'écrasant au sol, ses gémissements\n"
"d'agonie se déversent de son visage\n"
"que vous avez laissé en charpie.\n"
"\n"
"Le manège est fermé!\n";
//
@ -709,7 +728,7 @@ TXT_FRAGLIMIT = "Limite de frags atteinte.";
TXT_TIMELIMIT = "Limite de temps atteinte.";
// Spree messages
SPREEKILLSELF = "%o était en pleine folie meurtrière que %g ne se bute!";
SPREEKILLSELF = "%o était en pleine folie meurtrière avant que %g ne se bute!";
SPREEOVER = "La folie meurtrière de %o à été terminée par %!k";
SPREE5 = "%k est en folie meurtrière!";
SPREE10 = "%k est en plein massacre!";
@ -732,7 +751,7 @@ OB_EXIT = "%o a tenté de partir.";
OB_WATER = "%o ne sait pas nager.";
OB_SLIME = "%o a muté.";
OB_LAVA = "%o a fondu.";
OB_BARREL = "%o a sauté.";
OB_BARREL = "%o s'est pété la face.";
OB_SPLASH = "%o s'est tenu au mauvais endroit.";
OB_R_SPLASH = "%o aurait dû garder ses distances.";
OB_ROCKET = "%o aurait dû garder ses distances.";
@ -788,7 +807,7 @@ OB_IRONLICH = "%o a été dévasté par une Liche de Fer.";
OB_IRONLICHHIT = "%o a fait ami-ami avec une Liche de Fer.";
OB_BONEKNIGHT = "%o s'est pris la hache d'un guerrier mort-vivant.";
OB_BONEKNIGHTHIT = "%o s'est fait pourfendre par un guerrier mort-vivant.";
OB_MINOTAUR = "%o was blasted into cinders by a Maulotaur.";
OB_MINOTAUR = "%o s'est fait incinérer par un Massetaure.";
OB_MINOTAURHIT = "%o s'est fait éclater par un Massetaure.";
OB_MUMMY = "%o a été défoncé par un golem.";
OB_MUMMYLEADER = "%o s'est fait percer les tympans par un nitrogolem.";
@ -796,7 +815,7 @@ OB_SNAKE = "%o s est fait secouer par un ophidien.";
OB_WIZARD = "%o a été maudit par un sorcier.";
OB_WIZARDHIT = "%o a été palpé par un sorcier.";
OB_FIREDEMON = "%o a gouté au feu d'un Afrit.";
OB_FIREDEMON = "%o a goûté au feu d'un Afrit.";
OB_DEMON1 = "%o a été brûlé par un Serpent.";
OB_DEMON2 = "%o a été empoisonné par un Serpent.";
OB_ETTIN = "%o a été réduit en purée par un Ettin.";
@ -818,10 +837,10 @@ OB_HERESIARCH = "%o s'est fait rouler les os par l'Hérésiarche.";
OB_ACOLYTE = "%o a souffert d'une bavure policière.";
OB_MACIL = "%o n'aurait jamais du se rebeller contre Macil.";
OB_REBEL = "%o a été abattu par un Rebel.";
OB_REBEL = "%o a été abattu par un rebelle.";
OB_BEGGAR = "%o a été battu a mort par un pauvre.";
OB_PEASANT = "%o n'aurait jamais du chercher des noises a un civil.";
OB_ALIENSPECTRE = "%o a été terrasse par le Spectre.";
OB_ALIENSPECTRE = "%o a été terrassé par le Spectre.";
OB_ENTITY = "%o a senti le courroux du Seul Dieu.";
OB_LOREMASTER = "%o n'a pu échapper a l'emprise du Maître des Traditions.";
OB_PROGRAMMER = "%o a été effacé par le Programmeur.";
@ -882,14 +901,14 @@ OB_MPCWEAPWRAITHVERGE = "%o wa été purifié par la Verge Phantasmale de %k.";
OB_MPMWEAPWAND = "%o s'est pris un rayon saphirique en trop de la part de %k.";
OB_MPMWEAPFROST = "%o s'est fait transformer en glaçon par %k.";
OB_MPMWEAPLIGHTNING = "%o a reçu un sacré coup de jus de la part de %k.";
OB_MPMWEAPBLOODSCOURGE = "%o s'est fait effacer de l'univers par la Menace Sanglante de %k.";
OB_MPMWEAPBLOODSCOURGE = "%o s'est fait effacer de l'univers par le Fléau Sanglant de %k.";
OB_MPPUNCHDAGGER = "%o s'est fait planter un lame dans le dos de la part de %k.";
OB_MPELECTRICBOLT = "%o s'est fait clouer au mur par %k.";
OB_MPPOISONBOLT = "%o a recu une dose létale de la colère de %k.";
OB_MPASSAULTGUN = "%o s'est fait couvrir de trous par le fusil d'assaut de %k.";
OB_MPMINIMISSILELAUNCHER = "%o a avalé le missile de %k.";
OB_MPSTRIFEGRENADE = "%o a été mis sens dessus dessous pa la grenade explosive de %k.";
OB_MPSTRIFEGRENADE = "%o a été mis sens dessus dessous par la grenade explosive de %k.";
OB_MPPHOSPHOROUSGRENADE = "%o s'est permis une pyroclave dans les flammes phosphoriques de %k.";
OB_MPFLAMETHROWER = "%o est passé au barbecue de %k.";
OB_MPMAULER1 = "%o s'est fait électrocuter par %k.";
@ -897,7 +916,7 @@ OB_MPMAULER = "%o à été vicieusement vaporisé par %k.";
OB_MPSIGIL = "%o s'est prosterné face à la toute puissance du Sigil de %k.";
// Same as OB_MPTELEFRAG, but shown when a monster telefrags you
OB_MONTELEFRAG = "%o a été telefrague.";
OB_MONTELEFRAG = "%o a été telefragué.";
OB_DEFAULT = "%o est mort.";
OB_FRIENDLY1 = "%k a tué un de ses équipiers.";
@ -905,21 +924,12 @@ OB_FRIENDLY2 = "%k vérifie ses lunettes.";
OB_FRIENDLY3 = "%k marque un point pour l'autre équipe.";
OB_FRIENDLY4 = "%k a perdu un autre ami.";
SAVEGAMENAME = "zdoomsv";
STARTUP1 = "";
STARTUP2 = "";
STARTUP3 = "";
STARTUP4 = "";
STARTUP5 = "";
SCORE_ITEMS = "OBJETS";
SCORE_BONUS = "BONUS";
SCORE_COLOR = "COULEUR";
SCORE_SECRET = "SECRET";
SCORE_NAME = "NOM";
SCORE_DELAY = "DELAI(ms)";
SCORE_KILLS = "VICTIMES";
SCORE_FRAGS = "FRAGS";
SCORE_DEATHS = "MORTS";
SCORE_MISSED = "RATES";
SCORE_TOTAL = "TOTAL";
@ -971,7 +981,7 @@ TAG_ARTITORCH = "Torche";
TAG_CWEAPMACE = "Masse de Pénitence";
TAG_CWEAPSTAFF = "Sceptre du Serpent";
TAG_CWEAPFLAME = "Tempête de Feu";
TAG_CWEAPWRAITHVERGE = "Bâton du Courroux";
TAG_CWEAPWRAITHVERGE = "Verge Phantasmale";
TAG_FWEAPFIST = "Gantelets à Pointes";
TAG_FWEAPAXE = "Hache de Timon";
TAG_FWEAPHAMMER = "Marteau de la Rétribution";
@ -1033,7 +1043,7 @@ TAG_SIGIL = "SIGIL";
TAG_COIN = "Pièce";
TAG_MEDPATCH = "Pansement";
TAG_MEDICALKIT = "Kit Médical";
TAG_SURGERYKIT = "Kit de Chirurgie"; // "full_health" in the Teaser
TAG_SURGERYKIT = "Kit de Chirurgie";
TAG_BELDINSRING = "Anneau";
TAG_OFFERINGCHALICE = "Calice d'Obole";
TAG_EAR = "Oreille";
@ -1059,20 +1069,20 @@ TAG_TELEPORTERBEACON = "Balise de téléportation";
TAG_METALARMOR = "Armure en Métal";
TAG_LEATHER = "Armure en Cuir";
TAG_HEGRENADES = "Grenades Explosives";
TAG_PHGRENADES = "Grenades Incendiaires"; // "Fire-Grenade_Rounds" in the Teaser
TAG_CLIPOFBULLETS = "Chargeur d'Assaut"; // "bullets" in the Teaser
TAG_PHGRENADES = "Grenades Incendiaires";
TAG_CLIPOFBULLETS = "Chargeur d'Assaut";
TAG_BOXOFBULLETS = "Bôite de Munitions";
TAG_MINIMISSILES = "Mini-Missiles"; //"rocket" in the Teaser
TAG_CRATEOFMISSILES = "Caisse de Mini-Missiles"; //"box_of_rockets" in the Teaser
TAG_MINIMISSILES = "Mini-Missiles";
TAG_CRATEOFMISSILES = "Caisse de Mini-Missiles";
TAG_ENERGYPOD = "Cellule Energétique";
TAG_ENERGYPACK = "Pack Energétique";
TAG_POISONBOLTS = "Carreaux Empoisonnés"; // "poison_arrows" in the Teaser
TAG_ELECTRICBOLTS = "Carreaux Electriques"; // "electric_arrows" in the Teaser
TAG_AMMOSATCHEL = "Sacoche à munitions"; // "Back_pack" in the Teaser
TAG_POISONBOLTS = "Carreaux Empoisonnés";
TAG_ELECTRICBOLTS = "Carreaux Electriques";
TAG_AMMOSATCHEL = "Sacoche à munitions";
// Item tags: Strife keys
TAG_BASEKEY = "Clé de la base";
TAG_GOVSKEY = "Clé du Gouverneur"; // "Rebel_Key" in the Teaser
TAG_GOVSKEY = "Clé du Gouverneur";
TAG_PASSCARD = "Passe";
TAG_IDBADGE = "Badge d'Identification";
TAG_PRISONKEY = "Clé de la Prison";
@ -1091,13 +1101,12 @@ TAG_BRASSKEY = "Clé en Bronze";
TAG_REDCRYSTALKEY = "Clé de Cristal Rouge";
TAG_BLUECRYSTALKEY = "Clé de Crisal Bleu";
TAG_CHAPELKEY = "Clé de la Chapelle";
TAG_CATACOMBKEY = "Clé des Catacombes"; // "Tunnel_Key" in the Teaser
TAG_CATACOMBKEY = "Clé des Catacombes";
TAG_SECURITYKEY = "Clé de la Sécurité";
TAG_COREKEY = "Clé du Réacteur"; // "New_Key1" in the Teaser
TAG_MAULERKEY = "Clé du Broyeur"; // "New_Key2" in the Teaser
TAG_FACTORYKEY = "Clé de l'Usine"; // "New_Key3" in the Teaser
TAG_MINEKEY = "Clé de la Mine"; // "New_Key4" in the Teaser
TAG_NEWKEY5 = "New Key5";
TAG_COREKEY = "Clé du Réacteur";
TAG_MAULERKEY = "Clé du Broyeur";
TAG_FACTORYKEY = "Clé de l'Usine";
TAG_MINEKEY = "Clé de la Mine";
TAG_ORACLEPASS = "Passe de l'Oracle";
// Item tags: misc Strife stuff
@ -1105,9 +1114,6 @@ TAG_10GOLD = "10 Pièces";
TAG_25GOLD = "25 Pièces";
TAG_50GOLD = "50 Pièces";
TAG_300GOLD = "300 Pièces";
TAG_QUEST4 = "quest4";
TAG_QUEST5 = "quest5";
TAG_QUEST6 = "quest4";
// Item tags: Strife NPCs
TAG_ACOLYTE = "Acolyte";
@ -1130,7 +1136,7 @@ TAG_SPORK = "Super Fourchette";
TAG_MINIZORCHER = "Mini Zorcheur";
TAG_LARGEZORCHER = "Zorcheur Large";
TAG_SUPERLARGEZORCHER = "Zorcheur Extra-large";
TAG_RAPIDZORCHER = "Zorcheur";
TAG_RAPIDZORCHER = "Zorcheur Rapide";
TAG_ZORCHPROPULSOR = "Propulseur de Zorch";
TAG_PHASINGZORCHER = "Zorcheur à Phase";
TAG_LAZDEVICE = "ZZL";
@ -1138,113 +1144,113 @@ TAG_LAZDEVICE = "ZZL";
// Heretic strings
HE1TEXT =
"avec la destruction des sangsues\n"
"de fer et leur seides, les derniers\n"
"des mort-vivants furent nettoye de\n"
"cette face de l'existence.\n\n"
"ces creatures durent venir de \n"
"quelquepart, bien que,vous eutes le\n"
"soupcon sournois que l ardent\n"
"portail de l'enfer put conduire\n"
"Avec la destruction des liches\n"
"de fer et leur serviteurs, les derniers\n"
"mort-vivants furent eliminés de\n"
"cette plaine de l'existence.\n\n"
"ces créatures doivent venir de \n"
"quelque part, bien que vous ayez\n"
"un soupçon que ce portail\n"
"ardent de l'enfer puisse conduire\n"
"dans leur dimension.\n\n"
"pour etre sur que beaucoup de\n"
"mort-vivants ou pire ne viennent\n"
"par son biais, vous dutes scelle le\n"
"portail de l enfer de l'autre cote.\n"
"bien sur cela veut dire que vous\n"
"eutes pu rester coince dans un monde\n"
"tres hostile, mais personne n'a\n"
"jamais dis qu'etre un heretic eut\n"
"ete facile!";
"pour etre sûr qu'aucun des\n"
"mort-vivants ou pire ne suivent\n"
"ce chemin, vous scemllez dûment le\n"
"portail de l'autre côté.\n"
"Bien sur cela veut dire que vous\n"
"auriez pû rester coincé dans un monde\n"
"très hostile, mais personne n'a\n"
"jamais dit qu'être un hérétique\n"
"soit facile!";
HE2TEXT =
"les puissants massotaures eurent \n"
"prouve ne pas vous correspondre,\n"
"et leurs cadavres vaporeux glissant sur\n"
"le sol, vous sentites l effroyable\n"
"satisfaction qu ils furent\n"
"detruit.\n\n"
"les passerelles qu'ils garderent\n"
"furent ouvertes, revelant ce que vous\n"
"esperates etre le chemin du retour.\n"
"mais au fur et a mesure que vous \n"
"avancates ,un rire moqueur sonna a\n"
"vos oreilles.\n\n"
"etait ce quelqu'autre force controlant\n"
"les massotaures? eusse t'elles pu etre\n"
"plus atroces les creatures dans\n"
"cette porte? le balayage d'un dome\n"
"de crystal\n"
"depasse ou le ciel aurait du etre\n"
"ce ne fut pas de bon augure....";
"les puissants massetaures ont fini par\n"
"prouver qu'il n'étaient pas votre égal,\n"
"et leurs cadavres fumants étalés sur\n"
"le sol, vous sentez l'infernale\n"
"satisfaction de les avoir complètement\n"
"détruits.\n\n"
"la passage qu'ils gardaient\n"
"s'ouvrit, révélant ce que vous\n"
"espérez être le chemin du retour.\n"
"Mais au fur et a mesure que vous \n"
"avancez, un rire moqueur sonne\n"
"à vos oreilles.\n\n"
"était-ce quelque autre force contrôlant\n"
"les massetaures? Ait elle pû être\n"
"plus atroce que les créatures de\n"
"ce portail? La forme d'un dôme\n"
"de cristal dépasse de\n"
"l'horizon, couvrant le ciel,\n"
"ce n'est pas de bon augure....";
HE3TEXT =
"la mort de d'sparil a liberes\n"
"la mort de d'sparil a liberé\n"
"les liens magiques liant\n"
"les creatures de cette face,\n"
"leurs cri en mourrant surpasserent\n"
"ses propres cris d agonie.\n\n"
"les créatures de ce monde,\n"
"leurs cris d'agonie surpassant\n"
"ses propres hurlements.\n\n"
"votre serment de vengeance rempli,\n"
"vous entrate dans le portail pour\n"
"votre monde, moments insignifiants\n"
"avant que la coupole ne volasse en \neclats.\n"
"mais si le pouvoir de d'sparil\n"
"fut rompu a jamais, pourquoi ne pas\n"
"ne pas vous sentir en securite?\n"
"fut ce son dernier cri\n"
"celui qui resonna comme une\n"
"malediction? une invoquation? vous\n"
"ne putes en etre sur vraiment, mais\n"
"il s'eut put n'etre qu un cri.\n\n"
"puis de nouveau, que devenirent\n"
"les autres serpents coureurs?";
"vous pénétrez dans le portail vers\n"
"votre monde, un court moment\n"
"avant que la coupole vole en éclats.\n"
"Mais avec le pouvoir de d'sparil\n"
"rompu a jamais, pourquoi vous ne\n"
"pouvez pas vous sentir en sécurite?\n"
"Serai-çe à cause de son dernier cri\n"
"celui qui résonna comme une\n"
"malédiction? une invocation? vous\n"
"ne pouvez pas en être sûr, mais\n"
"ce n'est peut être qu un cri.\n\n"
"De plus, qu'adviendrat-il\n"
"des autres chevaucheurs de serpent?";
HE4TEXT =
"vous crutes pouvoir retourner dans\n"
"vous aviez cru pouvoir retourner dans\n"
"votre monde apres que d'sparil\n"
"trepassa , mais son acte\n"
"ne trépasse, mais son acte\n"
"final fut de vous bannir dans sa\n"
"propre dimension. ici vous entrates\n"
" dans des restes effondres de terres\n"
"conquisent par d'sparil. vous eutes\n"
"propre dimension. Ici vous errez\n"
"dans les territoires ruinés des\n"
"conquêtes de d'sparil. vous êtes\n"
"le dernier gardien de ces terres,\n"
"mais a ce moment vous vous tenites\n"
"mais a ce moment vous vous tenez\n"
"devant le bastion de d'sparil."
"jusqua ce moment vous n'eutes \n"
"jusqu'à ce moment vous n'aviez\n"
"aucun doute sur votre capacite\n"
"d affronter tout ce que vous pouviez\n"
"rencontrer,mais derriere ce portail\n"
"git le coeur profond du mal\n"
"à affronter tout ce que vous pouviez\n"
"rencontrer, mais derrière ce portail\n"
"gît le coeur du mal profond\n"
"qui envahit votre monde. d'sparil\n"
"eut pu etre mort,mais le puit ou\n"
"il fut ne demeura. maintenant vous\n"
"dutes entrer dans ce puit dans l'espoir\n"
"de trouver une sortie.et quelque part,\n"
"peut être mort, mais le puis d'où\n"
"il est sorti ne l'est pas. Maintenant\n"
"vous devez y entrer dans l'espoir\n"
"de trouver une sortie, quelque part,\n"
"dans la plus sombre partie du\n"
"royaume de d'sparil,\n"
"sa garde personnelle attendit votre\n"
"arrivee ...";
"Sa garde personnelle attend votre\n"
"arrivée ...";
HE5TEXT =
"des que le massotaure final eu mugit\n"
"son agonie mortelle, vous realisates que\n"
"vous n'eutes jamais ete aussi proche de\n"
"votre propre destruction.meme le \n"
"dès que le massetaure final eu mugit\n"
"son râle d'agonie, vous réalisez que\n"
"vous n'avez jamais été aussi proche de\n"
"votre propre mort. Même le \n"
"combat contre d'sparil et ses\n"
"disciples n'eut ete a ce point \n"
"desespere. souriant, quand vous \n"
"regardates fixement le portail s'ouvrir \n"
"devant vous ,vous demandant s'il menait \n"
"chez vous,ou si il ouvrait sur une\n"
"innimaginable horreur. vous vous \n"
"demandates si vous eutes la force d'y aller,\n"
"éreintant. Souriant, vous \n"
"regardez fixement le portail s'ouvrir \n"
"devant vous, vous demandant s'il mêne\n"
"chez vous, où si il ouvre sur une\n"
"horreur inimaginable. Vous n'êtes \n"
"pas sûr d'avoir la force d'y aller,\n"
"si rien d'autre que souffrance\n"
"et mort vous eurent attendu.\n"
"mais que putes vous faire d'autre, si\n"
"la volonte de vous battre s'eut enfuie?\n"
"putes vous,vous meme vous forcer a \n"
"continuer face a un tel desespoir? \n"
"eutes vous le courage? vous trouvates,\n"
"a la fin ,ce ne fut pas dans votre nature\n"
"de vous rendre sans un combat. les yeux\n"
"larges ,vous partates rencontrer votre\n"
"destinee.";
"et mort ne vous y attendent.\n"
"mais que faire d'autre, si la\n"
"volonté de vous battre disparaît?\n"
"Comment voulez-vous vous forcer à\n"
"continuer face a un tel désespoir? \n"
"En avez vous le courage? Vous pensez,\n"
"a la fin que ce n'est pas dans votre nature\n"
"de vous rendre sans combattre. les yeux\n"
"larges, vous partez rencontrer votre\n"
"destinée.";
// EPISODE 1 - LA CITE DES DAMNES
HHUSTR_E1M1 = "LES DOCKS";
@ -1352,7 +1358,7 @@ TXT_WPNSKULLROD = "BATON INFERNAL";
TXT_WPNPHOENIXROD = "BATON INFERNAL";
TXT_WPNGAUNTLETS = "GANTELETS DU NECROMANCIEN";
TXT_NEEDBLUEKEY = "CETTE PORTE NESCESSITE UNE CLE BLEU POUR S'OUVRIR";
TXT_NEEDBLUEKEY = "CETTE PORTE NESCESSITE UNE CLE BLEUE POUR S'OUVRIR";
TXT_NEEDGREENKEY = "CETTE PORTE NESCESSITE UNE CLE VERTE POUR S'OUVRIR";
TXT_NEEDYELLOWKEY = "CETTE PORTE NESCESSITE UNE CLE JAUNE POUR S'OUVRIR";
@ -1367,7 +1373,6 @@ TXT_CHEATIDKFA = "TRICHEUR - TU NE MERITE PAS D'ARMES!";
TXT_CHEATTICKERON = "COMPTEUR ALLUME";
TXT_CHEATTICKEROFF = "COMPTER ETEINT";
TXT_CHEATARTIFACTS3 = "VOUS L'AVEZ";
TXT_MIDASTOUCH = "YOU GOT THE MIDAS TOUCH, BABY!";
TXT_GOTSTUFF = "Voilà ton équipement!";
TXT_FREEZEON = "Temps arrêté.";
TXT_FREEZEOFF = "Le temps reprend son cours..";
@ -1385,6 +1390,19 @@ TXT_IMTIME = "TEMPS";
RAVENQUITMSG = "ETES VOUS SUR DE VOULOIR QUITTER?";
FN_CHICKEN = "Poulet";
FN_BEAST = "Dragon-garou";
FN_CLINK = "Sabregriffe";
FN_DSPARIL = "D'Sparil";
FN_HERETICIMP = "Gargouille";
FN_IRONLICH = "Liche de Fer";
FN_BONEKNIGHT = "Guerrier Mort-Vivant";
FN_MINOTAUR = "Massetaure";
FN_MUMMY = "Golem";
FN_MUMMYLEADER = "Nitrogolem";
FN_SNAKE = "Ophidien";
FN_WIZARD = "Magicien";
// Hexen strings
// Mana
@ -1400,7 +1418,7 @@ TXT_KEY_CAVE = "CLE DE LA CAVE";
TXT_KEY_AXE = "CLE DE LA HACHE";
TXT_KEY_FIRE = "CLE DU FEU";
TXT_KEY_EMERALD = "CLE D'EMERAUDE";
TXT_KEY_DUNGEON = "CLE DU DONGEON";
TXT_KEY_DUNGEON = "CLE DU DONJON";
TXT_KEY_SILVER = "CLE D'ARGENT";
TXT_KEY_RUSTED = "CLE ROUILLEE";
TXT_KEY_HORN = "CLE CORNE";
@ -1412,10 +1430,10 @@ TXT_NEED_KEY_CAVE = "Vous avez besoin de la CLE DE LA CAVE";
TXT_NEED_KEY_AXE = "Vous avez besoin de la CLE DE LA HACHE";
TXT_NEED_KEY_FIRE = "Vous avez besoin de la CLE DU FEU";
TXT_NEED_KEY_EMERALD = "Vous avez besoin de la CLE D'EMERAUDE";
TXT_NEED_KEY_DUNGEON = "Vous avez besoin de la CLE DU DONGEON";
TXT_NEED_KEY_DUNGEON = "Vous avez besoin de la CLE DU DONJON";
TXT_NEED_KEY_SILVER = "Vous avez besoin de la CLE D'ARGENT";
TXT_NEED_KEY_RUSTED = "Vous avez besoin de la CLE ROUILLEE";
TXT_NEED_KEY_HORN = "Vous avez besoin de la CLE ROUILLEE";
TXT_NEED_KEY_HORN = "Vous avez besoin de la CLE CORNE";
TXT_NEED_KEY_SWAMP = "Vous avez besoin de la CLE DES MARECAGES";
TXT_NEED_KEY_CASTLE = "Vous avez besoin de la CLE DU CHATEAU";
@ -1464,13 +1482,13 @@ TXT_WEAPON_F3 = "MARTEAU DE LA RETRIBUTION";
TXT_WEAPON_F4 = "QUIETUS ASSEMBLE";
TXT_WEAPON_C2 = "SCEPTRE DU SERPENT";
TXT_WEAPON_C3 = "TEMPETE DE FEU";
TXT_WEAPON_C4 = "BATON DU COURROUX ASSEMBLE";
TXT_WEAPON_C4 = "VERGE PHANTASMALE ASSEMBLE";
TXT_WEAPON_M2 = "ECLATS DE GIVRE";
TXT_WEAPON_M3 = "FOUDRE MORTELLE";
TXT_WEAPON_M4 = "FLEAU SANGLANT ASSEMBLE";
TXT_WEAPONPIECE = "Une piece d'arme! C'est votre jour de chance!";
TXT_QUIETUS_PIECE = "SEGMENT DE QUIETUS";
TXT_WRAITHVERGE_PIECE = "SEGMENT DU BATON DU COURROUX";
TXT_WRAITHVERGE_PIECE = "SEGMENT DE LA VERGE PHANTASMALE";
TXT_BLOODSCOURGE_PIECE = "SEGMENT DU FLEAU SANGLANT";
// Strife locks
@ -1488,6 +1506,8 @@ TXT_NEED_SILVERKEY = "Vous avez besoin de la clé en argent.";
TXT_NEED_BRASSKEY = "Vous avez besoin de la clé en bronze.";
TXT_NEED_REDCRYSTAL = "Vous avez besoin du cristal rouge.";
TXT_NEED_BLUECRYSTAL = "Vous avez besoin du cristal bleu.";
TXT_RETAIL_ONLY = "CETTE ZONE N'EST ACCESSIBLE QUE DANS LA VERSION COMPLETE DE STRIFE";
TXT_DOES_NOT_WORK = "Cela ne semble pas fonctionner.";
// Strife Quest messages
@ -1599,8 +1619,8 @@ TXT_RANDOM_REBEL_03 = "On couvre tes arrières, t'inquiète pas.";
TXT_RANDOM_REBEL_04 = "Ne vous approchez pas trop des gros robots. Ils brûleront jusqu'à l'os!";
TXT_RANDOM_REBEL_05 = "Le jour de gloire arrivera bientôt, et ceux qui s'opposeront a nous seront écrasés!";
TXT_RANDOM_REBEL_06 = "Ne vous reposez pas sur vos lauriers. Du travail nous attend encore.";
TXT_RANDOM_REBEL_07 = "Macil nous dis que tu es notre nouvel espoir. Garde ca à l'esprit.";
TXT_RANDOM_REBEL_08 = "Une fois que nous nous serons débarassés de ces charlatans, nous serons capable de rebatir le monde tel qu'il devrait être.";
TXT_RANDOM_REBEL_07 = "Macil nous dit que tu es notre nouvel espoir. Garde ca à l'esprit.";
TXT_RANDOM_REBEL_08 = "Une fois que nous nous serons débarassés de ces charlatans, nous serons capable de rebâtir le monde tel qu'il devrait être.";
TXT_RANDOM_REBEL_09 = "Souviens-toi, tu ne te bas pas seulement pour toi, mais pour tous le monde ici et ailleurs.";
TXT_RANDOM_REBEL_10 = "Aussi longtemps qu'un de nous est vivant, nous vaincrons.";
@ -1619,14 +1639,14 @@ TXT_RANDOM_BEGGAR_01 = "L'aumône pour les pauvres?";
TXT_RANDOM_BEGGAR_02 = "Tu regarde qui, habitant de la surface?";
TXT_RANDOM_BEGGAR_03 = "Aurais-tu de la nourriture en trop sur toi?";
TXT_RANDOM_BEGGAR_04 = "Vous, les gens de la surface, vous ne comprendrez jamais.";
TXT_RANDOM_BEGGAR_05 = "Ha, les gardes ne nous trouveront jamaiss, ces idios ne savent même pas que l'on existe!";
TXT_RANDOM_BEGGAR_05 = "Ha, les gardes ne nous trouveront jamais, ces idiots ne savent même pas qu'on existe!";
TXT_RANDOM_BEGGAR_06 = "Un jour, tous sauf les membres de l'ordre seront forcés de nous rejoindre.";
TXT_RANDOM_BEGGAR_07 = "Amuse toi à nous regarder autant que tu veus, mais tu sais que ceci sera aussi ton sort un jour.";
TXT_RANDOM_BEGGAR_08 = "Il n'y rien de plus barbant qu'un type de la surface et son attitude!";
TXT_RANDOM_BEGGAR_07 = "Moque nous si tu veux, mais tu sais que ceci sera aussi ton sort un jour.";
TXT_RANDOM_BEGGAR_08 = "Il n'y rien de plus barbant qu'un type de la surface et son orgeuil!";
TXT_RANDOM_BEGGAR_09 = "L'ordre se débarrassera de vos soldats pathétiques.";
TXT_RANDOM_BEGGAR_10 = "Prend guarde a toi, habitant de la surface. Nous connaîssons nos ennemis!";
TXT_RANDOM_PGUARD_01 = "Nous sommes les mains du destin. Apprendre notre colere est l'égal de trouver l'oubli!";
TXT_RANDOM_PGUARD_01 = "Nous sommes les mains du destin. Apprendre notre colère est l'égal de trouver l'oubli!";
TXT_RANDOM_PGUARD_02 = "L'ordre nettoira le monde des faibles et corrompus!";
TXT_RANDOM_PGUARD_03 = "Obéissez à la volonté de vos maîtres!";
TXT_RANDOM_PGUARD_04 = "Longue vie aux membres de l'Ordre!";
@ -1687,7 +1707,7 @@ MNU_DEMESNE = "LE DOMAINE STAGNANT";
MNU_WETNURSE = "VOUS AVEZ BESOIN D'UNE NOURRICE";
MNU_YELLOWBELLIES = "UN TROUILLARD-TU-EST";
MNU_BRINGEST = "AMMENEZ LES MOI!";
MNU_BRINGEST = "AMENEZ LES MOI!";
MNU_SMITE = "TU EST UN MAITRE-MEURTRIER";
MNU_BLACKPLAGUE = "LA PESTE NOIRE ME POSSEDE";
@ -1721,7 +1741,6 @@ MNU_WARRIOR = "GUERRIER";
MNU_ALTARBOY = "ENFANT DE CHOEUR";
MNU_PRIEST = "PRETRE";
MNU_CARDINAL = "CARDINAL";
MNU_POPE = "PAPE";
MNU_APPRENTICE = "APPRENTI";
@ -1754,7 +1773,7 @@ OPTMNU_CHANGERENDER = "Changer de Moteur de Rendu";
OPTMNU_DEFAULTS = "Réinitialiser les paramètres";
OPTMNU_RESETTOSAVED = "Recharger dernière config.";
OPTMNU_CONSOLE = "Ouvrir la console";
OPTMNU_REVERB = "Editeur environement de révérb.";
// Controls Menu
CNTRLMNU_TITLE = "MODIFIER CONTROLES";
@ -1821,7 +1840,7 @@ CNTRLMNU_OTHER = "Autres";
CNTRLMNU_AUTOMAP = "Activer Carte";
CNTRLMNU_CHASECAM = "Caméra 3ième personne";
CNTRLMNU_COOPSPY = "Espionner Coéquiper";
CNTRLMNU_SCREENSHOT = "Capture d'Ecran";
CNTRLMNU_SCREENSHOT = "Capture d'écran";
CNTRLMNU_CONSOLE = "Ouvrir Console";
CNTRLMNU_POPUPS = "Popups de Strife";
CNTRLMNU_MISSION = "Objectifs de Mission";
@ -1836,7 +1855,7 @@ MOUSEMNU_MOUSEINMENU = "Activer Souris dans les Menus";
MOUSEMNU_SHOWBACKBUTTON = "Afficher le bouton retour";
MOUSEMNU_CURSOR = "Curseur";
MOUSEMNU_SENSITIVITY = "Sensibilité générale";
MOUSEMNU_NOPRESCALE = "Prescaling movement souris";
MOUSEMNU_NOPRESCALE = "Prescaling mouvement souris";
MOUSEMNU_SMOOTHMOUSE = "Lissage Souris";
MOUSEMNU_TURNSPEED = "Vitesse pour tourner";
MOUSEMNU_MOUSELOOKSPEED = "Vitesse Vue Souris";
@ -2119,7 +2138,7 @@ GMPLYMNU_ALLOWSPYING = "Autoriser espionnage";
GMPLYMNU_CHASECAM = "Cheat caméra 3ième personne";
GMPLYMNU_DONTCHECKAMMO = "Vérifier munitions pour changement arme";
GMPLYMNU_KILLBOSSSPAWNS = "Tuer L'Icône tue tous ses monstres";
GMPLYMNU_NOCOUNTENDMONSTER = "Ennemis dans secteur de sortie comptent";
GMPLYMNU_NOCOUNTENDMONSTER = "Ennemis du secteur sortie comptés";
GMPLYMNU_DEATHMATCH = "Options Deathmatch";
GMPLYMNU_WEAPONSSTAY = "Armes restent au sol quand récupérées";
GMPLYMNU_ALLOWPOWERUPS = "Autoriser powerups";
@ -2149,21 +2168,21 @@ GMPLYMNU_SPAWNWHEREDIED = "Réapparaitre sur lieu de mort";
CMPTMNU_TITLE = "OPTIONS COMPATIBILITE";
CMPTMNU_MODE = "Mode de compatibilité";
CMPTMNU_ACTORBEHAVIOR = "Comportement des Acteurs";
CMPTMNU_CORPSEGIBS = "Monstres écrasés peuvent être ressucités";
CMPTMNU_NOBLOCKFRIENDS = "Monstres amicaux ne sont pas bloqués";
CMPTMNU_LIMITPAIN = "Limite sur les âmes des élémentaires";
CMPTMNU_MBFMONSTERMOVE = "Mouvement monstre affecté par les effets";
CMPTMNU_CORPSEGIBS = "Monstres écrasés résucitables";
CMPTMNU_NOBLOCKFRIENDS = "Monstres amicaux non bloqués";
CMPTMNU_LIMITPAIN = "Limiter âmes des élémentaires";
CMPTMNU_MBFMONSTERMOVE = "Mouvement monstre affecté par effets";
CMPTMNU_CROSSDROPOFF = "Monstres ne passent pas les corniches";
CMPTMNU_DROPOFF = "Monstres bloqués par les corniches";
CMPTMNU_INVISIBILITY = "Monstres voient joueurs invisibles";
CMPTMNU_MINOTAUR = "Pas de feu de Massetaur sur l'eau";
CMPTMNU_NOTOSSDROPS = "OBjets lâchés sont direct au sol";
CMPTMNU_NOTOSSDROPS = "Objets lâchés direct au sol";
CMPTMNU_DEHACKEDBEHAVIOR = "Comportement DeHackEd";
CMPTMNU_DEHHEALTH = "Niveaux de santé DEH comme Doom2.EXE";
CMPTMNU_MUSHROOM = "Vitesse A_Mushroom originale pour DEH";
CMPTMNU_MAPACTIONBEHAVIOR = "Comportement Niveau/Actions";
CMPTMNU_USEBLOCKING = "Toute ligne d'action bloque <utiliser>";
CMPTMNU_ANYBOSSDEATH = "N'importe quel boss peut activer actions boss";
CMPTMNU_ANYBOSSDEATH = "N'importe quel boss active actions boss";
CMPTMNU_NODOORLIGHT = "Pas d'effet de lumière BOOM sur portes";
CMPTMNU_LIGHT = "Trouver prochaine texture comme DOOM";
CMPTMNU_SHORTTEX = "Trouver plus petite texture comme Doom";
@ -2200,7 +2219,7 @@ SNDMNU_SFXVOLUME = "Volume des Sons";
SNDMNU_MENUVOLUME = "Volume du Menu";
SNDMNU_MUSICVOLUME = "Volume Musique";
SNDMNU_MIDIDEVICE = "Sortie MIDI";
SNDMNU_BACKGROUND = "Sons activé en arrière plan";
SNDMNU_BACKGROUND = "Son activé en arrière plan";
SNDMNU_UNDERWATERREVERB = "Reverbération sous l'eau";
SNDMNU_RANDOMIZEPITCHES = "Tons sonores aléatoires";
SNDMNU_CHANNELS = "Canaux sonores";
@ -2218,7 +2237,7 @@ OPENALMNU_RESAMPLER = "Resampler";
// Advanced Sound Options
ADVSNDMNU_TITLE = "OPTIONS SONORES AVANCEES";
ADVSNDMNU_SAMPLERATE = "Sample rate";
ADVSNDMNU_SAMPLERATE = "Cadence de Sampling";
ADVSNDMNU_HRTF = "HRTF";
ADVSNDMNU_OPLSYNTHESIS = "Synthèse OPL";
ADVSNDMNU_OPLNUMCHIPS = "Puces OPL émulées";
@ -2229,18 +2248,24 @@ ADVSNDMNU_GUSCONFIG = "Fichier Config. GUS";
ADVSNDMNU_MIDIVOICES = "Voix MIDI";
ADVSNDMNU_DMXGUS = "Lire fichiers DMXGUS";
ADVSNDMNU_GUSMEMSIZE = "Taille mémoire GUS";
ADVSNDMNU_FLUIDSYNTH = "FluidSynth";
ADVSNDMNU_FLUIDPATCHSET = "Patchset";
ADVSNDMNU_FLUIDGAIN = "Gain";
ADVSNDMNU_REVERB = "Reverb";
ADVSNDMNU_CHORUS = "Chorus";
ADVSNDMNU_TIMIDITY = "Timidity++";
ADVSNDMNU_TIMIDITYEXE = "Chemin exécutable";
ADVSNDMNU_TIMIDITYCONFIG = "Fichier de config. TiMidity";
ADVSNDMNU_TIMIDITYVOLUME = "Volume Relatif";
ADVSNDMNU_WILDMIDI = "WildMidi";
ADVSNDMNU_WILDMIDICONFIG = "Fichier config. WildMidi";
ADVSNDMNU_SELCONFIG = "Sélectionner configuration";
ADVSNDMNU_ADVRESAMPLING = "Resampling Avancé";
ADVSNDMNU_OPLBANK = "Banque OPL";
ADVSNDMNU_ADLOPLCORES = "Coeur Emulateur OPL";
ADVSNDMNU_RUNPCMRATE = "Emulateur utilise cadence PCM";
ADVSNDMNU_ADLNUMCHIPS = "Puces OPL émulées";
ADVSNDMNU_VLMODEL = "Modèle de Volume";
ADVSNDMNU_OPNNUMCHIPS = "Puces OPN émulées";
// ADLMIDI's volume models
ADLVLMODEL_AUTO = "Auto (Utiliser paramètre banque)";
ADLVLMODEL_GENERIC = "Générique";
ADLVLMODEL_NATIVE = "OPL Natif";
// Module Replayer Options
MODMNU_TITLE = "OPTIONS LECTEUR MODULES";
@ -2248,7 +2273,6 @@ MODMNU_REPLAYERENGINE = "Moteur de lecture";
MODMNU_MASTERVOLUME = "Volume maître";
MODMNU_QUALITY = "Qualité";
MODMNU_VOLUMERAMPING = "Rampe du volume";
MODMNU_CHIPOMATIC = "Chip-o-matic";
// Renderer Options
RNDMNU_TITLE = "SELECTION MOTEUR RENDU";
@ -2259,6 +2283,7 @@ RNDMNU_CANVAS = "Canvas Software";
// Video Options
VIDMNU_TITLE = "MODE VIDEO";
IDMNU_RENDERMODE = "Mode de Rendu";
VIDMNU_FULLSCREEN = "Plein écran";
VIDMNU_HIDPI = "Support Retina/HiDPI ";
VIDMNU_BRDLSS = "Mode fenêtré sans bordures";
@ -2272,6 +2297,16 @@ VIDMNU_ENTERTEXT = "Appuyez sur ENTREE pour choisir un mode";
VIDMNU_TESTTEXT1 = "Appuyez sur T pour tester ce mode pendant 5 secondes.";
VIDMNU_TESTTEXT2 = "Veuillez attendre 5 secondes...";
VIDMNU_USELINEAR = "Mise à l'échelle Linéaire (Plein écran)";
VIDMNU_CUSTOMRES = "Résolution Personalisée";
VIDMNU_CUSTOMX = "Largeur Personalisée";
VIDMNU_CUSTOMY = "Hauteur Personalisée";
VIDMNU_APPLYW = "Appliquer Changements (Fenêtre)";
VIDMNU_APPLYFS = "Appliquer Changements (Plein écran)";
VIDMNU_RESPRESET = "Choisir paramètre personalisé";
VIDMNU_RESPRESETTTL = "Résolutions Personalisée";
VIDMNU_RESPRESETHEAD = "Choisir mode de Résolution";
// Network Options
NETMNU_TITLE = "OPTIONS RESEAU";
NETMNU_LOCALOPTIONS = "Options Locales";
@ -2405,6 +2440,33 @@ OPTVAL_VTAZDOOM = "Auto (ZDoom Préféré)";
OPTVAL_VTAVANILLA = "Auto (Vanilla Préféré)";
OPTVAL_SCALENEAREST = "Mise à l'échelle (Proche Voisin)";
OPTVAL_SCALELINEAR = "Mise à l'échelle (Linéaire)";
OPTVAL_LINEAR = "Linéaire";
OPTVAL_CUBIC = "Cubique";
OPTVAL_BLEP = "Step limité par bande";
OPTVAL_LINEARSLOW = "Linéaire (Lent)";
OPTVAL_BLAM = "Linéaire limité par bande";
OPTVAL_CUBICSLOW = "Cubique (Lent)";
OPTVAL_NOTEONOFFONLY = "Note on/off seulement";
OPTVAL_FULLRAMPING = "Rampe complète";
OPTVAL_ALLUNACKNOWLEDGED = "Tout non-acknowledged";
OPTVAL_ERRORS = "Erreurs";
OPTVAL_WARNINGS = "Avertissements";
OPTVAL_EVERYTHING = "Tout";
OPTVAL_FULLSCREENONLY = "Plein écran seulement";
OPTVAL_HWPOLY = "Accéléré par OpenGL";
OPTVAL_SWDOOM = "Rendu Software Doom";
OPTVAL_SWDOOMTC = "Rendu Software Couleurs Réeles";
OPTVAL_SWPOLY = "Rendu Softpoly";
OPTVAL_SWPOLYTC = "Softpoly Couleurs Réeles";
OPTVAL_DEDICATED = "Hautes Performances";
OPTVAL_INTEGRATED = "Economie d'Energie";
OPTVAL_VTFZDOOM = "ZDoom (Forcé)";
OPTVAL_VTFVANILLA = "Vanilla (Forcé)";
OPTVAL_VTAZDOOM = "Auto (ZDoom Préféré)";
OPTVAL_VTAVANILLA = "Auto (Vanilla Préféré)";
OPTVAL_SCALENEAREST = "Mis à l'échelle (Proche Voisin)";
OPTVAL_SCALELINEAR = "Mis à l'échelle (Linéaire)";
// Colors
C_BRICK = "\cabrique";

View file

@ -2290,6 +2290,8 @@ OptionMenu "OpenGLOptions" protected
{
Option "$GLPREFMNU_VRQUADSTEREO", vr_enable_quadbuffered, "OnOff"
}
Slider "$GLPREFMNU_VRIPD", vr_ipd, 0.041, 0.073, 0.001, 3
Slider "$GLPREFMNU_VRSCREENDIST", vr_screendist, 0.2, 10.0, 0.1, 1
StaticText " "
Option "$GLPREFMNU_MULTISAMPLE", gl_multisample, "Multisample"
Option "$GLPREFMNU_TONEMAP", gl_tonemap, "TonemapModes"

View file

@ -194,6 +194,7 @@ struct Screen native
native static vararg void DrawChar(Font font, int normalcolor, double x, double y, int character, ...);
native static vararg void DrawText(Font font, int normalcolor, double x, double y, String text, ...);
native static void DrawLine(int x0, int y0, int x1, int y1, Color color);
native static void DrawThickLine(int x0, int y0, int x1, int y1, double thickness, Color color);
native static void DrawFrame(int x, int y, int w, int h);
native static Vector2, Vector2 VirtualToRealCoords(Vector2 pos, Vector2 size, Vector2 vsize, bool vbottom=false, bool handleaspect=true);
native static double GetAspectRatio();
@ -815,7 +816,8 @@ struct StringStruct native
native int CharCodeAt(int pos) const;
native String Filter();
native int IndexOf(String substr, int startIndex = 0) const;
native int LastIndexOf(String substr, int endIndex = 2147483647) const;
deprecated("3.5.1") native int LastIndexOf(String substr, int endIndex = 2147483647) const;
native int RightIndexOf(String substr, int endIndex = 2147483647) const;
native void ToUpper();
native void ToLower();
native int ToInt(int base = 0) const;