Merge branch 'next' into kill-zshift

# Conflicts:
#	src/p_mobj.c
This commit is contained in:
MascaraSnake 2019-12-27 08:11:04 +01:00
commit e71d07fa8e
52 changed files with 8837 additions and 7122 deletions

View File

@ -0,0 +1,77 @@
// Default lump name for new map
defaultlumpname = "MAP01";
//GZDB specific. Don't try to load lumps that don't exist.
basegame = 0;
//Sky textures for vanilla maps
defaultskytextures
{
SKY1 = "MAP01,MAP02,MAP03,MAP33,MAP50,MAP60,MAPF0,MAPM0";
SKY2 = "MAPM7,MAPMB";
SKY4 = "MAP04,MAP06,MAP61,MAPF6,MAPM1";
SKY6 = "MAP05,MAP51,MAPMA";
SKY7 = "MAPM2,MAPM5";
SKY8 = "MAP07,MAP08,MAP09,MAP52,MAP62,MAPF1";
SKY10 = "MAP10,MAP12,MAP53,MAP63,MAPM3";
SKY11 = "MAP11,MAPF7";
SKY13 = "MAP13,MAP64";
SKY14 = "MAP14";
SKY15 = "MAP15,MAP54";
SKY17 = "MAP70";
SKY20 = "MAP32,MAP55,MAP65,MAPF2,MAPF5";
SKY21 = "MAPM4";
SKY22 = "MAP22,MAP23,MAP25,MAP26,MAP27,MAP56,MAP66,MAPF4,MAPM6";
SKY30 = "MAP30";
SKY31 = "MAP31";
SKY35 = "MAP42";
SKY40 = "MAP41,MAP71,MAPM9";
SKY55 = "MAPF3,MAPM8";
SKY68 = "MAPF8";
SKY99 = "MAP57,MAPZ0";
SKY159 = "MAP16";
SKY172 = "MAP40";
SKY300 = "MAP72";
SKY301 = "MAP73";
}
// Skill levels
skills
{
1 = "Normal";
}
// Skins
skins
{
Sonic;
Tails;
Knuckles;
Amy;
Fang;
Metalsonic;
}
// Gametypes
gametypes
{
-1 = "Single Player";
0 = "Co-op";
1 = "Competition";
2 = "Race";
3 = "Match";
4 = "Team Match";
5 = "Tag";
6 = "Hide and Seek";
7 = "CTF";
}
// Texture loading options
defaultwalltexture = "GFZROCK";
defaultfloortexture = "GFZFLR01";
defaultceilingtexture = "F_SKY1";
// Default texture sets
// (these are not required, but useful for new users)
texturesets
{
}

View File

@ -0,0 +1,309 @@
common
{
// Some common settings
// Default testing parameters
testparameters = "-file \"%AP\" \"%F\" -warp %L";
testshortpaths = true;
// Action special help (mxd)
actionspecialhelp = "https://wiki.srb2.org/wiki/Linedef_type_%K";
// Default nodebuilder configurations
defaultsavecompiler = "zennode_normal";
defaulttestcompiler = "zennode_fast";
// Generalized actions
generalizedlinedefs = false;
generalizedsectors = true;
mixtexturesflats = true;
defaulttexturescale = 1.0f;
defaultflatscale = 1.0f;
scaledtextureoffsets = true;
// Thing number for start position in 3D Mode
start3dmode = 3328;
// Texture sources
textures
{
include("SRB222_misc.cfg", "textures");
}
// Patch sources
patches
{
include("SRB222_misc.cfg", "patches");
}
// Sprite sources
sprites
{
include("SRB222_misc.cfg", "sprites");
}
// Flat sources
flats
{
include("SRB222_misc.cfg", "flats");
}
}
mapformat_doom
{
// The format interface handles the map data format - DoomMapSetIO for SRB2DB2, SRB2MapSetIO for Zone Builder
formatinterface = "SRB2MapSetIO";
/*
GAME DETECT PATTERN
Used to guess the game for which a WAD file is made.
1 = One of these lumps must exist
2 = None of these lumps must exist
3 = All of these lumps must exist
*/
gamedetect
{
EXTENDED = 2;
BEHAVIOR = 2;
E#M# = 2;
MAP?? = 1;
}
/*
MAP LUMP NAMES
Map lumps are loaded with the map as long as they are right after each other. When the editor
meets a lump which is not defined in this list it will ignore the map if not satisfied.
The order of items defines the order in which lumps will be written to WAD file on save.
To indicate the map header lump, use ~MAP
Legenda:
required = Lump is required to exist.
blindcopy = Lump will be copied along with the map blindly. (usefull for lumps Doom Builder doesn't use)
nodebuild = The nodebuilder generates this lump.
allowempty = The nodebuilder is allowed to leave this lump empty.
script = This lump is a text-based script. Specify the filename of the script configuration to use.
*/
maplumpnames
{
include("SRB222_misc.cfg", "doommaplumpnames");
}
// When this is set to true, sectors with the same tag will light up when a line is highlighted
linetagindicatesectors = true;
// Special linedefs
include("SRB222_misc.cfg", "speciallinedefs");
// Default flags for first new thing (As far as 2.2 goes, they're empty just like in 2.1)
defaultthingflags
{
}
// DEFAULT SECTOR BRIGHTNESS LEVELS
sectorbrightness
{
include("SRB222_misc.cfg", "sectorbrightness");
}
// SECTOR TYPES-----------------------------------------------------------------
sectortypes
{
include("SRB222_sectors.cfg", "sectortypes");
}
// GENERALISED SECTOR TYPES-----------------------------------------------------------------
gen_sectortypes
{
include("SRB222_sectors.cfg", "gen_sectortypes");
}
// LINEDEF FLAGS
linedefflags
{
include("SRB222_misc.cfg", "linedefflags");
}
// Linedef flags UDMF translation table
// This is needed for copy/paste and prefabs to work properly
// When the UDMF field name is prefixed with ! it is inverted
linedefflagstranslation
{
include("SRB222_misc.cfg", "linedefflagstranslation");
}
// LINEDEF ACTIVATIONS
linedefactivations
{
}
// LINEDEF TYPES
linedeftypes
{
include("SRB222_linedefs.cfg", "doom");
}
// THING FLAGS
thingflags
{
include("SRB222_misc.cfg", "thingflags");
}
// Thing flags UDMF translation table
// This is needed for copy/paste and prefabs to work properly
// When the UDMF field name is prefixed with ! it is inverted
thingflagstranslation
{
include("SRB222_misc.cfg", "thingflagstranslation");
}
// THING FLAGS ERROR MASK
// Mask for the thing flags which indicates the options
// that make the same thing appear in the same modes
thingflagsmask1 = 7; // 1 + 2 + 4
thingflagsmask2 = 0;
}
mapformat_udmf
{
// The format interface handles the map data format
formatinterface = "UniversalMapSetIO";
// Enables support for long (> 8 chars) texture names
// WARNING: this should only be enabled for UDMF game configurations!
// WARNING: enabling this will make maps incompatible with Doom Builder 2 and can lead to problems in Slade 3!
longtexturenames = false;
// Default nodebuilder configurations
defaultsavecompiler = "zdbsp_udmf_normal";
defaulttestcompiler = "zdbsp_udmf_fast";
engine = "srb2"; // override that so that DB2 uses the correct namespace
maplumpnames
{
include("UDMF_misc.cfg", "udmfmaplumpnames_begin");
include("SRB222_misc.cfg", "udmfmaplumpnames");
include("UDMF_misc.cfg", "udmfmaplumpnames_end");
}
universalfields
{
// include("SRB222_misc.cfg", "universalfields");
}
// When this is set to true, sectors with the same tag will light up when a line is highlighted
linetagindicatesectors = false;
// Special linedefs
include("SRB222_misc.cfg", "speciallinedefs_udmf");
// Default flags for first new thing (As far as 2.2 goes, they're empty just like in 2.1)
defaultthingflags
{
}
// Generalized actions
generalizedlinedefs = false;
// SECTOR FLAGS
sectorflags
{
// include("SRB222_misc.cfg", "sectorflags");
}
// DEFAULT SECTOR BRIGHTNESS LEVELS
sectorbrightness
{
include("SRB222_misc.cfg", "sectorbrightness");
}
// SECTOR TYPES
sectortypes
{
include("SRB222_sectors.cfg", "sectortypes");
}
// SECTOR RENSERSTYLES
/* sectorrenderstyles
{
include("SRB222_misc.cfg", "sectorrenderstyles");
}*/
// LINEDEF FLAGS
linedefflags
{
include("SRB222_misc.cfg", "linedefflags_udmf");
}
// LINEDEF ACTIVATIONS
linedefactivations
{
include("SRB222_misc.cfg", "linedefactivations_udmf");
}
linedefflagstranslation
{
}
// LINEDEF RENSERSTYLES
linedefrenderstyles
{
include("SRB222_misc.cfg", "linedefrenderstyles");
}
//SIDEDEF FLAGS
/* sidedefflags
{
include("UDMF_misc.cfg", "sidedefflags");
}*/
// THING FLAGS
thingflags
{
include("SRB222_misc.cfg", "thingflags_udmf");
}
// Thing flags UDMF translation table
// This is needed for copy/paste and prefabs to work properly
// When the UDMF field name is prefixed with ! it is inverted
thingflagstranslation
{
include("SRB222_misc.cfg", "thingflagstranslation");
}
// THING RENSERSTYLES
/* thingrenderstyles
{
include("SRB222_misc.cfg", "thingrenderstyles");
}*/
// How to compare thing flags (for the stuck things error checker)
/* thingflagscompare
{
include("UDMF_misc.cfg", "thingflagscompare");
}*/
//mxd. Thing flags UDMF translation table
// This is needed for copy/paste and prefabs to work properly
// When the UDMF field name is prefixed with ! it is inverted
thingflagstranslation
{
}
// LINEDEF TYPES
linedeftypes
{
include("SRB222_linedefs.cfg", "udmf");
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,726 @@
linedefflags
{
1 = "[0] Impassable";
2 = "[1] Block Enemies";
4 = "[2] Double-Sided";
8 = "[3] Upper Unpegged";
16 = "[4] Lower Unpegged";
32 = "[5] Slope Skew (E1)";
64 = "[6] Not Climbable";
128 = "[7] No Midtexture Skew (E2)";
256 = "[8] Peg Midtexture (E3)";
512 = "[9] Solid Midtexture (E4)";
1024 = "[10] Repeat Midtexture (E5)";
2048 = "[11] Netgame Only";
4096 = "[12] No Netgame";
8192 = "[13] Effect 6";
16384 = "[14] Bouncy Wall";
32768 = "[15] Transfer Line";
}
// LINEDEF ACTIVATIONS
// Make sure these are in order from lowest value to highest value
linedefactivations
{
}
// Linedef flags UDMF translation table
// This is needed for copy/paste and prefabs to work properly
// When the UDMF field name is prefixed with ! it is inverted
linedefflagstranslation
{
1 = "blocking";
2 = "blockmonsters";
4 = "twosided";
8 = "dontpegtop";
16 = "dontpegbottom";
32 = "skewtd";
64 = "noclimb";
128 = "noskew";
256 = "midpeg";
512 = "midsolid";
1024 = "wrapmidtex";
2048 = "netonly";
4096 = "nonet";
8192 = "effect6";
16384 = "bouncy";
32768 = "transfer";
}
linedefflags_udmf
{
blocking = "Impassable";
blockmonsters = "Block Enemies";
twosided = "Double-Sided";
dontpegtop = "Upper Unpegged";
dontpegbottom = "Lower Unpegged";
skewtd = "Slope Skew";
noclimb = "Not Climbable";
noskew = "No Midtexture Skew";
midpeg = "Peg Midtexture";
midsolid = "Solid Midtexture";
wrapmidtex = "Repeat Midtexture";
// netonly = "Netgame-Only special";
// nonet = "No netgame special";
// effect6 = "Effect 6";
bouncy = "Bouncy Wall";
// transfer = "Transfer Line";
}
linedefactivations_udmf
{
notriggerorder = "Out of Order";
netonly = "Netgame-Only";
nonet = "No netgame";
}
sidedefflags
{
clipmidtex = "Clip middle texture";
wrapmidtex = "Wrap middle texture";
smoothlighting = "Smooth lighting";
nofakecontrast = "Even lighting";
nodecals = "No decals";
lightfog = "Use sidedef brightness on fogged walls";
}
//RENDER STYLES
thingrenderstyles
{
}
linedefrenderstyles
{
translucent = "Translucent";
fog = "Fog";
}
sectorrenderstyles
{
}
thingflags
{
1 = "[1] Extra";
2 = "[2] Flip";
4 = "[4] Special";
8 = "[8] Ambush";
}
// THING FLAGS
thingflags_udmf
{
extra = "Extra";
flip = "Flip";
special = "Special";
ambush = "Ambush";
}
// Thing flags UDMF translation table
// This is needed for copy/paste and prefabs to work properly
// When the UDMF field name is prefixed with ! it is inverted
thingflagstranslation
{
1 = "extra";
2 = "flip";
4 = "special";
8 = "ambush";
}
// DEFAULT SECTOR BRIGHTNESS LEVELS
sectorbrightness
{
255;
248;
240;
232;
224;
216;
208;
200;
192;
184;
176;
168;
160;
152;
144;
136;
128;
120;
112;
104;
96;
88;
80;
72;
64;
56;
48;
40;
32;
24;
16;
8;
0;
}
/*
TEXTURES AND FLAT SOURCES
This tells Doom Builder where to find the information for textures
and flats in the IWAD file, Addition WAD file and Map WAD file.
Start and end lumps must be given in a structure (of which the
key name doesnt matter) and any textures or flats in between them
are loaded in either the textures category or flats category.
For textures: PNAMES, TEXTURE1 and TEXTURE2 are loaded by default.
*/
textures
{
zdoom1
{
start = "TX_START";
end = "TX_END";
}
}
/*
ADDITIONAL UNIVERSAL DOOM MAP FORMAT FIELD DEFINITIONS
Only add fields here that Doom Builder does not edit with its own user-interface!
The "default" field must match the UDMF specifications!
Field data types:
0 = integer *
1 = float
2 = string
3 = bool
4 = linedef action (integer) *
5 = sector effect (integer) *
6 = texture (string)
7 = flat (string)
8 = angle in degrees (integer)
9 = angle in radians (float)
10 = XXRRGGBB color (integer)
11 = enum option (integer) *
12 = enum bits (integer) *
13 = sector tag (integer) *
14 = thing tag (integer) *
15 = linedef tag (integer) *
16 = enum option (string)
17 = angle in degrees (float)
22 = byte angle (integer)
*/
universalfields
{
sector
{
friction
{
name = "Friction";
type = 1;
default = 1;
}
specialeffectplanes
{
type = 11;
enum = "floorceiling";
default = 0;
}
colormapbegin
{
type = 0;
default = 0;
}
colormapend
{
type = 0;
default = 33;
}
foglighting
{
type = 3;
default = false;
}
teambase
{
type = 11;
enum = "ctfteam";
default = 0;
}
triggersector
{
type = 3;
default = false;
}
triggerobject
{
type = 11;
enum = "triggerobjects";
default = 0;
}
triggersurface
{
type = 11;
enum = "triggersurfaces";
default = 0;
}
ringdrain
{
type = 1;
default = 0;
}
}
linedef
{
executordelay
{
type = 0;
default = 0;
}
midtexrepetitions
{
type = 0;
default = 0;
}
arg5
{
type = 0;
default = 0;
}
arg1str
{
type = 2;
default = "";
}
}
thing
{
}
}
/*
MAP LUMP NAMES
Map lumps are loaded with the map as long as they are right after each other. When the editor
meets a lump which is not defined in this list it will ignore the map if not satisfied.
The order of items defines the order in which lumps will be written to WAD file on save.
To indicate the map header lump, use ~MAP
Legenda:
required = Lump is required to exist.
blindcopy = Lump will be copied along with the map blindly. (useful for lumps Doom Builder doesn't use)
nodebuild = The nodebuilder generates this lump.
allowempty = The nodebuilder is allowed to leave this lump empty.
scriptbuild = This lump is a text-based script, which should be compiled using current script compiler;
script = This lump is a text-based script. Specify the filename of the script configuration to use.
*/
doommaplumpnames
{
~MAP
{
required = true;
blindcopy = true;
nodebuild = false;
}
THINGS
{
required = true;
nodebuild = true;
allowempty = true;
}
LINEDEFS
{
required = true;
nodebuild = true;
allowempty = false;
}
SIDEDEFS
{
required = true;
nodebuild = true;
allowempty = false;
}
VERTEXES
{
required = true;
nodebuild = true;
allowempty = false;
}
SEGS
{
required = false;
nodebuild = true;
allowempty = false;
}
SSECTORS
{
required = false;
nodebuild = true;
allowempty = false;
}
NODES
{
required = false;
nodebuild = true;
allowempty = false;
}
SECTORS
{
required = true;
nodebuild = true;
allowempty = false;
}
REJECT
{
required = false;
nodebuild = true;
allowempty = false;
}
BLOCKMAP
{
required = false;
nodebuild = true;
allowempty = true;
}
}
udmfmaplumpnames
{
ZNODES
{
required = false;
nodebuild = true;
allowempty = false;
}
REJECT
{
required = false;
nodebuild = true;
allowempty = false;
}
BLOCKMAP
{
required = false;
nodebuild = true;
allowempty = true;
}
}
// ENUMERATIONS
// These are enumerated lists for linedef types and UDMF fields.
// Reserved names are: angledeg, anglerad, color, texture, flat
enums
{
falsetrue
{
0 = "False";
1 = "True";
}
yesno
{
0 = "Yes";
1 = "No";
}
noyes
{
0 = "No";
1 = "Yes";
}
onoff
{
0 = "On";
1 = "Off";
}
offon
{
0 = "Off";
1 = "On";
}
updown
{
0 = "Up";
1 = "Down";
}
downup
{
0 = "Down";
1 = "Up";
}
addset
{
0 = "Add";
1 = "Set";
}
floorceiling
{
0 = "Floor";
1 = "Ceiling";
2 = "Floor and ceiling";
}
triggertype
{
0 = "Continuous";
1 = "Each Time (Enter)";
2 = "Each Time (Enter and leave)";
3 = "Once";
}
frontback
{
0 = "None";
1 = "Front";
2 = "Back";
}
ctfteam
{
0 = "None";
1 = "Red";
2 = "Blue";
}
triggerobjects
{
0 = "Any player";
1 = "All players";
2 = "Pushable object";
3 = "Any object with thinker";
}
triggersurfaces
{
0 = "Floor touch";
1 = "Ceiling touch";
2 = "Floor or ceiling touch";
3 = "Anywhere in sector";
}
tangibility
{
1 = "Intangible from top";
2 = "Intangible from bottom";
4 = "Don't block players";
8 = "Don't block non-players";
}
}
//Default things filters
thingsfilters
{
filter0
{
name = "Player starts";
category = "starts";
type = -1;
}
filter1
{
name = "Enemies";
category = "enemies";
type = -1;
}
filter2
{
name = "NiGHTS Track";
category = "nightstrk";
type = -1;
}
filter3
{
name = "Normal Gravity";
category = "";
type = -1;
fields
{
2 = false;
}
}
filter4
{
name = "Reverse Gravity";
category = "";
type = -1;
fields
{
2 = true;
}
}
}
thingsfilters_udmf
{
}
// Special linedefs
speciallinedefs
{
soundlinedefflag = 64; // See linedefflags
singlesidedflag = 1; // See linedefflags
doublesidedflag = 4; // See linedefflags
impassableflag = 1;
upperunpeggedflag = 8;
lowerunpeggedflag = 16;
repeatmidtextureflag = 1024;
pegmidtextureflag = 256;
}
speciallinedefs_udmf
{
soundlinedefflag = "noclimb";
singlesidedflag = "blocking";
doublesidedflag = "twosided";
impassableflag = "blocking";
upperunpeggedflag = "dontpegtop";
lowerunpeggedflag = "dontpegbottom";
repeatmidtextureflag = "wrapmidtex";
pegmidtextureflag = "midpeg";
}
scriptlumpnames
{
MAINCFG
{
script = "SOC.cfg";
}
OBJCTCFG
{
script = "SOC.cfg";
}
SOC_
{
script = "SOC.cfg";
isprefix = true;
}
LUA_
{
script = "Lua.cfg";
isprefix = true;
}
}
// Texture sources
textures
{
zdoom1
{
start = "TX_START";
end = "TX_END";
}
}
// Patch sources
patches
{
standard1
{
start = "P_START";
end = "P_END";
}
standard2
{
start = "PP_START";
end = "PP_END";
}
}
// Sprite sources
sprites
{
standard1
{
start = "S_START";
end = "S_END";
}
standard2
{
start = "SS_START";
end = "SS_END";
}
}
// Flat sources
flats
{
standard1
{
start = "F_START";
end = "F_END";
}
standard2
{
start = "FF_START";
end = "FF_END";
}
standard3
{
start = "FF_START";
end = "F_END";
}
standard4
{
start = "F_START";
end = "FF_END";
}
}

View File

@ -0,0 +1,109 @@
sectortypes
{
0 = "Normal";
1 = "Damage";
2 = "Damage (Water)";
3 = "Damage (Fire)";
4 = "Damage (Electrical)";
5 = "Spikes";
6 = "Death Pit (Camera Tilt)";
7 = "Death Pit (No Camera Tilt)";
8 = "Instant Kill";
9 = "Ring Drainer (Floor Touch)";
10 = "Ring Drainer (Anywhere in Sector)";
11 = "Special Stage Damage";
12 = "Space Countdown";
13 = "Ramp Sector (double step-up/down)";
14 = "Non-Ramp Sector (no step-down)";
15 = "Bouncy FOF";
16 = "Trigger Line Ex. (Pushable Objects)";
32 = "Trigger Line Ex. (Anywhere, All Players)";
48 = "Trigger Line Ex. (Floor Touch, All Players)";
64 = "Trigger Line Ex. (Anywhere in Sector)";
80 = "Trigger Line Ex. (Floor Touch)";
96 = "Trigger Line Ex. (Emerald Check)";
112 = "Trigger Line Ex. (NiGHTS Mare)";
128 = "Check for Linedef Executor on FOFs";
144 = "Egg Capsule";
160 = "Special Stage Time/Rings Parameters";
176 = "Custom Global Gravity";
512 = "Wind/Current";
1024 = "Conveyor Belt";
1280 = "Speed Pad";
4096 = "Star Post Activator";
8192 = "Exit/Special Stage Pit/Return Flag";
12288 = "CTF Red Team Base";
16384 = "CTF Blue Team Base";
20480 = "Fan Sector";
24576 = "Super Sonic Transform";
28672 = "Force Spin";
32768 = "Zoom Tube Start";
36864 = "Zoom Tube End";
40960 = "Circuit Finish Line";
45056 = "Rope Hang";
49152 = "Intangible to the Camera";
}
gen_sectortypes
{
first
{
0 = "Normal";
1 = "Damage";
2 = "Damage (Water)";
3 = "Damage (Fire)";
4 = "Damage (Electrical)";
5 = "Spikes";
6 = "Death Pit (Camera Tilt)";
7 = "Death Pit (No Camera Tilt)";
8 = "Instant Kill";
9 = "Ring Drainer (Floor Touch)";
10 = "Ring Drainer (Anywhere in Sector)";
11 = "Special Stage Damage";
12 = "Space Countdown";
13 = "Ramp Sector (double step-up/down)";
14 = "Non-Ramp Sector (no step-down)";
15 = "Bouncy FOF";
}
second
{
0 = "Normal";
16 = "Trigger Line Ex. (Pushable Objects)";
32 = "Trigger Line Ex. (Anywhere, All Players)";
48 = "Trigger Line Ex. (Floor Touch, All Players)";
64 = "Trigger Line Ex. (Anywhere in Sector)";
80 = "Trigger Line Ex. (Floor Touch)";
96 = "Trigger Line Ex. (Emerald Check)";
112 = "Trigger Line Ex. (NiGHTS Mare)";
128 = "Check for Linedef Executor on FOFs";
144 = "Egg Capsule";
160 = "Special Stage Time/Rings Parameters";
176 = "Custom Global Gravity";
}
third
{
0 = "Normal";
512 = "Wind/Current";
1024 = "Conveyor Belt";
1280 = "Speed Pad";
}
fourth
{
0 = "Normal";
4096 = "Star Post Activator";
8192 = "Exit/Special Stage Pit/Return Flag";
12288 = "CTF Red Team Base";
16384 = "CTF Blue Team Base";
20480 = "Fan Sector";
24576 = "Super Sonic Transform";
28672 = "Force Spin";
32768 = "Zoom Tube Start";
36864 = "Zoom Tube End";
40960 = "Circuit Finish Line";
45056 = "Rope Hang";
49152 = "Intangible to the Camera";
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,38 @@
/************************************************************************\
Zone Builder Game Configuration for Sonic Robo Blast 2 Version 2.2
\************************************************************************/
// This is required to prevent accidental use of a different configuration
type = "Doom Builder 2 Game Configuration";
// This is the title to show for this game
game = "Sonic Robo Blast 2 - 2.2 (Doom format)";
// This is the simplified game engine/sourceport name
engine = "zdoom";
// Settings common to all games and all map formats
include("Includes\\SRB222_common.cfg", "common");
// Settings common to Doom map format
include("Includes\\SRB222_common.cfg", "mapformat_doom");
include("Includes\\Game_SRB222.cfg");
// Script lumps detection
scriptlumpnames
{
include("Includes\\SRB222_misc.cfg", "scriptlumpnames");
}
// THING TYPES
thingtypes
{
include("Includes\\SRB222_things.cfg");
}
//Default things filters
thingsfilters
{
include("Includes\\SRB222_misc.cfg", "thingsfilters");
}

View File

@ -0,0 +1,47 @@
/************************************************************************\
Zone Builder Game Configuration for Sonic Robo Blast 2 Version 2.2
\************************************************************************/
// This is required to prevent accidental use of a different configuration
type = "Doom Builder 2 Game Configuration";
// This is the title to show for this game
game = "Sonic Robo Blast 2 - 2.2 (UDMF)";
// This is the simplified game engine/sourceport name
engine = "zdoom";
// Settings common to all games and all map formats
include("Includes\\SRB222_common.cfg", "common");
// Settings common to Doom map format
include("Includes\\SRB222_common.cfg", "mapformat_udmf");
include("Includes\\Game_SRB222.cfg");
// Script lumps detection
scriptlumpnames
{
include("Includes\\SRB222_misc.cfg", "scriptlumpnames");
}
// THING TYPES
thingtypes
{
include("Includes\\SRB222_things.cfg");
}
//Default things filters
thingsfilters
{
include("Includes\\SRB222_misc.cfg", "thingsfilters");
}
// ENUMERATIONS
// Each engine has its own additional thing types
// These are enumerated lists for linedef types and UDMF fields.
enums
{
// Basic game enums
include("Includes\\SRB222_misc.cfg", "enums");
}

View File

@ -611,11 +611,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->health = LONG(players[i].mo->health); rsp->health = LONG(players[i].mo->health);
rsp->angle = (angle_t)LONG(players[i].mo->angle); rsp->angle = (angle_t)LONG(players[i].mo->angle);
#ifdef ROTSPRITE
rsp->rollangle = (angle_t)LONG(players[i].mo->rollangle); rsp->rollangle = (angle_t)LONG(players[i].mo->rollangle);
#else
rsp->rollangle = 0;
#endif
rsp->x = LONG(players[i].mo->x); rsp->x = LONG(players[i].mo->x);
rsp->y = LONG(players[i].mo->y); rsp->y = LONG(players[i].mo->y);
rsp->z = LONG(players[i].mo->z); rsp->z = LONG(players[i].mo->z);
@ -766,9 +762,7 @@ static void resynch_read_player(resynch_pak *rsp)
//At this point, the player should have a body, whether they were respawned or not. //At this point, the player should have a body, whether they were respawned or not.
P_UnsetThingPosition(players[i].mo); P_UnsetThingPosition(players[i].mo);
players[i].mo->angle = (angle_t)LONG(rsp->angle); players[i].mo->angle = (angle_t)LONG(rsp->angle);
#ifdef ROTSPRITE
players[i].mo->rollangle = (angle_t)LONG(rsp->rollangle); players[i].mo->rollangle = (angle_t)LONG(rsp->rollangle);
#endif
players[i].mo->eflags = (UINT16)SHORT(rsp->eflags); players[i].mo->eflags = (UINT16)SHORT(rsp->eflags);
players[i].mo->flags = LONG(rsp->flags); players[i].mo->flags = LONG(rsp->flags);
players[i].mo->flags2 = LONG(rsp->flags2); players[i].mo->flags2 = LONG(rsp->flags2);
@ -1025,7 +1019,7 @@ static void SV_SendResynch(INT32 node)
netbuffer->packettype = PT_RESYNCHEND; netbuffer->packettype = PT_RESYNCHEND;
netbuffer->u.resynchend.randomseed = P_GetRandSeed(); netbuffer->u.resynchend.randomseed = P_GetRandSeed();
if (gametype == GT_CTF) if (gametyperules & GTR_TEAMFLAGS)
resynch_write_ctf(&netbuffer->u.resynchend); resynch_write_ctf(&netbuffer->u.resynchend);
resynch_write_others(&netbuffer->u.resynchend); resynch_write_others(&netbuffer->u.resynchend);
@ -2111,10 +2105,10 @@ static void CL_ConnectToServer(boolean viams)
if (i != -1) if (i != -1)
{ {
UINT8 num = serverlist[i].info.gametype; UINT16 num = serverlist[i].info.gametype;
const char *gametypestr = NULL; const char *gametypestr = NULL;
CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername); CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername);
if (num < NUMGAMETYPES) if (num < gametypecount)
gametypestr = Gametype_Names[num]; gametypestr = Gametype_Names[num];
if (gametypestr) if (gametypestr)
CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr); CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr);
@ -2430,7 +2424,7 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason)
} }
} }
if (gametype == GT_CTF) if (gametyperules & GTR_TEAMFLAGS)
P_PlayerFlagBurst(&players[playernum], false); // Don't take the flag with you! P_PlayerFlagBurst(&players[playernum], false); // Don't take the flag with you!
// If in a special stage, redistribute the player's spheres across // If in a special stage, redistribute the player's spheres across
@ -2486,6 +2480,17 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason)
(void)reason; (void)reason;
#endif #endif
// don't look through someone's view who isn't there
if (playernum == displayplayer)
{
#ifdef HAVE_BLUA
// Call ViewpointSwitch hooks here.
// The viewpoint was forcibly changed.
LUAh_ViewpointSwitch(&players[consoleplayer], &players[displayplayer], true);
#endif
displayplayer = consoleplayer;
}
// Reset player data // Reset player data
CL_ClearPlayer(playernum); CL_ClearPlayer(playernum);
@ -2503,16 +2508,13 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason)
RemoveAdminPlayer(playernum); // don't stay admin after you're gone RemoveAdminPlayer(playernum); // don't stay admin after you're gone
} }
if (playernum == displayplayer)
displayplayer = consoleplayer; // don't look through someone's view who isn't there
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
LUA_InvalidatePlayer(&players[playernum]); LUA_InvalidatePlayer(&players[playernum]);
#endif #endif
if (G_TagGametype()) //Check if you still have a game. Location flexible. =P if (G_TagGametype()) //Check if you still have a game. Location flexible. =P
P_CheckSurvivors(); P_CheckSurvivors();
else if (gametype == GT_RACE || gametype == GT_COMPETITION) else if (gametyperules & GTR_RACE)
P_CheckRacers(); P_CheckRacers();
} }
@ -3461,7 +3463,7 @@ void SV_StartSinglePlayerServer(void)
server = true; server = true;
netgame = false; netgame = false;
multiplayer = false; multiplayer = false;
gametype = GT_COOP; G_SetGametype(GT_COOP);
// no more tic the game with this settings! // no more tic the game with this settings!
SV_StopServer(); SV_StopServer();
@ -3740,7 +3742,7 @@ static void HandlePacketFromAwayNode(SINT8 node)
if (client) if (client)
{ {
maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic);
gametype = netbuffer->u.servercfg.gametype; G_SetGametype(netbuffer->u.servercfg.gametype);
modifiedgame = netbuffer->u.servercfg.modifiedgame; modifiedgame = netbuffer->u.servercfg.modifiedgame;
for (j = 0; j < MAXPLAYERS; j++) for (j = 0; j < MAXPLAYERS; j++)
adminplayers[j] = netbuffer->u.servercfg.adminplayers[j]; adminplayers[j] = netbuffer->u.servercfg.adminplayers[j];
@ -4124,7 +4126,7 @@ static void HandlePacketFromPlayer(SINT8 node)
P_SetRandSeed(netbuffer->u.resynchend.randomseed); P_SetRandSeed(netbuffer->u.resynchend.randomseed);
if (gametype == GT_CTF) if (gametyperules & GTR_TEAMFLAGS)
resynch_read_ctf(&netbuffer->u.resynchend); resynch_read_ctf(&netbuffer->u.resynchend);
resynch_read_others(&netbuffer->u.resynchend); resynch_read_others(&netbuffer->u.resynchend);

View File

@ -762,7 +762,7 @@ void D_StartTitle(void)
gameaction = ga_nothing; gameaction = ga_nothing;
displayplayer = consoleplayer = 0; displayplayer = consoleplayer = 0;
gametype = GT_COOP; G_SetGametype(GT_COOP);
paused = false; paused = false;
advancedemo = false; advancedemo = false;
F_InitMenuPresValues(); F_InitMenuPresValues();
@ -1419,14 +1419,14 @@ void D_SRB2Main(void)
if (newgametype == -1) // reached end of the list with no match if (newgametype == -1) // reached end of the list with no match
{ {
j = atoi(sgametype); // assume they gave us a gametype number, which is okay too j = atoi(sgametype); // assume they gave us a gametype number, which is okay too
if (j >= 0 && j < NUMGAMETYPES) if (j >= 0 && j < gametypecount)
newgametype = (INT16)j; newgametype = (INT16)j;
} }
if (newgametype != -1) if (newgametype != -1)
{ {
j = gametype; j = gametype;
gametype = newgametype; G_SetGametype(newgametype);
D_GameTypeChanged(j); D_GameTypeChanged(j);
} }
} }

