Merge branch 'master' into mt

This commit is contained in:
Christoph Oelckers 2018-10-31 10:20:29 +01:00
commit 533ded8d1e
16 changed files with 119 additions and 80 deletions

View file

@ -59,7 +59,7 @@ struct SoundAndString
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
void SexMessage (const char *from, char *to, int gender,
void PronounMessage (const char *from, char *to, int pronoun,
const char *victim, const char *killer);
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
@ -266,7 +266,7 @@ bool AnnounceKill (AActor *killer, AActor *killee)
{
char assembled[1024];
SexMessage (message, assembled, killee->player->userinfo.GetGender(),
PronounMessage (message, assembled, killee->player->userinfo.GetGender(),
killee->player->userinfo.GetName(), killerName);
Printf (PRINT_MEDIUM, "%s\n", assembled);
}
@ -298,7 +298,7 @@ bool AnnounceTelefrag (AActor *killer, AActor *killee)
{
char assembled[1024];
SexMessage (message, assembled, killee->player->userinfo.GetGender(),
PronounMessage (message, assembled, killee->player->userinfo.GetGender(),
killee->player->userinfo.GetName(), killer->player->userinfo.GetName());
Printf (PRINT_MEDIUM, "%s\n", assembled);
}

View file

@ -36,8 +36,17 @@
#include "c_cvars.h"
enum
{
GENDER_MALE,
GENDER_FEMALE,
GENDER_NEUTER,
GENDER_OBJECT,
GENDER_MAX
};
int D_GenderToInt (const char *gender);
extern const char *GenderNames[3];
extern const char *GenderNames[GENDER_MAX];
int D_PlayerClassToInt (const char *classname);

View file

@ -83,7 +83,7 @@ enum
INFO_ClassicFlight,
};
const char *GenderNames[3] = { "male", "female", "other" };
const char *GenderNames[GENDER_MAX] = { "male", "female", "neutral", "other" };
// Replace \ with %/ and % with %%
FString D_EscapeUserInfo (const char *str)
@ -136,12 +136,14 @@ FString D_UnescapeUserInfo (const char *str, size_t len)
int D_GenderToInt (const char *gender)
{
if (!stricmp (gender, "female"))
if (gender[0] == 'f')
return GENDER_FEMALE;
else if (!stricmp (gender, "other") || !stricmp (gender, "cyborg"))
else if (gender[0] == 'm')
return GENDER_MALE;
else if (gender[0] == 'n')
return GENDER_NEUTER;
else
return GENDER_MALE;
return GENDER_OBJECT;
}
int D_PlayerClassToInt (const char *classname)
@ -726,7 +728,8 @@ void D_WriteUserInfoStrings (int pnum, uint8_t **stream, bool compact)
case NAME_Gender:
*stream += sprintf(*((char **)stream), "\\%s",
*static_cast<FIntCVar *>(pair->Value) == GENDER_FEMALE ? "female" :
*static_cast<FIntCVar *>(pair->Value) == GENDER_NEUTER ? "other" : "male");
*static_cast<FIntCVar *>(pair->Value) == GENDER_MALE ? "male" :
*static_cast<FIntCVar *>(pair->Value) == GENDER_NEUTER ? "neutral" : "other");
break;
case NAME_PlayerClass:

View file

@ -34,6 +34,8 @@
#include "a_weapons.h"
#include "d_netinf.h"
// The player data structure depends on a number
// of other structs: items (internal inventory),
// animation states (closely tied to the sprites
@ -261,13 +263,6 @@ public:
extern TArray<FPlayerClass> PlayerClasses;
// User info (per-player copies of each CVAR_USERINFO cvar)
enum
{
GENDER_MALE,
GENDER_FEMALE,
GENDER_NEUTER
};
struct userinfo_t : TMap<FName,FBaseCVar *>
{
~userinfo_t();

View file

@ -440,7 +440,8 @@ void FGLRenderState::SetStencil(int offs, int op, int flags)
glStencilOp(GL_KEEP, GL_KEEP, op2gl[op]); // this stage doesn't modify the stencil
bool cmon = !(flags & SF_ColorMaskOff);
glColorMask(cmon, cmon, cmon, cmon); // don't write to the graphics buffer
bool cmalpha = cmon || (flags & SF_ColorMaskAlpha);
glColorMask(cmon, cmon, cmon, cmalpha); // don't write to the graphics buffer
glDepthMask(!(flags & SF_DepthMaskOff));
}

View file

@ -1,5 +1,8 @@
#pragma once
#include <stddef.h>
#include <assert.h>
// The low level code needs to know which attributes exist.
// OpenGL needs to change the state of all of them per buffer binding.
// VAOs are mostly useless for this because they lump buffer and binding state together which the model code does not want.
@ -75,4 +78,4 @@ public:
virtual void BindRange(size_t start, size_t length) = 0;
virtual void BindBase() = 0;
};
};

View file

@ -301,7 +301,7 @@ void HWPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestenci
state.EnableTexture(false);
state.SetRenderStyle(STYLE_Source);
state.SetStencil(0, SOP_Keep, SF_ColorMaskOff);
state.SetStencil(0, SOP_Keep, SF_ColorMaskOff | SF_ColorMaskAlpha); // SSAO needs the alpha channel as a marker.
if (needdepth) state.Clear(CT_Depth);
state.SetDepthRange(0, 1);
state.SetDepthFunc(DF_LEqual);
@ -946,8 +946,8 @@ void HWEEHorizonPortal::DrawContents(HWDrawInfo *di, FRenderState &state)
{
GLSkyInfo skyinfo;
skyinfo.init(sector->sky, 0);
//GLSkyPortal sky(mState, &skyinfo, true);
//sky.DrawContents(di, state);
HWSkyPortal sky(screen->mSkyData, mState, &skyinfo, true);
sky.DrawContents(di, state);
}
if (sector->GetTexture(sector_t::ceiling) != skyflatnum)
{

View file

@ -57,6 +57,7 @@ enum EStencilFlags
SF_AllOn = 0,
SF_ColorMaskOff = 1,
SF_DepthMaskOff = 2,
SF_ColorMaskAlpha = 4, // hack value for SSAO
};
enum EStencilOp
@ -485,21 +486,21 @@ public:
virtual void DrawIndexed(int dt, int index, int count, bool apply = true) = 0;
// Immediate render state change commands. These only change infrequently and should not clutter the render state.
virtual bool SetDepthClamp(bool on) = 0;
virtual void SetDepthMask(bool on) = 0;
virtual void SetDepthFunc(int func) = 0;
virtual void SetDepthRange(float min, float max) = 0;
virtual void EnableDrawBufferAttachments(bool on) = 0;
virtual void SetStencil(int offs, int op, int flags) = 0;
virtual void SetCulling(int mode) = 0;
virtual void EnableClipDistance(int num, bool state) = 0;
virtual void Clear(int targets) = 0;
virtual void EnableStencil(bool on) = 0;
virtual void SetScissor(int x, int y, int w, int h) = 0;
virtual void SetViewport(int x, int y, int w, int h) = 0;
virtual void EnableDepthTest(bool on) = 0;
virtual void EnableMultisampling(bool on) = 0;
virtual void EnableLineSmooth(bool on) = 0;
virtual bool SetDepthClamp(bool on) = 0; // Deactivated only by skyboxes.
virtual void SetDepthMask(bool on) = 0; // Used by decals and indirectly by portal setup.
virtual void SetDepthFunc(int func) = 0; // Used by models, portals and mirror surfaces.
virtual void SetDepthRange(float min, float max) = 0; // Used by portal setup.
virtual void EnableDrawBufferAttachments(bool on) = 0; // Used by fog boundary drawer.
virtual void SetStencil(int offs, int op, int flags) = 0; // Used by portal setup and render hacks.
virtual void SetCulling(int mode) = 0; // Used by model drawer only.
virtual void EnableClipDistance(int num, bool state) = 0; // Use by sprite sorter for vertical splits.
virtual void Clear(int targets) = 0; // not used during normal rendering
virtual void EnableStencil(bool on) = 0; // always on for 3D, always off for 2D
virtual void SetScissor(int x, int y, int w, int h) = 0; // constant for 3D, changes for 2D
virtual void SetViewport(int x, int y, int w, int h) = 0; // constant for all 3D and all 2D
virtual void EnableDepthTest(bool on) = 0; // used by 2D, portals and render hacks.
virtual void EnableMultisampling(bool on) = 0; // only active for 2D
virtual void EnableLineSmooth(bool on) = 0; // constant setting for each 2D drawer operation
};