View File

@ -327,6 +327,10 @@ consvar_t cv_numlaps = {"numlaps", "4", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_con
static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}}; static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}};
consvar_t cv_basenumlaps = {"basenumlaps", "Map default", CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_basenumlaps = {"basenumlaps", "Map default", CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL};
// Point and time limits for every gametype
INT32 pointlimits[NUMGAMETYPES];
INT32 timelimits[NUMGAMETYPES];
// log elemental hazards -- not a netvar, is local to current player // log elemental hazards -- not a netvar, is local to current player
consvar_t cv_hazardlog = {"hazardlog", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_hazardlog = {"hazardlog", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -381,6 +385,9 @@ char timedemo_csv_id[256];
boolean timedemo_quit; boolean timedemo_quit;
INT16 gametype = GT_COOP; INT16 gametype = GT_COOP;
UINT32 gametyperules = 0;
INT16 gametypecount = (GT_CTF + 1);
boolean splitscreen = false; boolean splitscreen = false;
boolean circuitmap = false; boolean circuitmap = false;
INT32 adminplayers[MAXPLAYERS]; INT32 adminplayers[MAXPLAYERS];
@ -1126,7 +1133,7 @@ UINT8 CanChangeSkin(INT32 playernum)
return true; return true;
// Can change skin during initial countdown. // Can change skin during initial countdown.
if ((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE) if ((gametyperules & GTR_RACE) && leveltime < 4*TICRATE)
return true; return true;
if (G_TagGametype()) if (G_TagGametype())
@ -1942,7 +1949,7 @@ static void Command_Map_f(void)
if (isdigit(gametypename[0])) if (isdigit(gametypename[0]))
{ {
d = atoi(gametypename); d = atoi(gametypename);
if (d >= 0 && d < NUMGAMETYPES) if (d >= 0 && d < gametypecount)
newgametype = d; newgametype = d;
else else
{ {
@ -1950,7 +1957,7 @@ static void Command_Map_f(void)
"Gametype number %d is out of range. Use a number between" "Gametype number %d is out of range. Use a number between"
" 0 and %d inclusive. ...Or just use the name. :v\n", " 0 and %d inclusive. ...Or just use the name. :v\n",
d, d,
NUMGAMETYPES-1); gametypecount-1);
Z_Free(realmapname); Z_Free(realmapname);
Z_Free(mapname); Z_Free(mapname);
return; return;
@ -2069,8 +2076,9 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
lastgametype = gametype; lastgametype = gametype;
gametype = READUINT8(*cp); gametype = READUINT8(*cp);
G_SetGametype(gametype); // I fear putting that macro as an argument
if (gametype < 0 || gametype >= NUMGAMETYPES) if (gametype < 0 || gametype >= gametypecount)
gametype = lastgametype; gametype = lastgametype;
else if (gametype != lastgametype) else if (gametype != lastgametype)
D_GameTypeChanged(lastgametype); // emulate consvar_t behavior for gametype D_GameTypeChanged(lastgametype); // emulate consvar_t behavior for gametype
@ -2413,7 +2421,7 @@ static void Command_Teamchange_f(void)
} }
//additional check for hide and seek. Don't allow change of status after hidetime ends. //additional check for hide and seek. Don't allow change of status after hidetime ends.
if (gametype == GT_HIDEANDSEEK && leveltime >= (hidetime * TICRATE)) if ((gametyperules & GTR_HIDEFROZEN) && leveltime >= (hidetime * TICRATE))
{ {
CONS_Alert(CONS_NOTICE, M_GetText("Hiding time expired; no Hide and Seek status changes allowed!\n")); CONS_Alert(CONS_NOTICE, M_GetText("Hiding time expired; no Hide and Seek status changes allowed!\n"));
return; return;
@ -2510,7 +2518,7 @@ static void Command_Teamchange2_f(void)
} }
//additional check for hide and seek. Don't allow change of status after hidetime ends. //additional check for hide and seek. Don't allow change of status after hidetime ends.
if (gametype == GT_HIDEANDSEEK && leveltime >= (hidetime * TICRATE)) if ((gametyperules & GTR_HIDEFROZEN) && leveltime >= (hidetime * TICRATE))
{ {
CONS_Alert(CONS_NOTICE, M_GetText("Hiding time expired; no Hide and Seek status changes allowed!\n")); CONS_Alert(CONS_NOTICE, M_GetText("Hiding time expired; no Hide and Seek status changes allowed!\n"));
return; return;
@ -2639,7 +2647,7 @@ static void Command_ServerTeamChange_f(void)
} }
//additional check for hide and seek. Don't allow change of status after hidetime ends. //additional check for hide and seek. Don't allow change of status after hidetime ends.
if (gametype == GT_HIDEANDSEEK && leveltime >= (hidetime * TICRATE)) if ((gametyperules & GTR_HIDEFROZEN) && leveltime >= (hidetime * TICRATE))
{ {
CONS_Alert(CONS_NOTICE, M_GetText("Hiding time expired; no Hide and Seek status changes allowed!\n")); CONS_Alert(CONS_NOTICE, M_GetText("Hiding time expired; no Hide and Seek status changes allowed!\n"));
return; return;
@ -2728,6 +2736,16 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
return; return;
} }
#ifdef HAVE_BLUA
// Don't switch team, just go away, please, go awaayyyy, aaauuauugghhhghgh
if (!LUAh_TeamSwitch(&players[playernum], NetPacket.packet.newteam, players[playernum].spectator, NetPacket.packet.autobalance, NetPacket.packet.scrambled))
return;
#endif
//no status changes after hidetime
if ((gametyperules & GTR_HIDEFROZEN) && (leveltime >= (hidetime * TICRATE)))
error = true;
//Make sure that the right team number is sent. Keep in mind that normal clients cannot change to certain teams in certain gametypes. //Make sure that the right team number is sent. Keep in mind that normal clients cannot change to certain teams in certain gametypes.
switch (gametype) switch (gametype)
{ {
@ -2882,7 +2900,15 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
//reset view if you are changed, or viewing someone who was changed. //reset view if you are changed, or viewing someone who was changed.
if (playernum == consoleplayer || displayplayer == playernum) if (playernum == consoleplayer || displayplayer == playernum)
{
#ifdef HAVE_BLUA
// Call ViewpointSwitch hooks here.
// The viewpoint was forcibly changed.
if (displayplayer != consoleplayer) // You're already viewing yourself. No big deal.
LUAh_ViewpointSwitch(&players[playernum], &players[displayplayer], true);
#endif
displayplayer = consoleplayer; displayplayer = consoleplayer;
}
if (G_GametypeHasTeams()) if (G_GametypeHasTeams())
{ {
@ -3618,7 +3644,7 @@ static void Command_ShowGametype_f(void)
} }
// get name string for current gametype // get name string for current gametype
if (gametype >= 0 && gametype < NUMGAMETYPES) if (gametype >= 0 && gametype < gametypecount)
gametypestr = Gametype_Names[gametype]; gametypestr = Gametype_Names[gametype];
if (gametypestr) if (gametypestr)
@ -3680,7 +3706,7 @@ void ItemFinder_OnChange(void)
static void PointLimit_OnChange(void) static void PointLimit_OnChange(void)
{ {
// Don't allow pointlimit in Single Player/Co-Op/Race! // Don't allow pointlimit in Single Player/Co-Op/Race!
if (server && Playing() && G_PlatformGametype()) if (server && Playing() && !(gametyperules & GTR_POINTLIMIT))
{ {
if (cv_pointlimit.value) if (cv_pointlimit.value)
CV_StealthSetValue(&cv_pointlimit, 0); CV_StealthSetValue(&cv_pointlimit, 0);
@ -3843,7 +3869,7 @@ UINT32 timelimitintics = 0;
static void TimeLimit_OnChange(void) static void TimeLimit_OnChange(void)
{ {
// Don't allow timelimit in Single Player/Co-Op/Race! // Don't allow timelimit in Single Player/Co-Op/Race!
if (server && Playing() && cv_timelimit.value != 0 && G_PlatformGametype()) if (server && Playing() && cv_timelimit.value != 0 && !(gametyperules & GTR_TIMELIMIT))
{ {
CV_SetValue(&cv_timelimit, 0); CV_SetValue(&cv_timelimit, 0);
return; return;
@ -3879,9 +3905,9 @@ void D_GameTypeChanged(INT32 lastgametype)
{ {
const char *oldgt = NULL, *newgt = NULL; const char *oldgt = NULL, *newgt = NULL;
if (lastgametype >= 0 && lastgametype < NUMGAMETYPES) if (lastgametype >= 0 && lastgametype < gametypecount)
oldgt = Gametype_Names[lastgametype]; oldgt = Gametype_Names[lastgametype];
if (gametype >= 0 && lastgametype < NUMGAMETYPES) if (gametype >= 0 && lastgametype < gametypecount)
newgt = Gametype_Names[gametype]; newgt = Gametype_Names[gametype];
if (oldgt && newgt) if (oldgt && newgt)
@ -3935,11 +3961,20 @@ void D_GameTypeChanged(INT32 lastgametype)
if (!cv_itemrespawntime.changed) if (!cv_itemrespawntime.changed)
CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue); // respawn normally CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue); // respawn normally
break; break;
default:
if (!cv_timelimit.changed && !cv_pointlimit.changed) // user hasn't changed limits
{
CV_SetValue(&cv_timelimit, timelimits[gametype]);
CV_SetValue(&cv_pointlimit, pointlimits[gametype]);
}
if (!cv_itemrespawntime.changed)
CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue); // respawn normally
break;
} }
} }
else if (!multiplayer && !netgame) else if (!multiplayer && !netgame)
{ {
gametype = GT_COOP; G_SetGametype(GT_COOP);
// These shouldn't matter anymore // These shouldn't matter anymore
//CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue); //CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue);
//CV_SetValue(&cv_itemrespawn, 0); //CV_SetValue(&cv_itemrespawn, 0);
@ -3948,7 +3983,7 @@ void D_GameTypeChanged(INT32 lastgametype)
// reset timelimit and pointlimit in race/coop, prevent stupid cheats // reset timelimit and pointlimit in race/coop, prevent stupid cheats
if (server) if (server)
{ {
if (G_PlatformGametype()) if (!(gametyperules & GTR_POINTLIMIT))
{ {
if (cv_timelimit.value) if (cv_timelimit.value)
CV_SetValue(&cv_timelimit, 0); CV_SetValue(&cv_timelimit, 0);
@ -3966,6 +4001,7 @@ void D_GameTypeChanged(INT32 lastgametype)
// When swapping to a gametype that supports spectators, // When swapping to a gametype that supports spectators,
// make everyone a spectator initially. // make everyone a spectator initially.
// Averted with GTR_NOSPECTATORSPAWN.
if (!splitscreen && (G_GametypeHasSpectators())) if (!splitscreen && (G_GametypeHasSpectators()))
{ {
INT32 i; INT32 i;
@ -3973,7 +4009,7 @@ void D_GameTypeChanged(INT32 lastgametype)
if (playeringame[i]) if (playeringame[i])
{ {
players[i].ctfteam = 0; players[i].ctfteam = 0;
players[i].spectator = true; players[i].spectator = (gametyperules & GTR_NOSPECTATORSPAWN) ? false : true;
} }
} }

View File

@ -22,6 +22,7 @@
#include "m_menu.h" #include "m_menu.h"
#include "m_misc.h" #include "m_misc.h"
#include "f_finale.h" #include "f_finale.h"
#include "y_inter.h"
#include "dehacked.h" #include "dehacked.h"
#include "st_stuff.h" #include "st_stuff.h"
#include "i_system.h" #include "i_system.h"
@ -76,6 +77,7 @@ static UINT16 get_mus(const char *word, UINT8 dehacked_mode);
static hudnum_t get_huditem(const char *word); static hudnum_t get_huditem(const char *word);
static menutype_t get_menutype(const char *word); static menutype_t get_menutype(const char *word);
#ifndef HAVE_BLUA #ifndef HAVE_BLUA
static INT16 get_gametype(const char *word);
static powertype_t get_power(const char *word); static powertype_t get_power(const char *word);
#endif #endif
@ -590,6 +592,16 @@ static void readfreeslots(MYFILE *f)
} else } else
CONS_Alert(CONS_WARNING, "Ran out of free SPR2 slots!\n"); CONS_Alert(CONS_WARNING, "Ran out of free SPR2 slots!\n");
} }
else if (fastcmp(type, "TOL"))
{
if (lastcustomtol > 31)
CONS_Alert(CONS_WARNING, "Ran out of free typeoflevel slots!\n");
else
{
G_AddTOL((1<<lastcustomtol), word);
lastcustomtol++;
}
}
else else
deh_warning("Freeslots: unknown enum class '%s' for '%s_%s'", type, type, word); deh_warning("Freeslots: unknown enum class '%s' for '%s_%s'", type, type, word);
} }
@ -863,14 +875,12 @@ static void readspriteframe(MYFILE *f, spriteinfo_t *sprinfo, UINT8 frame)
strupr(word); strupr(word);
value = atoi(word2); // used for numerical settings value = atoi(word2); // used for numerical settings
#ifdef ROTSPRITE
if (fastcmp(word, "XPIVOT")) if (fastcmp(word, "XPIVOT"))
sprinfo->pivot[frame].x = value; sprinfo->pivot[frame].x = value;
else if (fastcmp(word, "YPIVOT")) else if (fastcmp(word, "YPIVOT"))
sprinfo->pivot[frame].y = value; sprinfo->pivot[frame].y = value;
else if (fastcmp(word, "ROTAXIS")) else if (fastcmp(word, "ROTAXIS"))
sprinfo->pivot[frame].rotaxis = value; sprinfo->pivot[frame].rotaxis = value;
#endif
else else
{ {
f->curpos = lastline; f->curpos = lastline;
@ -1095,10 +1105,10 @@ static void readsprite2(MYFILE *f, INT32 num)
Z_Free(s); Z_Free(s);
} }
static const struct { INT32 numtolinfo = NUMBASETOL;
const char *name; UINT32 lastcustomtol = 13;
const UINT16 flag;
} TYPEOFLEVEL[] = { tolinfo_t TYPEOFLEVEL[NUMMAXTOL] = {
{"SOLO",TOL_SP}, {"SOLO",TOL_SP},
{"SP",TOL_SP}, {"SP",TOL_SP},
{"SINGLEPLAYER",TOL_SP}, {"SINGLEPLAYER",TOL_SP},
@ -1114,8 +1124,6 @@ static const struct {
{"TAG",TOL_TAG}, {"TAG",TOL_TAG},
{"CTF",TOL_CTF}, {"CTF",TOL_CTF},
{"CUSTOM",TOL_CUSTOM},
{"2D",TOL_2D}, {"2D",TOL_2D},
{"MARIO",TOL_MARIO}, {"MARIO",TOL_MARIO},
{"NIGHTS",TOL_NIGHTS}, {"NIGHTS",TOL_NIGHTS},
@ -1128,6 +1136,216 @@ static const struct {
{NULL, 0} {NULL, 0}
}; };
// copypasted from readPlayer :sleep:
static const char *const GAMETYPERULE_LIST[];
static void readgametype(MYFILE *f, char *gtname)
{
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
char *word;
char *word2, *word2lwr = NULL;
char *tmp;
INT32 i, j;
INT16 newgtidx = 0;
UINT32 newgtrules = 0;
UINT32 newgttol = 0;
INT32 newgtpointlimit = 0;
INT32 newgttimelimit = 0;
UINT8 newgtleftcolor = 0;
UINT8 newgtrightcolor = 0;
INT16 newgtrankingstype = -1;
int newgtinttype = 0;
char gtdescription[441];
char gtconst[MAXLINELEN];
// Empty strings.
gtdescription[0] = '\0';
gtconst[0] = '\0';
do
{
if (myfgets(s, MAXLINELEN, f))
{
if (s[0] == '\n')
break;
word = strtok(s, " ");
if (word)
strupr(word);
else
break;
if (fastcmp(word, "DESCRIPTION"))
{
char *descr = NULL;
for (i = 0; i < MAXLINELEN-3; i++)
{
if (s[i] == '=')
{
descr = &s[i+2];
break;
}
}
if (descr)
{
strcpy(gtdescription, descr);
strcat(gtdescription, myhashfgets(descr, sizeof (gtdescription), f));
}
else
strcpy(gtdescription, "");
// For some reason, cutting the string did not work above. Most likely due to strcpy or strcat...
// It works down here, though.
{
INT32 numline = 0;
for (i = 0; i < MAXLINELEN-1; i++)
{
if (numline < 20 && gtdescription[i] == '\n')
numline++;
if (numline >= 20 || gtdescription[i] == '\0' || gtdescription[i] == '#')
break;
}
}
gtdescription[strlen(gtdescription)-1] = '\0';
gtdescription[i] = '\0';
continue;
}
word2 = strtok(NULL, " = ");
if (word2)
{
if (!word2lwr)
word2lwr = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
strcpy(word2lwr, word2);
strupr(word2);
}
else
break;
if (word2[strlen(word2)-1] == '\n')
word2[strlen(word2)-1] = '\0';
i = atoi(word2);
// Game type rules
if (fastcmp(word, "RULES"))
{
// GTR_
newgtrules = (UINT32)get_number(word2);
}
// Identifier
else if (fastcmp(word, "IDENTIFIER"))
{
// GT_
strncpy(gtconst, word2, MAXLINELEN);
}
// Point and time limits
else if (fastcmp(word, "DEFAULTPOINTLIMIT"))
newgtpointlimit = (INT32)i;
else if (fastcmp(word, "DEFAULTTIMELIMIT"))
newgttimelimit = (INT32)i;
// Level platter
else if (fastcmp(word, "HEADERCOLOR") || fastcmp(word, "HEADERCOLOUR"))
newgtleftcolor = newgtrightcolor = (UINT8)get_number(word2);
else if (fastcmp(word, "HEADERLEFTCOLOR") || fastcmp(word, "HEADERLEFTCOLOUR"))
newgtleftcolor = (UINT8)get_number(word2);
else if (fastcmp(word, "HEADERRIGHTCOLOR") || fastcmp(word, "HEADERRIGHTCOLOUR"))
newgtrightcolor = (UINT8)get_number(word2);
// Rankings type
else if (fastcmp(word, "RANKINGTYPE"))
{
// Case insensitive
newgtrankingstype = (int)get_number(word2);
}
// Intermission type
else if (fastcmp(word, "INTERMISSIONTYPE"))
{
// Case sensitive
newgtinttype = (int)get_number(word2lwr);
}
// Type of level
else if (fastcmp(word, "TYPEOFLEVEL"))
{
if (i) // it's just a number
newgttol = (UINT32)i;
else
{
UINT16 tol = 0;
tmp = strtok(word2,",");
do {
for (i = 0; TYPEOFLEVEL[i].name; i++)
if (fasticmp(tmp, TYPEOFLEVEL[i].name))
break;
if (!TYPEOFLEVEL[i].name)
deh_warning("readgametype %s: unknown typeoflevel flag %s\n", gtname, tmp);
tol |= TYPEOFLEVEL[i].flag;
} while((tmp = strtok(NULL,",")) != NULL);
newgttol = tol;
}
}
// The SOC probably provided gametype rules as words,
// instead of using the RULES keyword.
// Like for example "NOSPECTATORSPAWN = TRUE".
// This is completely valid, and looks better anyway.
else
{
UINT32 wordgt = 0;
for (j = 0; GAMETYPERULE_LIST[j]; j++)
if (fastcmp(word, GAMETYPERULE_LIST[j])) {
if (!j) // GTR_CAMPAIGN
wordgt |= 1;
else
wordgt |= (1<<j);
if (i || word2[0] == 'T' || word2[0] == 'Y')
newgtrules |= wordgt;
break;
}
if (!wordgt)
deh_warning("readgametype %s: unknown word '%s'", gtname, word);
}
}
} while (!myfeof(f)); // finish when the line is empty
// Free strings.
Z_Free(s);
if (word2lwr)
Z_Free(word2lwr);
// Ran out of gametype slots
if (gametypecount == NUMGAMETYPEFREESLOTS)
{
CONS_Alert(CONS_WARNING, "Ran out of free gametype slots!\n");
return;
}
// Add the new gametype
newgtidx = G_AddGametype(newgtrules);
G_AddGametypeTOL(newgtidx, newgttol);
G_SetGametypeDescription(newgtidx, gtdescription, newgtleftcolor, newgtrightcolor);
// Not covered by G_AddGametype alone.
if (newgtrankingstype == -1)
newgtrankingstype = newgtidx;
gametyperankings[newgtidx] = newgtrankingstype;
intermissiontypes[newgtidx] = newgtinttype;
pointlimits[newgtidx] = newgtpointlimit;
timelimits[newgtidx] = newgttimelimit;
// Write the new gametype name.
Gametype_Names[newgtidx] = Z_StrDup((const char *)gtname);
// Write the constant name.
if (gtconst[0] == '\0')
strncpy(gtconst, gtname, MAXLINELEN);
G_AddGametypeConstant(newgtidx, (const char *)gtconst);
// Update gametype_cons_t accordingly.
G_UpdateGametypeSelections();
CONS_Printf("Added gametype %s\n", Gametype_Names[newgtidx]);
}
static const struct { static const struct {
const char *name; const char *name;
const mobjtype_t type; const mobjtype_t type;
@ -1395,7 +1613,7 @@ static void readlevelheader(MYFILE *f, INT32 num)
else if (fastcmp(word, "TYPEOFLEVEL")) else if (fastcmp(word, "TYPEOFLEVEL"))
{ {
if (i) // it's just a number if (i) // it's just a number
mapheaderinfo[num-1]->typeoflevel = (UINT16)i; mapheaderinfo[num-1]->typeoflevel = (UINT32)i;
else else
{ {
UINT16 tol = 0; UINT16 tol = 0;
@ -2690,11 +2908,9 @@ static actionpointer_t actionpointers[] =
{{A_SpawnObjectRelative}, "A_SPAWNOBJECTRELATIVE"}, {{A_SpawnObjectRelative}, "A_SPAWNOBJECTRELATIVE"},
{{A_ChangeAngleRelative}, "A_CHANGEANGLERELATIVE"}, {{A_ChangeAngleRelative}, "A_CHANGEANGLERELATIVE"},
{{A_ChangeAngleAbsolute}, "A_CHANGEANGLEABSOLUTE"}, {{A_ChangeAngleAbsolute}, "A_CHANGEANGLEABSOLUTE"},
#ifdef ROTSPRITE
{{A_RollAngle}, "A_ROLLANGLE"}, {{A_RollAngle}, "A_ROLLANGLE"},
{{A_ChangeRollAngleRelative},"A_CHANGEROLLANGLERELATIVE"}, {{A_ChangeRollAngleRelative},"A_CHANGEROLLANGLERELATIVE"},
{{A_ChangeRollAngleAbsolute},"A_CHANGEROLLANGLEABSOLUTE"}, {{A_ChangeRollAngleAbsolute},"A_CHANGEROLLANGLEABSOLUTE"},
#endif
{{A_PlaySound}, "A_PLAYSOUND"}, {{A_PlaySound}, "A_PLAYSOUND"},
{{A_FindTarget}, "A_FINDTARGET"}, {{A_FindTarget}, "A_FINDTARGET"},
{{A_FindTracer}, "A_FINDTRACER"}, {{A_FindTracer}, "A_FINDTRACER"},
@ -4172,6 +4388,7 @@ static void ignorelines(MYFILE *f)
static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
{ {
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
char textline[MAXLINELEN];
char *word; char *word;
char *word2; char *word2;
INT32 i; INT32 i;
@ -4192,6 +4409,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
char *traverse; char *traverse;
myfgets(s, MAXLINELEN, f); myfgets(s, MAXLINELEN, f);
memcpy(textline, s, MAXLINELEN);
if (s[0] == '\n' || s[0] == '#') if (s[0] == '\n' || s[0] == '#')
continue; continue;
@ -4380,6 +4598,36 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
ignorelines(f); ignorelines(f);
} }
} }
else if (fastcmp(word, "GAMETYPE"))
{
// Get the gametype name from textline
// instead of word2, so that gametype names
// aren't allcaps
INT32 c;
for (c = 0; c < MAXLINELEN; c++)
{
if (textline[c] == '\0')
break;
if (textline[c] == ' ')
{
char *gtname = (textline+c+1);
if (gtname)
{
// remove funny characters
INT32 j;
for (j = 0; j < (MAXLINELEN - c); j++)
{
if (gtname[j] == '\0')
break;
if (gtname[j] < 32)
gtname[j] = '\0';
}
readgametype(f, gtname);
}
break;
}
}
}
else if (fastcmp(word, "CUTSCENE")) else if (fastcmp(word, "CUTSCENE"))
{ {
if (i > 0 && i < 129) if (i > 0 && i < 129)
@ -8650,6 +8898,39 @@ static const char *const PLAYERFLAG_LIST[] = {
NULL // stop loop here. NULL // stop loop here.
}; };
static const char *const GAMETYPERULE_LIST[] = {
"CAMPAIGN",
"RINGSLINGER",
"SPECTATORS",
"FRIENDLYFIRE",
"LIVES",
"TEAMS",
"RACE",
"TAG",
"POINTLIMIT",
"TIMELIMIT",
"HIDETIME",
"HIDEFROZEN",
"BLINDFOLDED",
"FIRSTPERSON",
"MATCHEMERALDS",
"TEAMFLAGS",
"PITYSHIELD",
"DEATHPENALTY",
"NOSPECTATORSPAWN",
"DEATHMATCHSTARTS",
"SPECIALSTAGES",
"EMERALDTOKENS",
"EMERALDHUNT",
"SPAWNENEMIES",
"ALLOWEXIT",
"NOTITLECARD",
"OVERTIME",
"HURTMESSAGES",
"SPAWNINVUL",
NULL
};
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
// Linedef flags // Linedef flags
static const char *const ML_LIST[16] = { static const char *const ML_LIST[16] = {
@ -9065,21 +9346,6 @@ struct {
{"tr_trans90",tr_trans90}, {"tr_trans90",tr_trans90},
{"NUMTRANSMAPS",NUMTRANSMAPS}, {"NUMTRANSMAPS",NUMTRANSMAPS},
// Type of levels
{"TOL_SP",TOL_SP},
{"TOL_COOP",TOL_COOP},
{"TOL_COMPETITION",TOL_COMPETITION},
{"TOL_RACE",TOL_RACE},
{"TOL_MATCH",TOL_MATCH},
{"TOL_TAG",TOL_TAG},
{"TOL_CTF",TOL_CTF},
{"TOL_CUSTOM",TOL_CUSTOM},
{"TOL_2D",TOL_2D},
{"TOL_MARIO",TOL_MARIO},
{"TOL_NIGHTS",TOL_NIGHTS},
{"TOL_ERZ3",TOL_ERZ3},
{"TOL_XMAS",TOL_XMAS},
// Level flags // Level flags
{"LF_SCRIPTISFILE",LF_SCRIPTISFILE}, {"LF_SCRIPTISFILE",LF_SCRIPTISFILE},
{"LF_SPEEDMUSIC",LF_SPEEDMUSIC}, {"LF_SPEEDMUSIC",LF_SPEEDMUSIC},
@ -9262,15 +9528,16 @@ struct {
{"DMG_CANHURTSELF",DMG_CANHURTSELF}, {"DMG_CANHURTSELF",DMG_CANHURTSELF},
{"DMG_DEATHMASK",DMG_DEATHMASK}, {"DMG_DEATHMASK",DMG_DEATHMASK},
// Gametypes, for use with global var "gametype" // Intermission types
{"GT_COOP",GT_COOP}, {"int_none",int_none},
{"GT_COMPETITION",GT_COMPETITION}, {"int_coop",int_coop},
{"GT_RACE",GT_RACE}, {"int_match",int_match},
{"GT_MATCH",GT_MATCH}, {"int_teammatch",int_teammatch},
{"GT_TEAMMATCH",GT_TEAMMATCH}, //{"int_tag",int_tag},
{"GT_TAG",GT_TAG}, {"int_ctf",int_ctf},
{"GT_HIDEANDSEEK",GT_HIDEANDSEEK}, {"int_spec",int_spec},
{"GT_CTF",GT_CTF}, {"int_race",int_race},
{"int_comp",int_comp},
// Jingles (jingletype_t) // Jingles (jingletype_t)
{"JT_NONE",JT_NONE}, {"JT_NONE",JT_NONE},
@ -9443,12 +9710,10 @@ struct {
{"DI_SOUTHEAST",DI_SOUTHEAST}, {"DI_SOUTHEAST",DI_SOUTHEAST},
{"NUMDIRS",NUMDIRS}, {"NUMDIRS",NUMDIRS},
#ifdef ROTSPRITE
// Sprite rotation axis (rotaxis_t) // Sprite rotation axis (rotaxis_t)
{"ROTAXIS_X",ROTAXIS_X}, {"ROTAXIS_X",ROTAXIS_X},
{"ROTAXIS_Y",ROTAXIS_Y}, {"ROTAXIS_Y",ROTAXIS_Y},
{"ROTAXIS_Z",ROTAXIS_Z}, {"ROTAXIS_Z",ROTAXIS_Z},
#endif
// Buttons (ticcmd_t) // Buttons (ticcmd_t)
{"BT_WEAPONMASK",BT_WEAPONMASK}, //our first four bits. {"BT_WEAPONMASK",BT_WEAPONMASK}, //our first four bits.
@ -9563,7 +9828,7 @@ struct {
}; };
static mobjtype_t get_mobjtype(const char *word) static mobjtype_t get_mobjtype(const char *word)
{ // Returns the vlaue of MT_ enumerations { // Returns the value of MT_ enumerations
mobjtype_t i; mobjtype_t i;
if (*word >= '0' && *word <= '9') if (*word >= '0' && *word <= '9')
return atoi(word); return atoi(word);
@ -9715,8 +9980,22 @@ static menutype_t get_menutype(const char *word)
} }
#ifndef HAVE_BLUA #ifndef HAVE_BLUA
static INT16 get_gametype(const char *word)
{ // Returns the value of GT_ enumerations
INT16 i;
if (*word >= '0' && *word <= '9')
return atoi(word);
if (fastncmp("GT_",word,3))
word += 3; // take off the GT_
for (i = 0; i < NUMGAMETYPES; i++)
if (fastcmp(word, Gametype_ConstantNames[i]+3))
return i;
deh_warning("Couldn't find gametype named 'GT_%s'",word);
return GT_COOP;
}
static powertype_t get_power(const char *word) static powertype_t get_power(const char *word)
{ // Returns the vlaue of pw_ enumerations { // Returns the value of pw_ enumerations
powertype_t i; powertype_t i;
if (*word >= '0' && *word <= '9') if (*word >= '0' && *word <= '9')
return atoi(word); return atoi(word);
@ -9910,11 +10189,42 @@ static fixed_t find_const(const char **rword)
free(word); free(word);
return r; return r;
} }
else if (fastncmp("MN_",word,4)) { else if (fastncmp("MN_",word,3)) {
r = get_menutype(word); r = get_menutype(word);
free(word); free(word);
return r; return r;
} }
else if (fastncmp("GT_",word,4)) {
r = get_gametype(word);
free(word);
return r;
}
else if (fastncmp("GTR_", word, 4)) {
char *p = word+4;
for (i = 0; GAMETYPERULE_LIST[i]; i++)
if (fastcmp(p, GAMETYPERULE_LIST[i])) {
free(word);
return (1<<i);
}
// Not found error
const_warning("game type rule",word);
free(word);
return 0;
}
else if (fastncmp("TOL_", word, 4)) {
char *p = word+4;
for (i = 0; TYPEOFLEVEL[i].name; i++)
if (fastcmp(p, TYPEOFLEVEL[i].name)) {
free(word);
return TYPEOFLEVEL[i].flag;
}
// Not found error
const_warning("typeoflevel",word);
free(word);
return 0;
}
else if (fastncmp("HUD_",word,4)) { else if (fastncmp("HUD_",word,4)) {
r = get_huditem(word); r = get_huditem(word);
free(word); free(word);
@ -10124,6 +10434,20 @@ static inline int lib_freeslot(lua_State *L)
} }
r++; r++;
} }
else if (fastcmp(type, "TOL"))
{
if (lastcustomtol > 31)
CONS_Alert(CONS_WARNING, "Ran out of free typeoflevel slots!\n");
else
{
UINT32 newtol = (1<<lastcustomtol);
CONS_Printf("TypeOfLevel TOL_%s allocated.\n",word);
G_AddTOL(newtol, word);
lua_pushinteger(L, newtol);
lastcustomtol++;
r++;
}
}
Z_Free(s); Z_Free(s);
lua_remove(L, 1); lua_remove(L, 1);
continue; continue;
@ -10228,6 +10552,36 @@ static inline int lib_getenum(lua_State *L)
if (mathlib) return luaL_error(L, "playerflag '%s' could not be found.\n", word); if (mathlib) return luaL_error(L, "playerflag '%s' could not be found.\n", word);
return 0; return 0;
} }
else if (fastncmp("GT_", word, 3)) {
p = word;
for (i = 0; Gametype_ConstantNames[i]; i++)
if (fastcmp(p, Gametype_ConstantNames[i])) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "gametype '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("GTR_", word, 4)) {
p = word+4;
for (i = 0; GAMETYPERULE_LIST[i]; i++)
if (fastcmp(p, GAMETYPERULE_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "game type rule '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("TOL_", word, 4)) {
p = word+4;
for (i = 0; TYPEOFLEVEL[i].name; i++)
if (fastcmp(p, TYPEOFLEVEL[i].name)) {
lua_pushinteger(L, TYPEOFLEVEL[i].flag);
return 1;
}
if (mathlib) return luaL_error(L, "typeoflevel '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("ML_", word, 3)) { else if (fastncmp("ML_", word, 3)) {
p = word+3; p = word+3;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
@ -10465,198 +10819,7 @@ static inline int lib_getenum(lua_State *L)
// DYNAMIC variables too!! // DYNAMIC variables too!!
// Try not to add anything that would break netgames or timeattack replays here. // Try not to add anything that would break netgames or timeattack replays here.
// You know, like consoleplayer, displayplayer, secondarydisplayplayer, or gametime. // You know, like consoleplayer, displayplayer, secondarydisplayplayer, or gametime.
if (fastcmp(word,"gamemap")) { return LUA_PushGlobals(L, word);
lua_pushinteger(L, gamemap);
return 1;
} else if (fastcmp(word,"maptol")) {
lua_pushinteger(L, maptol);
return 1;
} else if (fastcmp(word,"ultimatemode")) {
lua_pushboolean(L, ultimatemode != 0);
return 1;
} else if (fastcmp(word,"mariomode")) {
lua_pushboolean(L, mariomode != 0);
return 1;
} else if (fastcmp(word,"twodlevel")) {
lua_pushboolean(L, twodlevel != 0);
return 1;
} else if (fastcmp(word,"circuitmap")) {
lua_pushboolean(L, circuitmap);
return 1;
} else if (fastcmp(word,"netgame")) {
lua_pushboolean(L, netgame);
return 1;
} else if (fastcmp(word,"multiplayer")) {
lua_pushboolean(L, multiplayer);
return 1;
} else if (fastcmp(word,"modeattacking")) {
lua_pushboolean(L, modeattacking);
return 1;
} else if (fastcmp(word,"splitscreen")) {
lua_pushboolean(L, splitscreen);
return 1;
} else if (fastcmp(word,"gamecomplete")) {
lua_pushboolean(L, gamecomplete);
return 1;
} else if (fastcmp(word,"devparm")) {
lua_pushboolean(L, devparm);
return 1;
} else if (fastcmp(word,"modifiedgame")) {
lua_pushboolean(L, modifiedgame && !savemoddata);
return 1;
} else if (fastcmp(word,"menuactive")) {
lua_pushboolean(L, menuactive);
return 1;
} else if (fastcmp(word,"paused")) {
lua_pushboolean(L, paused);
return 1;
// begin map vars
} else if (fastcmp(word,"spstage_start")) {
lua_pushinteger(L, spstage_start);
return 1;
} else if (fastcmp(word,"sstage_start")) {
lua_pushinteger(L, sstage_start);
return 1;
} else if (fastcmp(word,"sstage_end")) {
lua_pushinteger(L, sstage_end);
return 1;
} else if (fastcmp(word,"smpstage_start")) {
lua_pushinteger(L, smpstage_start);
return 1;
} else if (fastcmp(word,"smpstage_end")) {
lua_pushinteger(L, smpstage_end);
return 1;
} else if (fastcmp(word,"titlemap")) {
lua_pushinteger(L, titlemap);
return 1;
} else if (fastcmp(word,"titlemapinaction")) {
lua_pushboolean(L, (titlemapinaction != TITLEMAP_OFF));
return 1;
} else if (fastcmp(word,"bootmap")) {
lua_pushinteger(L, bootmap);
return 1;
} else if (fastcmp(word,"tutorialmap")) {
lua_pushinteger(L, tutorialmap);
return 1;
} else if (fastcmp(word,"tutorialmode")) {
lua_pushboolean(L, tutorialmode);
return 1;
// end map vars
// begin CTF colors
} else if (fastcmp(word,"skincolor_redteam")) {
lua_pushinteger(L, skincolor_redteam);
return 1;
} else if (fastcmp(word,"skincolor_blueteam")) {
lua_pushinteger(L, skincolor_blueteam);
return 1;
} else if (fastcmp(word,"skincolor_redring")) {
lua_pushinteger(L, skincolor_redring);
return 1;
} else if (fastcmp(word,"skincolor_bluering")) {
lua_pushinteger(L, skincolor_bluering);
return 1;
// end CTF colors
// begin timers
} else if (fastcmp(word,"invulntics")) {
lua_pushinteger(L, invulntics);
return 1;
} else if (fastcmp(word,"sneakertics")) {
lua_pushinteger(L, sneakertics);
return 1;
} else if (fastcmp(word,"flashingtics")) {
lua_pushinteger(L, flashingtics);
return 1;
} else if (fastcmp(word,"tailsflytics")) {
lua_pushinteger(L, tailsflytics);
return 1;
} else if (fastcmp(word,"underwatertics")) {
lua_pushinteger(L, underwatertics);
return 1;
} else if (fastcmp(word,"spacetimetics")) {
lua_pushinteger(L, spacetimetics);
return 1;
} else if (fastcmp(word,"extralifetics")) {
lua_pushinteger(L, extralifetics);
return 1;
} else if (fastcmp(word,"nightslinktics")) {
lua_pushinteger(L, nightslinktics);
return 1;
} else if (fastcmp(word,"gameovertics")) {
lua_pushinteger(L, gameovertics);
return 1;
} else if (fastcmp(word,"ammoremovaltics")) {
lua_pushinteger(L, ammoremovaltics);
return 1;
// end timers
} else if (fastcmp(word,"gametype")) {
lua_pushinteger(L, gametype);
return 1;
} else if (fastcmp(word,"leveltime")) {
lua_pushinteger(L, leveltime);
return 1;
} else if (fastcmp(word,"curWeather")) {
lua_pushinteger(L, curWeather);
return 1;
} else if (fastcmp(word,"globalweather")) {
lua_pushinteger(L, globalweather);
return 1;
} else if (fastcmp(word,"levelskynum")) {
lua_pushinteger(L, levelskynum);
return 1;
} else if (fastcmp(word,"globallevelskynum")) {
lua_pushinteger(L, globallevelskynum);
return 1;
} else if (fastcmp(word,"mapmusname")) {
lua_pushstring(L, mapmusname);
return 1;
} else if (fastcmp(word,"mapmusflags")) {
lua_pushinteger(L, mapmusflags);
return 1;
} else if (fastcmp(word,"mapmusposition")) {
lua_pushinteger(L, mapmusposition);
return 1;
// local player variables, by popular request
} else if (fastcmp(word,"consoleplayer")) { // player controlling console (aka local player 1)
if (consoleplayer < 0 || !playeringame[consoleplayer])
return 0;
LUA_PushUserdata(L, &players[consoleplayer], META_PLAYER);
return 1;
} else if (fastcmp(word,"displayplayer")) { // player visible on screen (aka display player 1)
if (displayplayer < 0 || !playeringame[displayplayer])
return 0;
LUA_PushUserdata(L, &players[displayplayer], META_PLAYER);
return 1;
} else if (fastcmp(word,"secondarydisplayplayer")) { // local/display player 2, for splitscreen
if (!splitscreen || secondarydisplayplayer < 0 || !playeringame[secondarydisplayplayer])
return 0;
LUA_PushUserdata(L, &players[secondarydisplayplayer], META_PLAYER);
return 1;
// end local player variables
} else if (fastcmp(word,"server")) {
if ((!multiplayer || !netgame) && !playeringame[serverplayer])
return 0;
LUA_PushUserdata(L, &players[serverplayer], META_PLAYER);
return 1;
} else if (fastcmp(word,"admin")) { // BACKWARDS COMPATIBILITY HACK: This was replaced with IsPlayerAdmin(), but some 2.1 Lua scripts still use the admin variable. It now points to the first admin player in the array.
LUA_Deprecated(L, "admin", "IsPlayerAdmin(player)");
if (!playeringame[adminplayers[0]] || IsPlayerAdmin(serverplayer))
return 0;
LUA_PushUserdata(L, &players[adminplayers[0]], META_PLAYER);
return 1;
} else if (fastcmp(word,"emeralds")) {
lua_pushinteger(L, emeralds);
return 1;
} else if (fastcmp(word,"gravity")) {
lua_pushinteger(L, gravity);
return 1;
} else if (fastcmp(word,"VERSIONSTRING")) {
lua_pushstring(L, VERSIONSTRING);
return 1;
} else if (fastcmp(word, "token")) {
lua_pushinteger(L, token);
return 1;
}
return 0;
} }
int LUA_EnumLib(lua_State *L) int LUA_EnumLib(lua_State *L)
@ -10723,6 +10886,8 @@ static int lib_getActionName(lua_State *L)
return luaL_typerror(L, 1, "action userdata or Lua function"); return luaL_typerror(L, 1, "action userdata or Lua function");
} }
int LUA_SOCLib(lua_State *L) int LUA_SOCLib(lua_State *L)
{ {
lua_register(L,"freeslot",lib_freeslot); lua_register(L,"freeslot",lib_freeslot);

View File

@ -626,7 +626,7 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Sprite rotation /// Sprite rotation
#define ROTSPRITE #define ROTSPRITE
#define ROTANGLES 24 // Needs to be a divisor of 360 (45, 60, 90, 120...) #define ROTANGLES 72 // Needs to be a divisor of 360 (45, 60, 90, 120...)
#define ROTANGDIFF (360 / ROTANGLES) #define ROTANGDIFF (360 / ROTANGLES)
/// PNG support /// PNG support

View File

@ -39,7 +39,7 @@ extern UINT32 mapmusposition;
#define MUSIC_FORCERESET 0x4000 // -*-------------- #define MUSIC_FORCERESET 0x4000 // -*--------------
// Use other bits if necessary. // Use other bits if necessary.
extern INT16 maptol; extern UINT32 maptol;
extern UINT8 globalweather; extern UINT8 globalweather;
extern INT32 curWeather; extern INT32 curWeather;
extern INT32 cursaveslot; extern INT32 cursaveslot;
@ -84,6 +84,9 @@ extern boolean addedtogame; // true after the server has added you
extern boolean multiplayer; extern boolean multiplayer;
extern INT16 gametype; extern INT16 gametype;
extern UINT32 gametyperules;
extern INT16 gametypecount;
extern boolean splitscreen; extern boolean splitscreen;
extern boolean circuitmap; // Does this level have 'circuit mode'? extern boolean circuitmap; // Does this level have 'circuit mode'?
extern boolean fromlevelselect; extern boolean fromlevelselect;
@ -284,7 +287,7 @@ typedef struct
char lvlttl[22]; ///< Level name without "Zone". (21 character limit instead of 32, 21 characters can display on screen max anyway) char lvlttl[22]; ///< Level name without "Zone". (21 character limit instead of 32, 21 characters can display on screen max anyway)
char subttl[33]; ///< Subtitle for level char subttl[33]; ///< Subtitle for level
UINT8 actnum; ///< Act number or 0 for none. UINT8 actnum; ///< Act number or 0 for none.
UINT16 typeoflevel; ///< Combination of typeoflevel flags. UINT32 typeoflevel; ///< Combination of typeoflevel flags.
INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end. INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end.
char musname[7]; ///< Music track to play. "" for no music. char musname[7]; ///< Music track to play. "" for no music.
UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore. UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
@ -366,6 +369,70 @@ typedef struct
extern mapheader_t* mapheaderinfo[NUMMAPS]; extern mapheader_t* mapheaderinfo[NUMMAPS];
// Gametypes
#define NUMGAMETYPEFREESLOTS 128
enum GameType
{
GT_COOP = 0, // also used in single player
GT_COMPETITION, // Classic "Race"
GT_RACE,
GT_MATCH,
GT_TEAMMATCH,
GT_TAG,
GT_HIDEANDSEEK,
GT_CTF, // capture the flag
GT_FIRSTFREESLOT,
GT_LASTFREESLOT = GT_FIRSTFREESLOT + NUMGAMETYPEFREESLOTS - 1,
NUMGAMETYPES
};
// If you alter this list, update dehacked.c, MISC_ChangeGameTypeMenu in m_menu.c, and Gametype_Names in g_game.c
// Gametype rules
enum GameTypeRules
{
GTR_CAMPAIGN = 1, // Linear Co-op map progression, don't allow random maps
GTR_RINGSLINGER = 1<<1, // Outside of Co-op, Competition, and Race (overriden by cv_ringslinger)
GTR_SPECTATORS = 1<<2, // Outside of Co-op, Competition, and Race
GTR_FRIENDLYFIRE = 1<<3, // Always allow friendly fire
GTR_LIVES = 1<<4, // Co-op and Competition
GTR_TEAMS = 1<<5, // Team Match, CTF
GTR_RACE = 1<<6, // Race and Competition
GTR_TAG = 1<<7, // Tag and Hide and Seek
GTR_POINTLIMIT = 1<<8, // Ringslinger point limit
GTR_TIMELIMIT = 1<<9, // Ringslinger time limit
GTR_HIDETIME = 1<<10, // Hide time (Tag and Hide and Seek)
GTR_HIDEFROZEN = 1<<11, // Frozen after hide time (Hide and Seek, but not Tag)
GTR_BLINDFOLDED = 1<<12, // Blindfolded view (Tag and Hide and Seek)
GTR_FIRSTPERSON = 1<<13, // First person camera
GTR_MATCHEMERALDS = 1<<14, // Ringslinger emeralds (Match and CTF)
GTR_TEAMFLAGS = 1<<15, // Gametype has team flags (CTF)
GTR_PITYSHIELD = 1<<16, // Award pity shield
GTR_DEATHPENALTY = 1<<17, // Death score penalty
GTR_NOSPECTATORSPAWN = 1<<18, // Use with GTR_SPECTATORS, spawn in the map instead of with the spectators
GTR_DEATHMATCHSTARTS = 1<<19, // Use deathmatch starts
GTR_SPECIALSTAGES = 1<<20, // Allow special stages
GTR_EMERALDTOKENS = 1<<21, // Spawn emerald tokens
GTR_EMERALDHUNT = 1<<22, // Emerald Hunt
GTR_SPAWNENEMIES = 1<<23, // Spawn enemies
GTR_ALLOWEXIT = 1<<24, // Allow exit sectors
GTR_NOTITLECARD = 1<<25, // Don't show the title card
GTR_OVERTIME = 1<<26, // Allow overtime
GTR_HURTMESSAGES = 1<<27, // Hit and death messages
GTR_SPAWNINVUL = 1<<28, // Babysitting deterrent
};
// String names for gametypes
extern const char *Gametype_Names[NUMGAMETYPES];
extern const char *Gametype_ConstantNames[NUMGAMETYPES];
// Point and time limits for every gametype
extern INT32 pointlimits[NUMGAMETYPES];
extern INT32 timelimits[NUMGAMETYPES];
enum TypeOfLevel enum TypeOfLevel
{ {
TOL_SP = 0x01, ///< Single Player TOL_SP = 0x01, ///< Single Player
@ -381,36 +448,26 @@ enum TypeOfLevel
TOL_CTF = 0x40, ///< Capture the Flag TOL_CTF = 0x40, ///< Capture the Flag
// CTF default = 64 // CTF default = 64
TOL_CUSTOM = 0x80, ///< Custom (Lua-scripted, etc.) // 0x80 was here
TOL_2D = 0x0100, ///< 2D TOL_2D = 0x0100, ///< 2D
TOL_MARIO = 0x0200, ///< Mario TOL_MARIO = 0x0200, ///< Mario
TOL_NIGHTS = 0x0400, ///< NiGHTS TOL_NIGHTS = 0x0400, ///< NiGHTS
TOL_ERZ3 = 0x0800, ///< ERZ3 TOL_ERZ3 = 0x0800, ///< ERZ3
TOL_XMAS = 0x1000 ///< Christmas NiGHTS TOL_XMAS = 0x1000, ///< Christmas NiGHTS
}; };
// Gametypes #define NUMBASETOL 18
enum GameType #define NUMMAXTOL (18 + NUMGAMETYPEFREESLOTS)
typedef struct
{ {
GT_COOP = 0, // also used in single player const char *name;
GT_COMPETITION, // Classic "Race" UINT32 flag;
GT_RACE, } tolinfo_t;
extern tolinfo_t TYPEOFLEVEL[NUMMAXTOL];
GT_MATCH, extern INT32 numtolinfo;
GT_TEAMMATCH, extern UINT32 lastcustomtol;
GT_TAG,
GT_HIDEANDSEEK,
GT_CTF, // capture the flag
NUMGAMETYPES
};
// If you alter this list, update dehacked.c, MISC_ChangeGameTypeMenu in m_menu.c, and Gametype_Names in g_game.c
// String names for gametypes
extern const char *Gametype_Names[NUMGAMETYPES];
extern tic_t totalplaytime; extern tic_t totalplaytime;

View File

@ -79,7 +79,7 @@ UINT16 mapmusflags; // Track and reset bit
UINT32 mapmusposition; // Position to jump to UINT32 mapmusposition; // Position to jump to
INT16 gamemap = 1; INT16 gamemap = 1;
INT16 maptol; UINT32 maptol;
UINT8 globalweather = 0; UINT8 globalweather = 0;
INT32 curWeather = PRECIP_NONE; INT32 curWeather = PRECIP_NONE;
INT32 cursaveslot = 0; // Auto-save 1p savegame slot INT32 cursaveslot = 0; // Auto-save 1p savegame slot
@ -1066,7 +1066,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
// why build a ticcmd if we're paused? // why build a ticcmd if we're paused?
// Or, for that matter, if we're being reborn. // Or, for that matter, if we're being reborn.
// ...OR if we're blindfolded. No looking into the floor. // ...OR if we're blindfolded. No looking into the floor.
if (paused || P_AutoPause() || (gamestate == GS_LEVEL && (player->playerstate == PST_REBORN || ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) if (paused || P_AutoPause() || (gamestate == GS_LEVEL && (player->playerstate == PST_REBORN || ((gametyperules & GTR_TAG)
&& (leveltime < hidetime * TICRATE) && (player->pflags & PF_TAGIT))))) && (leveltime < hidetime * TICRATE) && (player->pflags & PF_TAGIT)))))
{ {
cmd->angleturn = (INT16)(localangle >> 16); cmd->angleturn = (INT16)(localangle >> 16);
@ -1159,14 +1159,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
else else
{ {
if (turnright) if (turnright)
cmd->angleturn = (INT16)(cmd->angleturn - angleturn[tspeed]); cmd->angleturn = (INT16)(cmd->angleturn - ((angleturn[tspeed] * cv_cam_turnmultiplier.value)>>FRACBITS));
else if (turnleft) else if (turnleft)
cmd->angleturn = (INT16)(cmd->angleturn + angleturn[tspeed]); cmd->angleturn = (INT16)(cmd->angleturn + ((angleturn[tspeed] * cv_cam_turnmultiplier.value)>>FRACBITS));
if (analogjoystickmove && lookjoystickvector.xaxis != 0) if (analogjoystickmove && lookjoystickvector.xaxis != 0)
{ {
// JOYAXISRANGE should be 1023 (divide by 1024) // JOYAXISRANGE should be 1023 (divide by 1024)
cmd->angleturn = (INT16)(cmd->angleturn - ((lookjoystickvector.xaxis * angleturn[1]) >> 10)); // ANALOG! cmd->angleturn = (INT16)(cmd->angleturn - ((((lookjoystickvector.xaxis * angleturn[1]) >> 10) * cv_cam_turnmultiplier.value)>>FRACBITS)); // ANALOG!
} }
} }
@ -1379,7 +1379,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
//Reset away view if a command is given. //Reset away view if a command is given.
if ((cmd->forwardmove || cmd->sidemove || cmd->buttons) if ((cmd->forwardmove || cmd->sidemove || cmd->buttons)
&& displayplayer != consoleplayer) && displayplayer != consoleplayer)
{
#ifdef HAVE_BLUA
// Call ViewpointSwitch hooks here.
// The viewpoint was forcibly changed.
LUAh_ViewpointSwitch(player, &players[displayplayer], true);
#endif
displayplayer = consoleplayer; displayplayer = consoleplayer;
}
} }
// like the g_buildticcmd 1 but using mouse2, gamcontrolbis, ... // like the g_buildticcmd 1 but using mouse2, gamcontrolbis, ...
@ -1497,14 +1504,14 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
else else
{ {
if (turnright) if (turnright)
cmd->angleturn = (INT16)(cmd->angleturn - angleturn[tspeed]); cmd->angleturn = (INT16)(cmd->angleturn - (((angleturn[tspeed]<<FRACBITS) * cv_cam2_turnmultiplier.value)>>FRACBITS));
else if (turnleft) else if (turnleft)
cmd->angleturn = (INT16)(cmd->angleturn + angleturn[tspeed]); cmd->angleturn = (INT16)(cmd->angleturn + (((angleturn[tspeed]<<FRACBITS) * cv_cam2_turnmultiplier.value)>>FRACBITS));
if (analogjoystickmove && lookjoystickvector.xaxis != 0) if (analogjoystickmove && lookjoystickvector.xaxis != 0)
{ {
// JOYAXISRANGE should be 1023 (divide by 1024) // JOYAXISRANGE should be 1023 (divide by 1024)
cmd->angleturn = (INT16)(cmd->angleturn - ((lookjoystickvector.xaxis * angleturn[1]) >> 10)); // ANALOG! cmd->angleturn = (INT16)(cmd->angleturn - ((((lookjoystickvector.xaxis * angleturn[1]) >> 10) * cv_cam2_turnmultiplier.value)>>FRACBITS)); // ANALOG!
} }
} }
@ -1885,7 +1892,7 @@ void G_StartTitleCard(void)
{ {
// The title card has been disabled for this map. // The title card has been disabled for this map.
// Oh well. // Oh well.
if (mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD) if (!G_IsTitleCardAvailable())
{ {
WipeStageTitle = false; WipeStageTitle = false;
return; return;
@ -1930,6 +1937,23 @@ void G_PreLevelTitleCard(void)
wipestyleflags = WSF_CROSSFADE; wipestyleflags = WSF_CROSSFADE;
} }
//
// Returns true if the current level has a title card.
//
boolean G_IsTitleCardAvailable(void)
{
// The current level header explicitly disabled the title card.
if (mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD)
return false;
// The current gametype doesn't have a title card.
if (gametyperules & GTR_NOTITLECARD)
return false;
// The title card is available.
return true;
}
INT32 pausedelay = 0; INT32 pausedelay = 0;
boolean pausebreakkey = false; boolean pausebreakkey = false;
static INT32 camtoggledelay, camtoggledelay2 = 0; static INT32 camtoggledelay, camtoggledelay2 = 0;
@ -2020,6 +2044,11 @@ boolean G_Responder(event_t *ev)
if (gamestate == GS_LEVEL && ev->type == ev_keydown if (gamestate == GS_LEVEL && ev->type == ev_keydown
&& (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1])) && (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1]))
{ {
// ViewpointSwitch Lua hook.
#ifdef HAVE_BLUA
UINT8 canSwitchView = 0;
#endif
if (splitscreen || !netgame) if (splitscreen || !netgame)
displayplayer = consoleplayer; displayplayer = consoleplayer;
else else
@ -2034,6 +2063,15 @@ boolean G_Responder(event_t *ev)
if (!playeringame[displayplayer]) if (!playeringame[displayplayer])
continue; continue;
#ifdef HAVE_BLUA
// Call ViewpointSwitch hooks here.
canSwitchView = LUAh_ViewpointSwitch(&players[consoleplayer], &players[displayplayer], false);
if (canSwitchView == 1) // Set viewpoint to this player
break;
else if (canSwitchView == 2) // Skip this player
continue;
#endif
if (players[displayplayer].spectator) if (players[displayplayer].spectator)
continue; continue;
@ -2642,7 +2680,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost)
// -- CTF -- // -- CTF --
// Order: CTF->DM->Coop // Order: CTF->DM->Coop
if (gametype == GT_CTF && players[playernum].ctfteam) if ((gametyperules & (GTR_TEAMFLAGS|GTR_TEAMS)) && players[playernum].ctfteam)
{ {
if (!(spawnpoint = G_FindCTFStart(playernum)) // find a CTF start if (!(spawnpoint = G_FindCTFStart(playernum)) // find a CTF start
&& !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start && !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start
@ -2651,7 +2689,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost)
// -- DM/Tag/CTF-spectator/etc -- // -- DM/Tag/CTF-spectator/etc --
// Order: DM->CTF->Coop // Order: DM->CTF->Coop
else if (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF else if ((gametyperules & GTR_DEATHMATCHSTARTS) || gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF
|| ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && !(players[playernum].pflags & PF_TAGIT))) || ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && !(players[playernum].pflags & PF_TAGIT)))
{ {
if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start
@ -2698,7 +2736,7 @@ mapthing_t *G_FindCTFStart(INT32 playernum)
if (!numredctfstarts && !numbluectfstarts) //why even bother, eh? if (!numredctfstarts && !numbluectfstarts) //why even bother, eh?
{ {
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer)) if ((gametyperules & GTR_TEAMFLAGS) && (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer)))
CONS_Alert(CONS_WARNING, M_GetText("No CTF starts in this map!\n")); CONS_Alert(CONS_WARNING, M_GetText("No CTF starts in this map!\n"));
return NULL; return NULL;
} }
@ -3104,7 +3142,7 @@ void G_ExitLevel(void)
CV_SetValue(&cv_teamscramble, cv_scrambleonchange.value); CV_SetValue(&cv_teamscramble, cv_scrambleonchange.value);
} }
if (gametype != GT_COOP) if (!(gametyperules & GTR_CAMPAIGN))
CONS_Printf(M_GetText("The round has ended.\n")); CONS_Printf(M_GetText("The round has ended.\n"));
// Remove CEcho text on round end. // Remove CEcho text on round end.
@ -3136,6 +3174,221 @@ const char *Gametype_Names[NUMGAMETYPES] =
"CTF" // GT_CTF "CTF" // GT_CTF
}; };
// For dehacked
const char *Gametype_ConstantNames[NUMGAMETYPES] =
{
"GT_COOP", // GT_COOP
"GT_COMPETITION", // GT_COMPETITION
"GT_RACE", // GT_RACE
"GT_MATCH", // GT_MATCH
"GT_TEAMMATCH", // GT_TEAMMATCH
"GT_TAG", // GT_TAG
"GT_HIDEANDSEEK", // GT_HIDEANDSEEK
"GT_CTF" // GT_CTF
};
// Gametype rules
UINT32 gametypedefaultrules[NUMGAMETYPES] =
{
// Co-op
GTR_CAMPAIGN|GTR_LIVES|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDHUNT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES,
// Competition
GTR_RACE|GTR_LIVES|GTR_SPAWNENEMIES|GTR_EMERALDTOKENS|GTR_SPAWNINVUL|GTR_ALLOWEXIT,
// Race
GTR_RACE|GTR_SPAWNENEMIES|GTR_SPAWNINVUL|GTR_ALLOWEXIT,
// Match
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_SPAWNINVUL|GTR_PITYSHIELD|GTR_DEATHPENALTY,
// Team Match
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_SPAWNINVUL|GTR_PITYSHIELD,
// Tag
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL,
// Hide and Seek
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL,
// CTF
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_SPAWNINVUL|GTR_PITYSHIELD,
};
//
// G_SetGametype
//
// Set a new gametype, also setting gametype rules accordingly. Yay!
//
void G_SetGametype(INT16 gtype)
{
gametype = gtype;
gametyperules = gametypedefaultrules[gametype];
}
//
// G_AddGametype
//
// Add a gametype. Returns the new gametype number.
//
INT16 G_AddGametype(UINT32 rules)
{
INT16 newgtype = gametypecount;
gametypecount++;
// Set gametype rules.
gametypedefaultrules[newgtype] = rules;
Gametype_Names[newgtype] = "???";
// Update gametype_cons_t accordingly.
G_UpdateGametypeSelections();
return newgtype;
}
//
// G_AddGametypeConstant
//
// Self-explanatory. Filters out "bad" characters.
//
void G_AddGametypeConstant(INT16 gtype, const char *newgtconst)
{
char *gtconst = Z_Malloc(strlen(newgtconst) + 3, PU_STATIC, NULL);
// Copy GT_ and the gametype name.
strcpy(gtconst, "GT_");
strcat(gtconst, newgtconst);
// Make uppercase.
strupr(gtconst);
// Remove characters.
#define REMOVECHAR(chr) \
{ \
char *chrfind = strchr(gtconst, chr); \
while (chrfind) \
{ \
*chrfind = '_'; \
chrfind = strchr(chrfind, chr); \
} \
}
// Space
REMOVECHAR(' ')
// Used for operations
REMOVECHAR('+')
REMOVECHAR('-')
REMOVECHAR('*')
REMOVECHAR('/')
REMOVECHAR('%')
REMOVECHAR('^')
// Part of Lua's syntax
REMOVECHAR('#')
REMOVECHAR('=')
REMOVECHAR('~')
REMOVECHAR('<')
REMOVECHAR('>')
REMOVECHAR('(')
REMOVECHAR(')')
REMOVECHAR('{')
REMOVECHAR('}')
REMOVECHAR('[')
REMOVECHAR(']')
REMOVECHAR(':')
REMOVECHAR(';')
REMOVECHAR(',')
REMOVECHAR('.')
#undef REMOVECHAR
// Finally, set the constant string.
Gametype_ConstantNames[gtype] = gtconst;
}
//
// G_UpdateGametypeSelections
//
// Updates gametype_cons_t.
//
void G_UpdateGametypeSelections(void)
{
INT32 i;
for (i = 0; i < gametypecount; i++)
{
gametype_cons_t[i].value = i;
gametype_cons_t[i].strvalue = Gametype_Names[i];
}
gametype_cons_t[NUMGAMETYPES].value = 0;
gametype_cons_t[NUMGAMETYPES].strvalue = NULL;
}
//
// G_SetGametypeDescription
//
// Set a description for the specified gametype.
// (Level platter)
//
void G_SetGametypeDescription(INT16 gtype, char *descriptiontext, UINT8 leftcolor, UINT8 rightcolor)
{
if (descriptiontext != NULL)
strncpy(gametypedesc[gtype].notes, descriptiontext, 441);
gametypedesc[gtype].col[0] = leftcolor;
gametypedesc[gtype].col[1] = rightcolor;
}
// Gametype rankings
INT16 gametyperankings[NUMGAMETYPES] =
{
GT_COOP,
GT_COMPETITION,
GT_RACE,
GT_MATCH,
GT_TEAMMATCH,
GT_TAG,
GT_HIDEANDSEEK,
GT_CTF,
};
// Gametype to TOL (Type Of Level)
UINT32 gametypetol[NUMGAMETYPES] =
{
TOL_COOP, // Co-op
TOL_COMPETITION, // Competition
TOL_RACE, // Race
TOL_MATCH, // Match
TOL_MATCH, // Team Match
TOL_TAG, // Tag
TOL_TAG, // Hide and Seek
TOL_CTF, // CTF
};
//
// G_AddTOL
//
// Adds a type of level.
//
void G_AddTOL(UINT32 newtol, const char *tolname)
{
TYPEOFLEVEL[numtolinfo].name = Z_StrDup(tolname);
TYPEOFLEVEL[numtolinfo].flag = newtol;
numtolinfo++;
TYPEOFLEVEL[numtolinfo].name = NULL;
TYPEOFLEVEL[numtolinfo].flag = 0;
}
//
// G_AddTOL
//
// Assigns a type of level to a gametype.
//
void G_AddGametypeTOL(INT16 gtype, UINT32 newtol)
{
gametypetol[gtype] = newtol;
}
// //
// G_GetGametypeByName // G_GetGametypeByName
// //
@ -3178,8 +3431,8 @@ boolean G_IsSpecialStage(INT32 mapnum)
// //
boolean G_GametypeUsesLives(void) boolean G_GametypeUsesLives(void)
{ {
// Coop, Competitive // Coop, Competitive
if ((gametype == GT_COOP || gametype == GT_COMPETITION) if ((gametyperules & GTR_LIVES)
&& !(modeattacking || metalrecording) // No lives in Time Attack && !(modeattacking || metalrecording) // No lives in Time Attack
&& !G_IsSpecialStage(gamemap) && !G_IsSpecialStage(gamemap)
&& !(maptol & TOL_NIGHTS)) // No lives in NiGHTS && !(maptol & TOL_NIGHTS)) // No lives in NiGHTS
@ -3195,7 +3448,7 @@ boolean G_GametypeUsesLives(void)
// //
boolean G_GametypeHasTeams(void) boolean G_GametypeHasTeams(void)
{ {
return (gametype == GT_TEAMMATCH || gametype == GT_CTF); return (gametyperules & GTR_TEAMS);
} }
// //
@ -3206,7 +3459,7 @@ boolean G_GametypeHasTeams(void)
// //
boolean G_GametypeHasSpectators(void) boolean G_GametypeHasSpectators(void)
{ {
return (gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE); return (gametyperules & GTR_SPECTATORS);
} }
// //
@ -3217,7 +3470,7 @@ boolean G_GametypeHasSpectators(void)
// //
boolean G_RingSlingerGametype(void) boolean G_RingSlingerGametype(void)
{ {
return ((gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE) || (cv_ringslinger.value)); return ((gametyperules & GTR_RINGSLINGER) || (cv_ringslinger.value));
} }
// //
@ -3227,7 +3480,7 @@ boolean G_RingSlingerGametype(void)
// //
boolean G_PlatformGametype(void) boolean G_PlatformGametype(void)
{ {
return (gametype == GT_COOP || gametype == GT_RACE || gametype == GT_COMPETITION); return (!(gametyperules & GTR_RINGSLINGER));
} }
// //
@ -3237,7 +3490,7 @@ boolean G_PlatformGametype(void)
// //
boolean G_TagGametype(void) boolean G_TagGametype(void)
{ {
return (gametype == GT_TAG || gametype == GT_HIDEANDSEEK); return (gametyperules & GTR_TAG);
} }
/** Get the typeoflevel flag needed to indicate support of a gametype. /** Get the typeoflevel flag needed to indicate support of a gametype.
@ -3248,18 +3501,9 @@ boolean G_TagGametype(void)
*/ */
INT16 G_TOLFlag(INT32 pgametype) INT16 G_TOLFlag(INT32 pgametype)
{ {
if (!multiplayer) return TOL_SP; if (!multiplayer)
if (pgametype == GT_COOP) return TOL_COOP; return TOL_SP;
if (pgametype == GT_COMPETITION) return TOL_COMPETITION; return gametypetol[pgametype];
if (pgametype == GT_RACE) return TOL_RACE;
if (pgametype == GT_MATCH) return TOL_MATCH;
if (pgametype == GT_TEAMMATCH) return TOL_MATCH;
if (pgametype == GT_TAG) return TOL_TAG;
if (pgametype == GT_HIDEANDSEEK) return TOL_TAG;
if (pgametype == GT_CTF) return TOL_CTF;
CONS_Alert(CONS_ERROR, M_GetText("Unknown gametype! %d\n"), pgametype);
return INT16_MAX;
} }
/** Select a random map with the given typeoflevel flags. /** Select a random map with the given typeoflevel flags.
@ -3270,7 +3514,7 @@ INT16 G_TOLFlag(INT32 pgametype)
* has those flags. * has those flags.
* \author Graue <graue@oceanbase.org> * \author Graue <graue@oceanbase.org>
*/ */
static INT16 RandMap(INT16 tolflags, INT16 pprevmap) static INT16 RandMap(UINT32 tolflags, INT16 pprevmap)
{ {
INT16 *okmaps = Z_Malloc(NUMMAPS * sizeof(INT16), PU_STATIC, NULL); INT16 *okmaps = Z_Malloc(NUMMAPS * sizeof(INT16), PU_STATIC, NULL);
INT32 numokmaps = 0; INT32 numokmaps = 0;
@ -3428,10 +3672,10 @@ static void G_DoCompleted(void)
I_Error("Followed map %d to invalid map %d\n", prevmap + 1, nextmap + 1); I_Error("Followed map %d to invalid map %d\n", prevmap + 1, nextmap + 1);
// wrap around in race // wrap around in race
if (nextmap >= 1100-1 && nextmap <= 1102-1 && (gametype == GT_RACE || gametype == GT_COMPETITION)) if (nextmap >= 1100-1 && nextmap <= 1102-1 && !(gametyperules & GTR_CAMPAIGN))
nextmap = (INT16)(spstage_start-1); nextmap = (INT16)(spstage_start-1);
if ((gottoken = (gametype == GT_COOP && token))) if ((gottoken = ((gametyperules & GTR_SPECIALSTAGES) && token)))
{ {
token--; token--;
@ -3451,7 +3695,7 @@ static void G_DoCompleted(void)
automapactive = false; automapactive = false;
if (gametype != GT_COOP) if (!(gametyperules & GTR_CAMPAIGN))
{ {
if (cv_advancemap.value == 0) // Stay on same map. if (cv_advancemap.value == 0) // Stay on same map.
nextmap = prevmap; nextmap = prevmap;

View File

@ -143,6 +143,7 @@ void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar,
void G_DoLoadLevel(boolean resetplayer); void G_DoLoadLevel(boolean resetplayer);
void G_StartTitleCard(void); void G_StartTitleCard(void);
void G_PreLevelTitleCard(void); void G_PreLevelTitleCard(void);
boolean G_IsTitleCardAvailable(void);
void G_DeferedPlayDemo(const char *demo); void G_DeferedPlayDemo(const char *demo);
// Can be called by the startup code or M_Responder, calls P_SetupLevel. // Can be called by the startup code or M_Responder, calls P_SetupLevel.
@ -202,6 +203,18 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill);
void G_StopDemo(void); void G_StopDemo(void);
boolean G_CheckDemoStatus(void); boolean G_CheckDemoStatus(void);
extern UINT32 gametypedefaultrules[NUMGAMETYPES];
extern UINT32 gametypetol[NUMGAMETYPES];
extern INT16 gametyperankings[NUMGAMETYPES];
void G_SetGametype(INT16 gametype);
INT16 G_AddGametype(UINT32 rules);
void G_AddGametypeConstant(INT16 gtype, const char *newgtconst);
void G_UpdateGametypeSelections(void);
void G_AddTOL(UINT32 newtol, const char *tolname);
void G_AddGametypeTOL(INT16 gtype, UINT32 newtol);
void G_SetGametypeDescription(INT16 gtype, char *descriptiontext, UINT8 leftcolor, UINT8 rightcolor);
INT32 G_GetGametypeByName(const char *gametypestr); INT32 G_GetGametypeByName(const char *gametypestr);
boolean G_IsSpecialStage(INT32 mapnum); boolean G_IsSpecialStage(INT32 mapnum);
boolean G_GametypeUsesLives(void); boolean G_GametypeUsesLives(void);

View File

@ -115,13 +115,11 @@ typedef struct
FLOAT fovxangle, fovyangle; FLOAT fovxangle, fovyangle;
UINT8 splitscreen; UINT8 splitscreen;
boolean flip; // screenflip boolean flip; // screenflip
#ifdef ROTSPRITE
boolean roll; boolean roll;
SINT8 rollflip; SINT8 rollflip;
FLOAT rollangle; // done to not override USE_FTRANSFORM_ANGLEZ FLOAT rollangle; // done to not override USE_FTRANSFORM_ANGLEZ
UINT8 rotaxis; UINT8 rotaxis;
FLOAT centerx, centery; FLOAT centerx, centery;
#endif
#ifdef USE_FTRANSFORM_MIRROR #ifdef USE_FTRANSFORM_MIRROR
boolean mirror; // SRB2Kart: Encore Mode boolean mirror; // SRB2Kart: Encore Mode
#endif #endif

View File

@ -1148,10 +1148,8 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !(spr->mobj->frame & FF_VERTICALFLIP)); const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !(spr->mobj->frame & FF_VERTICALFLIP));
spritedef_t *sprdef; spritedef_t *sprdef;
spriteframe_t *sprframe; spriteframe_t *sprframe;
#ifdef ROTSPRITE
spriteinfo_t *sprinfo; spriteinfo_t *sprinfo;
angle_t ang; angle_t ang;
#endif
INT32 mod; INT32 mod;
float finalscale; float finalscale;
@ -1175,16 +1173,12 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
{ {
md2 = &md2_playermodels[(skin_t*)spr->mobj->skin-skins]; md2 = &md2_playermodels[(skin_t*)spr->mobj->skin-skins];
md2->skin = (skin_t*)spr->mobj->skin-skins; md2->skin = (skin_t*)spr->mobj->skin-skins;
#ifdef ROTSPRITE
sprinfo = &((skin_t *)spr->mobj->skin)->sprinfo[spr->mobj->sprite2]; sprinfo = &((skin_t *)spr->mobj->skin)->sprinfo[spr->mobj->sprite2];
#endif
} }
else else
{ {
md2 = &md2_models[spr->mobj->sprite]; md2 = &md2_models[spr->mobj->sprite];
#ifdef ROTSPRITE
sprinfo = &spriteinfo[spr->mobj->sprite]; sprinfo = &spriteinfo[spr->mobj->sprite];
#endif
} }
if (md2->error) if (md2->error)
@ -1384,9 +1378,8 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
p.angley = FIXED_TO_FLOAT(anglef); p.angley = FIXED_TO_FLOAT(anglef);
} }
#ifdef ROTSPRITE
p.rollangle = 0.0f; p.rollangle = 0.0f;
p.rollflip = 0; p.rollflip = 1;
p.rotaxis = 0; p.rotaxis = 0;
if (spr->mobj->rollangle) if (spr->mobj->rollangle)
{ {
@ -1409,7 +1402,6 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left
p.rollflip = -1; p.rollflip = -1;
} }
#endif
p.anglex = 0.0f; p.anglex = 0.0f;

View File

@ -2076,7 +2076,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f); pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f);
pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f); pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f);
#ifdef ROTSPRITE
if (pos->roll) if (pos->roll)
{ {
float roll = (1.0f * pos->rollflip); float roll = (1.0f * pos->rollflip);
@ -2089,7 +2088,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
pglRotatef(pos->rollangle, roll, 0.0f, 0.0f); pglRotatef(pos->rollangle, roll, 0.0f, 0.0f);
pglTranslatef(-pos->centerx, -pos->centery, 0); pglTranslatef(-pos->centerx, -pos->centery, 0);
} }
#endif
pglScalef(scalex, scaley, scalez); pglScalef(scalex, scaley, scalez);

View File

@ -2066,7 +2066,7 @@ static void HU_drawGametype(void)
{ {
const char *strvalue = NULL; const char *strvalue = NULL;
if (gametype < 0 || gametype >= NUMGAMETYPES) if (gametype < 0 || gametype >= gametypecount)
return; // not a valid gametype??? return; // not a valid gametype???
strvalue = Gametype_Names[gametype]; strvalue = Gametype_Names[gametype];
@ -2371,7 +2371,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
for (i = 0; i < scorelines; i++) for (i = 0; i < scorelines; i++)
{ {
if (players[tab[i].num].spectator && gametype != GT_COOP) if (players[tab[i].num].spectator && gametyperankings[gametype] != GT_COOP)
continue; //ignore them. continue; //ignore them.
greycheck = greycheckdef; greycheck = greycheckdef;
@ -2434,7 +2434,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
} }
} }
if (G_GametypeUsesLives() && !(gametype == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives if (G_GametypeUsesLives() && !(gametyperankings[gametype] == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives
V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|(greycheck ? V_60TRANS : 0), va("%dx", players[tab[i].num].lives)); V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|(greycheck ? V_60TRANS : 0), va("%dx", players[tab[i].num].lives));
else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT)
{ {
@ -2447,7 +2447,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
if (players[tab[i].num].exiting || (players[tab[i].num].pflags & PF_FINISHED)) if (players[tab[i].num].exiting || (players[tab[i].num].pflags & PF_FINISHED))
V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon); V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon);
if (gametype == GT_RACE) if (gametyperankings[gametype] == GT_RACE)
{ {
if (circuitmap) if (circuitmap)
{ {
@ -2541,7 +2541,7 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer)
| (greycheck ? 0 : V_TRANSLUCENT) | (greycheck ? 0 : V_TRANSLUCENT)
| V_ALLOWLOWERCASE, name); | V_ALLOWLOWERCASE, name);
if (gametype == GT_CTF) if (gametyperules & GTR_TEAMFLAGS)
{ {
if (players[tab[i].num].gotflag & GF_REDFLAG) // Red if (players[tab[i].num].gotflag & GF_REDFLAG) // Red
V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, rflagico, 0); V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, rflagico, 0);
@ -2669,7 +2669,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
| (greycheck ? V_TRANSLUCENT : 0) | (greycheck ? V_TRANSLUCENT : 0)
| V_ALLOWLOWERCASE, name); | V_ALLOWLOWERCASE, name);
if (gametype == GT_CTF) if (gametyperules & GTR_TEAMFLAGS)
{ {
if (players[tab[i].num].gotflag & GF_REDFLAG) // Red if (players[tab[i].num].gotflag & GF_REDFLAG) // Red
V_DrawSmallScaledPatch(x-28, y-4, 0, rflagico); V_DrawSmallScaledPatch(x-28, y-4, 0, rflagico);
@ -2726,7 +2726,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
for (i = 0; i < scorelines; i++) for (i = 0; i < scorelines; i++)
{ {
if (players[tab[i].num].spectator && gametype != GT_COOP) if (players[tab[i].num].spectator && gametyperankings[gametype] != GT_COOP)
continue; //ignore them. continue; //ignore them.
greycheck = greycheckdef; greycheck = greycheckdef;
@ -2743,7 +2743,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
| (greycheck ? V_TRANSLUCENT : 0) | (greycheck ? V_TRANSLUCENT : 0)
| V_ALLOWLOWERCASE, name); | V_ALLOWLOWERCASE, name);
if (G_GametypeUsesLives() && !(gametype == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives if (G_GametypeUsesLives() && !(gametyperankings[gametype] == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives
V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE, va("%dx", players[tab[i].num].lives)); V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE, va("%dx", players[tab[i].num].lives));
else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT)
V_DrawSmallScaledPatch(x-28, y-4, 0, tagico); V_DrawSmallScaledPatch(x-28, y-4, 0, tagico);
@ -2792,7 +2792,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
} }
// All data drawn with thin string for space. // All data drawn with thin string for space.
if (gametype == GT_RACE) if (gametyperankings[gametype] == GT_RACE)
{ {
if (circuitmap) if (circuitmap)
{ {
@ -2832,7 +2832,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor
for (i = 0; i < scorelines; i++) for (i = 0; i < scorelines; i++)
{ {
if (players[tab[i].num].spectator && gametype != GT_COOP) if (players[tab[i].num].spectator && gametyperankings[gametype] != GT_COOP)
continue; //ignore them. continue; //ignore them.
greycheck = greycheckdef; greycheck = greycheckdef;
@ -2902,7 +2902,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor
} }
// All data drawn with thin string for space. // All data drawn with thin string for space.
if (gametype == GT_RACE) if (gametyperankings[gametype] == GT_RACE)
{ {
if (circuitmap) if (circuitmap)
{ {
@ -3026,21 +3026,21 @@ static void HU_DrawRankings(void)
// draw the current gametype in the lower right // draw the current gametype in the lower right
HU_drawGametype(); HU_drawGametype();
if (gametype != GT_RACE && gametype != GT_COMPETITION && gametype != GT_COOP) if (gametyperules & (GTR_TIMELIMIT|GTR_POINTLIMIT))
{ {
if (cv_timelimit.value && timelimitintics > 0) if ((gametyperules & GTR_TIMELIMIT) && cv_timelimit.value && timelimitintics > 0)
{ {
V_DrawCenteredString(64, 8, 0, "TIME"); V_DrawCenteredString(64, 8, 0, "TIME");
V_DrawCenteredString(64, 16, 0, va("%i:%02i", G_TicsToMinutes(stplyr->realtime, true), G_TicsToSeconds(stplyr->realtime))); V_DrawCenteredString(64, 16, 0, va("%i:%02i", G_TicsToMinutes(stplyr->realtime, true), G_TicsToSeconds(stplyr->realtime)));
} }
if (cv_pointlimit.value > 0) if ((gametyperules & GTR_POINTLIMIT) && cv_pointlimit.value > 0)
{ {
V_DrawCenteredString(256, 8, 0, "POINT LIMIT"); V_DrawCenteredString(256, 8, 0, "POINT LIMIT");
V_DrawCenteredString(256, 16, 0, va("%d", cv_pointlimit.value)); V_DrawCenteredString(256, 16, 0, va("%d", cv_pointlimit.value));
} }
} }
else if (gametype == GT_COOP) else if (gametyperankings[gametype] == GT_COOP)
{ {
INT32 totalscore = 0; INT32 totalscore = 0;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
@ -3074,7 +3074,7 @@ static void HU_DrawRankings(void)
tab[i].num = -1; tab[i].num = -1;
tab[i].name = 0; tab[i].name = 0;
if (gametype == GT_RACE && !circuitmap) if (gametyperankings[gametype] == GT_RACE && !circuitmap)
tab[i].count = INT32_MAX; tab[i].count = INT32_MAX;
} }
@ -3083,7 +3083,7 @@ static void HU_DrawRankings(void)
if (!playeringame[j]) if (!playeringame[j])
continue; continue;
if (gametype != GT_COOP && players[j].spectator) if (!G_PlatformGametype() && players[j].spectator)
continue; continue;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
@ -3091,10 +3091,10 @@ static void HU_DrawRankings(void)
if (!playeringame[i]) if (!playeringame[i])
continue; continue;
if (gametype != GT_COOP && players[i].spectator) if (!G_PlatformGametype() && players[i].spectator)
continue; continue;
if (gametype == GT_RACE) if (gametyperankings[gametype] == GT_RACE)
{ {
if (circuitmap) if (circuitmap)
{ {
@ -3117,7 +3117,7 @@ static void HU_DrawRankings(void)
} }
} }
} }
else if (gametype == GT_COMPETITION) else if (gametyperankings[gametype] == GT_COMPETITION)
{ {
// todo put something more fitting for the gametype here, such as current // todo put something more fitting for the gametype here, such as current
// number of categories led // number of categories led

View File

@ -155,11 +155,9 @@ void A_SpawnObjectAbsolute();
void A_SpawnObjectRelative(); void A_SpawnObjectRelative();
void A_ChangeAngleRelative(); void A_ChangeAngleRelative();
void A_ChangeAngleAbsolute(); void A_ChangeAngleAbsolute();
#ifdef ROTSPRITE
void A_RollAngle(); void A_RollAngle();
void A_ChangeRollAngleRelative(); void A_ChangeRollAngleRelative();
void A_ChangeRollAngleAbsolute(); void A_ChangeRollAngleAbsolute();
#endif
void A_PlaySound(); void A_PlaySound();
void A_FindTarget(); void A_FindTarget();
void A_FindTracer(); void A_FindTracer();

View File

@ -12,6 +12,7 @@
#include "doomdef.h" #include "doomdef.h"
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
#include "fastcmp.h"
#include "p_local.h" #include "p_local.h"
#include "p_setup.h" // So we can have P_SetupLevelSky #include "p_setup.h" // So we can have P_SetupLevelSky
#ifdef ESLOPE #ifdef ESLOPE
@ -23,6 +24,8 @@
#include "m_random.h" #include "m_random.h"
#include "s_sound.h" #include "s_sound.h"
#include "g_game.h" #include "g_game.h"
#include "m_menu.h"
#include "y_inter.h"
#include "hu_stuff.h" // HU_AddChatText #include "hu_stuff.h" // HU_AddChatText
#include "console.h" #include "console.h"
#include "d_netcmd.h" // IsPlayerAdmin #include "d_netcmd.h" // IsPlayerAdmin
@ -144,10 +147,8 @@ static const struct {
{META_MOBJINFO, "mobjinfo_t"}, {META_MOBJINFO, "mobjinfo_t"},
{META_SFXINFO, "sfxinfo_t"}, {META_SFXINFO, "sfxinfo_t"},
{META_SPRITEINFO, "spriteinfo_t"}, {META_SPRITEINFO, "spriteinfo_t"},
#ifdef ROTSPRITE
{META_PIVOTLIST, "spriteframepivot_t[]"}, {META_PIVOTLIST, "spriteframepivot_t[]"},
{META_FRAMEPIVOT, "spriteframepivot_t"}, {META_FRAMEPIVOT, "spriteframepivot_t"},
#endif
{META_MOBJ, "mobj_t"}, {META_MOBJ, "mobj_t"},
{META_MAPTHING, "mapthing_t"}, {META_MAPTHING, "mapthing_t"},
@ -2632,6 +2633,145 @@ static int lib_sStartMusicCaption(lua_State *L)
// G_GAME // G_GAME
//////////// ////////////
// Copypasted from lib_cvRegisterVar :]
static int lib_gAddGametype(lua_State *L)
{
const char *k;
lua_Integer i;
const char *gtname = NULL;
const char *gtconst = NULL;
const char *gtdescription = NULL;
INT16 newgtidx = 0;
UINT32 newgtrules = 0;
UINT32 newgttol = 0;
INT32 newgtpointlimit = 0;
INT32 newgttimelimit = 0;
UINT8 newgtleftcolor = 0;
UINT8 newgtrightcolor = 0;
INT16 newgtrankingstype = -1;
int newgtinttype = 0;
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one.
if (!lua_lumploading)
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
// Ran out of gametype slots
if (gametypecount == NUMGAMETYPEFREESLOTS)
return luaL_error(L, "Ran out of free gametype slots!");
#define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("G_AddGametype") " (%s)", e);
#define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1)))
lua_pushnil(L);
while (lua_next(L, 1)) {
// stack: gametype table, key/index, value
// 1 2 3
i = 0;
k = NULL;
if (lua_isnumber(L, 2))
i = lua_tointeger(L, 2);
else if (lua_isstring(L, 2))
k = lua_tostring(L, 2);
// Sorry, no gametype rules as key names.
if (i == 1 || (k && fasticmp(k, "name"))) {
if (!lua_isstring(L, 3))
TYPEERROR("name", LUA_TSTRING)
gtname = Z_StrDup(lua_tostring(L, 3));
} else if (i == 2 || (k && fasticmp(k, "identifier"))) {
if (!lua_isstring(L, 3))
TYPEERROR("identifier", LUA_TSTRING)
gtconst = Z_StrDup(lua_tostring(L, 3));
} else if (i == 3 || (k && fasticmp(k, "rules"))) {
if (!lua_isnumber(L, 3))
TYPEERROR("rules", LUA_TNUMBER)
newgtrules = (UINT32)lua_tointeger(L, 3);
} else if (i == 4 || (k && fasticmp(k, "typeoflevel"))) {
if (!lua_isnumber(L, 3))
TYPEERROR("typeoflevel", LUA_TNUMBER)
newgttol = (UINT32)lua_tointeger(L, 3);
} else if (i == 5 || (k && fasticmp(k, "rankingtype"))) {
if (!lua_isnumber(L, 3))
TYPEERROR("rankingtype", LUA_TNUMBER)
newgtrankingstype = (INT16)lua_tointeger(L, 3);
} else if (i == 6 || (k && fasticmp(k, "intermissiontype"))) {
if (!lua_isnumber(L, 3))
TYPEERROR("intermissiontype", LUA_TNUMBER)
newgtinttype = (int)lua_tointeger(L, 3);
} else if (i == 7 || (k && fasticmp(k, "defaultpointlimit"))) {
if (!lua_isnumber(L, 3))
TYPEERROR("defaultpointlimit", LUA_TNUMBER)
newgtpointlimit = (INT32)lua_tointeger(L, 3);
} else if (i == 8 || (k && fasticmp(k, "defaulttimelimit"))) {
if (!lua_isnumber(L, 3))
TYPEERROR("defaulttimelimit", LUA_TNUMBER)
newgttimelimit = (INT32)lua_tointeger(L, 3);
} else if (i == 9 || (k && fasticmp(k, "description"))) {
if (!lua_isstring(L, 3))
TYPEERROR("description", LUA_TSTRING)
gtdescription = Z_StrDup(lua_tostring(L, 3));
} else if (i == 10 || (k && fasticmp(k, "headerleftcolor"))) {
if (!lua_isnumber(L, 3))
TYPEERROR("headerleftcolor", LUA_TNUMBER)
newgtleftcolor = (UINT8)lua_tointeger(L, 3);
} else if (i == 11 || (k && fasticmp(k, "headerrightcolor"))) {
if (!lua_isnumber(L, 3))
TYPEERROR("headerrightcolor", LUA_TNUMBER)
newgtrightcolor = (UINT8)lua_tointeger(L, 3);
// Key name specified
} else if ((!i) && (k && fasticmp(k, "headercolor"))) {
if (!lua_isnumber(L, 3))
TYPEERROR("headercolor", LUA_TNUMBER)
newgtleftcolor = newgtrightcolor = (UINT8)lua_tointeger(L, 3);
}
lua_pop(L, 1);
}
#undef FIELDERROR
#undef TYPEERROR
// pop gametype table
lua_pop(L, 1);
// Set defaults
if (gtname == NULL)
gtname = Z_StrDup("Unnamed gametype");
if (gtdescription == NULL)
gtdescription = Z_StrDup("???");
// Add the new gametype
newgtidx = G_AddGametype(newgtrules);
G_AddGametypeTOL(newgtidx, newgttol);
G_SetGametypeDescription(newgtidx, NULL, newgtleftcolor, newgtrightcolor);
strncpy(gametypedesc[newgtidx].notes, gtdescription, 441);
// Not covered by G_AddGametype alone.
if (newgtrankingstype == -1)
newgtrankingstype = newgtidx;
gametyperankings[newgtidx] = newgtrankingstype;
intermissiontypes[newgtidx] = newgtinttype;
pointlimits[newgtidx] = newgtpointlimit;
timelimits[newgtidx] = newgttimelimit;
// Write the new gametype name.
Gametype_Names[newgtidx] = gtname;
// Write the constant name.
if (gtconst == NULL)
gtconst = gtname;
G_AddGametypeConstant(newgtidx, gtconst);
// Update gametype_cons_t accordingly.
G_UpdateGametypeSelections();
// done
CONS_Printf("Added gametype %s\n", Gametype_Names[newgtidx]);
return 0;
}
static int lib_gBuildMapName(lua_State *L) static int lib_gBuildMapName(lua_State *L)
{ {
INT32 map = luaL_optinteger(L, 1, gamemap); INT32 map = luaL_optinteger(L, 1, gamemap);
@ -2991,6 +3131,7 @@ static luaL_Reg lib[] = {
{"S_StartMusicCaption", lib_sStartMusicCaption}, {"S_StartMusicCaption", lib_sStartMusicCaption},
// g_game // g_game
{"G_AddGametype", lib_gAddGametype},
{"G_BuildMapName",lib_gBuildMapName}, {"G_BuildMapName",lib_gBuildMapName},
{"G_DoReborn",lib_gDoReborn}, {"G_DoReborn",lib_gDoReborn},
{"G_SetCustomExitVars",lib_gSetCustomExitVars}, {"G_SetCustomExitVars",lib_gSetCustomExitVars},

View File

@ -51,6 +51,8 @@ enum hook {
hook_PlayerCanDamage, hook_PlayerCanDamage,
hook_PlayerQuit, hook_PlayerQuit,
hook_IntermissionThinker, hook_IntermissionThinker,
hook_TeamSwitch,
hook_ViewpointSwitch,
hook_MAX // last hook hook_MAX // last hook
}; };
@ -93,5 +95,7 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAft
UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage
void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting
void LUAh_IntermissionThinker(void); // Hook for Y_Ticker void LUAh_IntermissionThinker(void); // Hook for Y_Ticker
boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh....
UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode
#endif #endif

View File

@ -62,6 +62,8 @@ const char *const hookNames[hook_MAX+1] = {
"PlayerCanDamage", "PlayerCanDamage",
"PlayerQuit", "PlayerQuit",
"IntermissionThinker", "IntermissionThinker",
"TeamSwitch",
"ViewpointSwitch",
NULL NULL
}; };
@ -203,6 +205,8 @@ static int lib_addHook(lua_State *L)
case hook_PlayerSpawn: case hook_PlayerSpawn:
case hook_FollowMobj: case hook_FollowMobj:
case hook_PlayerCanDamage: case hook_PlayerCanDamage:
case hook_TeamSwitch:
case hook_ViewpointSwitch:
case hook_ShieldSpawn: case hook_ShieldSpawn:
case hook_ShieldSpecial: case hook_ShieldSpecial:
lastp = &playerhooks; lastp = &playerhooks;
@ -1352,4 +1356,101 @@ void LUAh_IntermissionThinker(void)
} }
} }
// Hook for team switching
// It's just an edit of LUAh_ViewpointSwitch.
boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble)
{
hook_p hookp;
boolean canSwitchTeam = true;
if (!gL || !(hooksAvailable[hook_TeamSwitch/8] & (1<<(hook_TeamSwitch%8))))
return true;
lua_settop(gL, 0);
for (hookp = playerhooks; hookp; hookp = hookp->next)
{
if (hookp->type != hook_TeamSwitch)
continue;
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, player, META_PLAYER);
lua_pushinteger(gL, newteam);
lua_pushboolean(gL, fromspectators);
lua_pushboolean(gL, tryingautobalance);
lua_pushboolean(gL, tryingscramble);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -6);
lua_pushvalue(gL, -6);
lua_pushvalue(gL, -6);
lua_pushvalue(gL, -6);
lua_pushvalue(gL, -6);
if (lua_pcall(gL, 5, 1, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1))
canSwitchTeam = false; // Can't switch team
lua_pop(gL, 1);
}
lua_settop(gL, 0);
return canSwitchTeam;
}
// Hook for spy mode
UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced)
{
hook_p hookp;
UINT8 canSwitchView = 0; // 0 = default, 1 = force yes, 2 = force no.
if (!gL || !(hooksAvailable[hook_ViewpointSwitch/8] & (1<<(hook_ViewpointSwitch%8))))
return 0;
lua_settop(gL, 0);
hud_running = true;
for (hookp = playerhooks; hookp; hookp = hookp->next)
{
if (hookp->type != hook_ViewpointSwitch)
continue;
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, player, META_PLAYER);
LUA_PushUserdata(gL, newdisplayplayer, META_PLAYER);
lua_pushboolean(gL, forced);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
if (lua_pcall(gL, 3, 1, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (!lua_isnil(gL, -1))
{ // if nil, leave canSwitchView = 0.
if (lua_toboolean(gL, -1))
canSwitchView = 1; // Force viewpoint switch
else
canSwitchView = 2; // Skip viewpoint switch
}
lua_pop(gL, 1);
}
lua_settop(gL, 0);
hud_running = false;
return canSwitchView;
}
#endif #endif

View File

@ -34,6 +34,9 @@ enum hud {
hud_coopemeralds, hud_coopemeralds,
hud_tokens, hud_tokens,
hud_tabemblems, hud_tabemblems,
// Intermission
hud_intermissiontally,
hud_intermissionmessages,
hud_MAX hud_MAX
}; };
@ -44,4 +47,5 @@ boolean LUA_HudEnabled(enum hud option);
void LUAh_GameHUD(player_t *stplyr); void LUAh_GameHUD(player_t *stplyr);
void LUAh_ScoresHUD(void); void LUAh_ScoresHUD(void);
void LUAh_TitleHUD(void); void LUAh_TitleHUD(void);
void LUAh_TitleCardHUD(player_t *stplyr); void LUAh_TitleCardHUD(player_t *stplayr);
void LUAh_IntermissionHUD(void);

View File

@ -61,6 +61,9 @@ static const char *const hud_disable_options[] = {
"coopemeralds", "coopemeralds",
"tokens", "tokens",
"tabemblems", "tabemblems",
"intermissiontally",
"intermissionmessages",
NULL}; NULL};
enum hudinfo { enum hudinfo {
@ -93,12 +96,14 @@ static const char *const patch_opt[] = {
enum hudhook { enum hudhook {
hudhook_game = 0, hudhook_game = 0,
hudhook_scores, hudhook_scores,
hudhook_intermission,
hudhook_title, hudhook_title,
hudhook_titlecard hudhook_titlecard
}; };
static const char *const hudhook_opt[] = { static const char *const hudhook_opt[] = {
"game", "game",
"scores", "scores",
"intermission",
"title", "title",
"titlecard", "titlecard",
NULL}; NULL};
@ -1051,13 +1056,16 @@ int LUA_HudLib(lua_State *L)
lua_rawseti(L, -2, 2); // HUD[2] = game rendering functions array lua_rawseti(L, -2, 2); // HUD[2] = game rendering functions array
lua_newtable(L); lua_newtable(L);
lua_rawseti(L, -2, 3); // HUD[2] = scores rendering functions array lua_rawseti(L, -2, 3); // HUD[3] = scores rendering functions array
lua_newtable(L); lua_newtable(L);
lua_rawseti(L, -2, 4); // HUD[3] = title rendering functions array lua_rawseti(L, -2, 4); // HUD[4] = intermission rendering functions array
lua_newtable(L); lua_newtable(L);
lua_rawseti(L, -2, 5); // HUD[4] = title card rendering functions array lua_rawseti(L, -2, 5); // HUD[5] = title rendering functions array
lua_newtable(L);
lua_rawseti(L, -2, 6); // HUD[6] = title card rendering functions array
lua_setfield(L, LUA_REGISTRYINDEX, "HUD"); lua_setfield(L, LUA_REGISTRYINDEX, "HUD");
luaL_newmetatable(L, META_HUDINFO); luaL_newmetatable(L, META_HUDINFO);
@ -1229,4 +1237,29 @@ void LUAh_TitleCardHUD(player_t *stplayr)
hud_running = false; hud_running = false;
} }
void LUAh_IntermissionHUD(void)
{
if (!gL || !(hudAvailable & (1<<hudhook_intermission)))
return;
hud_running = true;
lua_pop(gL, -1);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, 4); // HUD[4] = rendering funcs
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
I_Assert(lua_istable(gL, -1));
lua_remove(gL, -3); // pop HUD
lua_pushnil(gL);
while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // graphics library (HUD[1])
LUA_Call(gL, 1);
}
lua_pop(gL, -1);
hud_running = false;
}
#endif #endif

View File

@ -266,7 +266,6 @@ static int lib_getSpriteInfo(lua_State *L)
#define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to spriteinfo[] (%s)", e); #define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to spriteinfo[] (%s)", e);
#define TYPEERROR(f, t1, t2) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t1), lua_typename(L, t2))) #define TYPEERROR(f, t1, t2) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t1), lua_typename(L, t2)))
#ifdef ROTSPRITE
static int PopPivotSubTable(spriteframepivot_t *pivot, lua_State *L, int stk, int idx) static int PopPivotSubTable(spriteframepivot_t *pivot, lua_State *L, int stk, int idx)
{ {
int okcool = 0; int okcool = 0;
@ -360,7 +359,6 @@ static int PopPivotTable(spriteinfo_t *info, lua_State *L, int stk)
return 0; return 0;
} }
#endif
static int lib_setSpriteInfo(lua_State *L) static int lib_setSpriteInfo(lua_State *L)
{ {
@ -393,14 +391,11 @@ static int lib_setSpriteInfo(lua_State *L)
if (lua_isnumber(L, 2)) if (lua_isnumber(L, 2))
{ {
i = lua_tointeger(L, 2); i = lua_tointeger(L, 2);
#ifndef ROTSPRITE
i++; // shift index in case of missing rotsprite support i++; // shift index in case of missing rotsprite support
#endif
} }
else else
str = luaL_checkstring(L, 2); str = luaL_checkstring(L, 2);
#ifdef ROTSPRITE
if (i == 1 || (str && fastcmp(str, "pivot"))) if (i == 1 || (str && fastcmp(str, "pivot")))
{ {
// pivot[] is a table // pivot[] is a table
@ -409,7 +404,6 @@ static int lib_setSpriteInfo(lua_State *L)
else else
FIELDERROR("pivot", va("%s expected, got %s", lua_typename(L, LUA_TTABLE), luaL_typename(L, -1))) FIELDERROR("pivot", va("%s expected, got %s", lua_typename(L, LUA_TTABLE), luaL_typename(L, -1)))
} }
#endif
lua_pop(L, 1); lua_pop(L, 1);
} }
@ -434,7 +428,6 @@ static int spriteinfo_get(lua_State *L)
I_Assert(sprinfo != NULL); I_Assert(sprinfo != NULL);
#ifdef ROTSPRITE
// push spriteframepivot_t userdata // push spriteframepivot_t userdata
if (fastcmp(field, "pivot")) if (fastcmp(field, "pivot"))
{ {
@ -448,7 +441,6 @@ static int spriteinfo_get(lua_State *L)
return 1; return 1;
} }
else else
#endif
return luaL_error(L, LUA_QL("spriteinfo_t") " has no field named " LUA_QS, field); return luaL_error(L, LUA_QL("spriteinfo_t") " has no field named " LUA_QS, field);
return 0; return 0;
@ -473,6 +465,7 @@ static int spriteinfo_set(lua_State *L)
#ifdef ROTSPRITE #ifdef ROTSPRITE
if (sprites != NULL) if (sprites != NULL)
R_FreeSingleRotSprite(&sprites[sprinfo-spriteinfo]); R_FreeSingleRotSprite(&sprites[sprinfo-spriteinfo]);
#endif
if (fastcmp(field, "pivot")) if (fastcmp(field, "pivot"))
{ {
@ -488,7 +481,6 @@ static int spriteinfo_set(lua_State *L)
} }
} }
else else
#endif
return luaL_error(L, va("Field %s does not exist in spriteinfo_t", field)); return luaL_error(L, va("Field %s does not exist in spriteinfo_t", field));
return 0; return 0;
@ -506,7 +498,6 @@ static int spriteinfo_num(lua_State *L)
} }
// framepivot_t // framepivot_t
#ifdef ROTSPRITE
static int pivotlist_get(lua_State *L) static int pivotlist_get(lua_State *L)
{ {
void **userdata; void **userdata;
@ -616,7 +607,6 @@ static int framepivot_num(lua_State *L)
lua_pushinteger(L, 2); lua_pushinteger(L, 2);
return 1; return 1;
} }
#endif
//////////////// ////////////////
// STATE INFO // // STATE INFO //
@ -1538,7 +1528,6 @@ int LUA_InfoLib(lua_State *L)
lua_setfield(L, -2, "__len"); lua_setfield(L, -2, "__len");
lua_pop(L, 1); lua_pop(L, 1);
#ifdef ROTSPRITE
luaL_newmetatable(L, META_PIVOTLIST); luaL_newmetatable(L, META_PIVOTLIST);
lua_pushcfunction(L, pivotlist_get); lua_pushcfunction(L, pivotlist_get);
lua_setfield(L, -2, "__index"); lua_setfield(L, -2, "__index");
@ -1560,7 +1549,6 @@ int LUA_InfoLib(lua_State *L)
lua_pushcfunction(L, framepivot_num); lua_pushcfunction(L, framepivot_num);
lua_setfield(L, -2, "__len"); lua_setfield(L, -2, "__len");
lua_pop(L, 1); lua_pop(L, 1);
#endif
lua_newuserdata(L, 0); lua_newuserdata(L, 0);
lua_createtable(L, 0, 2); lua_createtable(L, 0, 2);

View File

@ -23,10 +23,8 @@ extern lua_State *gL;
#define META_MOBJINFO "MOBJINFO_T*" #define META_MOBJINFO "MOBJINFO_T*"
#define META_SFXINFO "SFXINFO_T*" #define META_SFXINFO "SFXINFO_T*"
#define META_SPRITEINFO "SPRITEINFO_T*" #define META_SPRITEINFO "SPRITEINFO_T*"
#ifdef ROTSPRITE
#define META_PIVOTLIST "SPRITEFRAMEPIVOT_T[]" #define META_PIVOTLIST "SPRITEFRAMEPIVOT_T[]"
#define META_FRAMEPIVOT "SPRITEFRAMEPIVOT_T*" #define META_FRAMEPIVOT "SPRITEFRAMEPIVOT_T*"
#endif
#define META_MOBJ "MOBJ_T*" #define META_MOBJ "MOBJ_T*"
#define META_MAPTHING "MAPTHING_T*" #define META_MAPTHING "MAPTHING_T*"

View File

@ -32,9 +32,7 @@ enum mobj_e {
mobj_snext, mobj_snext,
mobj_sprev, mobj_sprev,
mobj_angle, mobj_angle,
#ifdef ROTSPRITE
mobj_rollangle, mobj_rollangle,
#endif
mobj_sprite, mobj_sprite,
mobj_frame, mobj_frame,
mobj_sprite2, mobj_sprite2,
@ -101,9 +99,7 @@ static const char *const mobj_opt[] = {
"snext", "snext",
"sprev", "sprev",
"angle", "angle",
#ifdef ROTSPRITE
"rollangle", "rollangle",
#endif
"sprite", "sprite",
"frame", "frame",
"sprite2", "sprite2",
@ -205,11 +201,9 @@ static int mobj_get(lua_State *L)
case mobj_angle: case mobj_angle:
lua_pushangle(L, mo->angle); lua_pushangle(L, mo->angle);
break; break;
#ifdef ROTSPRITE
case mobj_rollangle: case mobj_rollangle:
lua_pushangle(L, mo->rollangle); lua_pushangle(L, mo->rollangle);
break; break;
#endif
case mobj_sprite: case mobj_sprite:
lua_pushinteger(L, mo->sprite); lua_pushinteger(L, mo->sprite);
break; break;
@ -462,11 +456,9 @@ static int mobj_set(lua_State *L)
else if (mo->player == &players[secondarydisplayplayer]) else if (mo->player == &players[secondarydisplayplayer])
localangle2 = mo->angle; localangle2 = mo->angle;
break; break;
#ifdef ROTSPRITE
case mobj_rollangle: case mobj_rollangle:
mo->rollangle = luaL_checkangle(L, 3); mo->rollangle = luaL_checkangle(L, 3);
break; break;
#endif
case mobj_sprite: case mobj_sprite:
mo->sprite = luaL_checkinteger(L, 3); mo->sprite = luaL_checkinteger(L, 3);
break; break;

View File

@ -18,7 +18,9 @@
#include "w_wad.h" #include "w_wad.h"
#include "p_setup.h" #include "p_setup.h"
#include "r_state.h" #include "r_state.h"
#include "r_sky.h"
#include "g_game.h" #include "g_game.h"
#include "f_finale.h"
#include "byteptr.h" #include "byteptr.h"
#include "p_saveg.h" #include "p_saveg.h"
#include "p_local.h" #include "p_local.h"
@ -79,8 +81,239 @@ FUNCNORETURN static int LUA_Panic(lua_State *L)
#endif #endif
} }
// Moved here from lib_getenum.
int LUA_PushGlobals(lua_State *L, const char *word)
{
if (fastcmp(word,"gamemap")) {
lua_pushinteger(L, gamemap);
return 1;
} else if (fastcmp(word,"maptol")) {
lua_pushinteger(L, maptol);
return 1;
} else if (fastcmp(word,"ultimatemode")) {
lua_pushboolean(L, ultimatemode != 0);
return 1;
} else if (fastcmp(word,"mariomode")) {
lua_pushboolean(L, mariomode != 0);
return 1;
} else if (fastcmp(word,"twodlevel")) {
lua_pushboolean(L, twodlevel != 0);
return 1;
} else if (fastcmp(word,"circuitmap")) {
lua_pushboolean(L, circuitmap);
return 1;
} else if (fastcmp(word,"netgame")) {
lua_pushboolean(L, netgame);
return 1;
} else if (fastcmp(word,"multiplayer")) {
lua_pushboolean(L, multiplayer);
return 1;
} else if (fastcmp(word,"modeattacking")) {
lua_pushboolean(L, modeattacking);
return 1;
} else if (fastcmp(word,"splitscreen")) {
lua_pushboolean(L, splitscreen);
return 1;
} else if (fastcmp(word,"gamecomplete")) {
lua_pushboolean(L, gamecomplete);
return 1;
} else if (fastcmp(word,"devparm")) {
lua_pushboolean(L, devparm);
return 1;
} else if (fastcmp(word,"modifiedgame")) {
lua_pushboolean(L, modifiedgame && !savemoddata);
return 1;
} else if (fastcmp(word,"menuactive")) {
lua_pushboolean(L, menuactive);
return 1;
} else if (fastcmp(word,"paused")) {
lua_pushboolean(L, paused);
return 1;
} else if (fastcmp(word,"bluescore")) {
lua_pushinteger(L, bluescore);
return 1;
} else if (fastcmp(word,"redscore")) {
lua_pushinteger(L, redscore);
return 1;
} else if (fastcmp(word,"timelimit")) {
lua_pushinteger(L, cv_timelimit.value);
return 1;
} else if (fastcmp(word,"pointlimit")) {
lua_pushinteger(L, cv_pointlimit.value);
return 1;
// begin map vars
} else if (fastcmp(word,"spstage_start")) {
lua_pushinteger(L, spstage_start);
return 1;
} else if (fastcmp(word,"sstage_start")) {
lua_pushinteger(L, sstage_start);
return 1;
} else if (fastcmp(word,"sstage_end")) {
lua_pushinteger(L, sstage_end);
return 1;
} else if (fastcmp(word,"smpstage_start")) {
lua_pushinteger(L, smpstage_start);
return 1;
} else if (fastcmp(word,"smpstage_end")) {
lua_pushinteger(L, smpstage_end);
return 1;
} else if (fastcmp(word,"titlemap")) {
lua_pushinteger(L, titlemap);
return 1;
} else if (fastcmp(word,"titlemapinaction")) {
lua_pushboolean(L, (titlemapinaction != TITLEMAP_OFF));
return 1;
} else if (fastcmp(word,"bootmap")) {
lua_pushinteger(L, bootmap);
return 1;
} else if (fastcmp(word,"tutorialmap")) {
lua_pushinteger(L, tutorialmap);
return 1;
} else if (fastcmp(word,"tutorialmode")) {
lua_pushboolean(L, tutorialmode);
return 1;
// end map vars
// begin CTF colors
} else if (fastcmp(word,"skincolor_redteam")) {
lua_pushinteger(L, skincolor_redteam);
return 1;
} else if (fastcmp(word,"skincolor_blueteam")) {
lua_pushinteger(L, skincolor_blueteam);
return 1;
} else if (fastcmp(word,"skincolor_redring")) {
lua_pushinteger(L, skincolor_redring);
return 1;
} else if (fastcmp(word,"skincolor_bluering")) {
lua_pushinteger(L, skincolor_bluering);
return 1;
// end CTF colors
// begin timers
} else if (fastcmp(word,"invulntics")) {
lua_pushinteger(L, invulntics);
return 1;
} else if (fastcmp(word,"sneakertics")) {
lua_pushinteger(L, sneakertics);
return 1;
} else if (fastcmp(word,"flashingtics")) {
lua_pushinteger(L, flashingtics);
return 1;
} else if (fastcmp(word,"tailsflytics")) {
lua_pushinteger(L, tailsflytics);
return 1;
} else if (fastcmp(word,"underwatertics")) {
lua_pushinteger(L, underwatertics);
return 1;
} else if (fastcmp(word,"spacetimetics")) {
lua_pushinteger(L, spacetimetics);
return 1;
} else if (fastcmp(word,"extralifetics")) {
lua_pushinteger(L, extralifetics);
return 1;
} else if (fastcmp(word,"nightslinktics")) {
lua_pushinteger(L, nightslinktics);
return 1;
} else if (fastcmp(word,"gameovertics")) {
lua_pushinteger(L, gameovertics);
return 1;
} else if (fastcmp(word,"ammoremovaltics")) {
lua_pushinteger(L, ammoremovaltics);
return 1;
// end timers
} else if (fastcmp(word,"gametype")) {
lua_pushinteger(L, gametype);
return 1;
} else if (fastcmp(word,"gametyperules")) {
lua_pushinteger(L, gametyperules);
return 1;
} else if (fastcmp(word,"leveltime")) {
lua_pushinteger(L, leveltime);
return 1;
} else if (fastcmp(word,"sstimer")) {
lua_pushinteger(L, sstimer);
return 1;
} else if (fastcmp(word,"curWeather")) {
lua_pushinteger(L, curWeather);
return 1;
} else if (fastcmp(word,"globalweather")) {
lua_pushinteger(L, globalweather);
return 1;
} else if (fastcmp(word,"levelskynum")) {
lua_pushinteger(L, levelskynum);
return 1;
} else if (fastcmp(word,"globallevelskynum")) {
lua_pushinteger(L, globallevelskynum);
return 1;
} else if (fastcmp(word,"mapmusname")) {
lua_pushstring(L, mapmusname);
return 1;
} else if (fastcmp(word,"mapmusflags")) {
lua_pushinteger(L, mapmusflags);
return 1;
} else if (fastcmp(word,"mapmusposition")) {
lua_pushinteger(L, mapmusposition);
return 1;
// local player variables, by popular request
} else if (fastcmp(word,"consoleplayer")) { // player controlling console (aka local player 1)
if (consoleplayer < 0 || !playeringame[consoleplayer])
return 0;
LUA_PushUserdata(L, &players[consoleplayer], META_PLAYER);
return 1;
} else if (fastcmp(word,"displayplayer")) { // player visible on screen (aka display player 1)
if (displayplayer < 0 || !playeringame[displayplayer])
return 0;
LUA_PushUserdata(L, &players[displayplayer], META_PLAYER);
return 1;
} else if (fastcmp(word,"secondarydisplayplayer")) { // local/display player 2, for splitscreen
if (!splitscreen || secondarydisplayplayer < 0 || !playeringame[secondarydisplayplayer])
return 0;
LUA_PushUserdata(L, &players[secondarydisplayplayer], META_PLAYER);
return 1;
// end local player variables
} else if (fastcmp(word,"server")) {
if ((!multiplayer || !netgame) && !playeringame[serverplayer])
return 0;
LUA_PushUserdata(L, &players[serverplayer], META_PLAYER);
return 1;
} else if (fastcmp(word,"admin")) { // BACKWARDS COMPATIBILITY HACK: This was replaced with IsPlayerAdmin(), but some 2.1 Lua scripts still use the admin variable. It now points to the first admin player in the array.
LUA_Deprecated(L, "admin", "IsPlayerAdmin(player)");
if (!playeringame[adminplayers[0]] || IsPlayerAdmin(serverplayer))
return 0;
LUA_PushUserdata(L, &players[adminplayers[0]], META_PLAYER);
return 1;
} else if (fastcmp(word,"emeralds")) {
lua_pushinteger(L, emeralds);
return 1;
} else if (fastcmp(word,"gravity")) {
lua_pushinteger(L, gravity);
return 1;
} else if (fastcmp(word,"VERSIONSTRING")) {
lua_pushstring(L, VERSIONSTRING);
return 1;
} else if (fastcmp(word, "token")) {
lua_pushinteger(L, token);
return 1;
}
return 0;
}
// See the above.
int LUA_CheckGlobals(lua_State *L, const char *word)
{
if (fastcmp(word, "gametyperules"))
gametyperules = (UINT32)luaL_checkinteger(L, 2);
else if (fastcmp(word, "redscore"))
redscore = (UINT32)luaL_checkinteger(L, 2);
else if (fastcmp(word, "bluescore"))
bluescore = (UINT32)luaL_checkinteger(L, 2);
else
return 0;
// Global variable set, so return and don't error.
return 1;
}
// This function decides which global variables you are allowed to set. // This function decides which global variables you are allowed to set.
static int noglobals(lua_State *L) static int setglobals(lua_State *L)
{ {
const char *csname; const char *csname;
char *name; char *name;
@ -106,6 +339,9 @@ static int noglobals(lua_State *L)
return 0; return 0;
} }
if (LUA_CheckGlobals(L, csname))
return 0;
Z_Free(name); Z_Free(name);
return luaL_error(L, "Implicit global " LUA_QS " prevented. Create a local variable instead.", csname); return luaL_error(L, "Implicit global " LUA_QS " prevented. Create a local variable instead.", csname);
} }
@ -144,7 +380,7 @@ static void LUA_ClearState(void)
// lock the global namespace // lock the global namespace
lua_getmetatable(L, LUA_GLOBALSINDEX); lua_getmetatable(L, LUA_GLOBALSINDEX);
lua_pushcfunction(L, noglobals); lua_pushcfunction(L, setglobals);
lua_setfield(L, -2, "__newindex"); lua_setfield(L, -2, "__newindex");
lua_newtable(L); lua_newtable(L);
lua_setfield(L, -2, "__metatable"); lua_setfield(L, -2, "__metatable");

View File

@ -54,6 +54,8 @@ void LUA_InvalidatePlayer(player_t *player);
void LUA_Step(void); void LUA_Step(void);
void LUA_Archive(void); void LUA_Archive(void);
void LUA_UnArchive(void); void LUA_UnArchive(void);
int LUA_PushGlobals(lua_State *L, const char *word);
int LUA_CheckGlobals(lua_State *L, const char *word);
void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c
void LUA_CVarChanged(const char *name); // lua_consolelib.c void LUA_CVarChanged(const char *name); // lua_consolelib.c
int Lua_optoption(lua_State *L, int narg, int Lua_optoption(lua_State *L, int narg,

View File

@ -772,7 +772,7 @@ void Command_CauseCfail_f(void)
P_SetThingPosition(players[consoleplayer].mo); P_SetThingPosition(players[consoleplayer].mo);
// CTF consistency test // CTF consistency test
if (gametype == GT_CTF) if (gametyperules & GTR_TEAMFLAGS)
{ {
if (blueflag) { if (blueflag) {
P_RemoveMobj(blueflag); P_RemoveMobj(blueflag);

View File

@ -605,7 +605,7 @@ static menuitem_t MISC_ChangeTeamMenu[] =
{IT_WHITESTRING|IT_CALL, NULL, "Confirm", M_ConfirmTeamChange, 90}, {IT_WHITESTRING|IT_CALL, NULL, "Confirm", M_ConfirmTeamChange, 90},
}; };
static const gtdesc_t gametypedesc[] = gtdesc_t gametypedesc[NUMGAMETYPES] =
{ {
{{ 54, 54}, "Play through the single-player campaign with your friends, teaming up to beat Dr Eggman's nefarious challenges!"}, {{ 54, 54}, "Play through the single-player campaign with your friends, teaming up to beat Dr Eggman's nefarious challenges!"},
{{103, 103}, "Speed your way through the main acts, competing in several different categories to see who's the best."}, {{103, 103}, "Speed your way through the main acts, competing in several different categories to see who's the best."},
@ -1181,7 +1181,8 @@ static menuitem_t OP_CameraOptionsMenu[] =
{IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Distance", &cv_cam_dist, 60}, {IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Distance", &cv_cam_dist, 60},
{IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Height", &cv_cam_height, 70}, {IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Height", &cv_cam_height, 70},
{IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Camera Speed", &cv_cam_speed, 80}, {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Camera Spacial Speed", &cv_cam_speed, 80},
{IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Camera Turning Speed", &cv_cam_turnmultiplier, 90},
{IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair, 100}, {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair, 100},
}; };
@ -1195,7 +1196,8 @@ static menuitem_t OP_Camera2OptionsMenu[] =
{IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Distance", &cv_cam2_dist, 60}, {IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Distance", &cv_cam2_dist, 60},
{IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Height", &cv_cam2_height, 70}, {IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Height", &cv_cam2_height, 70},
{IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Camera Speed", &cv_cam2_speed, 80}, {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Camera Spacial Speed", &cv_cam2_speed, 80},
{IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Camera Turning Speed", &cv_cam2_turnmultiplier, 90},
{IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair2, 100}, {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair2, 100},
}; };
@ -4688,6 +4690,9 @@ static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt)
if (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) if (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE))
return true; return true;
if (gt > 0 && gt < gametypecount && (mapheaderinfo[mapnum]->typeoflevel & gametypetol[gt]))
return true;
return false; return false;
case LLM_LEVELSELECT: case LLM_LEVELSELECT:
@ -9936,7 +9941,7 @@ static void M_DrawConnectMenu(void)
va("Ping: %u", (UINT32)LONG(serverlist[slindex].info.time))); va("Ping: %u", (UINT32)LONG(serverlist[slindex].info.time)));
gt = "Unknown"; gt = "Unknown";
if (serverlist[slindex].info.gametype < NUMGAMETYPES) if (serverlist[slindex].info.gametype < gametypecount)
gt = Gametype_Names[serverlist[slindex].info.gametype]; gt = Gametype_Names[serverlist[slindex].info.gametype];
V_DrawSmallString(currentMenu->x+46,S_LINEY(i)+8, globalflags, V_DrawSmallString(currentMenu->x+46,S_LINEY(i)+8, globalflags,

View File

@ -371,6 +371,7 @@ typedef struct
UINT8 col[2]; UINT8 col[2];
char notes[441]; char notes[441];
} gtdesc_t; } gtdesc_t;
extern gtdesc_t gametypedesc[NUMGAMETYPES];
// mode descriptions for video mode menu // mode descriptions for video mode menu
typedef struct typedef struct

View File

@ -181,11 +181,9 @@ void A_SpawnObjectAbsolute(mobj_t *actor);
void A_SpawnObjectRelative(mobj_t *actor); void A_SpawnObjectRelative(mobj_t *actor);
void A_ChangeAngleRelative(mobj_t *actor); void A_ChangeAngleRelative(mobj_t *actor);
void A_ChangeAngleAbsolute(mobj_t *actor); void A_ChangeAngleAbsolute(mobj_t *actor);
#ifdef ROTSPRITE
void A_RollAngle(mobj_t *actor); void A_RollAngle(mobj_t *actor);
void A_ChangeRollAngleRelative(mobj_t *actor); void A_ChangeRollAngleRelative(mobj_t *actor);
void A_ChangeRollAngleAbsolute(mobj_t *actor); void A_ChangeRollAngleAbsolute(mobj_t *actor);
#endif // ROTSPRITE
void A_PlaySound(mobj_t *actor); void A_PlaySound(mobj_t *actor);
void A_FindTarget(mobj_t *actor); void A_FindTarget(mobj_t *actor);
void A_FindTracer(mobj_t *actor); void A_FindTracer(mobj_t *actor);
@ -4985,7 +4983,7 @@ void A_ThrownRing(mobj_t *actor)
continue; continue;
// Don't home in on teammates. // Don't home in on teammates.
if (gametype == GT_CTF if ((gametyperules & GTR_TEAMFLAGS)
&& actor->target->player->ctfteam == player->ctfteam) && actor->target->player->ctfteam == player->ctfteam)
continue; continue;
} }
@ -6591,7 +6589,7 @@ void A_OldRingExplode(mobj_t *actor) {
if (changecolor) if (changecolor)
{ {
if (gametype != GT_CTF) if (!(gametyperules & GTR_TEAMFLAGS))
mo->color = actor->target->color; //copy color mo->color = actor->target->color; //copy color
else if (actor->target->player->ctfteam == 2) else if (actor->target->player->ctfteam == 2)
mo->color = skincolor_bluering; mo->color = skincolor_bluering;
@ -6607,7 +6605,7 @@ void A_OldRingExplode(mobj_t *actor) {
if (changecolor) if (changecolor)
{ {
if (gametype != GT_CTF) if (!(gametyperules & GTR_TEAMFLAGS))
mo->color = actor->target->color; //copy color mo->color = actor->target->color; //copy color
else if (actor->target->player->ctfteam == 2) else if (actor->target->player->ctfteam == 2)
mo->color = skincolor_bluering; mo->color = skincolor_bluering;
@ -6622,7 +6620,7 @@ void A_OldRingExplode(mobj_t *actor) {
if (changecolor) if (changecolor)
{ {
if (gametype != GT_CTF) if (!(gametyperules & GTR_TEAMFLAGS))
mo->color = actor->target->color; //copy color mo->color = actor->target->color; //copy color
else if (actor->target->player->ctfteam == 2) else if (actor->target->player->ctfteam == 2)
mo->color = skincolor_bluering; mo->color = skincolor_bluering;
@ -8627,7 +8625,6 @@ void A_ChangeAngleAbsolute(mobj_t *actor)
actor->angle = FixedAngle(P_RandomRange(amin, amax)); actor->angle = FixedAngle(P_RandomRange(amin, amax));
} }
#ifdef ROTSPRITE
// Function: A_RollAngle // Function: A_RollAngle
// //
// Description: Changes the roll angle. // Description: Changes the roll angle.
@ -8663,16 +8660,10 @@ void A_RollAngle(mobj_t *actor)
// //
void A_ChangeRollAngleRelative(mobj_t *actor) void A_ChangeRollAngleRelative(mobj_t *actor)
{ {
// Oh god, the old code /sucked/. Changed this and the absolute version to get a random range using amin and amax instead of
// getting a random angle from the _entire_ spectrum and then clipping. While we're at it, do the angle conversion to the result
// rather than the ranges, so <0 and >360 work as possible values. -Red
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
//angle_t angle = (P_RandomByte()+1)<<24;
const fixed_t amin = locvar1*FRACUNIT; const fixed_t amin = locvar1*FRACUNIT;
const fixed_t amax = locvar2*FRACUNIT; const fixed_t amax = locvar2*FRACUNIT;
//const angle_t amin = FixedAngle(locvar1*FRACUNIT);
//const angle_t amax = FixedAngle(locvar2*FRACUNIT);
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
if (LUA_CallAction("A_ChangeRollAngleRelative", actor)) if (LUA_CallAction("A_ChangeRollAngleRelative", actor))
return; return;
@ -8682,11 +8673,6 @@ void A_ChangeRollAngleRelative(mobj_t *actor)
if (amin > amax) if (amin > amax)
I_Error("A_ChangeRollAngleRelative: var1 is greater than var2"); I_Error("A_ChangeRollAngleRelative: var1 is greater than var2");
#endif #endif
/*
if (angle < amin)
angle = amin;
if (angle > amax)
angle = amax;*/
actor->rollangle += FixedAngle(P_RandomRange(amin, amax)); actor->rollangle += FixedAngle(P_RandomRange(amin, amax));
} }
@ -8702,11 +8688,8 @@ void A_ChangeRollAngleAbsolute(mobj_t *actor)
{ {
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
//angle_t angle = (P_RandomByte()+1)<<24;
const fixed_t amin = locvar1*FRACUNIT; const fixed_t amin = locvar1*FRACUNIT;
const fixed_t amax = locvar2*FRACUNIT; const fixed_t amax = locvar2*FRACUNIT;
//const angle_t amin = FixedAngle(locvar1*FRACUNIT);
//const angle_t amax = FixedAngle(locvar2*FRACUNIT);
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
if (LUA_CallAction("A_ChangeRollAngleAbsolute", actor)) if (LUA_CallAction("A_ChangeRollAngleAbsolute", actor))
return; return;
@ -8716,15 +8699,9 @@ void A_ChangeRollAngleAbsolute(mobj_t *actor)
if (amin > amax) if (amin > amax)
I_Error("A_ChangeRollAngleAbsolute: var1 is greater than var2"); I_Error("A_ChangeRollAngleAbsolute: var1 is greater than var2");
#endif #endif
/*
if (angle < amin)
angle = amin;
if (angle > amax)
angle = amax;*/
actor->rollangle = FixedAngle(P_RandomRange(amin, amax)); actor->rollangle = FixedAngle(P_RandomRange(amin, amax));
} }
#endif // ROTSPRITE
// Function: A_PlaySound // Function: A_PlaySound
// //

View File

@ -625,7 +625,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
P_AddPlayerScore(player, 1000); P_AddPlayerScore(player, 1000);
if (gametype != GT_COOP || modeattacking) // score only? if (!(gametyperules & GTR_SPECIALSTAGES) || modeattacking) // score only?
{ {
S_StartSound(toucher, sfx_chchng); S_StartSound(toucher, sfx_chchng);
break; break;
@ -1888,7 +1888,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
char targetname[MAXPLAYERNAME+4]; char targetname[MAXPLAYERNAME+4];
char sourcename[MAXPLAYERNAME+4]; char sourcename[MAXPLAYERNAME+4];
if (G_PlatformGametype()) if (!(gametyperules & (GTR_RINGSLINGER|GTR_HURTMESSAGES)))
return; // Not in coop, etc. return; // Not in coop, etc.
if (!player) if (!player)
@ -2093,7 +2093,7 @@ void P_CheckTimeLimit(void)
if (!(multiplayer || netgame)) if (!(multiplayer || netgame))
return; return;
if (G_PlatformGametype()) if (!(gametyperules & GTR_TIMELIMIT))
return; return;
if (leveltime < timelimitintics) if (leveltime < timelimitintics)
@ -2124,7 +2124,7 @@ void P_CheckTimeLimit(void)
} }
//Optional tie-breaker for Match/CTF //Optional tie-breaker for Match/CTF
else if (cv_overtime.value) else if ((cv_overtime.value) && (gametyperules & GTR_OVERTIME))
{ {
INT32 playerarray[MAXPLAYERS]; INT32 playerarray[MAXPLAYERS];
INT32 tempplayer = 0; INT32 tempplayer = 0;
@ -2206,7 +2206,7 @@ void P_CheckPointLimit(void)
if (!(multiplayer || netgame)) if (!(multiplayer || netgame))
return; return;
if (G_PlatformGametype()) if (!(gametyperules & GTR_POINTLIMIT))
return; return;
// pointlimit is nonzero, check if it's been reached by this player // pointlimit is nonzero, check if it's been reached by this player
@ -2389,7 +2389,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
{ {
if (metalrecording) // Ack! Metal Sonic shouldn't die! Cut the tape, end recording! if (metalrecording) // Ack! Metal Sonic shouldn't die! Cut the tape, end recording!
G_StopMetalRecording(true); G_StopMetalRecording(true);
if (gametype == GT_MATCH // note, no team match suicide penalty if ((gametyperules & GTR_DEATHPENALTY) // note, no team match suicide penalty
&& ((target == source) || (source == NULL && inflictor == NULL) || (source && !source->player))) && ((target == source) || (source == NULL && inflictor == NULL) || (source && !source->player)))
{ // Suicide penalty { // Suicide penalty
if (target->player->score >= 50) if (target->player->score >= 50)
@ -2978,7 +2978,7 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source)
player->flyangle += 180; // Shuffle's BETTERNIGHTSMOVEMENT? player->flyangle += 180; // Shuffle's BETTERNIGHTSMOVEMENT?
player->flyangle %= 360; player->flyangle %= 360;
if (gametype == GT_RACE || gametype == GT_COMPETITION) if (gametyperules & GTR_RACE)
player->drillmeter -= 5*20; player->drillmeter -= 5*20;
else else
{ {
@ -3005,9 +3005,7 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source)
P_SetPlayerMobjState(target, S_PLAY_NIGHTS_STUN); P_SetPlayerMobjState(target, S_PLAY_NIGHTS_STUN);
S_StartSound(target, sfx_nghurt); S_StartSound(target, sfx_nghurt);
#ifdef ROTSPRITE
player->mo->rollangle = 0; player->mo->rollangle = 0;
#endif
if (oldnightstime > 10*TICRATE if (oldnightstime > 10*TICRATE
&& player->nightstime < 10*TICRATE) && player->nightstime < 10*TICRATE)
@ -3042,7 +3040,7 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou
return false; return false;
// Ignore IT players shooting each other, unless friendlyfire is on. // Ignore IT players shooting each other, unless friendlyfire is on.
if ((player->pflags & PF_TAGIT && !((cv_friendlyfire.value || (damagetype & DMG_CANHURTSELF)) && if ((player->pflags & PF_TAGIT && !((cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE) || (damagetype & DMG_CANHURTSELF)) &&
source && source->player && source->player->pflags & PF_TAGIT))) source && source->player && source->player->pflags & PF_TAGIT)))
{ {
if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK))
@ -3058,7 +3056,7 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou
// Don't allow players on the same team to hurt one another, // Don't allow players on the same team to hurt one another,
// unless cv_friendlyfire is on. // unless cv_friendlyfire is on.
if (!(cv_friendlyfire.value || (damagetype & DMG_CANHURTSELF)) && (player->pflags & PF_TAGIT) == (source->player->pflags & PF_TAGIT)) if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE) || (damagetype & DMG_CANHURTSELF)) && (player->pflags & PF_TAGIT) == (source->player->pflags & PF_TAGIT))
{ {
if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK))
{ {
@ -3143,7 +3141,7 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj
return false; return false;
// In COOP/RACE, you can't hurt other players unless cv_friendlyfire is on // In COOP/RACE, you can't hurt other players unless cv_friendlyfire is on
if (!cv_friendlyfire.value && (G_PlatformGametype())) if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) && (G_PlatformGametype()))
{ {
if (gametype == GT_COOP && inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) // co-op only if (gametype == GT_COOP && inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) // co-op only
{ {
@ -3166,7 +3164,7 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj
{ {
// Don't allow players on the same team to hurt one another, // Don't allow players on the same team to hurt one another,
// unless cv_friendlyfire is on. // unless cv_friendlyfire is on.
if (!cv_friendlyfire.value && target->player->ctfteam == source->player->ctfteam) if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) && target->player->ctfteam == source->player->ctfteam)
{ {
if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK))
{ {
@ -3224,7 +3222,7 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
player->mo->flags2 &= ~MF2_DONTDRAW; player->mo->flags2 &= ~MF2_DONTDRAW;
P_SetPlayerMobjState(player->mo, player->mo->info->deathstate); P_SetPlayerMobjState(player->mo, player->mo->info->deathstate);
if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{ {
P_PlayerFlagBurst(player, false); P_PlayerFlagBurst(player, false);
if (source && source->player) if (source && source->player)
@ -3349,7 +3347,7 @@ static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source,
else else
S_StartSound (player->mo, sfx_shldls); // Ba-Dum! Shield loss. S_StartSound (player->mo, sfx_shldls); // Ba-Dum! Shield loss.
if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{ {
P_PlayerFlagBurst(player, false); P_PlayerFlagBurst(player, false);
if (source && source->player) if (source && source->player)
@ -3383,7 +3381,7 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN
P_AddPlayerScore(source->player, 50); P_AddPlayerScore(source->player, 50);
} }
if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{ {
P_PlayerFlagBurst(player, false); P_PlayerFlagBurst(player, false);
if (source && source->player) if (source && source->player)
@ -3426,6 +3424,24 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source)
if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super]) if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super])
return; return;
if (!cv_friendlyfire.value)
{
if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK))
{
if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers.
{
P_SwitchShield(player, SH_PINK);
S_StartSound(player->mo, mobjinfo[MT_PITY_ICON].seesound);
}
}
if (source->player->ctfteam == player->ctfteam)
return;
}
if (inflictor->type == MT_LHRT)
return;
if (player->powers[pw_shield] || player->bot) //If One-Hit Shield if (player->powers[pw_shield] || player->bot) //If One-Hit Shield
{ {
P_RemoveShield(player); P_RemoveShield(player);
@ -3442,7 +3458,7 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source)
P_DoPlayerPain(player, inflictor, source); P_DoPlayerPain(player, inflictor, source);
if (gametype == GT_CTF && player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)) if ((gametyperules & GTR_TEAMFLAGS) && player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))
P_PlayerFlagBurst(player, false); P_PlayerFlagBurst(player, false);
if (oldnightstime > 10*TICRATE if (oldnightstime > 10*TICRATE
@ -3593,7 +3609,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
{ {
if (source == target) if (source == target)
return false; // Don't hit yourself with your own paraloop, baka return false; // Don't hit yourself with your own paraloop, baka
if (source && source->player && !cv_friendlyfire.value if (source && source->player && !(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE))
&& (gametype == GT_COOP && (gametype == GT_COOP
|| (G_GametypeHasTeams() && player->ctfteam == source->player->ctfteam))) || (G_GametypeHasTeams() && player->ctfteam == source->player->ctfteam)))
return false; // Don't run eachother over in special stages and team games and such return false; // Don't run eachother over in special stages and team games and such
@ -3688,7 +3704,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
// by friendly fire. Spilling their rings and other items is enough. // by friendly fire. Spilling their rings and other items is enough.
else if (!force && G_GametypeHasTeams() else if (!force && G_GametypeHasTeams()
&& source && source->player && (source->player->ctfteam == player->ctfteam) && source && source->player && (source->player->ctfteam == player->ctfteam)
&& cv_friendlyfire.value) && (cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)))
{ {
damage = 0; damage = 0;
P_ShieldDamage(player, inflictor, source, damage, damagetype); P_ShieldDamage(player, inflictor, source, damage, damagetype);

View File

@ -115,10 +115,10 @@ typedef struct camera_s
extern camera_t camera, camera2; extern camera_t camera, camera2;
extern consvar_t cv_cam_dist, cv_cam_still, cv_cam_height; extern consvar_t cv_cam_dist, cv_cam_still, cv_cam_height;
extern consvar_t cv_cam_speed, cv_cam_rotate, cv_cam_rotspeed, cv_cam_orbit, cv_cam_adjust; extern consvar_t cv_cam_speed, cv_cam_rotate, cv_cam_rotspeed, cv_cam_turnmultiplier, cv_cam_orbit, cv_cam_adjust;
extern consvar_t cv_cam2_dist, cv_cam2_still, cv_cam2_height; extern consvar_t cv_cam2_dist, cv_cam2_still, cv_cam2_height;
extern consvar_t cv_cam2_speed, cv_cam2_rotate, cv_cam2_rotspeed, cv_cam2_orbit, cv_cam2_adjust; extern consvar_t cv_cam2_speed, cv_cam2_rotate, cv_cam2_rotspeed, cv_cam2_turnmultiplier, cv_cam2_orbit, cv_cam2_adjust;
extern fixed_t t_cam_dist, t_cam_height, t_cam_rotate; extern fixed_t t_cam_dist, t_cam_height, t_cam_rotate;
extern fixed_t t_cam2_dist, t_cam2_height, t_cam2_rotate; extern fixed_t t_cam2_dist, t_cam2_height, t_cam2_rotate;

View File

@ -615,7 +615,7 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails)
// Why block opposing teams from tailsflying each other? // Why block opposing teams from tailsflying each other?
// Sneaking into the hands of a flying tails player in Race might be a viable strategy, who knows. // Sneaking into the hands of a flying tails player in Race might be a viable strategy, who knows.
/* /*
if (gametype == GT_RACE || gametype == GT_COMPETITION if ((gametyperules & GTR_RACE)
|| (netgame && (tails->spectator || sonic->spectator)) || (netgame && (tails->spectator || sonic->spectator))
|| (G_TagGametype() && (!(tails->pflags & PF_TAGIT) != !(sonic->pflags & PF_TAGIT))) || (G_TagGametype() && (!(tails->pflags & PF_TAGIT) != !(sonic->pflags & PF_TAGIT)))
|| (gametype == GT_MATCH) || (gametype == GT_MATCH)

View File

@ -8322,6 +8322,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj)
static void P_TracerAngleThink(mobj_t *mobj) static void P_TracerAngleThink(mobj_t *mobj)
{ {
angle_t ang; angle_t ang;
if (!mobj->tracer) if (!mobj->tracer)
return; return;
@ -9762,15 +9763,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
P_DragonbomberThink(mobj); P_DragonbomberThink(mobj);
break; break;
case MT_MINUS: case MT_MINUS:
#ifdef ROTSPRITE
{
if (P_IsObjectOnGround(mobj)) if (P_IsObjectOnGround(mobj))
mobj->rollangle = 0; mobj->rollangle = 0;
else else
mobj->rollangle = R_PointToAngle2(0, 0, mobj->momz, (mobj->scale << 1) - min(abs(mobj->momz), mobj->scale << 1)); mobj->rollangle = R_PointToAngle2(0, 0, mobj->momz, (mobj->scale << 1) - min(abs(mobj->momz), mobj->scale << 1));
} break;
#endif
break;
case MT_SPINFIRE: case MT_SPINFIRE:
if (mobj->flags & MF_NOGRAVITY) if (mobj->flags & MF_NOGRAVITY)
{ {
@ -11347,7 +11344,10 @@ void P_SpawnPlayer(INT32 playernum)
{ {
p->outofcoop = false; p->outofcoop = false;
if (netgame && p->jointime < 1) if (netgame && p->jointime < 1)
p->spectator = true; {
// Averted by GTR_NOSPECTATORSPAWN.
p->spectator = (gametyperules & GTR_NOSPECTATORSPAWN) ? false : true;
}
else if (multiplayer && !netgame) else if (multiplayer && !netgame)
{ {
// If you're in a team game and you don't have a team assigned yet... // If you're in a team game and you don't have a team assigned yet...
@ -11390,7 +11390,7 @@ void P_SpawnPlayer(INT32 playernum)
p->skincolor = skincolor_blueteam; p->skincolor = skincolor_blueteam;
} }
if ((netgame || multiplayer) && (gametype != GT_COOP || leveltime) && !p->spectator && !(maptol & TOL_NIGHTS)) if ((netgame || multiplayer) && ((gametyperules & GTR_SPAWNINVUL) || leveltime) && !p->spectator && !(maptol & TOL_NIGHTS))
p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent
mobj = P_SpawnMobj(0, 0, 0, MT_PLAYER); mobj = P_SpawnMobj(0, 0, 0, MT_PLAYER);
@ -11790,7 +11790,7 @@ static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing)
else if (mthing->type == mobjinfo[MT_EMERHUNT].doomednum) else if (mthing->type == mobjinfo[MT_EMERHUNT].doomednum)
{ {
// Emerald Hunt is Coop only. Don't spawn the emerald yet, but save the spawnpoint for later. // Emerald Hunt is Coop only. Don't spawn the emerald yet, but save the spawnpoint for later.
if (gametype == GT_COOP && numhuntemeralds < MAXHUNTEMERALDS) if ((gametyperules & GTR_EMERALDHUNT) && numhuntemeralds < MAXHUNTEMERALDS)
huntemeralds[numhuntemeralds++] = mthing; huntemeralds[numhuntemeralds++] = mthing;
return true; return true;
} }
@ -11823,7 +11823,7 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i)
if (!cv_powerstones.value) if (!cv_powerstones.value)
return false; return false;
if (!(gametype == GT_MATCH || gametype == GT_CTF)) if (!(gametyperules & GTR_MATCHEMERALDS))
return false; return false;
runemeraldmanager = true; runemeraldmanager = true;
@ -11837,7 +11837,7 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i)
break; break;
case MT_TOKEN: case MT_TOKEN:
if (gametype != GT_COOP && gametype != GT_COMPETITION) if (!(gametyperules & GTR_EMERALDTOKENS))
return false; // Gametype's not right return false; // Gametype's not right
if (tokenbits == 30) if (tokenbits == 30)
@ -11867,20 +11867,20 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i)
return false; return false;
} }
if (!G_PlatformGametype()) if (((mobjinfo[i].flags & MF_ENEMY) || (mobjinfo[i].flags & MF_BOSS)) && !(gametyperules & GTR_SPAWNENEMIES))
{ return false; // No enemies in ringslinger modes
if ((mobjinfo[i].flags & MF_ENEMY) || (mobjinfo[i].flags & MF_BOSS))
return false; // No enemies in ringslinger modes
if (i == MT_SIGN || i == MT_STARPOST) if (!(gametyperules & GTR_ALLOWEXIT) && (i == MT_SIGN))
return false; // Don't spawn exit signs or starposts in wrong game modes return false; // Don't spawn exit signs in wrong game modes
}
if (!G_PlatformGametype() && (i == MT_STARPOST))
return false; // Don't spawn starposts in wrong game modes
if (!G_RingSlingerGametype() || !cv_specialrings.value) if (!G_RingSlingerGametype() || !cv_specialrings.value)
if (P_WeaponOrPanel(i)) if (P_WeaponOrPanel(i))
return false; // Don't place weapons/panels in non-ringslinger modes return false; // Don't place weapons/panels in non-ringslinger modes
if (gametype != GT_CTF) // CTF specific things if (!(gametyperules & GTR_TEAMFLAGS)) // CTF specific things
{ {
if (i == MT_BLUEFLAG || i == MT_REDFLAG) if (i == MT_BLUEFLAG || i == MT_REDFLAG)
return false; // No flags in non-CTF modes! return false; // No flags in non-CTF modes!
@ -11928,7 +11928,7 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i)
// Yeah, this is a dirty hack. // Yeah, this is a dirty hack.
if ((mobjinfo[i].flags & (MF_MONITOR|MF_GRENADEBOUNCE)) == MF_MONITOR) if ((mobjinfo[i].flags & (MF_MONITOR|MF_GRENADEBOUNCE)) == MF_MONITOR)
{ {
if (gametype == GT_COMPETITION || gametype == GT_RACE) if (gametyperules & GTR_RACE)
{ {
// Set powerup boxes to user settings for competition. // Set powerup boxes to user settings for competition.
switch (cv_competitionboxes.value) switch (cv_competitionboxes.value)
@ -11972,7 +11972,7 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i)
return MT_NIGHTSCHIP; return MT_NIGHTSCHIP;
} }
if (gametype != GT_CTF) if (!(gametyperules & GTR_TEAMS))
{ {
if (i == MT_BLUETEAMRING || i == MT_REDTEAMRING) if (i == MT_BLUETEAMRING || i == MT_REDTEAMRING)
return MT_RING; return MT_RING;

View File

@ -279,9 +279,7 @@ typedef struct mobj_s
// More drawing info: to determine current sprite. // More drawing info: to determine current sprite.
angle_t angle; // orientation angle_t angle; // orientation
#ifdef ROTSPRITE
angle_t rollangle; angle_t rollangle;
#endif
spritenum_t sprite; // used to find patch_t and flip value spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h UINT32 frame; // frame number, plus bits see p_pspr.h
UINT8 sprite2; // player sprites UINT8 sprite2; // player sprites
@ -402,9 +400,7 @@ typedef struct precipmobj_s
// More drawing info: to determine current sprite. // More drawing info: to determine current sprite.
angle_t angle; // orientation angle_t angle; // orientation
#ifdef ROTSPRITE
angle_t rollangle; angle_t rollangle;
#endif
spritenum_t sprite; // used to find patch_t and flip value spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h UINT32 frame; // frame number, plus bits see p_pspr.h
UINT8 sprite2; // player sprites UINT8 sprite2; // player sprites

View File

@ -1252,9 +1252,7 @@ typedef enum
MD2_SLOPE = 1<<11, MD2_SLOPE = 1<<11,
#endif #endif
MD2_COLORIZED = 1<<12, MD2_COLORIZED = 1<<12,
#ifdef ROTSPRITE
MD2_ROLLANGLE = 1<<13, MD2_ROLLANGLE = 1<<13,
#endif
} mobj_diff2_t; } mobj_diff2_t;
typedef enum typedef enum
@ -1474,10 +1472,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
#endif #endif
if (mobj->colorized) if (mobj->colorized)
diff2 |= MD2_COLORIZED; diff2 |= MD2_COLORIZED;
#ifdef ROTSPRITE
if (mobj->rollangle) if (mobj->rollangle)
diff2 |= MD2_ROLLANGLE; diff2 |= MD2_ROLLANGLE;
#endif
if (diff2 != 0) if (diff2 != 0)
diff |= MD_MORE; diff |= MD_MORE;
@ -1642,10 +1638,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
#endif #endif
if (diff2 & MD2_COLORIZED) if (diff2 & MD2_COLORIZED)
WRITEUINT8(save_p, mobj->colorized); WRITEUINT8(save_p, mobj->colorized);
#ifdef ROTSPRITE
if (diff2 & MD2_ROLLANGLE) if (diff2 & MD2_ROLLANGLE)
WRITEANGLE(save_p, mobj->rollangle); WRITEANGLE(save_p, mobj->rollangle);
#endif
WRITEUINT32(save_p, mobj->mobjnum); WRITEUINT32(save_p, mobj->mobjnum);
} }
@ -2722,12 +2716,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
#endif #endif
if (diff2 & MD2_COLORIZED) if (diff2 & MD2_COLORIZED)
mobj->colorized = READUINT8(save_p); mobj->colorized = READUINT8(save_p);
#ifdef ROTSPRITE
if (diff2 & MD2_ROLLANGLE) if (diff2 & MD2_ROLLANGLE)
mobj->rollangle = READANGLE(save_p); mobj->rollangle = READANGLE(save_p);
else
mobj->rollangle = 0;
#endif
if (diff & MD_REDFLAG) if (diff & MD_REDFLAG)
{ {

View File

@ -2539,8 +2539,7 @@ boolean P_SetupLevel(boolean skipprecip)
// chasecam on in chaos, race, coop // chasecam on in chaos, race, coop
// chasecam off in match, tag, capture the flag // chasecam off in match, tag, capture the flag
chase = (gametype == GT_RACE || gametype == GT_COMPETITION || gametype == GT_COOP) chase = (!(gametyperules & GTR_FIRSTPERSON)) || (maptol & TOL_2D);
|| (maptol & TOL_2D);
if (!dedicated) if (!dedicated)
{ {

View File

@ -4692,7 +4692,7 @@ DoneSection2:
} }
case 2: // Special stage GOAL sector / Exit Sector / CTF Flag Return case 2: // Special stage GOAL sector / Exit Sector / CTF Flag Return
if (player->bot || !G_PlatformGametype()) if (player->bot || !(gametyperules & GTR_ALLOWEXIT))
break; break;
if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && player->nightstime > 6) if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && player->nightstime > 6)
{ {
@ -4727,7 +4727,7 @@ DoneSection2:
break; break;
case 3: // Red Team's Base case 3: // Red Team's Base
if (gametype == GT_CTF && P_IsObjectOnGround(player->mo)) if ((gametyperules & GTR_TEAMFLAGS) && P_IsObjectOnGround(player->mo))
{ {
if (player->ctfteam == 1 && (player->gotflag & GF_BLUEFLAG)) if (player->ctfteam == 1 && (player->gotflag & GF_BLUEFLAG))
{ {
@ -4760,7 +4760,7 @@ DoneSection2:
break; break;
case 4: // Blue Team's Base case 4: // Blue Team's Base
if (gametype == GT_CTF && P_IsObjectOnGround(player->mo)) if ((gametyperules & GTR_TEAMFLAGS) && P_IsObjectOnGround(player->mo))
{ {
if (player->ctfteam == 2 && (player->gotflag & GF_REDFLAG)) if (player->ctfteam == 2 && (player->gotflag & GF_REDFLAG))
{ {
@ -7224,14 +7224,14 @@ void P_SpawnSpecials(INT32 fromnetsave)
break; break;
case 308: // Race-only linedef executor. Triggers once. case 308: // Race-only linedef executor. Triggers once.
if (gametype != GT_RACE && gametype != GT_COMPETITION) if (!(gametyperules & GTR_RACE))
lines[i].special = 0; lines[i].special = 0;
break; break;
// Linedef executor triggers for CTF teams. // Linedef executor triggers for CTF teams.
case 309: case 309:
case 311: case 311:
if (gametype != GT_CTF) if (!(gametyperules & GTR_TEAMFLAGS))
lines[i].special = 0; lines[i].special = 0;
break; break;

View File

@ -387,7 +387,7 @@ UINT8 P_FindLowestMare(void)
mobj_t *mo2; mobj_t *mo2;
UINT8 mare = UINT8_MAX; UINT8 mare = UINT8_MAX;
if (gametype == GT_RACE || gametype == GT_COMPETITION) if (gametyperules & GTR_RACE)
return 0; return 0;
// scan the thinkers // scan the thinkers
@ -638,9 +638,7 @@ static void P_DeNightserizePlayer(player_t *player)
player->marebonuslap = 0; player->marebonuslap = 0;
player->flyangle = 0; player->flyangle = 0;
player->anotherflyangle = 0; player->anotherflyangle = 0;
#ifdef ROTSPRITE
player->mo->rollangle = 0; player->mo->rollangle = 0;
#endif
P_SetTarget(&player->mo->target, NULL); P_SetTarget(&player->mo->target, NULL);
P_SetTarget(&player->axis1, P_SetTarget(&player->axis2, NULL)); P_SetTarget(&player->axis1, P_SetTarget(&player->axis2, NULL));
@ -768,9 +766,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
player->secondjump = 0; player->secondjump = 0;
player->flyangle = 0; player->flyangle = 0;
player->anotherflyangle = 0; player->anotherflyangle = 0;
#ifdef ROTSPRITE
player->mo->rollangle = 0; player->mo->rollangle = 0;
#endif
player->powers[pw_shield] = SH_NONE; player->powers[pw_shield] = SH_NONE;
player->powers[pw_super] = 0; player->powers[pw_super] = 0;
@ -793,7 +789,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
P_RestoreMusic(player); P_RestoreMusic(player);
} }
if (gametype == GT_RACE || gametype == GT_COMPETITION) if (gametyperules & GTR_RACE)
{ {
if (player->drillmeter < 48*20) if (player->drillmeter < 48*20)
player->drillmeter = 48*20; player->drillmeter = 48*20;
@ -2181,7 +2177,7 @@ void P_DoPlayerExit(player_t *player)
if (cv_allowexitlevel.value == 0 && !G_PlatformGametype()) if (cv_allowexitlevel.value == 0 && !G_PlatformGametype())
return; return;
else if (gametype == GT_RACE || gametype == GT_COMPETITION) // If in Race Mode, allow else if (gametyperules & GTR_RACE) // If in Race Mode, allow
{ {
if (!countdown) // a 60-second wait ala Sonic 2. if (!countdown) // a 60-second wait ala Sonic 2.
countdown = (cv_countdowntime.value - 1)*TICRATE + 1; // Use cv_countdowntime countdown = (cv_countdowntime.value - 1)*TICRATE + 1; // Use cv_countdowntime
@ -3110,7 +3106,7 @@ static void P_DoPlayerHeadSigns(player_t *player)
} }
} }
} }
else if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) // If you have the flag (duh). else if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) // If you have the flag (duh).
{ {
// Spawn a got-flag message over the head of the player that // Spawn a got-flag message over the head of the player that
// has it (but not on your own screen if you have the flag). // has it (but not on your own screen if you have the flag).
@ -4670,7 +4666,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
if (player->powers[pw_carry] == CR_BRAKGOOP) if (player->powers[pw_carry] == CR_BRAKGOOP)
player->dashspeed = 0; player->dashspeed = 0;
if (!((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE)) if (!((gametyperules & GTR_RACE) && leveltime < 4*TICRATE))
{ {
if (player->dashspeed) if (player->dashspeed)
{ {
@ -5048,7 +5044,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
{ {
if (onground || player->climbing || player->powers[pw_carry]) if (onground || player->climbing || player->powers[pw_carry])
; ;
else if (gametype == GT_CTF && player->gotflag) else if ((gametyperules & GTR_TEAMFLAGS) && player->gotflag)
; ;
else if (player->pflags & (PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player has used an ability previously else if (player->pflags & (PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player has used an ability previously
; ;
@ -5269,7 +5265,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
player->secondjump = 0; player->secondjump = 0;
player->pflags &= ~PF_THOKKED; player->pflags &= ~PF_THOKKED;
} }
else if (player->pflags & PF_SLIDING || (gametype == GT_CTF && player->gotflag) || player->pflags & PF_SHIELDABILITY) else if (player->pflags & PF_SLIDING || ((gametyperules & GTR_TEAMFLAGS) && player->gotflag) || player->pflags & PF_SHIELDABILITY)
; ;
/*else if (P_SuperReady(player)) /*else if (P_SuperReady(player))
{ {
@ -5556,7 +5552,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
{ {
player->pflags |= PF_JUMPDOWN; player->pflags |= PF_JUMPDOWN;
if ((gametype != GT_CTF || !player->gotflag) && !player->exiting) if ((!(gametyperules & GTR_TEAMFLAGS) || !player->gotflag) && !player->exiting)
{ {
if (player->secondjump == 1 && player->charability != CA_DOUBLEJUMP) if (player->secondjump == 1 && player->charability != CA_DOUBLEJUMP)
{ {
@ -6820,7 +6816,6 @@ static void P_DoNiGHTSCapsule(player_t *player)
P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); P_SetPlayerMobjState(player->mo, S_PLAY_ROLL);
} }
#ifdef ROTSPRITE
if (!(player->charflags & SF_NONIGHTSROTATION)) if (!(player->charflags & SF_NONIGHTSROTATION))
{ {
if ((player->mo->state == &states[S_PLAY_NIGHTS_PULL]) if ((player->mo->state == &states[S_PLAY_NIGHTS_PULL])
@ -6829,7 +6824,6 @@ static void P_DoNiGHTSCapsule(player_t *player)
else else
player->mo->rollangle = 0; player->mo->rollangle = 0;
} }
#endif
if (G_IsSpecialStage(gamemap)) if (G_IsSpecialStage(gamemap))
{ // In special stages, share rings. Everyone gives up theirs to the capsule player always, because we can't have any individualism here! { // In special stages, share rings. Everyone gives up theirs to the capsule player always, because we can't have any individualism here!
@ -7092,9 +7086,7 @@ static void P_NiGHTSMovement(player_t *player)
INT32 i; INT32 i;
statenum_t flystate; statenum_t flystate;
UINT16 visangle; UINT16 visangle;
#ifdef ROTSPRITE
angle_t rollangle = 0; angle_t rollangle = 0;
#endif
player->pflags &= ~PF_DRILLING; player->pflags &= ~PF_DRILLING;
@ -7133,7 +7125,7 @@ static void P_NiGHTSMovement(player_t *player)
&& !player->exiting) && !player->exiting)
player->nightstime--; player->nightstime--;
} }
else if (gametype != GT_RACE && gametype != GT_COMPETITION else if (!(gametyperules & GTR_RACE)
&& !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1] && !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1]
&& player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6]) && player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6])
&& !(player->capsule && player->capsule->reactiontime) && !(player->capsule && player->capsule->reactiontime)
@ -7279,9 +7271,7 @@ static void P_NiGHTSMovement(player_t *player)
&& player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6]) && player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6])
{ {
player->mo->momx = player->mo->momy = player->mo->momz = 0; player->mo->momx = player->mo->momy = player->mo->momz = 0;
#ifdef ROTSPRITE
player->mo->rollangle = 0; player->mo->rollangle = 0;
#endif
return; return;
} }
@ -7289,7 +7279,7 @@ static void P_NiGHTSMovement(player_t *player)
{ {
player->mo->momx = player->mo->momy = 0; player->mo->momx = player->mo->momy = 0;
if (gametype != GT_RACE && gametype != GT_COMPETITION) if (!(gametyperules & GTR_RACE))
P_SetObjectMomZ(player->mo, FRACUNIT/2, (P_MobjFlip(player->mo)*player->mo->momz >= 0)); P_SetObjectMomZ(player->mo, FRACUNIT/2, (P_MobjFlip(player->mo)*player->mo->momz >= 0));
else else
player->mo->momz = 0; player->mo->momz = 0;
@ -7607,7 +7597,6 @@ static void P_NiGHTSMovement(player_t *player)
flystate += (visangle*2); // S_PLAY_NIGHTS_FLY0-C - the *2 is to skip over drill states flystate += (visangle*2); // S_PLAY_NIGHTS_FLY0-C - the *2 is to skip over drill states
#endif #endif
} }
#ifdef ROTSPRITE
else else
{ {
angle_t a = R_PointToAngle(player->mo->x, player->mo->y) - player->mo->angle; angle_t a = R_PointToAngle(player->mo->x, player->mo->y) - player->mo->angle;
@ -7625,18 +7614,15 @@ static void P_NiGHTSMovement(player_t *player)
rollangle = FixedAngle(visangle<<FRACBITS); rollangle = FixedAngle(visangle<<FRACBITS);
} }
#endif
} }
if (player->mo->state != &states[flystate]) if (player->mo->state != &states[flystate])
P_SetPlayerMobjState(player->mo, flystate); P_SetPlayerMobjState(player->mo, flystate);
#ifdef ROTSPRITE
if (player->charflags & SF_NONIGHTSROTATION) if (player->charflags & SF_NONIGHTSROTATION)
player->mo->rollangle = 0; player->mo->rollangle = 0;
else else
player->mo->rollangle = rollangle; player->mo->rollangle = rollangle;
#endif
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
localangle = player->mo->angle; localangle = player->mo->angle;
@ -9531,12 +9517,12 @@ static void P_DeathThink(player_t *player)
player->playerstate = PST_REBORN; player->playerstate = PST_REBORN;
} }
if (gametype == GT_RACE || gametype == GT_COMPETITION || (gametype == GT_COOP && (multiplayer || netgame))) if ((gametyperules & GTR_RACE) || (gametype == GT_COOP && (multiplayer || netgame)))
{ {
// Keep time rolling in race mode // Keep time rolling in race mode
if (!(countdown2 && !countdown) && !player->exiting && !(player->pflags & PF_GAMETYPEOVER) && !stoppedclock) if (!(countdown2 && !countdown) && !player->exiting && !(player->pflags & PF_GAMETYPEOVER) && !stoppedclock)
{ {
if (gametype == GT_RACE || gametype == GT_COMPETITION) if (gametyperules & GTR_RACE)
{ {
if (leveltime >= 4*TICRATE) if (leveltime >= 4*TICRATE)
player->realtime = leveltime - 4*TICRATE; player->realtime = leveltime - 4*TICRATE;
@ -9585,6 +9571,7 @@ static void CV_CamRotate2_OnChange(void)
static CV_PossibleValue_t CV_CamSpeed[] = {{0, "MIN"}, {1*FRACUNIT, "MAX"}, {0, NULL}}; static CV_PossibleValue_t CV_CamSpeed[] = {{0, "MIN"}, {1*FRACUNIT, "MAX"}, {0, NULL}};
static CV_PossibleValue_t rotation_cons_t[] = {{1, "MIN"}, {45, "MAX"}, {0, NULL}}; static CV_PossibleValue_t rotation_cons_t[] = {{1, "MIN"}, {45, "MAX"}, {0, NULL}};
static CV_PossibleValue_t CV_CamRotate[] = {{-720, "MIN"}, {720, "MAX"}, {0, NULL}}; static CV_PossibleValue_t CV_CamRotate[] = {{-720, "MIN"}, {720, "MAX"}, {0, NULL}};
static CV_PossibleValue_t multiplier_cons_t[] = {{0, "MIN"}, {3*FRACUNIT, "MAX"}, {0, NULL}};
consvar_t cv_cam_dist = {"cam_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_dist = {"cam_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_height = {"cam_height", "25", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_height = {"cam_height", "25", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -9592,6 +9579,7 @@ consvar_t cv_cam_still = {"cam_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL,
consvar_t cv_cam_speed = {"cam_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_speed = {"cam_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_rotate = {"cam_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_rotate = {"cam_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_rotspeed = {"cam_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_rotspeed = {"cam_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_turnmultiplier = {"cam_turnmultiplier", "1.0", CV_FLOAT|CV_SAVE, multiplier_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_orbit = {"cam_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_orbit = {"cam_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_adjust = {"cam_adjust", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_adjust = {"cam_adjust", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_dist = {"cam2_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_dist = {"cam2_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -9600,6 +9588,7 @@ consvar_t cv_cam2_still = {"cam2_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL
consvar_t cv_cam2_speed = {"cam2_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_speed = {"cam2_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_rotate = {"cam2_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate2_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_rotate = {"cam2_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_rotspeed = {"cam2_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_rotspeed = {"cam2_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_turnmultiplier = {"cam2_turnmultiplier", "1.0", CV_FLOAT|CV_SAVE, multiplier_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_orbit = {"cam2_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_orbit = {"cam2_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_adjust = {"cam2_adjust", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_adjust = {"cam2_adjust", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -10360,6 +10349,11 @@ boolean P_SpectatorJoinGame(player_t *player)
else else
changeto = (P_RandomFixed() & 1) + 1; changeto = (P_RandomFixed() & 1) + 1;
#ifdef HAVE_BLUA
if (!LUAh_TeamSwitch(player, changeto, true, false, false))
return false;
#endif
if (player->mo) if (player->mo)
{ {
P_RemoveMobj(player->mo); P_RemoveMobj(player->mo);
@ -10371,7 +10365,14 @@ boolean P_SpectatorJoinGame(player_t *player)
//Reset away view //Reset away view
if (P_IsLocalPlayer(player) && displayplayer != consoleplayer) if (P_IsLocalPlayer(player) && displayplayer != consoleplayer)
{
#ifdef HAVE_BLUA
// Call ViewpointSwitch hooks here.
// The viewpoint was forcibly changed.
LUAh_ViewpointSwitch(player, &players[displayplayer], true);
#endif
displayplayer = consoleplayer; displayplayer = consoleplayer;
}
if (changeto == 1) if (changeto == 1)
CONS_Printf(M_GetText("%s switched to the %c%s%c.\n"), player_names[player-players], '\x85', M_GetText("Red team"), '\x80'); CONS_Printf(M_GetText("%s switched to the %c%s%c.\n"), player_names[player-players], '\x85', M_GetText("Red team"), '\x80');
@ -10385,8 +10386,12 @@ boolean P_SpectatorJoinGame(player_t *player)
{ {
// Exception for hide and seek. Don't join a game when you simply // Exception for hide and seek. Don't join a game when you simply
// respawn in place and sit there for the rest of the round. // respawn in place and sit there for the rest of the round.
if (!(gametype == GT_HIDEANDSEEK && leveltime > (hidetime * TICRATE))) if (!((gametyperules & GTR_HIDEFROZEN) && leveltime > (hidetime * TICRATE)))
{ {
#ifdef HAVE_BLUA
if (!LUAh_TeamSwitch(player, 3, true, false, false))
return false;
#endif
if (player->mo) if (player->mo)
{ {
P_RemoveMobj(player->mo); P_RemoveMobj(player->mo);
@ -10409,7 +10414,14 @@ boolean P_SpectatorJoinGame(player_t *player)
//Reset away view //Reset away view
if (P_IsLocalPlayer(player) && displayplayer != consoleplayer) if (P_IsLocalPlayer(player) && displayplayer != consoleplayer)
{
#ifdef HAVE_BLUA
// Call ViewpointSwitch hooks here.
// The viewpoint was forcibly changed.
LUAh_ViewpointSwitch(player, &players[displayplayer], true);
#endif
displayplayer = consoleplayer; displayplayer = consoleplayer;
}
if (gametype != GT_COOP) if (gametype != GT_COOP)
CONS_Printf(M_GetText("%s entered the game.\n"), player_names[player-players]); CONS_Printf(M_GetText("%s entered the game.\n"), player_names[player-players]);
@ -10535,7 +10547,7 @@ void P_DoPityCheck(player_t *player)
{ {
// No pity outside of match or CTF. // No pity outside of match or CTF.
if (player->spectator if (player->spectator
|| !(gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF)) || !(gametyperules & GTR_PITYSHIELD))
return; return;
// Apply pity shield if available. // Apply pity shield if available.
@ -11368,7 +11380,7 @@ void P_PlayerThink(player_t *player)
I_Error("player %s is in PST_REBORN\n", sizeu1(playeri)); I_Error("player %s is in PST_REBORN\n", sizeu1(playeri));
#endif #endif
if (gametype == GT_RACE || gametype == GT_COMPETITION) if (gametyperules & GTR_RACE)
{ {
INT32 i; INT32 i;
@ -11431,7 +11443,7 @@ void P_PlayerThink(player_t *player)
player->exiting > 0 && player->exiting <= 1*TICRATE && player->exiting > 0 && player->exiting <= 1*TICRATE &&
(!multiplayer || gametype == GT_COOP ? !mapheaderinfo[gamemap-1]->musinterfadeout : true) && (!multiplayer || gametype == GT_COOP ? !mapheaderinfo[gamemap-1]->musinterfadeout : true) &&
// don't fade if we're fading during intermission. follows Y_StartIntermission intertype = int_coop // don't fade if we're fading during intermission. follows Y_StartIntermission intertype = int_coop
(gametype == GT_RACE || gametype == GT_COMPETITION ? countdown2 == 0 : true) && // don't fade on timeout ((gametyperules & GTR_RACE) ? countdown2 == 0 : true) && // don't fade on timeout
player->lives > 0 && // don't fade on game over (competition) player->lives > 0 && // don't fade on game over (competition)
P_IsLocalPlayer(player)) P_IsLocalPlayer(player))
{ {
@ -11546,7 +11558,7 @@ void P_PlayerThink(player_t *player)
player->lives = cv_startinglives.value; player->lives = cv_startinglives.value;
} }
if ((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE) if ((gametyperules & GTR_RACE) && leveltime < 4*TICRATE)
{ {
cmd->buttons &= BT_USE; // Remove all buttons except BT_USE cmd->buttons &= BT_USE; // Remove all buttons except BT_USE
cmd->forwardmove = 0; cmd->forwardmove = 0;
@ -11556,7 +11568,7 @@ void P_PlayerThink(player_t *player)
// Synchronizes the "real" amount of time spent in the level. // Synchronizes the "real" amount of time spent in the level.
if (!player->exiting && !stoppedclock) if (!player->exiting && !stoppedclock)
{ {
if (gametype == GT_RACE || gametype == GT_COMPETITION) if (gametyperules & GTR_RACE)
{ {
if (leveltime >= 4*TICRATE) if (leveltime >= 4*TICRATE)
player->realtime = leveltime - 4*TICRATE; player->realtime = leveltime - 4*TICRATE;

View File

@ -1192,6 +1192,7 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_cam_speed); CV_RegisterVar(&cv_cam_speed);
CV_RegisterVar(&cv_cam_rotate); CV_RegisterVar(&cv_cam_rotate);
CV_RegisterVar(&cv_cam_rotspeed); CV_RegisterVar(&cv_cam_rotspeed);
CV_RegisterVar(&cv_cam_turnmultiplier);
CV_RegisterVar(&cv_cam_orbit); CV_RegisterVar(&cv_cam_orbit);
CV_RegisterVar(&cv_cam_adjust); CV_RegisterVar(&cv_cam_adjust);
@ -1201,6 +1202,7 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_cam2_speed); CV_RegisterVar(&cv_cam2_speed);
CV_RegisterVar(&cv_cam2_rotate); CV_RegisterVar(&cv_cam2_rotate);
CV_RegisterVar(&cv_cam2_rotspeed); CV_RegisterVar(&cv_cam2_rotspeed);
CV_RegisterVar(&cv_cam2_turnmultiplier);
CV_RegisterVar(&cv_cam2_orbit); CV_RegisterVar(&cv_cam2_orbit);
CV_RegisterVar(&cv_cam2_adjust); CV_RegisterVar(&cv_cam2_adjust);

View File

@ -789,11 +789,9 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info)
size_t sprinfoTokenLength; size_t sprinfoTokenLength;
char *frameChar = NULL; char *frameChar = NULL;
UINT8 frameFrame = 0xFF; UINT8 frameFrame = 0xFF;
#ifdef ROTSPRITE
INT16 frameXPivot = 0; INT16 frameXPivot = 0;
INT16 frameYPivot = 0; INT16 frameYPivot = 0;
rotaxis_t frameRotAxis = 0; rotaxis_t frameRotAxis = 0;
#endif
// Sprite identifier // Sprite identifier
sprinfoToken = M_GetToken(NULL); sprinfoToken = M_GetToken(NULL);
@ -828,7 +826,6 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info)
} }
while (strcmp(sprinfoToken,"}")!=0) while (strcmp(sprinfoToken,"}")!=0)
{ {
#ifdef ROTSPRITE
if (stricmp(sprinfoToken, "XPIVOT")==0) if (stricmp(sprinfoToken, "XPIVOT")==0)
{ {
Z_Free(sprinfoToken); Z_Free(sprinfoToken);
@ -852,7 +849,6 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info)
else if ((stricmp(sprinfoToken, "Z")==0) || (stricmp(sprinfoToken, "ZAXIS")==0) || (stricmp(sprinfoToken, "YAW")==0)) else if ((stricmp(sprinfoToken, "Z")==0) || (stricmp(sprinfoToken, "ZAXIS")==0) || (stricmp(sprinfoToken, "YAW")==0))
frameRotAxis = ROTAXIS_Z; frameRotAxis = ROTAXIS_Z;
} }
#endif
Z_Free(sprinfoToken); Z_Free(sprinfoToken);
sprinfoToken = M_GetToken(NULL); sprinfoToken = M_GetToken(NULL);
@ -866,11 +862,9 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info)
} }
// set fields // set fields
#ifdef ROTSPRITE
info->pivot[frameFrame].x = frameXPivot; info->pivot[frameFrame].x = frameXPivot;
info->pivot[frameFrame].y = frameYPivot; info->pivot[frameFrame].y = frameYPivot;
info->pivot[frameFrame].rotaxis = frameRotAxis; info->pivot[frameFrame].rotaxis = frameRotAxis;
#endif
} }
// //
@ -1093,15 +1087,41 @@ void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps)
for (i = 0; i < numlumps; i++, lumpinfo++) for (i = 0; i < numlumps; i++, lumpinfo++)
{ {
name = lumpinfo->name; name = lumpinfo->name;
// load SPRTINFO lumps // Load SPRTINFO and SPR_ lumps as SpriteInfo
if (!stricmp(name, "SPRTINFO")) if (!memcmp(name, "SPRTINFO", 8) || !memcmp(name, "SPR_", 4))
R_ParseSPRTINFOLump(wadnum, i); R_ParseSPRTINFOLump(wadnum, i);
// load SPR_ lumps (as DEHACKED lump)
else if (!memcmp(name, "SPR_", 4))
DEH_LoadDehackedLumpPwad(wadnum, i, false);
} }
} }
static UINT16 GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip)
{
fixed_t ofs;
column_t *column;
UINT8 *source;
if (x >= 0 && x < SHORT(patch->width))
{
INT32 topdelta, prevdelta = -1;
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[flip ? (patch->width-1-x) : x]));
while (column->topdelta != 0xff)
{
topdelta = column->topdelta;
if (topdelta <= prevdelta)
topdelta += prevdelta;
prevdelta = topdelta;
source = (UINT8 *)(column) + 3;
for (ofs = 0; ofs < column->length; ofs++)
{
if ((topdelta + ofs) == y)
return source[ofs];
}
column = (column_t *)((UINT8 *)column + column->length + 4);
}
}
return 0xFF00;
}
#ifdef ROTSPRITE #ifdef ROTSPRITE
// //
// R_CacheRotSprite // R_CacheRotSprite
@ -1114,8 +1134,8 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
INT32 angle; INT32 angle;
patch_t *patch; patch_t *patch;
patch_t *newpatch; patch_t *newpatch;
UINT16 *rawsrc, *rawdst; UINT16 *rawdst;
size_t size, size2; size_t size;
INT32 bflip = (flip != 0x00); INT32 bflip = (flip != 0x00);
#define SPRITE_XCENTER (leftoffset) #define SPRITE_XCENTER (leftoffset)
@ -1160,18 +1180,7 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
leftoffset = width - leftoffset; leftoffset = width - leftoffset;
} }
// Draw the sprite to a temporary buffer. for (angle = 0; angle < ROTANGLES; angle++)
size = (width*height);
rawsrc = Z_Malloc(size * sizeof(UINT16), PU_STATIC, NULL);
// can't memset here
for (i = 0; i < size; i++)
rawsrc[i] = 0xFF00;
R_PatchToFlat_16bpp(patch, rawsrc, bflip);
// Don't cache angle = 0
for (angle = 1; angle < ROTANGLES; angle++)
{ {
INT32 newwidth, newheight; INT32 newwidth, newheight;
@ -1237,17 +1246,15 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
#undef BOUNDARYADJUST #undef BOUNDARYADJUST
} }
size2 = (newwidth * newheight); // Draw the rotated sprite to a temporary buffer.
if (!size2) size = (newwidth * newheight);
size2 = size; if (!size)
size = (width * height);
rawdst = Z_Malloc(size2 * sizeof(UINT16), PU_STATIC, NULL); rawdst = Z_Malloc(size * sizeof(UINT16), PU_STATIC, NULL);
for (i = 0; i < size; i++)
// can't memset here
for (i = 0; i < size2; i++)
rawdst[i] = 0xFF00; rawdst[i] = 0xFF00;
// Draw the rotated sprite to a temporary buffer.
for (dy = 0; dy < newheight; dy++) for (dy = 0; dy < newheight; dy++)
{ {
for (dx = 0; dx < newwidth; dx++) for (dx = 0; dx < newwidth; dx++)
@ -1259,7 +1266,7 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
sx >>= FRACBITS; sx >>= FRACBITS;
sy >>= FRACBITS; sy >>= FRACBITS;
if (sx >= 0 && sy >= 0 && sx < width && sy < height) if (sx >= 0 && sy >= 0 && sx < width && sy < height)
rawdst[(dy*newwidth)+dx] = rawsrc[(sy*width)+sx]; rawdst[(dy*newwidth)+dx] = GetPatchPixel(patch, sx, sy, bflip);
} }
} }
@ -1296,7 +1303,6 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
sprframe->rotsprite.cached[rot] = true; sprframe->rotsprite.cached[rot] = true;
// free image data // free image data
Z_Free(rawsrc);
Z_Free(patch); Z_Free(patch);
} }
#undef SPRITE_XCENTER #undef SPRITE_XCENTER

View File

@ -18,7 +18,6 @@
#include "doomdef.h" #include "doomdef.h"
// Structs // Structs
#ifdef ROTSPRITE
typedef enum typedef enum
{ {
ROTAXIS_X, // Roll (the default) ROTAXIS_X, // Roll (the default)
@ -31,13 +30,10 @@ typedef struct
INT32 x, y; INT32 x, y;
rotaxis_t rotaxis; rotaxis_t rotaxis;
} spriteframepivot_t; } spriteframepivot_t;
#endif
typedef struct typedef struct
{ {
#ifdef ROTSPRITE
spriteframepivot_t pivot[64]; spriteframepivot_t pivot[64];
#endif
boolean available; boolean available;
} spriteinfo_t; } spriteinfo_t;

View File

@ -500,7 +500,7 @@ void R_InitSprites(void)
{ {
size_t i; size_t i;
#ifdef ROTSPRITE #ifdef ROTSPRITE
INT32 angle, realangle = 0; INT32 angle, ra;
float fa; float fa;
#endif #endif
@ -510,10 +510,12 @@ void R_InitSprites(void)
#ifdef ROTSPRITE #ifdef ROTSPRITE
for (angle = 0; angle < ROTANGLES; angle++) for (angle = 0; angle < ROTANGLES; angle++)
{ {
fa = ANG2RAD(FixedAngle(realangle<<FRACBITS)); ra = (ROTANGDIFF * angle);
if (!ra)
ra = (ROTANGDIFF / 2) + 1;
fa = ANG2RAD(FixedAngle(ra<<FRACBITS));
cosang2rad[angle] = FLOAT_TO_FIXED(cos(-fa)); cosang2rad[angle] = FLOAT_TO_FIXED(cos(-fa));
sinang2rad[angle] = FLOAT_TO_FIXED(sin(-fa)); sinang2rad[angle] = FLOAT_TO_FIXED(sin(-fa));
realangle += ROTANGDIFF;
} }
#endif #endif

View File

@ -694,7 +694,7 @@ static void ST_drawTime(void)
else else
{ {
// Counting down the hidetime? // Counting down the hidetime?
if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (stplyr->realtime <= (hidetime*TICRATE))) if ((gametyperules & GTR_HIDETIME) && (stplyr->realtime <= (hidetime*TICRATE)))
{ {
tics = (hidetime*TICRATE - stplyr->realtime); tics = (hidetime*TICRATE - stplyr->realtime);
if (tics < 3*TICRATE) if (tics < 3*TICRATE)
@ -705,11 +705,11 @@ static void ST_drawTime(void)
else else
{ {
// Hidetime finish! // Hidetime finish!
if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (stplyr->realtime < ((hidetime+1)*TICRATE))) if ((gametyperules & GTR_HIDETIME) && (stplyr->realtime < ((hidetime+1)*TICRATE)))
ST_drawRaceNum(hidetime*TICRATE - stplyr->realtime); ST_drawRaceNum(hidetime*TICRATE - stplyr->realtime);
// Time limit? // Time limit?
if (gametype != GT_COOP && gametype != GT_RACE && gametype != GT_COMPETITION && cv_timelimit.value && timelimitintics > 0) if ((gametyperules & GTR_TIMELIMIT) && cv_timelimit.value && timelimitintics > 0)
{ {
if (timelimitintics > stplyr->realtime) if (timelimitintics > stplyr->realtime)
{ {
@ -723,7 +723,7 @@ static void ST_drawTime(void)
downwards = true; downwards = true;
} }
// Post-hidetime normal. // Post-hidetime normal.
else if (gametype == GT_TAG || gametype == GT_HIDEANDSEEK) else if (gametyperules & GTR_TAG)
tics = stplyr->realtime - hidetime*TICRATE; tics = stplyr->realtime - hidetime*TICRATE;
// "Shadow! What are you doing? Hurry and get back here // "Shadow! What are you doing? Hurry and get back here
// right now before the island blows up with you on it!" // right now before the island blows up with you on it!"
@ -912,7 +912,7 @@ static void ST_drawLivesArea(void)
else if (stplyr->spectator) else if (stplyr->spectator)
v_colmap = V_GRAYMAP; v_colmap = V_GRAYMAP;
// Tag // Tag
else if (gametype == GT_TAG || gametype == GT_HIDEANDSEEK) else if (gametyperules & GTR_TAG)
{ {
if (stplyr->pflags & PF_TAGIT) if (stplyr->pflags & PF_TAGIT)
{ {
@ -1228,6 +1228,9 @@ void ST_startTitleCard(void)
// //
void ST_preDrawTitleCard(void) void ST_preDrawTitleCard(void)
{ {
if (!G_IsTitleCardAvailable())
return;
if (lt_ticker >= (lt_endtime + TICRATE)) if (lt_ticker >= (lt_endtime + TICRATE))
return; return;
@ -1243,6 +1246,9 @@ void ST_preDrawTitleCard(void)
// //
void ST_runTitleCard(void) void ST_runTitleCard(void)
{ {
if (!G_IsTitleCardAvailable())
return;
if (lt_ticker >= (lt_endtime + TICRATE)) if (lt_ticker >= (lt_endtime + TICRATE))
return; return;
@ -1296,6 +1302,9 @@ void ST_drawTitleCard(void)
INT32 zzticker; INT32 zzticker;
patch_t *actpat, *zigzag, *zztext; patch_t *actpat, *zigzag, *zztext;
if (!G_IsTitleCardAvailable())
return;
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
if (!LUA_HudEnabled(hud_stagetitle)) if (!LUA_HudEnabled(hud_stagetitle))
goto luahook; goto luahook;
@ -1774,7 +1783,7 @@ static void ST_drawNiGHTSHUD(void)
ST_drawNiGHTSLink(); ST_drawNiGHTSLink();
} }
if (gametype == GT_RACE || gametype == GT_COMPETITION) if (gametyperules & GTR_RACE)
{ {
ST_drawScore(); ST_drawScore();
ST_drawTime(); ST_drawTime();
@ -2215,34 +2224,37 @@ static void ST_drawTextHUD(void)
if (G_IsSpecialStage(gamemap)) if (G_IsSpecialStage(gamemap))
textHUDdraw(M_GetText("\x82""Wait for the stage to end...")) textHUDdraw(M_GetText("\x82""Wait for the stage to end..."))
else if (gametype == GT_COOP) else if (G_PlatformGametype())
{ {
if (stplyr->lives <= 0 if (gametype == GT_COOP)
&& cv_cooplives.value == 2
&& (netgame || multiplayer))
{ {
INT32 i; if (stplyr->lives <= 0
for (i = 0; i < MAXPLAYERS; i++) && cv_cooplives.value == 2
&& (netgame || multiplayer))
{ {
if (!playeringame[i]) INT32 i;
continue; for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (&players[i] == stplyr) if (&players[i] == stplyr)
continue; continue;
if (players[i].lives > 1) if (players[i].lives > 1)
break; break;
} }
if (i != MAXPLAYERS) if (i != MAXPLAYERS)
textHUDdraw(M_GetText("You'll steal a life on respawn...")) textHUDdraw(M_GetText("You'll steal a life on respawn..."))
else
textHUDdraw(M_GetText("Wait to respawn..."))
}
else else
textHUDdraw(M_GetText("Wait to respawn...")) textHUDdraw(M_GetText("Wait to respawn..."))
} }
else
textHUDdraw(M_GetText("Wait to respawn..."))
} }
else else if (G_GametypeHasSpectators())
textHUDdraw(M_GetText("\x82""FIRE:""\x80 Enter game")) textHUDdraw(M_GetText("\x82""FIRE:""\x80 Enter game"))
} }
@ -2285,13 +2297,14 @@ static void ST_drawTextHUD(void)
} }
} }
} }
else if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (!stplyr->spectator)) else if ((gametyperules & GTR_TAG) && (!stplyr->spectator))
{ {
if (leveltime < hidetime * TICRATE) if (leveltime < hidetime * TICRATE)
{ {
if (stplyr->pflags & PF_TAGIT) if (stplyr->pflags & PF_TAGIT)
{ {
textHUDdraw(M_GetText("\x82""You are blindfolded!")) if (gametyperules & GTR_BLINDFOLDED)
textHUDdraw(M_GetText("\x82""You are blindfolded!"))
textHUDdraw(M_GetText("Waiting for players to hide...")) textHUDdraw(M_GetText("Waiting for players to hide..."))
} }
else if (gametype == GT_HIDEANDSEEK) else if (gametype == GT_HIDEANDSEEK)
@ -2306,7 +2319,8 @@ static void ST_drawTextHUD(void)
textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view"))
donef12 = true; donef12 = true;
} }
textHUDdraw(M_GetText("You cannot move while hiding.")) if (gametyperules & GTR_HIDEFROZEN)
textHUDdraw(M_GetText("You cannot move while hiding."))
} }
} }
@ -2328,27 +2342,27 @@ static void ST_drawTeamHUD(void)
if (F_GetPromptHideHud(0)) // y base is 0 if (F_GetPromptHideHud(0)) // y base is 0
return; return;
if (gametype == GT_CTF) if (gametyperules & GTR_TEAMFLAGS)
p = bflagico; p = bflagico;
else else
p = bmatcico; p = bmatcico;
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
if (LUA_HudEnabled(hud_teamscores)) if (LUA_HudEnabled(hud_teamscores))
#endif #endif
V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - SHORT(p->width)/4, 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p); V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - SHORT(p->width)/4, 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p);
if (gametype == GT_CTF) if (gametyperules & GTR_TEAMFLAGS)
p = rflagico; p = rflagico;
else else
p = rmatcico; p = rmatcico;
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
if (LUA_HudEnabled(hud_teamscores)) if (LUA_HudEnabled(hud_teamscores))
#endif #endif
V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - SHORT(p->width)/4, 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p); V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - SHORT(p->width)/4, 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p);
if (gametype != GT_CTF) if (!(gametyperules & GTR_TEAMFLAGS))
goto num; goto num;
{ {
INT32 i; INT32 i;
@ -2676,7 +2690,7 @@ static void ST_overlayDrawer(void)
} }
// If you are in overtime, put a big honkin' flashin' message on the screen. // If you are in overtime, put a big honkin' flashin' message on the screen.
if (G_RingSlingerGametype() && cv_overtime.value if (((gametyperules & GTR_TIMELIMIT) && (gametyperules & GTR_OVERTIME)) && cv_overtime.value
&& (leveltime > (timelimitintics + TICRATE/2)) && cv_timelimit.value && (leveltime/TICRATE % 2 == 0)) && (leveltime > (timelimitintics + TICRATE/2)) && cv_timelimit.value && (leveltime/TICRATE % 2 == 0))
V_DrawCenteredString(BASEVIDWIDTH/2, 184, V_PERPLAYER, M_GetText("OVERTIME!")); V_DrawCenteredString(BASEVIDWIDTH/2, 184, V_PERPLAYER, M_GetText("OVERTIME!"));
@ -2691,7 +2705,7 @@ static void ST_overlayDrawer(void)
ST_drawMatchHUD(); ST_drawMatchHUD();
// Race HUD Stuff // Race HUD Stuff
if (gametype == GT_RACE || gametype == GT_COMPETITION) if (gametyperules & GTR_RACE)
ST_drawRaceHUD(); ST_drawRaceHUD();
// Emerald Hunt Indicators // Emerald Hunt Indicators
@ -2796,7 +2810,7 @@ void ST_Drawer(void)
if (rendermode != render_none) ST_doPaletteStuff(); if (rendermode != render_none) ST_doPaletteStuff();
// Blindfold! // Blindfold!
if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) if ((gametyperules & GTR_BLINDFOLDED)
&& (leveltime < hidetime * TICRATE)) && (leveltime < hidetime * TICRATE))
{ {
if (players[displayplayer].pflags & PF_TAGIT) if (players[displayplayer].pflags & PF_TAGIT)

View File

@ -37,6 +37,10 @@
#include "m_cond.h" // condition sets #include "m_cond.h" // condition sets
#include "lua_hook.h" // IntermissionThinker hook #include "lua_hook.h" // IntermissionThinker hook
#ifdef HAVE_BLUA
#include "lua_hud.h"
#endif
#ifdef HWRENDER #ifdef HWRENDER
#include "hardware/hw_main.h" #include "hardware/hw_main.h"
#endif #endif
@ -164,6 +168,7 @@ static INT32 tallydonetic = -1;
static INT32 endtic = -1; static INT32 endtic = -1;
intertype_t intertype = int_none; intertype_t intertype = int_none;
intertype_t intermissiontypes[NUMGAMETYPES];
static void Y_RescaleScreenBuffer(void); static void Y_RescaleScreenBuffer(void);
static void Y_AwardCoopBonuses(void); static void Y_AwardCoopBonuses(void);
@ -318,9 +323,17 @@ void Y_IntermissionDrawer(void)
// Bonus loops // Bonus loops
INT32 i; INT32 i;
if (intertype == int_none || rendermode == render_none) if (rendermode == render_none)
return; return;
if (intertype == int_none)
{
#ifdef HAVE_BLUA
LUAh_IntermissionHUD();
#endif
return;
}
if (!usebuffer) if (!usebuffer)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
@ -358,6 +371,12 @@ void Y_IntermissionDrawer(void)
else else
V_DrawPatchFill(bgtile); V_DrawPatchFill(bgtile);
#ifdef HAVE_BLUA
LUAh_IntermissionHUD();
if (!LUA_HudEnabled(hud_intermissiontally))
goto skiptallydrawer;
#endif
if (intertype == int_coop) if (intertype == int_coop)
{ {
INT32 bonusy; INT32 bonusy;
@ -907,6 +926,12 @@ void Y_IntermissionDrawer(void)
} }
} }
#ifdef HAVE_BLUA
skiptallydrawer:
if (!LUA_HudEnabled(hud_intermissionmessages))
return;
#endif
if (timer) if (timer)
V_DrawCenteredString(BASEVIDWIDTH/2, 188, V_YELLOWMAP, V_DrawCenteredString(BASEVIDWIDTH/2, 188, V_YELLOWMAP,
va("start in %d seconds", timer/TICRATE)); va("start in %d seconds", timer/TICRATE));
@ -1187,7 +1212,9 @@ void Y_StartIntermission(void)
timer = 1; timer = 1;
} }
if (gametype == GT_COOP) if (intermissiontypes[gametype] != int_none)
intertype = intermissiontypes[gametype];
else if (gametype == GT_COOP)
intertype = (G_IsSpecialStage(gamemap)) ? int_spec : int_coop; intertype = (G_IsSpecialStage(gamemap)) ? int_spec : int_coop;
else if (gametype == GT_TEAMMATCH) else if (gametype == GT_TEAMMATCH)
intertype = int_teammatch; intertype = int_teammatch;

View File

@ -31,3 +31,4 @@ typedef enum
int_comp, // Competition int_comp, // Competition
} intertype_t; } intertype_t;
extern intertype_t intertype; extern intertype_t intertype;
extern intertype_t intermissiontypes[NUMGAMETYPES];