View file

@ -207,7 +207,13 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, GenderChanged)
// only allow if the menu is active to prevent abuse.
if (self == CurrentMenu)
{
cvar_set("gender", v == 0 ? "male" : v == 1 ? "female" : "other");
switch(v)
{
case 0: cvar_set("gender", "male"); break;
case 1: cvar_set("gender", "female"); break;
case 2: cvar_set("gender", "neutral"); break;
case 3: cvar_set("gender", "other"); break;
}
}
return 0;
}

View file

@ -112,30 +112,34 @@ void P_TouchSpecialThing (AActor *special, AActor *toucher)
// [RH]
// SexMessage: Replace parts of strings with gender-specific pronouns
// PronounMessage: Replace parts of strings with player-specific pronouns
//
// The following expansions are performed:
// %g -> he/she/it
// %h -> him/her/it
// %p -> his/her/its
// %g -> he/she/they/it
// %h -> him/her/them/it
// %p -> his/her/their/its
// %s -> his/hers/theirs/its
// %r -> he's/she's/they're/it's
// %o -> other (victim)
// %k -> killer
//
void SexMessage (const char *from, char *to, int gender, const char *victim, const char *killer)
void PronounMessage (const char *from, char *to, int pronoun, const char *victim, const char *killer)
{
static const char *genderstuff[3][3] =
static const char *pronouns[GENDER_MAX][5] =
{
{ "he", "him", "his" },
{ "she", "her", "her" },
{ "it", "it", "its" }
{ "he", "him", "his", "his", "he's" },
{ "she", "her", "her", "hers", "she's" },
{ "they", "them", "their", "theirs", "they're" },
{ "it", "it", "its", "its'", "it's" }
};
static const int gendershift[3][3] =
static const int pronounshift[GENDER_MAX][5] =
{
{ 2, 3, 3 },
{ 3, 3, 3 },
{ 2, 2, 3 }
{ 2, 3, 3, 3, 4 },
{ 3, 3, 3, 4, 5 },
{ 4, 4, 5, 6, 7 },
{ 2, 2, 3, 4, 4 }
};
const char *subst = NULL;
const char *substitute = NULL;
do
{
@ -145,32 +149,34 @@ void SexMessage (const char *from, char *to, int gender, const char *victim, con
}
else
{
int gendermsg = -1;
int grammarcase = -1;
switch (from[1])
{
case 'g': gendermsg = 0; break;
case 'h': gendermsg = 1; break;
case 'p': gendermsg = 2; break;
case 'o': subst = victim; break;
case 'k': subst = killer; break;
case 'g': grammarcase = 0; break; // Subject
case 'h': grammarcase = 1; break; // Object
case 'p': grammarcase = 2; break; // Possessive Determiner
case 's': grammarcase = 3; break; // Possessive Pronoun
case 'r': grammarcase = 4; break; // Perfective
case 'o': substitute = victim; break;
case 'k': substitute = killer; break;
}
if (subst != NULL)
if (substitute != nullptr)
{
size_t len = strlen (subst);
memcpy (to, subst, len);
size_t len = strlen (substitute);
memcpy (to, substitute, len);
to += len;
from++;
subst = NULL;
substitute = nullptr;
}
else if (gendermsg < 0)
else if (grammarcase < 0)
{
*to++ = '%';
}
else
{
strcpy (to, genderstuff[gender][gendermsg]);
to += gendershift[gender][gendermsg];
strcpy (to, pronouns[pronoun][grammarcase]);
to += pronounshift[pronoun][grammarcase];
from++;
}
}
@ -268,7 +274,7 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf
if (message == NULL || strlen(message) <= 0)
return;
SexMessage (message, gendermessage, self->player->userinfo.GetGender(),
PronounMessage (message, gendermessage, self->player->userinfo.GetGender(),
self->player->userinfo.GetName(), attacker->player->userinfo.GetName());
Printf (PRINT_MEDIUM, "%s\n", gendermessage);
}
@ -402,7 +408,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf
player->fragcount--;
if (deathmatch && player->spreecount >= 5 && cl_showsprees)
{
SexMessage (GStrings("SPREEKILLSELF"), buff,
PronounMessage (GStrings("SPREEKILLSELF"), buff,
player->userinfo.GetGender(), player->userinfo.GetName(),
player->userinfo.GetName());
StatusBar->AttachMessage (Create<DHUDMessageFadeOut>(SmallFont, buff,
@ -460,7 +466,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf
{
if (!AnnounceSpreeLoss (this))
{
SexMessage (GStrings("SPREEOVER"), buff, player->userinfo.GetGender(),
PronounMessage (GStrings("SPREEOVER"), buff, player->userinfo.GetGender(),
player->userinfo.GetName(), source->player->userinfo.GetName());
StatusBar->AttachMessage (Create<DHUDMessageFadeOut> (SmallFont, buff,
1.5f, 0.2f, 0, 0, CR_WHITE, 3.f, 0.5f), MAKE_ID('K','S','P','R'));
@ -470,7 +476,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf
{
if (!AnnounceSpree (source))
{
SexMessage (spreemsg, buff, player->userinfo.GetGender(),
PronounMessage (spreemsg, buff, player->userinfo.GetGender(),
player->userinfo.GetName(), source->player->userinfo.GetName());
StatusBar->AttachMessage (Create<DHUDMessageFadeOut> (SmallFont, buff,
1.5f, 0.2f, 0, 0, CR_WHITE, 3.f, 0.5f), MAKE_ID('K','S','P','R'));
@ -520,7 +526,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf
if (!AnnounceMultikill (source))
{
SexMessage (multimsg, buff, player->userinfo.GetGender(),
PronounMessage (multimsg, buff, player->userinfo.GetGender(),
player->userinfo.GetName(), source->player->userinfo.GetName());
StatusBar->AttachMessage (Create<DHUDMessageFadeOut> (SmallFont, buff,
1.5f, 0.8f, 0, 0, CR_RED, 3.f, 0.5f), MAKE_ID('M','K','I','L'));

View file

@ -80,7 +80,7 @@ struct FRandomSoundList
struct FPlayerClassLookup
{
FString Name;
uint16_t ListIndex[3]; // indices into PlayerSounds (0xffff means empty)
uint16_t ListIndex[GENDER_MAX]; // indices into PlayerSounds (0xffff means empty)
};
// Used to lookup a sound like "*grunt". This contains all player sounds for
@ -1622,7 +1622,8 @@ static int S_AddPlayerClass (const char *name)
FPlayerClassLookup lookup;
lookup.Name = name;
lookup.ListIndex[2] = lookup.ListIndex[1] = lookup.ListIndex[0] = 0xffff;
for(int i = 0; i < GENDER_MAX; i++)
lookup.ListIndex[i] = 0xffff;
cnum = (int)PlayerClassLookups.Push (lookup);
PlayerClassesIsSorted = false;
@ -1770,11 +1771,11 @@ static int S_LookupPlayerSound (int classidx, int gender, FSoundID refid)
{
int g;
for (g = 0; g < 3 && listidx == 0xffff; ++g)
for (g = 0; g < GENDER_MAX && listidx == 0xffff; ++g)
{
listidx = PlayerClassLookups[classidx].ListIndex[g];
}
if (g == 3)
if (g == GENDER_MAX)
{ // No sounds defined at all for this class (can this happen?)
if (classidx != DefPlayerClass)
{
@ -1796,7 +1797,7 @@ static int S_LookupPlayerSound (int classidx, int gender, FSoundID refid)
{ // This sound is unavailable.
if (ingender != 0)
{ // Try "male"
return S_LookupPlayerSound (classidx, 0, refid);
return S_LookupPlayerSound (classidx, GENDER_MALE, refid);
}
if (classidx != DefPlayerClass)
{ // Try the default class.
@ -1912,7 +1913,7 @@ bool S_AreSoundsEquivalent (AActor *actor, int id1, int id2)
int S_FindSkinnedSound (AActor *actor, FSoundID refid)
{
const char *pclass;
int gender = GENDER_MALE;
int gender = 0;
if (actor != NULL && actor->IsKindOf(RUNTIME_CLASS(APlayerPawn)))
{
@ -2074,7 +2075,7 @@ void S_MarkPlayerSounds (const char *playerclass)
{
classidx = DefPlayerClass;
}
for (int g = 0; g < 3; ++g)
for (int g = 0; g < GENDER_MAX; ++g)
{
int listidx = PlayerClassLookups[classidx].ListIndex[0];
if (listidx != 0xffff)
@ -2178,7 +2179,7 @@ CCMD (playersounds)
for (i = 0; i < PlayerClassLookups.Size(); ++i)
{
for (j = 0; j < 3; ++j)
for (j = 0; j < GENDER_MAX; ++j)
{
if ((l = PlayerClassLookups[i].ListIndex[j]) != 0xffff)
{

View file

@ -28,7 +28,8 @@ of the following entries:
is only useful when playing Doom.
Gender (opt) The gender to use for deciding which player sounds
to use for sounds not defined in the [Sounds] section.
Can be male, female, or cyborg. The default is male.
Can be male, female, neutral or cyborg.
The default is male.
ColorRange (opt) The range of palette entries to recolor to match
the player's color. Specified as <first>,<last>.
For Doom, this defaults to 112,127. For Heretic,

View file

@ -159,6 +159,9 @@ namespace swrenderer
auto viewport = Thread->Viewport.get();
Clip3DFloors *clip3d = Thread->Clip3D.get();
if (curline->sidedef->GetTexture(side_t::mid).isNull())
return false;
FTexture *tex = TexMan(curline->sidedef->GetTexture(side_t::mid), true);
if (i_compatflags & COMPATF_MASKEDMIDTEX)
{

View file

@ -2317,7 +2317,8 @@ OPTVAL_ON = "On";
OPTVAL_AUTO = "Auto";
OPTVAL_MALE = "Male";
OPTVAL_FEMALE = "Female";
OPTVAL_OTHER = "Robotic";
OPTVAL_NEUTRAL = "Neutral";
OPTVAL_OTHER = "Object";
OPTVAL_UPPERLEFT = "Upper left";
OPTVAL_UPPERRIGHT = "Upper right";
OPTVAL_LOWERLEFT = "Lower left";

View file

@ -368,7 +368,8 @@ OptionValue "Gender"
{
0, "$OPTVAL_MALE"
1, "$OPTVAL_FEMALE"
2, "$OPTVAL_OTHER"
2, "$OPTVAL_NEUTRAL"
3, "$OPTVAL_OTHER"
}
ListMenu "PlayerMenu"

View file

@ -1366,6 +1366,14 @@ enum EPlayerState
PST_GONE // Player has left the game
}
enum EPlayerGender
{
GENDER_MALE,
GENDER_FEMALE,
GENDER_NEUTRAL,
GENDER_OTHER
}
struct PlayerInfo native play // this is what internally is known as player_t
{
// technically engine constants but the only part of the playsim using them is the player.