Merge remote-tracking branch 'origin/next' into gtr-fixes
This commit is contained in:
commit
067d9b9a63
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0)
|
||||||
# DO NOT CHANGE THIS SRB2 STRING! Some variable names depend on this string.
|
# DO NOT CHANGE THIS SRB2 STRING! Some variable names depend on this string.
|
||||||
# Version change is fine.
|
# Version change is fine.
|
||||||
project(SRB2
|
project(SRB2
|
||||||
VERSION 2.2.2
|
VERSION 2.2.4
|
||||||
LANGUAGES C)
|
LANGUAGES C)
|
||||||
|
|
||||||
if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR})
|
if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
version: 2.2.2.{branch}-{build}
|
version: 2.2.4.{branch}-{build}
|
||||||
os: MinGW
|
os: MinGW
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
|
|
@ -750,12 +750,6 @@ linedeftypes
|
||||||
prefix = "(20)";
|
prefix = "(20)";
|
||||||
}
|
}
|
||||||
|
|
||||||
21
|
|
||||||
{
|
|
||||||
title = "Explicitly Include Line <disabled>";
|
|
||||||
prefix = "(21)";
|
|
||||||
}
|
|
||||||
|
|
||||||
22
|
22
|
||||||
{
|
{
|
||||||
title = "Parameters";
|
title = "Parameters";
|
||||||
|
@ -766,6 +760,7 @@ linedeftypes
|
||||||
flags128text = "[7] Intangible";
|
flags128text = "[7] Intangible";
|
||||||
flags256text = "[8] Stopped by pushables";
|
flags256text = "[8] Stopped by pushables";
|
||||||
flags512text = "[9] Render flats";
|
flags512text = "[9] Render flats";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
}
|
}
|
||||||
|
|
||||||
30
|
30
|
||||||
|
@ -920,6 +915,7 @@ linedeftypes
|
||||||
flags32text = "[5] Only block player";
|
flags32text = "[5] Only block player";
|
||||||
flags64text = "[6] Render insides";
|
flags64text = "[6] Render insides";
|
||||||
flags128text = "[7] Only block non-players";
|
flags128text = "[7] Only block non-players";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorflags = "195F";
|
3dfloorflags = "195F";
|
||||||
flags643dfloorflagsadd = "7C80";
|
flags643dfloorflagsadd = "7C80";
|
||||||
|
@ -979,6 +975,7 @@ linedeftypes
|
||||||
flags32text = "[5] Only block player";
|
flags32text = "[5] Only block player";
|
||||||
flags64text = "[6] Don't cast shadow";
|
flags64text = "[6] Don't cast shadow";
|
||||||
flags128text = "[7] Render insides/block non-plr";
|
flags128text = "[7] Render insides/block non-plr";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorflags = "200191F";
|
3dfloorflags = "200191F";
|
||||||
flags1283dfloorflagsadd = "7C80";
|
flags1283dfloorflagsadd = "7C80";
|
||||||
|
@ -992,6 +989,7 @@ linedeftypes
|
||||||
flags32text = "[5] Only block player";
|
flags32text = "[5] Only block player";
|
||||||
flags64text = "[6] Don't cast shadow";
|
flags64text = "[6] Don't cast shadow";
|
||||||
flags128text = "[7] Render insides/block non-plr";
|
flags128text = "[7] Render insides/block non-plr";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorflags = "2001917";
|
3dfloorflags = "2001917";
|
||||||
flags1283dfloorflagsadd = "7C80";
|
flags1283dfloorflagsadd = "7C80";
|
||||||
|
@ -1019,6 +1017,7 @@ linedeftypes
|
||||||
flags32text = "[5] Only block player";
|
flags32text = "[5] Only block player";
|
||||||
flags64text = "[6] Don't cast shadow";
|
flags64text = "[6] Don't cast shadow";
|
||||||
flags128text = "[7] Render insides/block non-plr";
|
flags128text = "[7] Render insides/block non-plr";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorflags = "400191F";
|
3dfloorflags = "400191F";
|
||||||
flags1283dfloorflagsadd = "7C80";
|
flags1283dfloorflagsadd = "7C80";
|
||||||
|
@ -1032,6 +1031,7 @@ linedeftypes
|
||||||
flags32text = "[5] Only block player";
|
flags32text = "[5] Only block player";
|
||||||
flags64text = "[6] Don't cast shadow";
|
flags64text = "[6] Don't cast shadow";
|
||||||
flags128text = "[7] Render insides/block non-plr";
|
flags128text = "[7] Render insides/block non-plr";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorflags = "4001917";
|
3dfloorflags = "4001917";
|
||||||
flags1283dfloorflagsadd = "7C80";
|
flags1283dfloorflagsadd = "7C80";
|
||||||
|
@ -1077,6 +1077,7 @@ linedeftypes
|
||||||
flags64text = "[6] Use two light levels";
|
flags64text = "[6] Use two light levels";
|
||||||
flags512text = "[9] Use target light level";
|
flags512text = "[9] Use target light level";
|
||||||
flags1024text = "[10] Ripple effect";
|
flags1024text = "[10] Ripple effect";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorflags = "9F39";
|
3dfloorflags = "9F39";
|
||||||
flags643dfloorflagsadd = "20000";
|
flags643dfloorflagsadd = "20000";
|
||||||
|
@ -1105,6 +1106,7 @@ linedeftypes
|
||||||
flags64text = "[6] Use two light levels";
|
flags64text = "[6] Use two light levels";
|
||||||
flags512text = "[9] Use target light level";
|
flags512text = "[9] Use target light level";
|
||||||
flags1024text = "[10] Ripple effect";
|
flags1024text = "[10] Ripple effect";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorflags = "1F31";
|
3dfloorflags = "1F31";
|
||||||
flags643dfloorflagsadd = "20000";
|
flags643dfloorflagsadd = "20000";
|
||||||
|
@ -1120,6 +1122,7 @@ linedeftypes
|
||||||
flags64text = "[6] Use two light levels";
|
flags64text = "[6] Use two light levels";
|
||||||
flags512text = "[9] Use target light level";
|
flags512text = "[9] Use target light level";
|
||||||
flags1024text = "[10] Ripple effect";
|
flags1024text = "[10] Ripple effect";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorflags = "209F39";
|
3dfloorflags = "209F39";
|
||||||
flags643dfloorflagsadd = "20000";
|
flags643dfloorflagsadd = "20000";
|
||||||
|
@ -1134,6 +1137,7 @@ linedeftypes
|
||||||
flags64text = "[6] Use two light levels";
|
flags64text = "[6] Use two light levels";
|
||||||
flags512text = "[9] Use target light level";
|
flags512text = "[9] Use target light level";
|
||||||
flags1024text = "[10] Ripple effect";
|
flags1024text = "[10] Ripple effect";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorflags = "201F31";
|
3dfloorflags = "201F31";
|
||||||
flags643dfloorflagsadd = "20000";
|
flags643dfloorflagsadd = "20000";
|
||||||
|
@ -1156,6 +1160,7 @@ linedeftypes
|
||||||
prefix = "(221)";
|
prefix = "(221)";
|
||||||
flags8text = "[3] Slope skew sides";
|
flags8text = "[3] Slope skew sides";
|
||||||
flags64text = "[6] Cast shadow";
|
flags64text = "[6] Cast shadow";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorflags = "1B59";
|
3dfloorflags = "1B59";
|
||||||
flags643dfloorflagsremove = "40";
|
flags643dfloorflagsremove = "40";
|
||||||
|
@ -1279,6 +1284,7 @@ linedeftypes
|
||||||
flags32text = "[5] Only block player";
|
flags32text = "[5] Only block player";
|
||||||
flags64text = "[6] Spindash to move";
|
flags64text = "[6] Spindash to move";
|
||||||
flags128text = "[7] Only block non-players";
|
flags128text = "[7] Only block non-players";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorflags = "195F";
|
3dfloorflags = "195F";
|
||||||
}
|
}
|
||||||
|
@ -1318,6 +1324,7 @@ linedeftypes
|
||||||
flags32text = "[5] Only block player";
|
flags32text = "[5] Only block player";
|
||||||
flags64text = "[6] Spindash, no shadow";
|
flags64text = "[6] Spindash, no shadow";
|
||||||
flags128text = "[7] Only block non-players";
|
flags128text = "[7] Only block non-players";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorflags = "2009D1F";
|
3dfloorflags = "2009D1F";
|
||||||
flags643dfloorflagsadd = "40";
|
flags643dfloorflagsadd = "40";
|
||||||
|
@ -1384,6 +1391,7 @@ linedeftypes
|
||||||
flags32text = "[5] Only block player";
|
flags32text = "[5] Only block player";
|
||||||
flags64text = "[6] Don't cast shadow";
|
flags64text = "[6] Don't cast shadow";
|
||||||
flags128text = "[7] Only block non-players";
|
flags128text = "[7] Only block non-players";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorflags = "210959F";
|
3dfloorflags = "210959F";
|
||||||
flags643dfloorflagsadd = "40";
|
flags643dfloorflagsadd = "40";
|
||||||
|
@ -1397,6 +1405,7 @@ linedeftypes
|
||||||
flags32text = "[5] Only block player";
|
flags32text = "[5] Only block player";
|
||||||
flags64text = "[6] Don't cast shadow";
|
flags64text = "[6] Don't cast shadow";
|
||||||
flags128text = "[7] Only block non-players";
|
flags128text = "[7] Only block non-players";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorflags = "218959F";
|
3dfloorflags = "218959F";
|
||||||
flags643dfloorflagsadd = "40";
|
flags643dfloorflagsadd = "40";
|
||||||
|
@ -1535,6 +1544,7 @@ linedeftypes
|
||||||
flags8text = "[3] Slope skew sides";
|
flags8text = "[3] Slope skew sides";
|
||||||
flags512text = "[9] Shattered by pushables";
|
flags512text = "[9] Shattered by pushables";
|
||||||
flags1024text = "[10] Trigger linedef executor";
|
flags1024text = "[10] Trigger linedef executor";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorflags = "880101D";
|
3dfloorflags = "880101D";
|
||||||
}
|
}
|
||||||
|
@ -1576,6 +1586,7 @@ linedeftypes
|
||||||
flags128text = "[7] Only block non-players";
|
flags128text = "[7] Only block non-players";
|
||||||
flags512text = "[9] Shattered by pushables";
|
flags512text = "[9] Shattered by pushables";
|
||||||
flags1024text = "[10] Trigger linedef executor";
|
flags1024text = "[10] Trigger linedef executor";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorflags = "1080101F";
|
3dfloorflags = "1080101F";
|
||||||
}
|
}
|
||||||
|
@ -1597,6 +1608,7 @@ linedeftypes
|
||||||
prefix = "(258)";
|
prefix = "(258)";
|
||||||
flags8text = "[3] Slope skew sides";
|
flags8text = "[3] Slope skew sides";
|
||||||
flags32text = "[5] Don't damage bosses";
|
flags32text = "[5] Don't damage bosses";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorflags = "959";
|
3dfloorflags = "959";
|
||||||
}
|
}
|
||||||
|
@ -1610,6 +1622,7 @@ linedeftypes
|
||||||
flags128text = "[7] Only block non-players";
|
flags128text = "[7] Only block non-players";
|
||||||
flags512text = "[9] Shattered by pushables";
|
flags512text = "[9] Shattered by pushables";
|
||||||
flags1024text = "[10] Trigger linedef executor";
|
flags1024text = "[10] Trigger linedef executor";
|
||||||
|
flags8192text = "[13] Cut cyan flat pixels";
|
||||||
3dfloor = true;
|
3dfloor = true;
|
||||||
3dfloorcustom = true;
|
3dfloorcustom = true;
|
||||||
}
|
}
|
||||||
|
@ -2603,45 +2616,63 @@ linedeftypes
|
||||||
|
|
||||||
500
|
500
|
||||||
{
|
{
|
||||||
title = "Scroll Wall Front Side Left";
|
title = "Scroll Front Wall Left";
|
||||||
prefix = "(500)";
|
prefix = "(500)";
|
||||||
}
|
}
|
||||||
|
|
||||||
501
|
501
|
||||||
{
|
{
|
||||||
title = "Scroll Wall Front Side Right";
|
title = "Scroll Front Wall Right";
|
||||||
prefix = "(501)";
|
prefix = "(501)";
|
||||||
}
|
}
|
||||||
|
|
||||||
502
|
502
|
||||||
{
|
{
|
||||||
title = "Scroll Wall According to Linedef";
|
title = "Scroll Tagged Wall";
|
||||||
prefix = "(502)";
|
prefix = "(502)";
|
||||||
|
flags128text = "[7] Use texture offsets";
|
||||||
|
flags256text = "[8] Scroll back side";
|
||||||
}
|
}
|
||||||
|
|
||||||
503
|
503
|
||||||
{
|
{
|
||||||
title = "Scroll Wall According to Linedef (Accelerative)";
|
title = "Scroll Tagged Wall (Accelerative)";
|
||||||
prefix = "(503)";
|
prefix = "(503)";
|
||||||
|
flags128text = "[7] Use texture offsets";
|
||||||
|
flags256text = "[8] Scroll back side";
|
||||||
}
|
}
|
||||||
|
|
||||||
504
|
504
|
||||||
{
|
{
|
||||||
title = "Scroll Wall According to Linedef (Displacement)";
|
title = "Scroll Tagged Wall (Displacement)";
|
||||||
prefix = "(504)";
|
prefix = "(504)";
|
||||||
|
flags128text = "[7] Use texture offsets";
|
||||||
|
flags256text = "[8] Scroll back side";
|
||||||
}
|
}
|
||||||
|
|
||||||
505
|
505
|
||||||
{
|
{
|
||||||
title = "Scroll Texture by Front Side Offsets";
|
title = "Scroll Front Wall by Front Side Offsets";
|
||||||
prefix = "(505)";
|
prefix = "(505)";
|
||||||
}
|
}
|
||||||
|
|
||||||
506
|
506
|
||||||
{
|
{
|
||||||
title = "Scroll Texture by Back Side Offsets";
|
title = "Scroll Front Wall by Back Side Offsets";
|
||||||
prefix = "(506)";
|
prefix = "(506)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
507
|
||||||
|
{
|
||||||
|
title = "Scroll Back Wall by Front Side Offsets";
|
||||||
|
prefix = "(507)";
|
||||||
|
}
|
||||||
|
|
||||||
|
508
|
||||||
|
{
|
||||||
|
title = "Scroll Back Wall by Back Side Offsets";
|
||||||
|
prefix = "(508)";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
planescroll
|
planescroll
|
||||||
|
|
|
@ -418,6 +418,7 @@ endif()
|
||||||
if(${SRB2_CONFIG_HWRENDER})
|
if(${SRB2_CONFIG_HWRENDER})
|
||||||
add_definitions(-DHWRENDER)
|
add_definitions(-DHWRENDER)
|
||||||
set(SRB2_HWRENDER_SOURCES
|
set(SRB2_HWRENDER_SOURCES
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c
|
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c
|
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c
|
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c
|
||||||
|
@ -433,6 +434,7 @@ if(${SRB2_CONFIG_HWRENDER})
|
||||||
)
|
)
|
||||||
|
|
||||||
set (SRB2_HWRENDER_HEADERS
|
set (SRB2_HWRENDER_HEADERS
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.h
|
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h
|
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h
|
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h
|
||||||
|
|
|
@ -222,12 +222,10 @@ endif
|
||||||
ifdef NOHW
|
ifdef NOHW
|
||||||
OPTS+=-DNOHW
|
OPTS+=-DNOHW
|
||||||
else
|
else
|
||||||
#Hurdler: not really supported and not tested recently
|
|
||||||
#OPTS+=-DUSE_PALETTED_TEXTURE
|
|
||||||
OPTS+=-DHWRENDER
|
OPTS+=-DHWRENDER
|
||||||
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \
|
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \
|
||||||
$(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o \
|
$(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o \
|
||||||
$(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o
|
$(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef NOHS
|
ifdef NOHS
|
||||||
|
|
|
@ -931,11 +931,8 @@ static inline void AM_drawWalls(void)
|
||||||
l.b.y = lines[i].v2->y >> FRACTOMAPBITS;
|
l.b.y = lines[i].v2->y >> FRACTOMAPBITS;
|
||||||
|
|
||||||
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
|
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
|
||||||
if (slope) { \
|
end1 = P_GetZAt(slope, lines[i].v1->x, lines[i].v1->y, normalheight); \
|
||||||
end1 = P_GetZAt(slope, lines[i].v1->x, lines[i].v1->y); \
|
end2 = P_GetZAt(slope, lines[i].v2->x, lines[i].v2->y, normalheight);
|
||||||
end2 = P_GetZAt(slope, lines[i].v2->x, lines[i].v2->y); \
|
|
||||||
} else \
|
|
||||||
end1 = end2 = normalheight;
|
|
||||||
|
|
||||||
SLOPEPARAMS(lines[i].frontsector->f_slope, frontf1, frontf2, lines[i].frontsector->floorheight)
|
SLOPEPARAMS(lines[i].frontsector->f_slope, frontf1, frontf2, lines[i].frontsector->floorheight)
|
||||||
SLOPEPARAMS(lines[i].frontsector->c_slope, frontc1, frontc2, lines[i].frontsector->ceilingheight)
|
SLOPEPARAMS(lines[i].frontsector->c_slope, frontc1, frontc2, lines[i].frontsector->ceilingheight)
|
||||||
|
|
|
@ -459,7 +459,6 @@ boolean B_CheckRespawn(player_t *player)
|
||||||
if (!sonic || sonic->health <= 0)
|
if (!sonic || sonic->health <= 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
#ifdef HAVE_BLUA
|
|
||||||
// B_RespawnBot doesn't do anything if the condition above this isn't met
|
// B_RespawnBot doesn't do anything if the condition above this isn't met
|
||||||
{
|
{
|
||||||
UINT8 shouldForce = LUAh_BotRespawn(sonic, tails);
|
UINT8 shouldForce = LUAh_BotRespawn(sonic, tails);
|
||||||
|
@ -472,7 +471,6 @@ boolean B_CheckRespawn(player_t *player)
|
||||||
else if (shouldForce == 2)
|
else if (shouldForce == 2)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Check if Sonic is busy first.
|
// Check if Sonic is busy first.
|
||||||
// If he's doing any of these things, he probably doesn't want to see us.
|
// If he's doing any of these things, he probably doesn't want to see us.
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "../doomdef.h"
|
||||||
|
#include "../lua_script.h"
|
||||||
|
#include "../w_wad.h"
|
||||||
|
|
||||||
#define lbaselib_c
|
#define lbaselib_c
|
||||||
#define LUA_LIB
|
#define LUA_LIB
|
||||||
|
|
||||||
|
@ -263,6 +267,27 @@ static int luaB_ipairs (lua_State *L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Edited to load PK3 entries instead
|
||||||
|
static int luaB_dofile (lua_State *L) {
|
||||||
|
const char *filename = luaL_checkstring(L, 1);
|
||||||
|
char fullfilename[256];
|
||||||
|
UINT16 lumpnum;
|
||||||
|
int n = lua_gettop(L);
|
||||||
|
|
||||||
|
if (wadfiles[numwadfiles - 1]->type != RET_PK3)
|
||||||
|
luaL_error(L, "dofile() only works with PK3 files");
|
||||||
|
|
||||||
|
snprintf(fullfilename, sizeof(fullfilename), "Lua/%s", filename);
|
||||||
|
lumpnum = W_CheckNumForFullNamePK3(fullfilename, numwadfiles - 1, 0);
|
||||||
|
if (lumpnum == INT16_MAX)
|
||||||
|
luaL_error(L, "can't find script " LUA_QS, fullfilename);
|
||||||
|
|
||||||
|
LUA_LoadLump(numwadfiles - 1, lumpnum, false);
|
||||||
|
|
||||||
|
return lua_gettop(L) - n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int luaB_assert (lua_State *L) {
|
static int luaB_assert (lua_State *L) {
|
||||||
luaL_checkany(L, 1);
|
luaL_checkany(L, 1);
|
||||||
if (!lua_toboolean(L, 1))
|
if (!lua_toboolean(L, 1))
|
||||||
|
@ -380,6 +405,7 @@ static const luaL_Reg base_funcs[] = {
|
||||||
{"assert", luaB_assert},
|
{"assert", luaB_assert},
|
||||||
{"collectgarbage", luaB_collectgarbage},
|
{"collectgarbage", luaB_collectgarbage},
|
||||||
{"error", luaB_error},
|
{"error", luaB_error},
|
||||||
|
{"dofile", luaB_dofile},
|
||||||
{"gcinfo", luaB_gcinfo},
|
{"gcinfo", luaB_gcinfo},
|
||||||
{"getfenv", luaB_getfenv},
|
{"getfenv", luaB_getfenv},
|
||||||
{"getmetatable", luaB_getmetatable},
|
{"getmetatable", luaB_getmetatable},
|
||||||
|
|
|
@ -284,8 +284,16 @@ void Got_LuaFile(UINT8 **cp, INT32 playernum)
|
||||||
// Push the first argument (file handle or nil) on the stack
|
// Push the first argument (file handle or nil) on the stack
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
|
char mode[4];
|
||||||
|
|
||||||
|
// Ensure we are opening in binary mode
|
||||||
|
// (if it's a text file, newlines have been converted already)
|
||||||
|
strcpy(mode, luafiletransfers->mode);
|
||||||
|
if (!strchr(mode, 'b'))
|
||||||
|
strcat(mode, "b");
|
||||||
|
|
||||||
pf = newfile(gL); // Create and push the file handle
|
pf = newfile(gL); // Create and push the file handle
|
||||||
*pf = fopen(luafiletransfers->realfilename, luafiletransfers->mode); // Open the file
|
*pf = fopen(luafiletransfers->realfilename, mode); // Open the file
|
||||||
if (!*pf)
|
if (!*pf)
|
||||||
I_Error("Can't open file \"%s\"\n", luafiletransfers->realfilename); // The file SHOULD exist
|
I_Error("Can't open file \"%s\"\n", luafiletransfers->realfilename); // The file SHOULD exist
|
||||||
}
|
}
|
||||||
|
@ -313,17 +321,14 @@ void Got_LuaFile(UINT8 **cp, INT32 playernum)
|
||||||
|
|
||||||
RemoveLuaFileTransfer();
|
RemoveLuaFileTransfer();
|
||||||
|
|
||||||
|
if (waitingforluafilecommand)
|
||||||
|
{
|
||||||
|
waitingforluafilecommand = false;
|
||||||
|
CL_PrepareDownloadLuaFile();
|
||||||
|
}
|
||||||
|
|
||||||
if (server && luafiletransfers)
|
if (server && luafiletransfers)
|
||||||
{
|
SV_PrepareSendLuaFile();
|
||||||
if (FIL_FileOK(luafiletransfers->realfilename))
|
|
||||||
SV_PrepareSendLuaFileToNextNode();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Send a net command with 0 as its first byte to indicate the file couldn't be opened
|
|
||||||
success = 0;
|
|
||||||
SendNetXCmd(XD_LUAFILE, &success, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,12 +28,14 @@
|
||||||
/* Manually defined asset hashes for non-CMake builds
|
/* Manually defined asset hashes for non-CMake builds
|
||||||
* Last updated 2020 / 02 / 15 - v2.2.1 - main assets
|
* Last updated 2020 / 02 / 15 - v2.2.1 - main assets
|
||||||
* Last updated 2020 / 02 / 22 - v2.2.2 - patch.pk3
|
* Last updated 2020 / 02 / 22 - v2.2.2 - patch.pk3
|
||||||
|
* Last updated 2020 / 05 / 10 - v2.2.3 - player.dta & patch.pk3
|
||||||
|
* Last updated 2020 / 05 / 11 - v2.2.4 - patch.pk3
|
||||||
*/
|
*/
|
||||||
#define ASSET_HASH_SRB2_PK3 "0277c9416756627004e83cbb5b2e3e28"
|
#define ASSET_HASH_SRB2_PK3 "0277c9416756627004e83cbb5b2e3e28"
|
||||||
#define ASSET_HASH_ZONES_PK3 "f7e88afb6af7996a834c7d663144bead"
|
#define ASSET_HASH_ZONES_PK3 "f7e88afb6af7996a834c7d663144bead"
|
||||||
#define ASSET_HASH_PLAYER_DTA "ad49e07b17cc662f1ad70c454910b4ae"
|
#define ASSET_HASH_PLAYER_DTA "8a4507ddf9bc0682c09174400f26ad65"
|
||||||
#ifdef USE_PATCH_DTA
|
#ifdef USE_PATCH_DTA
|
||||||
#define ASSET_HASH_PATCH_PK3 "ee54330ecb743314c5f962af4db731ff"
|
#define ASSET_HASH_PATCH_PK3 "bbbf6af3b20349612ee06e0b55979a76"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -770,7 +770,7 @@ boolean CON_Responder(event_t *ev)
|
||||||
// check for console toggle key
|
// check for console toggle key
|
||||||
if (ev->type != ev_console)
|
if (ev->type != ev_console)
|
||||||
{
|
{
|
||||||
if (modeattacking || metalrecording)
|
if (modeattacking || metalrecording || marathonmode)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (key == gamecontrol[gc_console][0] || key == gamecontrol[gc_console][1])
|
if (key == gamecontrol[gc_console][0] || key == gamecontrol[gc_console][1])
|
||||||
|
@ -1649,10 +1649,7 @@ void CON_Drawer(void)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (needpatchrecache)
|
if (needpatchrecache)
|
||||||
{
|
|
||||||
W_FlushCachedPatches();
|
|
||||||
HU_LoadGraphics();
|
HU_LoadGraphics();
|
||||||
}
|
|
||||||
|
|
||||||
if (con_recalc)
|
if (con_recalc)
|
||||||
{
|
{
|
||||||
|
|
702
src/d_clisrv.c
702
src/d_clisrv.c
|
@ -195,24 +195,25 @@ static inline void *G_ScpyTiccmd(ticcmd_t* dest, void* src, const size_t n)
|
||||||
// of 512 bytes is like 0.1)
|
// of 512 bytes is like 0.1)
|
||||||
UINT16 software_MAXPACKETLENGTH;
|
UINT16 software_MAXPACKETLENGTH;
|
||||||
|
|
||||||
/** Guesses the value of a tic from its lowest byte and from maketic
|
/** Guesses the full value of a tic from its lowest byte, for a specific node
|
||||||
*
|
*
|
||||||
* \param low The lowest byte of the tic value
|
* \param low The lowest byte of the tic value
|
||||||
|
* \param node The node to deduce the tic for
|
||||||
* \return The full tic value
|
* \return The full tic value
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
tic_t ExpandTics(INT32 low)
|
tic_t ExpandTics(INT32 low, INT32 node)
|
||||||
{
|
{
|
||||||
INT32 delta;
|
INT32 delta;
|
||||||
|
|
||||||
delta = low - (maketic & UINT8_MAX);
|
delta = low - (nettics[node] & UINT8_MAX);
|
||||||
|
|
||||||
if (delta >= -64 && delta <= 64)
|
if (delta >= -64 && delta <= 64)
|
||||||
return (maketic & ~UINT8_MAX) + low;
|
return (nettics[node] & ~UINT8_MAX) + low;
|
||||||
else if (delta > 64)
|
else if (delta > 64)
|
||||||
return (maketic & ~UINT8_MAX) - 256 + low;
|
return (nettics[node] & ~UINT8_MAX) - 256 + low;
|
||||||
else //if (delta < -64)
|
else //if (delta < -64)
|
||||||
return (maketic & ~UINT8_MAX) + 256 + low;
|
return (nettics[node] & ~UINT8_MAX) + 256 + low;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
|
@ -522,6 +523,9 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
|
||||||
rsp->pflags = (UINT32)LONG(players[i].pflags); //pflags_t
|
rsp->pflags = (UINT32)LONG(players[i].pflags); //pflags_t
|
||||||
rsp->panim = (UINT8)players[i].panim; //panim_t
|
rsp->panim = (UINT8)players[i].panim; //panim_t
|
||||||
|
|
||||||
|
rsp->angleturn = (INT16)SHORT(players[i].angleturn);
|
||||||
|
rsp->oldrelangleturn = (INT16)SHORT(players[i].oldrelangleturn);
|
||||||
|
|
||||||
rsp->aiming = (angle_t)LONG(players[i].aiming);
|
rsp->aiming = (angle_t)LONG(players[i].aiming);
|
||||||
rsp->currentweapon = LONG(players[i].currentweapon);
|
rsp->currentweapon = LONG(players[i].currentweapon);
|
||||||
rsp->ringweapons = LONG(players[i].ringweapons);
|
rsp->ringweapons = LONG(players[i].ringweapons);
|
||||||
|
@ -663,6 +667,9 @@ static void resynch_read_player(resynch_pak *rsp)
|
||||||
players[i].pflags = (UINT32)LONG(rsp->pflags); //pflags_t
|
players[i].pflags = (UINT32)LONG(rsp->pflags); //pflags_t
|
||||||
players[i].panim = (UINT8)rsp->panim; //panim_t
|
players[i].panim = (UINT8)rsp->panim; //panim_t
|
||||||
|
|
||||||
|
players[i].angleturn = (INT16)SHORT(rsp->angleturn);
|
||||||
|
players[i].oldrelangleturn = (INT16)SHORT(rsp->oldrelangleturn);
|
||||||
|
|
||||||
players[i].aiming = (angle_t)LONG(rsp->aiming);
|
players[i].aiming = (angle_t)LONG(rsp->aiming);
|
||||||
players[i].currentweapon = LONG(rsp->currentweapon);
|
players[i].currentweapon = LONG(rsp->currentweapon);
|
||||||
players[i].ringweapons = LONG(rsp->ringweapons);
|
players[i].ringweapons = LONG(rsp->ringweapons);
|
||||||
|
@ -1156,6 +1163,497 @@ static void CV_LoadPlayerNames(UINT8 **p)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CLIENT_LOADINGSCREEN
|
#ifdef CLIENT_LOADINGSCREEN
|
||||||
|
#define SNAKE_SPEED 5
|
||||||
|
|
||||||
|
#define SNAKE_NUM_BLOCKS_X 20
|
||||||
|
#define SNAKE_NUM_BLOCKS_Y 10
|
||||||
|
#define SNAKE_BLOCK_SIZE 12
|
||||||
|
#define SNAKE_BORDER_SIZE 12
|
||||||
|
|
||||||
|
#define SNAKE_MAP_WIDTH (SNAKE_NUM_BLOCKS_X * SNAKE_BLOCK_SIZE)
|
||||||
|
#define SNAKE_MAP_HEIGHT (SNAKE_NUM_BLOCKS_Y * SNAKE_BLOCK_SIZE)
|
||||||
|
|
||||||
|
#define SNAKE_LEFT_X ((BASEVIDWIDTH - SNAKE_MAP_WIDTH) / 2 - SNAKE_BORDER_SIZE)
|
||||||
|
#define SNAKE_RIGHT_X (SNAKE_LEFT_X + SNAKE_MAP_WIDTH + SNAKE_BORDER_SIZE * 2 - 1)
|
||||||
|
#define SNAKE_BOTTOM_Y (BASEVIDHEIGHT - 48)
|
||||||
|
#define SNAKE_TOP_Y (SNAKE_BOTTOM_Y - SNAKE_MAP_HEIGHT - SNAKE_BORDER_SIZE * 2 + 1)
|
||||||
|
|
||||||
|
enum snake_bonustype_s {
|
||||||
|
SNAKE_BONUS_NONE = 0,
|
||||||
|
SNAKE_BONUS_SLOW,
|
||||||
|
SNAKE_BONUS_FAST,
|
||||||
|
SNAKE_BONUS_GHOST,
|
||||||
|
SNAKE_BONUS_NUKE,
|
||||||
|
SNAKE_BONUS_SCISSORS,
|
||||||
|
SNAKE_BONUS_REVERSE,
|
||||||
|
SNAKE_BONUS_EGGMAN,
|
||||||
|
SNAKE_NUM_BONUSES,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *snake_bonuspatches[] = {
|
||||||
|
NULL,
|
||||||
|
"DL_SLOW",
|
||||||
|
"TVSSC0",
|
||||||
|
"TVIVC0",
|
||||||
|
"TVARC0",
|
||||||
|
"DL_SCISSORS",
|
||||||
|
"TVRCC0",
|
||||||
|
"TVEGC0",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *snake_backgrounds[] = {
|
||||||
|
"RVPUMICF",
|
||||||
|
"FRSTRCKF",
|
||||||
|
"TAR",
|
||||||
|
"MMFLRB4",
|
||||||
|
"RVDARKF1",
|
||||||
|
"RVZWALF1",
|
||||||
|
"RVZWALF4",
|
||||||
|
"RVZWALF5",
|
||||||
|
"RVZGRS02",
|
||||||
|
"RVZGRS04",
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct snake_s
|
||||||
|
{
|
||||||
|
boolean paused;
|
||||||
|
boolean pausepressed;
|
||||||
|
tic_t time;
|
||||||
|
tic_t nextupdate;
|
||||||
|
boolean gameover;
|
||||||
|
UINT8 background;
|
||||||
|
|
||||||
|
UINT16 snakelength;
|
||||||
|
enum snake_bonustype_s snakebonus;
|
||||||
|
tic_t snakebonustime;
|
||||||
|
UINT8 snakex[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y];
|
||||||
|
UINT8 snakey[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y];
|
||||||
|
UINT8 snakedir[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y];
|
||||||
|
|
||||||
|
UINT8 applex;
|
||||||
|
UINT8 appley;
|
||||||
|
|
||||||
|
enum snake_bonustype_s bonustype;
|
||||||
|
UINT8 bonusx;
|
||||||
|
UINT8 bonusy;
|
||||||
|
} snake_t;
|
||||||
|
|
||||||
|
static snake_t *snake = NULL;
|
||||||
|
|
||||||
|
static void Snake_Initialise(void)
|
||||||
|
{
|
||||||
|
if (!snake)
|
||||||
|
snake = malloc(sizeof(snake_t));
|
||||||
|
|
||||||
|
snake->paused = false;
|
||||||
|
snake->pausepressed = false;
|
||||||
|
snake->time = 0;
|
||||||
|
snake->nextupdate = SNAKE_SPEED;
|
||||||
|
snake->gameover = false;
|
||||||
|
snake->background = M_RandomKey(sizeof(snake_backgrounds) / sizeof(*snake_backgrounds));
|
||||||
|
|
||||||
|
snake->snakelength = 1;
|
||||||
|
snake->snakebonus = SNAKE_BONUS_NONE;
|
||||||
|
snake->snakex[0] = M_RandomKey(SNAKE_NUM_BLOCKS_X);
|
||||||
|
snake->snakey[0] = M_RandomKey(SNAKE_NUM_BLOCKS_Y);
|
||||||
|
snake->snakedir[0] = 0;
|
||||||
|
snake->snakedir[1] = 0;
|
||||||
|
|
||||||
|
snake->applex = M_RandomKey(SNAKE_NUM_BLOCKS_X);
|
||||||
|
snake->appley = M_RandomKey(SNAKE_NUM_BLOCKS_Y);
|
||||||
|
|
||||||
|
snake->bonustype = SNAKE_BONUS_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT8 Snake_GetOppositeDir(UINT8 dir)
|
||||||
|
{
|
||||||
|
if (dir == 1 || dir == 3)
|
||||||
|
return dir + 1;
|
||||||
|
else if (dir == 2 || dir == 4)
|
||||||
|
return dir - 1;
|
||||||
|
else
|
||||||
|
return 12 + 5 - dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Snake_FindFreeSlot(UINT8 *x, UINT8 *y, UINT8 headx, UINT8 heady)
|
||||||
|
{
|
||||||
|
UINT16 i;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*x = M_RandomKey(SNAKE_NUM_BLOCKS_X);
|
||||||
|
*y = M_RandomKey(SNAKE_NUM_BLOCKS_Y);
|
||||||
|
|
||||||
|
for (i = 0; i < snake->snakelength; i++)
|
||||||
|
if (*x == snake->snakex[i] && *y == snake->snakey[i])
|
||||||
|
break;
|
||||||
|
} while (i < snake->snakelength || (*x == headx && *y == heady));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Snake_Handle(void)
|
||||||
|
{
|
||||||
|
UINT8 x, y;
|
||||||
|
UINT8 oldx, oldy;
|
||||||
|
UINT16 i;
|
||||||
|
|
||||||
|
// Handle retry
|
||||||
|
if (snake->gameover && (PLAYER1INPUTDOWN(gc_jump) || gamekeydown[KEY_ENTER]))
|
||||||
|
{
|
||||||
|
Snake_Initialise();
|
||||||
|
snake->pausepressed = true; // Avoid accidental pause on respawn
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle pause
|
||||||
|
if (PLAYER1INPUTDOWN(gc_pause) || gamekeydown[KEY_ENTER])
|
||||||
|
{
|
||||||
|
if (!snake->pausepressed)
|
||||||
|
snake->paused = !snake->paused;
|
||||||
|
snake->pausepressed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
snake->pausepressed = false;
|
||||||
|
|
||||||
|
if (snake->paused)
|
||||||
|
return;
|
||||||
|
|
||||||
|
snake->time++;
|
||||||
|
|
||||||
|
x = snake->snakex[0];
|
||||||
|
y = snake->snakey[0];
|
||||||
|
oldx = snake->snakex[1];
|
||||||
|
oldy = snake->snakey[1];
|
||||||
|
|
||||||
|
// Update direction
|
||||||
|
if (gamekeydown[KEY_LEFTARROW])
|
||||||
|
{
|
||||||
|
if (snake->snakelength < 2 || x <= oldx)
|
||||||
|
snake->snakedir[0] = 1;
|
||||||
|
}
|
||||||
|
else if (gamekeydown[KEY_RIGHTARROW])
|
||||||
|
{
|
||||||
|
if (snake->snakelength < 2 || x >= oldx)
|
||||||
|
snake->snakedir[0] = 2;
|
||||||
|
}
|
||||||
|
else if (gamekeydown[KEY_UPARROW])
|
||||||
|
{
|
||||||
|
if (snake->snakelength < 2 || y <= oldy)
|
||||||
|
snake->snakedir[0] = 3;
|
||||||
|
}
|
||||||
|
else if (gamekeydown[KEY_DOWNARROW])
|
||||||
|
{
|
||||||
|
if (snake->snakelength < 2 || y >= oldy)
|
||||||
|
snake->snakedir[0] = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snake->snakebonustime)
|
||||||
|
{
|
||||||
|
snake->snakebonustime--;
|
||||||
|
if (!snake->snakebonustime)
|
||||||
|
snake->snakebonus = SNAKE_BONUS_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
snake->nextupdate--;
|
||||||
|
if (snake->nextupdate)
|
||||||
|
return;
|
||||||
|
if (snake->snakebonus == SNAKE_BONUS_SLOW)
|
||||||
|
snake->nextupdate = SNAKE_SPEED * 2;
|
||||||
|
else if (snake->snakebonus == SNAKE_BONUS_FAST)
|
||||||
|
snake->nextupdate = SNAKE_SPEED * 2 / 3;
|
||||||
|
else
|
||||||
|
snake->nextupdate = SNAKE_SPEED;
|
||||||
|
|
||||||
|
if (snake->gameover)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Find new position
|
||||||
|
switch (snake->snakedir[0])
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
if (x > 0)
|
||||||
|
x--;
|
||||||
|
else
|
||||||
|
snake->gameover = true;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (x < SNAKE_NUM_BLOCKS_X - 1)
|
||||||
|
x++;
|
||||||
|
else
|
||||||
|
snake->gameover = true;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (y > 0)
|
||||||
|
y--;
|
||||||
|
else
|
||||||
|
snake->gameover = true;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if (y < SNAKE_NUM_BLOCKS_Y - 1)
|
||||||
|
y++;
|
||||||
|
else
|
||||||
|
snake->gameover = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check collision with snake
|
||||||
|
if (snake->snakebonus != SNAKE_BONUS_GHOST)
|
||||||
|
for (i = 1; i < snake->snakelength - 1; i++)
|
||||||
|
if (x == snake->snakex[i] && y == snake->snakey[i])
|
||||||
|
{
|
||||||
|
if (snake->snakebonus == SNAKE_BONUS_SCISSORS)
|
||||||
|
{
|
||||||
|
snake->snakebonus = SNAKE_BONUS_NONE;
|
||||||
|
snake->snakelength = i;
|
||||||
|
S_StartSound(NULL, sfx_adderr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
snake->gameover = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snake->gameover)
|
||||||
|
{
|
||||||
|
S_StartSound(NULL, sfx_lose);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check collision with apple
|
||||||
|
if (x == snake->applex && y == snake->appley)
|
||||||
|
{
|
||||||
|
if (snake->snakelength + 1 < SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y)
|
||||||
|
{
|
||||||
|
snake->snakelength++;
|
||||||
|
snake->snakex [snake->snakelength - 1] = snake->snakex [snake->snakelength - 2];
|
||||||
|
snake->snakey [snake->snakelength - 1] = snake->snakey [snake->snakelength - 2];
|
||||||
|
snake->snakedir[snake->snakelength - 1] = snake->snakedir[snake->snakelength - 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spawn new apple
|
||||||
|
Snake_FindFreeSlot(&snake->applex, &snake->appley, x, y);
|
||||||
|
|
||||||
|
// Spawn new bonus
|
||||||
|
if (!(snake->snakelength % 5))
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
snake->bonustype = M_RandomKey(SNAKE_NUM_BONUSES - 1) + 1;
|
||||||
|
} while (snake->snakelength > SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y * 3 / 4
|
||||||
|
&& (snake->bonustype == SNAKE_BONUS_EGGMAN || snake->bonustype == SNAKE_BONUS_FAST || snake->bonustype == SNAKE_BONUS_REVERSE));
|
||||||
|
|
||||||
|
Snake_FindFreeSlot(&snake->bonusx, &snake->bonusy, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
S_StartSound(NULL, sfx_s3k6b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snake->snakelength > 1 && snake->snakedir[0])
|
||||||
|
{
|
||||||
|
UINT8 dir = snake->snakedir[0];
|
||||||
|
|
||||||
|
oldx = snake->snakex[1];
|
||||||
|
oldy = snake->snakey[1];
|
||||||
|
|
||||||
|
// Move
|
||||||
|
for (i = snake->snakelength - 1; i > 0; i--)
|
||||||
|
{
|
||||||
|
snake->snakex[i] = snake->snakex[i - 1];
|
||||||
|
snake->snakey[i] = snake->snakey[i - 1];
|
||||||
|
snake->snakedir[i] = snake->snakedir[i - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle corners
|
||||||
|
if (x < oldx && dir == 3)
|
||||||
|
dir = 5;
|
||||||
|
else if (x > oldx && dir == 3)
|
||||||
|
dir = 6;
|
||||||
|
else if (x < oldx && dir == 4)
|
||||||
|
dir = 7;
|
||||||
|
else if (x > oldx && dir == 4)
|
||||||
|
dir = 8;
|
||||||
|
else if (y < oldy && dir == 1)
|
||||||
|
dir = 9;
|
||||||
|
else if (y < oldy && dir == 2)
|
||||||
|
dir = 10;
|
||||||
|
else if (y > oldy && dir == 1)
|
||||||
|
dir = 11;
|
||||||
|
else if (y > oldy && dir == 2)
|
||||||
|
dir = 12;
|
||||||
|
snake->snakedir[1] = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
snake->snakex[0] = x;
|
||||||
|
snake->snakey[0] = y;
|
||||||
|
|
||||||
|
// Check collision with bonus
|
||||||
|
if (snake->bonustype != SNAKE_BONUS_NONE && x == snake->bonusx && y == snake->bonusy)
|
||||||
|
{
|
||||||
|
S_StartSound(NULL, sfx_ncchip);
|
||||||
|
|
||||||
|
switch (snake->bonustype)
|
||||||
|
{
|
||||||
|
case SNAKE_BONUS_SLOW:
|
||||||
|
snake->snakebonus = SNAKE_BONUS_SLOW;
|
||||||
|
snake->snakebonustime = 20 * TICRATE;
|
||||||
|
break;
|
||||||
|
case SNAKE_BONUS_FAST:
|
||||||
|
snake->snakebonus = SNAKE_BONUS_FAST;
|
||||||
|
snake->snakebonustime = 20 * TICRATE;
|
||||||
|
break;
|
||||||
|
case SNAKE_BONUS_GHOST:
|
||||||
|
snake->snakebonus = SNAKE_BONUS_GHOST;
|
||||||
|
snake->snakebonustime = 10 * TICRATE;
|
||||||
|
break;
|
||||||
|
case SNAKE_BONUS_NUKE:
|
||||||
|
for (i = 0; i < snake->snakelength; i++)
|
||||||
|
{
|
||||||
|
snake->snakex [i] = snake->snakex [0];
|
||||||
|
snake->snakey [i] = snake->snakey [0];
|
||||||
|
snake->snakedir[i] = snake->snakedir[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
S_StartSound(NULL, sfx_bkpoof);
|
||||||
|
break;
|
||||||
|
case SNAKE_BONUS_SCISSORS:
|
||||||
|
snake->snakebonus = SNAKE_BONUS_SCISSORS;
|
||||||
|
snake->snakebonustime = 60 * TICRATE;
|
||||||
|
break;
|
||||||
|
case SNAKE_BONUS_REVERSE:
|
||||||
|
for (i = 0; i < (snake->snakelength + 1) / 2; i++)
|
||||||
|
{
|
||||||
|
UINT16 i2 = snake->snakelength - 1 - i;
|
||||||
|
UINT8 tmpx = snake->snakex [i];
|
||||||
|
UINT8 tmpy = snake->snakey [i];
|
||||||
|
UINT8 tmpdir = snake->snakedir[i];
|
||||||
|
|
||||||
|
// Swap first segment with last segment
|
||||||
|
snake->snakex [i] = snake->snakex [i2];
|
||||||
|
snake->snakey [i] = snake->snakey [i2];
|
||||||
|
snake->snakedir[i] = Snake_GetOppositeDir(snake->snakedir[i2]);
|
||||||
|
snake->snakex [i2] = tmpx;
|
||||||
|
snake->snakey [i2] = tmpy;
|
||||||
|
snake->snakedir[i2] = Snake_GetOppositeDir(tmpdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
snake->snakedir[0] = 0;
|
||||||
|
|
||||||
|
S_StartSound(NULL, sfx_gravch);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (snake->snakebonus != SNAKE_BONUS_GHOST)
|
||||||
|
{
|
||||||
|
snake->gameover = true;
|
||||||
|
S_StartSound(NULL, sfx_lose);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snake->bonustype = SNAKE_BONUS_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Snake_Draw(void)
|
||||||
|
{
|
||||||
|
INT16 i;
|
||||||
|
|
||||||
|
// Background
|
||||||
|
V_DrawFlatFill(
|
||||||
|
SNAKE_LEFT_X + SNAKE_BORDER_SIZE,
|
||||||
|
SNAKE_TOP_Y + SNAKE_BORDER_SIZE,
|
||||||
|
SNAKE_MAP_WIDTH,
|
||||||
|
SNAKE_MAP_HEIGHT,
|
||||||
|
W_GetNumForName(snake_backgrounds[snake->background])
|
||||||
|
);
|
||||||
|
|
||||||
|
// Borders
|
||||||
|
V_DrawFill(SNAKE_LEFT_X, SNAKE_TOP_Y, SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_BORDER_SIZE, 242); // Top
|
||||||
|
V_DrawFill(SNAKE_LEFT_X + SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_TOP_Y, SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, 242); // Right
|
||||||
|
V_DrawFill(SNAKE_LEFT_X + SNAKE_BORDER_SIZE, SNAKE_TOP_Y + SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_BORDER_SIZE, 242); // Bottom
|
||||||
|
V_DrawFill(SNAKE_LEFT_X, SNAKE_TOP_Y + SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, 242); // Left
|
||||||
|
|
||||||
|
// Apple
|
||||||
|
V_DrawFixedPatch(
|
||||||
|
(SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->applex * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT,
|
||||||
|
(SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->appley * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT,
|
||||||
|
FRACUNIT / 4,
|
||||||
|
0,
|
||||||
|
W_CachePatchLongName("DL_APPLE", PU_HUDGFX),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
// Bonus
|
||||||
|
if (snake->bonustype != SNAKE_BONUS_NONE)
|
||||||
|
V_DrawFixedPatch(
|
||||||
|
(SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->bonusx * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2 ) * FRACUNIT,
|
||||||
|
(SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->bonusy * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2 + 4) * FRACUNIT,
|
||||||
|
FRACUNIT / 2,
|
||||||
|
0,
|
||||||
|
W_CachePatchLongName(snake_bonuspatches[snake->bonustype], PU_HUDGFX),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
// Snake
|
||||||
|
if (!snake->gameover || snake->time % 8 < 8 / 2) // Blink if game over
|
||||||
|
{
|
||||||
|
for (i = snake->snakelength - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
const char *patchname;
|
||||||
|
UINT8 dir = snake->snakedir[i];
|
||||||
|
|
||||||
|
if (i == 0) // Head
|
||||||
|
{
|
||||||
|
switch (dir)
|
||||||
|
{
|
||||||
|
case 1: patchname = "DL_SNAKEHEAD_L"; break;
|
||||||
|
case 2: patchname = "DL_SNAKEHEAD_R"; break;
|
||||||
|
case 3: patchname = "DL_SNAKEHEAD_T"; break;
|
||||||
|
case 4: patchname = "DL_SNAKEHEAD_B"; break;
|
||||||
|
default: patchname = "DL_SNAKEHEAD_M";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Body
|
||||||
|
{
|
||||||
|
switch (dir)
|
||||||
|
{
|
||||||
|
case 1: patchname = "DL_SNAKEBODY_L"; break;
|
||||||
|
case 2: patchname = "DL_SNAKEBODY_R"; break;
|
||||||
|
case 3: patchname = "DL_SNAKEBODY_T"; break;
|
||||||
|
case 4: patchname = "DL_SNAKEBODY_B"; break;
|
||||||
|
case 5: patchname = "DL_SNAKEBODY_LT"; break;
|
||||||
|
case 6: patchname = "DL_SNAKEBODY_RT"; break;
|
||||||
|
case 7: patchname = "DL_SNAKEBODY_LB"; break;
|
||||||
|
case 8: patchname = "DL_SNAKEBODY_RB"; break;
|
||||||
|
case 9: patchname = "DL_SNAKEBODY_TL"; break;
|
||||||
|
case 10: patchname = "DL_SNAKEBODY_TR"; break;
|
||||||
|
case 11: patchname = "DL_SNAKEBODY_BL"; break;
|
||||||
|
case 12: patchname = "DL_SNAKEBODY_BR"; break;
|
||||||
|
default: patchname = "DL_SNAKEBODY_B";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
V_DrawFixedPatch(
|
||||||
|
(SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->snakex[i] * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT,
|
||||||
|
(SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->snakey[i] * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT,
|
||||||
|
i == 0 && dir == 0 ? FRACUNIT / 5 : FRACUNIT / 2,
|
||||||
|
snake->snakebonus == SNAKE_BONUS_GHOST ? V_TRANSLUCENT : 0,
|
||||||
|
W_CachePatchLongName(patchname, PU_HUDGFX),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length
|
||||||
|
V_DrawString(SNAKE_RIGHT_X + 4, SNAKE_TOP_Y, V_MONOSPACE, va("%u", snake->snakelength));
|
||||||
|
|
||||||
|
// Bonus
|
||||||
|
if (snake->snakebonus != SNAKE_BONUS_NONE
|
||||||
|
&& (snake->snakebonustime >= 3 * TICRATE || snake->time % 4 < 4 / 2))
|
||||||
|
V_DrawFixedPatch(
|
||||||
|
(SNAKE_RIGHT_X + 10) * FRACUNIT,
|
||||||
|
(SNAKE_TOP_Y + 24) * FRACUNIT,
|
||||||
|
FRACUNIT / 2,
|
||||||
|
0,
|
||||||
|
W_CachePatchLongName(snake_bonuspatches[snake->snakebonus], PU_HUDGFX),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// CL_DrawConnectionStatus
|
// CL_DrawConnectionStatus
|
||||||
//
|
//
|
||||||
|
@ -1170,8 +1668,8 @@ static inline void CL_DrawConnectionStatus(void)
|
||||||
V_DrawFadeScreen(0xFF00, 16); // force default
|
V_DrawFadeScreen(0xFF00, 16); // force default
|
||||||
|
|
||||||
// Draw the bottom box.
|
// Draw the bottom box.
|
||||||
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1);
|
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-16-8, 32, 1);
|
||||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press ESC to abort");
|
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort");
|
||||||
|
|
||||||
if (cl_mode != CL_DOWNLOADFILES)
|
if (cl_mode != CL_DOWNLOADFILES)
|
||||||
{
|
{
|
||||||
|
@ -1180,8 +1678,9 @@ static inline void CL_DrawConnectionStatus(void)
|
||||||
// 15 pal entries total.
|
// 15 pal entries total.
|
||||||
const char *cltext;
|
const char *cltext;
|
||||||
|
|
||||||
|
if (!(cl_mode == CL_DOWNLOADSAVEGAME && lastfilenum != -1))
|
||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-24, 16, 8, palstart + ((animtime - i) & 15));
|
V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-16, 16, 8, palstart + ((animtime - i) & 15));
|
||||||
|
|
||||||
switch (cl_mode)
|
switch (cl_mode)
|
||||||
{
|
{
|
||||||
|
@ -1189,11 +1688,23 @@ static inline void CL_DrawConnectionStatus(void)
|
||||||
case CL_DOWNLOADSAVEGAME:
|
case CL_DOWNLOADSAVEGAME:
|
||||||
if (lastfilenum != -1)
|
if (lastfilenum != -1)
|
||||||
{
|
{
|
||||||
|
UINT32 currentsize = fileneeded[lastfilenum].currentsize;
|
||||||
|
UINT32 totalsize = fileneeded[lastfilenum].totalsize;
|
||||||
|
INT32 dldlength;
|
||||||
|
|
||||||
cltext = M_GetText("Downloading game state...");
|
cltext = M_GetText("Downloading game state...");
|
||||||
Net_GetNetStat();
|
Net_GetNetStat();
|
||||||
V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE,
|
|
||||||
va(" %4uK",fileneeded[lastfilenum].currentsize>>10));
|
dldlength = (INT32)((currentsize/(double)totalsize) * 256);
|
||||||
V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE,
|
if (dldlength > 256)
|
||||||
|
dldlength = 256;
|
||||||
|
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111);
|
||||||
|
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, dldlength, 8, 96);
|
||||||
|
|
||||||
|
V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE,
|
||||||
|
va(" %4uK/%4uK",currentsize>>10,totalsize>>10));
|
||||||
|
|
||||||
|
V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE,
|
||||||
va("%3.1fK/s ", ((double)getbps)/1024));
|
va("%3.1fK/s ", ((double)getbps)/1024));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1208,7 +1719,7 @@ static inline void CL_DrawConnectionStatus(void)
|
||||||
cltext = M_GetText("Connecting to server...");
|
cltext = M_GetText("Connecting to server...");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, cltext);
|
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, cltext);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1219,12 +1730,14 @@ static inline void CL_DrawConnectionStatus(void)
|
||||||
fileneeded_t *file = &fileneeded[lastfilenum];
|
fileneeded_t *file = &fileneeded[lastfilenum];
|
||||||
char *filename = file->filename;
|
char *filename = file->filename;
|
||||||
|
|
||||||
|
Snake_Draw();
|
||||||
|
|
||||||
Net_GetNetStat();
|
Net_GetNetStat();
|
||||||
dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256);
|
dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256);
|
||||||
if (dldlength > 256)
|
if (dldlength > 256)
|
||||||
dldlength = 256;
|
dldlength = 256;
|
||||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 111);
|
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111);
|
||||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, dldlength, 8, 96);
|
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, dldlength, 8, 96);
|
||||||
|
|
||||||
memset(tempname, 0, sizeof(tempname));
|
memset(tempname, 0, sizeof(tempname));
|
||||||
// offset filename to just the name only part
|
// offset filename to just the name only part
|
||||||
|
@ -1242,15 +1755,15 @@ static inline void CL_DrawConnectionStatus(void)
|
||||||
strncpy(tempname, filename, sizeof(tempname)-1);
|
strncpy(tempname, filename, sizeof(tempname)-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP,
|
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP,
|
||||||
va(M_GetText("Downloading \"%s\""), tempname));
|
va(M_GetText("Downloading \"%s\""), tempname));
|
||||||
V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE,
|
V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE,
|
||||||
va(" %4uK/%4uK",fileneeded[lastfilenum].currentsize>>10,file->totalsize>>10));
|
va(" %4uK/%4uK",fileneeded[lastfilenum].currentsize>>10,file->totalsize>>10));
|
||||||
V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE,
|
V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE,
|
||||||
va("%3.1fK/s ", ((double)getbps)/1024));
|
va("%3.1fK/s ", ((double)getbps)/1024));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP,
|
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP,
|
||||||
M_GetText("Waiting to download files..."));
|
M_GetText("Waiting to download files..."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1495,7 +2008,7 @@ static boolean SV_SendServerConfig(INT32 node)
|
||||||
if (!playeringame[i])
|
if (!playeringame[i])
|
||||||
continue;
|
continue;
|
||||||
netbuffer->u.servercfg.playerskins[i] = (UINT8)players[i].skin;
|
netbuffer->u.servercfg.playerskins[i] = (UINT8)players[i].skin;
|
||||||
netbuffer->u.servercfg.playercolor[i] = (UINT8)players[i].skincolor;
|
netbuffer->u.servercfg.playercolor[i] = (UINT16)players[i].skincolor;
|
||||||
netbuffer->u.servercfg.playeravailabilities[i] = (UINT32)LONG(players[i].availabilities);
|
netbuffer->u.servercfg.playeravailabilities[i] = (UINT32)LONG(players[i].availabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1598,7 +2111,7 @@ static void SV_SendSaveGame(INT32 node)
|
||||||
WRITEUINT32(savebuffer, 0);
|
WRITEUINT32(savebuffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SV_SendRam(node, buffertosend, length, SF_RAM, 0);
|
AddRamToSendQueue(node, buffertosend, length, SF_RAM, 0);
|
||||||
save_p = NULL;
|
save_p = NULL;
|
||||||
|
|
||||||
// Remember when we started sending the savegame so we can handle timeouts
|
// Remember when we started sending the savegame so we can handle timeouts
|
||||||
|
@ -1690,7 +2203,7 @@ static void CL_LoadReceivedSavegame(void)
|
||||||
// load a base level
|
// load a base level
|
||||||
if (P_LoadNetGame())
|
if (P_LoadNetGame())
|
||||||
{
|
{
|
||||||
const INT32 actnum = mapheaderinfo[gamemap-1]->actnum;
|
const UINT8 actnum = mapheaderinfo[gamemap-1]->actnum;
|
||||||
CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap));
|
CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap));
|
||||||
if (strcmp(mapheaderinfo[gamemap-1]->lvlttl, ""))
|
if (strcmp(mapheaderinfo[gamemap-1]->lvlttl, ""))
|
||||||
{
|
{
|
||||||
|
@ -1978,8 +2491,11 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// no problem if can't send packet, we will retry later
|
// no problem if can't send packet, we will retry later
|
||||||
if (CL_SendRequestFile())
|
if (CL_SendFileRequest())
|
||||||
|
{
|
||||||
cl_mode = CL_DOWNLOADFILES;
|
cl_mode = CL_DOWNLOADFILES;
|
||||||
|
Snake_Initialise();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2043,6 +2559,12 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic
|
||||||
if (waitmore)
|
if (waitmore)
|
||||||
break; // exit the case
|
break; // exit the case
|
||||||
|
|
||||||
|
if (snake)
|
||||||
|
{
|
||||||
|
free(snake);
|
||||||
|
snake = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
cl_mode = CL_ASKJOIN; // don't break case continue to cljoin request now
|
cl_mode = CL_ASKJOIN; // don't break case continue to cljoin request now
|
||||||
/* FALLTHRU */
|
/* FALLTHRU */
|
||||||
|
|
||||||
|
@ -2089,36 +2611,54 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic
|
||||||
// Call it only once by tic
|
// Call it only once by tic
|
||||||
if (*oldtic != I_GetTime())
|
if (*oldtic != I_GetTime())
|
||||||
{
|
{
|
||||||
INT32 key;
|
|
||||||
|
|
||||||
I_OsPolling();
|
I_OsPolling();
|
||||||
key = I_GetKey();
|
for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1))
|
||||||
if (key == KEY_ESCAPE || key == KEY_JOY1+1)
|
G_MapEventsToControls(&events[eventtail]);
|
||||||
|
|
||||||
|
if (gamekeydown[KEY_ESCAPE] || gamekeydown[KEY_JOY1+1])
|
||||||
{
|
{
|
||||||
CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
|
CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
|
||||||
// M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING);
|
// M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING);
|
||||||
|
|
||||||
|
if (snake)
|
||||||
|
{
|
||||||
|
free(snake);
|
||||||
|
snake = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
D_QuitNetGame();
|
D_QuitNetGame();
|
||||||
CL_Reset();
|
CL_Reset();
|
||||||
D_StartTitle();
|
D_StartTitle();
|
||||||
|
memset(gamekeydown, 0, NUMKEYS);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else if (cl_mode == CL_DOWNLOADFILES && snake)
|
||||||
|
Snake_Handle();
|
||||||
|
|
||||||
|
if (client && (cl_mode == CL_DOWNLOADFILES || cl_mode == CL_DOWNLOADSAVEGAME))
|
||||||
|
FileReceiveTicker();
|
||||||
|
|
||||||
// why are these here? this is for servers, we're a client
|
// why are these here? this is for servers, we're a client
|
||||||
//if (key == 's' && server)
|
//if (key == 's' && server)
|
||||||
// doomcom->numnodes = (INT16)pnumnodes;
|
// doomcom->numnodes = (INT16)pnumnodes;
|
||||||
//SV_FileSendTicker();
|
//FileSendTicker();
|
||||||
*oldtic = I_GetTime();
|
*oldtic = I_GetTime();
|
||||||
|
|
||||||
#ifdef CLIENT_LOADINGSCREEN
|
#ifdef CLIENT_LOADINGSCREEN
|
||||||
if (client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED)
|
if (client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED)
|
||||||
|
{
|
||||||
|
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_DOWNLOADSAVEGAME)
|
||||||
{
|
{
|
||||||
F_MenuPresTicker(true); // title sky
|
F_MenuPresTicker(true); // title sky
|
||||||
F_TitleScreenTicker(true);
|
F_TitleScreenTicker(true);
|
||||||
F_TitleScreenDrawer();
|
F_TitleScreenDrawer();
|
||||||
|
}
|
||||||
CL_DrawConnectionStatus();
|
CL_DrawConnectionStatus();
|
||||||
I_UpdateNoVsync(); // page flip or blit buffer
|
I_UpdateNoVsync(); // page flip or blit buffer
|
||||||
if (moviemode)
|
if (moviemode)
|
||||||
M_SaveFrame();
|
M_SaveFrame();
|
||||||
|
S_UpdateSounds();
|
||||||
|
S_UpdateClosedCaptions();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
CON_Drawer();
|
CON_Drawer();
|
||||||
|
@ -3240,6 +3780,7 @@ void D_QuitNetGame(void)
|
||||||
CloseNetFile();
|
CloseNetFile();
|
||||||
RemoveAllLuaFileTransfers();
|
RemoveAllLuaFileTransfers();
|
||||||
waitingforluafiletransfer = false;
|
waitingforluafiletransfer = false;
|
||||||
|
waitingforluafilecommand = false;
|
||||||
|
|
||||||
if (server)
|
if (server)
|
||||||
{
|
{
|
||||||
|
@ -3291,7 +3832,6 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
||||||
boolean splitscreenplayer;
|
boolean splitscreenplayer;
|
||||||
boolean rejoined;
|
boolean rejoined;
|
||||||
player_t *newplayer;
|
player_t *newplayer;
|
||||||
char *port;
|
|
||||||
|
|
||||||
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
|
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
|
||||||
{
|
{
|
||||||
|
@ -3322,12 +3862,17 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
||||||
|
|
||||||
if (server && I_GetNodeAddress)
|
if (server && I_GetNodeAddress)
|
||||||
{
|
{
|
||||||
strcpy(playeraddress[newplayernum], I_GetNodeAddress(node));
|
const char *address = I_GetNodeAddress(node);
|
||||||
|
char *port = NULL;
|
||||||
|
if (address) // MI: fix msvcrt.dll!_mbscat crash?
|
||||||
|
{
|
||||||
|
strcpy(playeraddress[newplayernum], address);
|
||||||
port = strchr(playeraddress[newplayernum], ':');
|
port = strchr(playeraddress[newplayernum], ':');
|
||||||
if (port)
|
if (port)
|
||||||
*port = '\0';
|
*port = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
newplayer = &players[newplayernum];
|
newplayer = &players[newplayernum];
|
||||||
|
|
||||||
|
@ -3346,6 +3891,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
||||||
displayplayer = newplayernum;
|
displayplayer = newplayernum;
|
||||||
secondarydisplayplayer = newplayernum;
|
secondarydisplayplayer = newplayernum;
|
||||||
DEBFILE("spawning me\n");
|
DEBFILE("spawning me\n");
|
||||||
|
ticcmd_oldangleturn[0] = newplayer->oldrelangleturn;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3353,7 +3899,9 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
||||||
DEBFILE("spawning my brother\n");
|
DEBFILE("spawning my brother\n");
|
||||||
if (botingame)
|
if (botingame)
|
||||||
newplayer->bot = 1;
|
newplayer->bot = 1;
|
||||||
|
ticcmd_oldangleturn[1] = newplayer->oldrelangleturn;
|
||||||
}
|
}
|
||||||
|
P_ForceLocalAngle(newplayer, (angle_t)(newplayer->angleturn << 16));
|
||||||
D_SendPlayerConfig();
|
D_SendPlayerConfig();
|
||||||
addedtogame = true;
|
addedtogame = true;
|
||||||
|
|
||||||
|
@ -3361,11 +3909,6 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
||||||
{
|
{
|
||||||
if (newplayer->mo)
|
if (newplayer->mo)
|
||||||
{
|
{
|
||||||
if (!splitscreenplayer)
|
|
||||||
localangle = newplayer->mo->angle;
|
|
||||||
else
|
|
||||||
localangle2 = newplayer->mo->angle;
|
|
||||||
|
|
||||||
newplayer->viewheight = 41*newplayer->height/48;
|
newplayer->viewheight = 41*newplayer->height/48;
|
||||||
|
|
||||||
if (newplayer->mo->eflags & MFE_VERTICALFLIP)
|
if (newplayer->mo->eflags & MFE_VERTICALFLIP)
|
||||||
|
@ -3877,7 +4420,7 @@ static void HandlePacketFromAwayNode(SINT8 node)
|
||||||
for (j = 0; j < MAXPLAYERS; j++)
|
for (j = 0; j < MAXPLAYERS; j++)
|
||||||
{
|
{
|
||||||
if (netbuffer->u.servercfg.playerskins[j] == 0xFF
|
if (netbuffer->u.servercfg.playerskins[j] == 0xFF
|
||||||
&& netbuffer->u.servercfg.playercolor[j] == 0xFF
|
&& netbuffer->u.servercfg.playercolor[j] == 0xFFFF
|
||||||
&& netbuffer->u.servercfg.playeravailabilities[j] == 0xFFFFFFFF)
|
&& netbuffer->u.servercfg.playeravailabilities[j] == 0xFFFFFFFF)
|
||||||
continue; // not in game
|
continue; // not in game
|
||||||
|
|
||||||
|
@ -3911,13 +4454,23 @@ static void HandlePacketFromAwayNode(SINT8 node)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
SERVERONLY
|
SERVERONLY
|
||||||
Got_Filetxpak();
|
PT_FileFragment();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PT_FILEACK:
|
||||||
|
if (server)
|
||||||
|
PT_FileAck();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PT_FILERECEIVED:
|
||||||
|
if (server)
|
||||||
|
PT_FileReceived();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_REQUESTFILE:
|
case PT_REQUESTFILE:
|
||||||
if (server)
|
if (server)
|
||||||
{
|
{
|
||||||
if (!cv_downloading.value || !Got_RequestFilePak(node))
|
if (!cv_downloading.value || !PT_RequestFile(node))
|
||||||
Net_CloseConnection(node); // close connection if one of the requested files could not be sent, or you disabled downloading anyway
|
Net_CloseConnection(node); // close connection if one of the requested files could not be sent, or you disabled downloading anyway
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -3999,8 +4552,8 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||||
|
|
||||||
// To save bytes, only the low byte of tic numbers are sent
|
// To save bytes, only the low byte of tic numbers are sent
|
||||||
// Use ExpandTics to figure out what the rest of the bytes are
|
// Use ExpandTics to figure out what the rest of the bytes are
|
||||||
realstart = ExpandTics(netbuffer->u.clientpak.client_tic);
|
realstart = ExpandTics(netbuffer->u.clientpak.client_tic, node);
|
||||||
realend = ExpandTics(netbuffer->u.clientpak.resendfrom);
|
realend = ExpandTics(netbuffer->u.clientpak.resendfrom, node);
|
||||||
|
|
||||||
if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS
|
if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS
|
||||||
|| netbuffer->packettype == PT_NODEKEEPALIVEMIS
|
|| netbuffer->packettype == PT_NODEKEEPALIVEMIS
|
||||||
|
@ -4213,11 +4766,7 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||||
break;
|
break;
|
||||||
case PT_ASKLUAFILE:
|
case PT_ASKLUAFILE:
|
||||||
if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_ASKED)
|
if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_ASKED)
|
||||||
{
|
AddLuaFileToSendQueue(node, luafiletransfers->realfilename);
|
||||||
char *name = va("%s" PATHSEP "%s", luafiledir, luafiletransfers->filename);
|
|
||||||
boolean textmode = !strchr(luafiletransfers->mode, 'b');
|
|
||||||
SV_SendLuaFile(node, name, textmode);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case PT_HASLUAFILE:
|
case PT_HASLUAFILE:
|
||||||
if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_SENDING)
|
if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_SENDING)
|
||||||
|
@ -4252,15 +4801,15 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
realstart = ExpandTics(netbuffer->u.serverpak.starttic);
|
realstart = netbuffer->u.serverpak.starttic;
|
||||||
realend = realstart + netbuffer->u.serverpak.numtics;
|
realend = realstart + netbuffer->u.serverpak.numtics;
|
||||||
|
|
||||||
if (!txtpak)
|
if (!txtpak)
|
||||||
txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots
|
txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots
|
||||||
* netbuffer->u.serverpak.numtics];
|
* netbuffer->u.serverpak.numtics];
|
||||||
|
|
||||||
if (realend > gametic + BACKUPTICS)
|
if (realend > gametic + CLIENTBACKUPTICS)
|
||||||
realend = gametic + BACKUPTICS;
|
realend = gametic + CLIENTBACKUPTICS;
|
||||||
cl_packetmissed = realstart > neededtic;
|
cl_packetmissed = realstart > neededtic;
|
||||||
|
|
||||||
if (realstart <= neededtic && realend > neededtic)
|
if (realstart <= neededtic && realend > neededtic)
|
||||||
|
@ -4348,7 +4897,15 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (client)
|
if (client)
|
||||||
Got_Filetxpak();
|
PT_FileFragment();
|
||||||
|
break;
|
||||||
|
case PT_FILEACK:
|
||||||
|
if (server)
|
||||||
|
PT_FileAck();
|
||||||
|
break;
|
||||||
|
case PT_FILERECEIVED:
|
||||||
|
if (server)
|
||||||
|
PT_FileReceived();
|
||||||
break;
|
break;
|
||||||
case PT_SENDINGLUAFILE:
|
case PT_SENDINGLUAFILE:
|
||||||
if (client)
|
if (client)
|
||||||
|
@ -4603,11 +5160,11 @@ static void SV_SendTics(void)
|
||||||
for (n = 1; n < MAXNETNODES; n++)
|
for (n = 1; n < MAXNETNODES; n++)
|
||||||
if (nodeingame[n])
|
if (nodeingame[n])
|
||||||
{
|
{
|
||||||
lasttictosend = maketic;
|
|
||||||
|
|
||||||
// assert supposedtics[n]>=nettics[n]
|
// assert supposedtics[n]>=nettics[n]
|
||||||
realfirsttic = supposedtics[n];
|
realfirsttic = supposedtics[n];
|
||||||
if (realfirsttic >= maketic)
|
lasttictosend = min(maketic, realfirsttic + CLIENTBACKUPTICS);
|
||||||
|
|
||||||
|
if (realfirsttic >= lasttictosend)
|
||||||
{
|
{
|
||||||
// well we have sent all tics we will so use extrabandwidth
|
// well we have sent all tics we will so use extrabandwidth
|
||||||
// to resent packet that are supposed lost (this is necessary since lost
|
// to resent packet that are supposed lost (this is necessary since lost
|
||||||
|
@ -4616,7 +5173,7 @@ static void SV_SendTics(void)
|
||||||
DEBFILE(va("Nothing to send node %u mak=%u sup=%u net=%u \n",
|
DEBFILE(va("Nothing to send node %u mak=%u sup=%u net=%u \n",
|
||||||
n, maketic, supposedtics[n], nettics[n]));
|
n, maketic, supposedtics[n], nettics[n]));
|
||||||
realfirsttic = nettics[n];
|
realfirsttic = nettics[n];
|
||||||
if (realfirsttic >= maketic || (I_GetTime() + n)&3)
|
if (realfirsttic >= lasttictosend || (I_GetTime() + n)&3)
|
||||||
// all tic are ok
|
// all tic are ok
|
||||||
continue;
|
continue;
|
||||||
DEBFILE(va("Sent %d anyway\n", realfirsttic));
|
DEBFILE(va("Sent %d anyway\n", realfirsttic));
|
||||||
|
@ -4659,7 +5216,7 @@ static void SV_SendTics(void)
|
||||||
|
|
||||||
// Send the tics
|
// Send the tics
|
||||||
netbuffer->packettype = PT_SERVERTICS;
|
netbuffer->packettype = PT_SERVERTICS;
|
||||||
netbuffer->u.serverpak.starttic = (UINT8)realfirsttic;
|
netbuffer->u.serverpak.starttic = realfirsttic;
|
||||||
netbuffer->u.serverpak.numtics = (UINT8)(lasttictosend - realfirsttic);
|
netbuffer->u.serverpak.numtics = (UINT8)(lasttictosend - realfirsttic);
|
||||||
netbuffer->u.serverpak.numslots = (UINT8)SHORT(doomcom->numslots);
|
netbuffer->u.serverpak.numslots = (UINT8)SHORT(doomcom->numslots);
|
||||||
bufpos = (UINT8 *)&netbuffer->u.serverpak.cmds;
|
bufpos = (UINT8 *)&netbuffer->u.serverpak.cmds;
|
||||||
|
@ -4721,41 +5278,6 @@ static void Local_Maketic(INT32 realtics)
|
||||||
localcmds2.angleturn |= TICCMD_RECEIVED;
|
localcmds2.angleturn |= TICCMD_RECEIVED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is utter bullshit and is responsible for
|
|
||||||
// the random desynch that happens when a player spawns.
|
|
||||||
// This is because ticcmds are resent to clients if a packet
|
|
||||||
// was dropped, and thus modifying them can lead to several
|
|
||||||
// clients having their ticcmds set to different values.
|
|
||||||
void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle)
|
|
||||||
{
|
|
||||||
tic_t tic;
|
|
||||||
UINT8 numadjust = 0;
|
|
||||||
|
|
||||||
(void)x;
|
|
||||||
(void)y;
|
|
||||||
|
|
||||||
// Revisionist history: adjust the angles in the ticcmds received
|
|
||||||
// for this player, because they actually preceded the player
|
|
||||||
// spawning, but will be applied afterwards.
|
|
||||||
|
|
||||||
for (tic = server ? maketic : (neededtic - 1); tic >= gametic; tic--)
|
|
||||||
{
|
|
||||||
if (numadjust++ == BACKUPTICS)
|
|
||||||
{
|
|
||||||
DEBFILE(va("SV_SpawnPlayer: All netcmds for player %d adjusted!\n", playernum));
|
|
||||||
// We already adjusted them all, waste of time doing the same thing over and over
|
|
||||||
// This shouldn't happen normally though, either gametic was 0 (which is handled now anyway)
|
|
||||||
// or maketic >= gametic + BACKUPTICS
|
|
||||||
// -- Monster Iestyn 16/01/18
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
netcmds[tic%BACKUPTICS][playernum].angleturn = (INT16)((angle>>16) | TICCMD_RECEIVED);
|
|
||||||
|
|
||||||
if (!tic) // failsafe for gametic == 0 -- Monster Iestyn 16/01/18
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create missed tic
|
// create missed tic
|
||||||
static void SV_Maketic(void)
|
static void SV_Maketic(void)
|
||||||
{
|
{
|
||||||
|
@ -5073,7 +5595,7 @@ void NetUpdate(void)
|
||||||
CON_Ticker();
|
CON_Ticker();
|
||||||
}
|
}
|
||||||
|
|
||||||
SV_FileSendTicker();
|
FileSendTicker();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the number of players playing.
|
/** Returns the number of players playing.
|
||||||
|
|
|
@ -34,6 +34,7 @@ applications may follow different packet versions.
|
||||||
|
|
||||||
// Networking and tick handling related.
|
// Networking and tick handling related.
|
||||||
#define BACKUPTICS 96
|
#define BACKUPTICS 96
|
||||||
|
#define CLIENTBACKUPTICS 32
|
||||||
#define MAXTEXTCMD 256
|
#define MAXTEXTCMD 256
|
||||||
//
|
//
|
||||||
// Packet structure
|
// Packet structure
|
||||||
|
@ -75,6 +76,8 @@ typedef enum
|
||||||
// In addition, this packet can't occupy all the available slots.
|
// In addition, this packet can't occupy all the available slots.
|
||||||
|
|
||||||
PT_FILEFRAGMENT = PT_CANFAIL, // A part of a file.
|
PT_FILEFRAGMENT = PT_CANFAIL, // A part of a file.
|
||||||
|
PT_FILEACK,
|
||||||
|
PT_FILERECEIVED,
|
||||||
|
|
||||||
PT_TEXTCMD, // Extra text commands from the client.
|
PT_TEXTCMD, // Extra text commands from the client.
|
||||||
PT_TEXTCMD2, // Splitscreen text commands.
|
PT_TEXTCMD2, // Splitscreen text commands.
|
||||||
|
@ -128,7 +131,7 @@ typedef struct
|
||||||
// this packet is too large
|
// this packet is too large
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UINT8 starttic;
|
tic_t starttic;
|
||||||
UINT8 numtics;
|
UINT8 numtics;
|
||||||
UINT8 numslots; // "Slots filled": Highest player number in use plus one.
|
UINT8 numslots; // "Slots filled": Highest player number in use plus one.
|
||||||
ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large
|
ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large
|
||||||
|
@ -171,6 +174,9 @@ typedef struct
|
||||||
UINT32 pflags; // pflags_t
|
UINT32 pflags; // pflags_t
|
||||||
UINT8 panim; // panim_t
|
UINT8 panim; // panim_t
|
||||||
|
|
||||||
|
INT16 angleturn;
|
||||||
|
INT16 oldrelangleturn;
|
||||||
|
|
||||||
angle_t aiming;
|
angle_t aiming;
|
||||||
INT32 currentweapon;
|
INT32 currentweapon;
|
||||||
INT32 ringweapons;
|
INT32 ringweapons;
|
||||||
|
@ -188,7 +194,7 @@ typedef struct
|
||||||
SINT8 xtralife;
|
SINT8 xtralife;
|
||||||
SINT8 pity;
|
SINT8 pity;
|
||||||
|
|
||||||
UINT8 skincolor;
|
UINT16 skincolor;
|
||||||
INT32 skin;
|
INT32 skin;
|
||||||
UINT32 availabilities;
|
UINT32 availabilities;
|
||||||
// Just in case Lua does something like
|
// Just in case Lua does something like
|
||||||
|
@ -308,7 +314,7 @@ typedef struct
|
||||||
|
|
||||||
// 0xFF == not in game; else player skin num
|
// 0xFF == not in game; else player skin num
|
||||||
UINT8 playerskins[MAXPLAYERS];
|
UINT8 playerskins[MAXPLAYERS];
|
||||||
UINT8 playercolor[MAXPLAYERS];
|
UINT16 playercolor[MAXPLAYERS];
|
||||||
UINT32 playeravailabilities[MAXPLAYERS];
|
UINT32 playeravailabilities[MAXPLAYERS];
|
||||||
|
|
||||||
UINT8 gametype;
|
UINT8 gametype;
|
||||||
|
@ -320,13 +326,30 @@ typedef struct
|
||||||
UINT8 varlengthinputs[0]; // Playernames and netvars
|
UINT8 varlengthinputs[0]; // Playernames and netvars
|
||||||
} ATTRPACK serverconfig_pak;
|
} ATTRPACK serverconfig_pak;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
|
{
|
||||||
UINT8 fileid;
|
UINT8 fileid;
|
||||||
|
UINT32 filesize;
|
||||||
|
UINT8 iteration;
|
||||||
UINT32 position;
|
UINT32 position;
|
||||||
UINT16 size;
|
UINT16 size;
|
||||||
UINT8 data[0]; // Size is variable using hardware_MAXPACKETLENGTH
|
UINT8 data[0]; // Size is variable using hardware_MAXPACKETLENGTH
|
||||||
} ATTRPACK filetx_pak;
|
} ATTRPACK filetx_pak;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UINT32 start;
|
||||||
|
UINT32 acks;
|
||||||
|
} ATTRPACK fileacksegment_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UINT8 fileid;
|
||||||
|
UINT8 iteration;
|
||||||
|
UINT8 numsegments;
|
||||||
|
fileacksegment_t segments[0];
|
||||||
|
} ATTRPACK fileack_pak;
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(default : 4200)
|
#pragma warning(default : 4200)
|
||||||
#endif
|
#endif
|
||||||
|
@ -414,7 +437,7 @@ typedef struct
|
||||||
{
|
{
|
||||||
char name[MAXPLAYERNAME+1];
|
char name[MAXPLAYERNAME+1];
|
||||||
UINT8 skin;
|
UINT8 skin;
|
||||||
UINT8 color;
|
UINT16 color;
|
||||||
UINT32 pflags;
|
UINT32 pflags;
|
||||||
UINT32 score;
|
UINT32 score;
|
||||||
UINT8 ctfteam;
|
UINT8 ctfteam;
|
||||||
|
@ -442,6 +465,8 @@ typedef struct
|
||||||
UINT8 resynchgot; //
|
UINT8 resynchgot; //
|
||||||
UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...)
|
UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...)
|
||||||
filetx_pak filetxpak; // 139 bytes
|
filetx_pak filetxpak; // 139 bytes
|
||||||
|
fileack_pak fileack;
|
||||||
|
UINT8 filereceived;
|
||||||
clientconfig_pak clientcfg; // 136 bytes
|
clientconfig_pak clientcfg; // 136 bytes
|
||||||
UINT8 md5sum[16];
|
UINT8 md5sum[16];
|
||||||
serverinfo_pak serverinfo; // 1024 bytes
|
serverinfo_pak serverinfo; // 1024 bytes
|
||||||
|
@ -520,7 +545,7 @@ extern consvar_t cv_resynchattempts, cv_blamecfail;
|
||||||
extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed;
|
extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed;
|
||||||
|
|
||||||
// Used in d_net, the only dependence
|
// Used in d_net, the only dependence
|
||||||
tic_t ExpandTics(INT32 low);
|
tic_t ExpandTics(INT32 low, INT32 node);
|
||||||
void D_ClientServerInit(void);
|
void D_ClientServerInit(void);
|
||||||
|
|
||||||
// Initialise the other field
|
// Initialise the other field
|
||||||
|
@ -534,7 +559,6 @@ void NetUpdate(void);
|
||||||
|
|
||||||
void SV_StartSinglePlayerServer(void);
|
void SV_StartSinglePlayerServer(void);
|
||||||
boolean SV_SpawnServer(void);
|
boolean SV_SpawnServer(void);
|
||||||
void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle);
|
|
||||||
void SV_StopServer(void);
|
void SV_StopServer(void);
|
||||||
void SV_ResetServer(void);
|
void SV_ResetServer(void);
|
||||||
void CL_AddSplitscreenPlayer(void);
|
void CL_AddSplitscreenPlayer(void);
|
||||||
|
|
106
src/d_main.c
106
src/d_main.c
|
@ -125,6 +125,12 @@ boolean advancedemo;
|
||||||
INT32 debugload = 0;
|
INT32 debugload = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
UINT16 numskincolors;
|
||||||
|
menucolor_t *menucolorhead, *menucolortail;
|
||||||
|
|
||||||
|
char savegamename[256];
|
||||||
|
char liveeventbackup[256];
|
||||||
|
|
||||||
char srb2home[256] = ".";
|
char srb2home[256] = ".";
|
||||||
char srb2path[256] = ".";
|
char srb2path[256] = ".";
|
||||||
boolean usehome = true;
|
boolean usehome = true;
|
||||||
|
@ -310,7 +316,9 @@ static void D_Display(void)
|
||||||
F_WipeStartScreen();
|
F_WipeStartScreen();
|
||||||
// Check for Mega Genesis fade
|
// Check for Mega Genesis fade
|
||||||
wipestyleflags = WSF_FADEOUT;
|
wipestyleflags = WSF_FADEOUT;
|
||||||
if (F_TryColormapFade(31))
|
if (wipegamestate == (gamestate_t)FORCEWIPE)
|
||||||
|
F_WipeColorFill(31);
|
||||||
|
else if (F_TryColormapFade(31))
|
||||||
wipetypepost = -1; // Don't run the fade below this one
|
wipetypepost = -1; // Don't run the fade below this one
|
||||||
F_WipeEndScreen();
|
F_WipeEndScreen();
|
||||||
F_RunWipe(wipetypepre, gamestate != GS_TIMEATTACK && gamestate != GS_TITLESCREEN);
|
F_RunWipe(wipetypepre, gamestate != GS_TIMEATTACK && gamestate != GS_TITLESCREEN);
|
||||||
|
@ -409,6 +417,7 @@ static void D_Display(void)
|
||||||
|
|
||||||
if (!automapactive && !dedicated && cv_renderview.value)
|
if (!automapactive && !dedicated && cv_renderview.value)
|
||||||
{
|
{
|
||||||
|
rs_rendercalltime = I_GetTimeMicros();
|
||||||
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
|
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
|
||||||
{
|
{
|
||||||
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
|
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
|
||||||
|
@ -455,6 +464,7 @@ static void D_Display(void)
|
||||||
if (postimgtype2)
|
if (postimgtype2)
|
||||||
V_DoPostProcessor(1, postimgtype2, postimgparam2);
|
V_DoPostProcessor(1, postimgtype2, postimgparam2);
|
||||||
}
|
}
|
||||||
|
rs_rendercalltime = I_GetTimeMicros() - rs_rendercalltime;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastdraw)
|
if (lastdraw)
|
||||||
|
@ -590,22 +600,96 @@ static void D_Display(void)
|
||||||
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s);
|
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cv_renderstats.value)
|
||||||
|
{
|
||||||
|
char s[50];
|
||||||
|
int frametime = I_GetTimeMicros() - rs_prevframetime;
|
||||||
|
int divisor = 1;
|
||||||
|
rs_prevframetime = I_GetTimeMicros();
|
||||||
|
|
||||||
|
if (rs_rendercalltime > 10000) divisor = 1000;
|
||||||
|
|
||||||
|
snprintf(s, sizeof s - 1, "ft %d", frametime / divisor);
|
||||||
|
V_DrawThinString(30, 10, V_MONOSPACE | V_YELLOWMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "rtot %d", rs_rendercalltime / divisor);
|
||||||
|
V_DrawThinString(30, 20, V_MONOSPACE | V_YELLOWMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "bsp %d", rs_bsptime / divisor);
|
||||||
|
V_DrawThinString(30, 30, V_MONOSPACE | V_YELLOWMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "nbsp %d", rs_numbspcalls);
|
||||||
|
V_DrawThinString(80, 10, V_MONOSPACE | V_BLUEMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "nspr %d", rs_numsprites);
|
||||||
|
V_DrawThinString(80, 20, V_MONOSPACE | V_BLUEMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "nnod %d", rs_numdrawnodes);
|
||||||
|
V_DrawThinString(80, 30, V_MONOSPACE | V_BLUEMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "npob %d", rs_numpolyobjects);
|
||||||
|
V_DrawThinString(80, 40, V_MONOSPACE | V_BLUEMAP, s);
|
||||||
|
if (rendermode == render_opengl) // OpenGL specific stats
|
||||||
|
{
|
||||||
|
snprintf(s, sizeof s - 1, "nsrt %d", rs_hw_nodesorttime / divisor);
|
||||||
|
V_DrawThinString(30, 40, V_MONOSPACE | V_YELLOWMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "ndrw %d", rs_hw_nodedrawtime / divisor);
|
||||||
|
V_DrawThinString(30, 50, V_MONOSPACE | V_YELLOWMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "ssrt %d", rs_hw_spritesorttime / divisor);
|
||||||
|
V_DrawThinString(30, 60, V_MONOSPACE | V_YELLOWMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "sdrw %d", rs_hw_spritedrawtime / divisor);
|
||||||
|
V_DrawThinString(30, 70, V_MONOSPACE | V_YELLOWMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "fin %d", rs_swaptime / divisor);
|
||||||
|
V_DrawThinString(30, 80, V_MONOSPACE | V_YELLOWMAP, s);
|
||||||
|
if (cv_grbatching.value)
|
||||||
|
{
|
||||||
|
snprintf(s, sizeof s - 1, "bsrt %d", rs_hw_batchsorttime / divisor);
|
||||||
|
V_DrawThinString(80, 55, V_MONOSPACE | V_REDMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "bdrw %d", rs_hw_batchdrawtime / divisor);
|
||||||
|
V_DrawThinString(80, 65, V_MONOSPACE | V_REDMAP, s);
|
||||||
|
|
||||||
|
snprintf(s, sizeof s - 1, "npol %d", rs_hw_numpolys);
|
||||||
|
V_DrawThinString(130, 10, V_MONOSPACE | V_PURPLEMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "ndc %d", rs_hw_numcalls);
|
||||||
|
V_DrawThinString(130, 20, V_MONOSPACE | V_PURPLEMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "nshd %d", rs_hw_numshaders);
|
||||||
|
V_DrawThinString(130, 30, V_MONOSPACE | V_PURPLEMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "nvrt %d", rs_hw_numverts);
|
||||||
|
V_DrawThinString(130, 40, V_MONOSPACE | V_PURPLEMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "ntex %d", rs_hw_numtextures);
|
||||||
|
V_DrawThinString(185, 10, V_MONOSPACE | V_PURPLEMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "npf %d", rs_hw_numpolyflags);
|
||||||
|
V_DrawThinString(185, 20, V_MONOSPACE | V_PURPLEMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "ncol %d", rs_hw_numcolors);
|
||||||
|
V_DrawThinString(185, 30, V_MONOSPACE | V_PURPLEMAP, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // software specific stats
|
||||||
|
{
|
||||||
|
snprintf(s, sizeof s - 1, "prtl %d", rs_sw_portaltime / divisor);
|
||||||
|
V_DrawThinString(30, 40, V_MONOSPACE | V_YELLOWMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "plns %d", rs_sw_planetime / divisor);
|
||||||
|
V_DrawThinString(30, 50, V_MONOSPACE | V_YELLOWMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "mskd %d", rs_sw_maskedtime / divisor);
|
||||||
|
V_DrawThinString(30, 60, V_MONOSPACE | V_YELLOWMAP, s);
|
||||||
|
snprintf(s, sizeof s - 1, "fin %d", rs_swaptime / divisor);
|
||||||
|
V_DrawThinString(30, 70, V_MONOSPACE | V_YELLOWMAP, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rs_swaptime = I_GetTimeMicros();
|
||||||
I_FinishUpdate(); // page flip or blit buffer
|
I_FinishUpdate(); // page flip or blit buffer
|
||||||
|
rs_swaptime = I_GetTimeMicros() - rs_swaptime;
|
||||||
}
|
}
|
||||||
|
|
||||||
needpatchflush = false;
|
needpatchflush = false;
|
||||||
needpatchrecache = false;
|
needpatchrecache = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lactozilla: Check the renderer's state
|
// Check the renderer's state
|
||||||
// after a possible renderer switch.
|
// after a possible renderer switch.
|
||||||
void D_CheckRendererState(void)
|
void D_CheckRendererState(void)
|
||||||
{
|
{
|
||||||
// flush all patches from memory
|
// flush all patches from memory
|
||||||
// (also frees memory tagged with PU_CACHE)
|
|
||||||
// (which are not necessarily patches but I don't care)
|
|
||||||
if (needpatchflush)
|
if (needpatchflush)
|
||||||
|
{
|
||||||
Z_FlushCachedPatches();
|
Z_FlushCachedPatches();
|
||||||
|
needpatchflush = false;
|
||||||
|
}
|
||||||
|
|
||||||
// some patches have been freed,
|
// some patches have been freed,
|
||||||
// so cache them again
|
// so cache them again
|
||||||
|
@ -661,7 +745,7 @@ void D_SRB2Loop(void)
|
||||||
*/
|
*/
|
||||||
/* Smells like a hack... Don't fade Sonic's ass into the title screen. */
|
/* Smells like a hack... Don't fade Sonic's ass into the title screen. */
|
||||||
if (gamestate != GS_TITLESCREEN)
|
if (gamestate != GS_TITLESCREEN)
|
||||||
V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(W_GetNumForName("CONSBACK"), PU_CACHE));
|
V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(W_GetNumForName("CONSBACK"), PU_PATCH));
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
@ -813,6 +897,7 @@ void D_StartTitle(void)
|
||||||
// In case someone exits out at the same time they start a time attack run,
|
// In case someone exits out at the same time they start a time attack run,
|
||||||
// reset modeattacking
|
// reset modeattacking
|
||||||
modeattacking = ATTACKING_NONE;
|
modeattacking = ATTACKING_NONE;
|
||||||
|
marathonmode = 0;
|
||||||
|
|
||||||
// empty maptol so mario/etc sounds don't play in sound test when they shouldn't
|
// empty maptol so mario/etc sounds don't play in sound test when they shouldn't
|
||||||
maptol = 0;
|
maptol = 0;
|
||||||
|
@ -991,6 +1076,7 @@ static void IdentifyVersion(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
MUSICTEST("music.dta")
|
MUSICTEST("music.dta")
|
||||||
|
MUSICTEST("patch_music.pk3")
|
||||||
#ifdef DEVELOP // remove when music_new.dta is merged into music.dta
|
#ifdef DEVELOP // remove when music_new.dta is merged into music.dta
|
||||||
MUSICTEST("music_new.dta")
|
MUSICTEST("music_new.dta")
|
||||||
#endif
|
#endif
|
||||||
|
@ -1128,6 +1214,7 @@ void D_SRB2Main(void)
|
||||||
|
|
||||||
// default savegame
|
// default savegame
|
||||||
strcpy(savegamename, SAVEGAMENAME"%u.ssg");
|
strcpy(savegamename, SAVEGAMENAME"%u.ssg");
|
||||||
|
strcpy(liveeventbackup, "live"SAVEGAMENAME".bkp"); // intentionally not ending with .ssg
|
||||||
|
|
||||||
{
|
{
|
||||||
const char *userhome = D_Home(); //Alam: path to home
|
const char *userhome = D_Home(); //Alam: path to home
|
||||||
|
@ -1156,6 +1243,7 @@ void D_SRB2Main(void)
|
||||||
|
|
||||||
// can't use sprintf since there is %u in savegamename
|
// can't use sprintf since there is %u in savegamename
|
||||||
strcatbf(savegamename, srb2home, PATHSEP);
|
strcatbf(savegamename, srb2home, PATHSEP);
|
||||||
|
strcatbf(liveeventbackup, srb2home, PATHSEP);
|
||||||
|
|
||||||
snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", srb2home);
|
snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", srb2home);
|
||||||
#else // DEFAULTDIR
|
#else // DEFAULTDIR
|
||||||
|
@ -1168,6 +1256,7 @@ void D_SRB2Main(void)
|
||||||
|
|
||||||
// can't use sprintf since there is %u in savegamename
|
// can't use sprintf since there is %u in savegamename
|
||||||
strcatbf(savegamename, userhome, PATHSEP);
|
strcatbf(savegamename, userhome, PATHSEP);
|
||||||
|
strcatbf(liveeventbackup, userhome, PATHSEP);
|
||||||
|
|
||||||
snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", userhome);
|
snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", userhome);
|
||||||
#endif // DEFAULTDIR
|
#endif // DEFAULTDIR
|
||||||
|
@ -1182,10 +1271,17 @@ void D_SRB2Main(void)
|
||||||
|
|
||||||
// rand() needs seeded regardless of password
|
// rand() needs seeded regardless of password
|
||||||
srand((unsigned int)time(NULL));
|
srand((unsigned int)time(NULL));
|
||||||
|
rand();
|
||||||
|
rand();
|
||||||
|
rand();
|
||||||
|
|
||||||
if (M_CheckParm("-password") && M_IsNextParm())
|
if (M_CheckParm("-password") && M_IsNextParm())
|
||||||
D_SetPassword(M_GetNextParm());
|
D_SetPassword(M_GetNextParm());
|
||||||
|
|
||||||
|
// player setup menu colors must be initialized before
|
||||||
|
// any wad file is added, as they may contain colors themselves
|
||||||
|
M_InitPlayerSetupColors();
|
||||||
|
|
||||||
CONS_Printf("Z_Init(): Init zone memory allocation daemon. \n");
|
CONS_Printf("Z_Init(): Init zone memory allocation daemon. \n");
|
||||||
Z_Init();
|
Z_Init();
|
||||||
|
|
||||||
|
|
10
src/d_net.c
10
src/d_net.c
|
@ -806,11 +806,15 @@ static const char *packettypename[NUMPACKETTYPE] =
|
||||||
"HASLUAFILE",
|
"HASLUAFILE",
|
||||||
|
|
||||||
"FILEFRAGMENT",
|
"FILEFRAGMENT",
|
||||||
|
"FILEACK",
|
||||||
|
"FILERECEIVED",
|
||||||
|
|
||||||
"TEXTCMD",
|
"TEXTCMD",
|
||||||
"TEXTCMD2",
|
"TEXTCMD2",
|
||||||
"CLIENTJOIN",
|
"CLIENTJOIN",
|
||||||
"NODETIMEOUT",
|
"NODETIMEOUT",
|
||||||
"RESYNCHING",
|
"RESYNCHING",
|
||||||
|
"LOGIN",
|
||||||
"PING"
|
"PING"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -837,7 +841,7 @@ static void DebugPrintpacket(const char *header)
|
||||||
size_t ntxtcmd = &((UINT8 *)netbuffer)[doomcom->datalength] - cmd;
|
size_t ntxtcmd = &((UINT8 *)netbuffer)[doomcom->datalength] - cmd;
|
||||||
|
|
||||||
fprintf(debugfile, " firsttic %u ply %d tics %d ntxtcmd %s\n ",
|
fprintf(debugfile, " firsttic %u ply %d tics %d ntxtcmd %s\n ",
|
||||||
(UINT32)ExpandTics(serverpak->starttic), serverpak->numslots, serverpak->numtics, sizeu1(ntxtcmd));
|
(UINT32)serverpak->starttic, serverpak->numslots, serverpak->numtics, sizeu1(ntxtcmd));
|
||||||
/// \todo Display more readable information about net commands
|
/// \todo Display more readable information about net commands
|
||||||
fprintfstringnewline((char *)cmd, ntxtcmd);
|
fprintfstringnewline((char *)cmd, ntxtcmd);
|
||||||
/*fprintfstring((char *)cmd, 3);
|
/*fprintfstring((char *)cmd, 3);
|
||||||
|
@ -856,8 +860,8 @@ static void DebugPrintpacket(const char *header)
|
||||||
case PT_NODEKEEPALIVE:
|
case PT_NODEKEEPALIVE:
|
||||||
case PT_NODEKEEPALIVEMIS:
|
case PT_NODEKEEPALIVEMIS:
|
||||||
fprintf(debugfile, " tic %4u resendfrom %u\n",
|
fprintf(debugfile, " tic %4u resendfrom %u\n",
|
||||||
(UINT32)ExpandTics(netbuffer->u.clientpak.client_tic),
|
(UINT32)ExpandTics(netbuffer->u.clientpak.client_tic, doomcom->remotenode),
|
||||||
(UINT32)ExpandTics (netbuffer->u.clientpak.resendfrom));
|
(UINT32)ExpandTics (netbuffer->u.clientpak.resendfrom, doomcom->remotenode));
|
||||||
break;
|
break;
|
||||||
case PT_TEXTCMD:
|
case PT_TEXTCMD:
|
||||||
case PT_TEXTCMD2:
|
case PT_TEXTCMD2:
|
||||||
|
|
|
@ -225,6 +225,7 @@ consvar_t cv_allowseenames = {"allowseenames", "Yes", CV_NETVAR, CV_YesNo, NULL,
|
||||||
consvar_t cv_playername = {"name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_playername = {"name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||||
consvar_t cv_playername2 = {"name2", "Tails", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name2_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_playername2 = {"name2", "Tails", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name2_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||||
// player colors
|
// player colors
|
||||||
|
UINT16 lastgoodcolor = SKINCOLOR_BLUE, lastgoodcolor2 = SKINCOLOR_BLUE;
|
||||||
consvar_t cv_playercolor = {"color", "Blue", CV_CALL|CV_NOINIT, Color_cons_t, Color_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_playercolor = {"color", "Blue", CV_CALL|CV_NOINIT, Color_cons_t, Color_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||||
consvar_t cv_playercolor2 = {"color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t, Color2_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_playercolor2 = {"color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t, Color2_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||||
// player's skin, saved for commodity, when using a favorite skins wad..
|
// player's skin, saved for commodity, when using a favorite skins wad..
|
||||||
|
@ -501,6 +502,8 @@ void D_RegisterServerCommands(void)
|
||||||
COM_AddCommand("archivetest", Command_Archivetest_f);
|
COM_AddCommand("archivetest", Command_Archivetest_f);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
COM_AddCommand("downloads", Command_Downloads_f);
|
||||||
|
|
||||||
// for master server connection
|
// for master server connection
|
||||||
AddMServCommands();
|
AddMServCommands();
|
||||||
|
|
||||||
|
@ -619,7 +622,7 @@ void D_RegisterClientCommands(void)
|
||||||
for (i = 0; i < MAXSKINCOLORS; i++)
|
for (i = 0; i < MAXSKINCOLORS; i++)
|
||||||
{
|
{
|
||||||
Color_cons_t[i].value = i;
|
Color_cons_t[i].value = i;
|
||||||
Color_cons_t[i].strvalue = Color_Names[i];
|
Color_cons_t[i].strvalue = skincolors[i].name;
|
||||||
}
|
}
|
||||||
Color_cons_t[MAXSKINCOLORS].value = 0;
|
Color_cons_t[MAXSKINCOLORS].value = 0;
|
||||||
Color_cons_t[MAXSKINCOLORS].strvalue = NULL;
|
Color_cons_t[MAXSKINCOLORS].strvalue = NULL;
|
||||||
|
@ -1221,15 +1224,20 @@ static void SendNameAndColor(void)
|
||||||
CV_StealthSetValue(&cv_playercolor, skincolor_blueteam);
|
CV_StealthSetValue(&cv_playercolor, skincolor_blueteam);
|
||||||
}
|
}
|
||||||
|
|
||||||
// never allow the color "none"
|
// don't allow inaccessible colors
|
||||||
if (!cv_playercolor.value)
|
if (!skincolors[cv_playercolor.value].accessible)
|
||||||
{
|
{
|
||||||
if (players[consoleplayer].skincolor)
|
if (players[consoleplayer].skincolor && skincolors[players[consoleplayer].skincolor].accessible)
|
||||||
CV_StealthSetValue(&cv_playercolor, players[consoleplayer].skincolor);
|
CV_StealthSetValue(&cv_playercolor, players[consoleplayer].skincolor);
|
||||||
else if (skins[players[consoleplayer].skin].prefcolor)
|
else if (skincolors[atoi(cv_playercolor.defaultvalue)].accessible)
|
||||||
CV_StealthSetValue(&cv_playercolor, skins[players[consoleplayer].skin].prefcolor);
|
|
||||||
else
|
|
||||||
CV_StealthSet(&cv_playercolor, cv_playercolor.defaultvalue);
|
CV_StealthSet(&cv_playercolor, cv_playercolor.defaultvalue);
|
||||||
|
else if (skins[players[consoleplayer].skin].prefcolor && skincolors[skins[players[consoleplayer].skin].prefcolor].accessible)
|
||||||
|
CV_StealthSetValue(&cv_playercolor, skins[players[consoleplayer].skin].prefcolor);
|
||||||
|
else {
|
||||||
|
UINT16 i = 0;
|
||||||
|
while (i<numskincolors && !skincolors[i].accessible) i++;
|
||||||
|
CV_StealthSetValue(&cv_playercolor, (i != numskincolors) ? i : SKINCOLOR_BLUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(cv_playername.string, player_names[consoleplayer])
|
if (!strcmp(cv_playername.string, player_names[consoleplayer])
|
||||||
|
@ -1276,10 +1284,10 @@ static void SendNameAndColor(void)
|
||||||
{
|
{
|
||||||
CV_StealthSetValue(&cv_playercolor, skins[cv_skin.value].prefcolor);
|
CV_StealthSetValue(&cv_playercolor, skins[cv_skin.value].prefcolor);
|
||||||
|
|
||||||
players[consoleplayer].skincolor = cv_playercolor.value % MAXSKINCOLORS;
|
players[consoleplayer].skincolor = cv_playercolor.value % numskincolors;
|
||||||
|
|
||||||
if (players[consoleplayer].mo)
|
if (players[consoleplayer].mo)
|
||||||
players[consoleplayer].mo->color = (UINT8)players[consoleplayer].skincolor;
|
players[consoleplayer].mo->color = (UINT16)players[consoleplayer].skincolor;
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1317,7 +1325,7 @@ static void SendNameAndColor(void)
|
||||||
// Finally write out the complete packet and send it off.
|
// Finally write out the complete packet and send it off.
|
||||||
WRITESTRINGN(p, cv_playername.zstring, MAXPLAYERNAME);
|
WRITESTRINGN(p, cv_playername.zstring, MAXPLAYERNAME);
|
||||||
WRITEUINT32(p, (UINT32)players[consoleplayer].availabilities);
|
WRITEUINT32(p, (UINT32)players[consoleplayer].availabilities);
|
||||||
WRITEUINT8(p, (UINT8)cv_playercolor.value);
|
WRITEUINT16(p, (UINT16)cv_playercolor.value);
|
||||||
WRITEUINT8(p, (UINT8)cv_skin.value);
|
WRITEUINT8(p, (UINT8)cv_skin.value);
|
||||||
SendNetXCmd(XD_NAMEANDCOLOR, buf, p - buf);
|
SendNetXCmd(XD_NAMEANDCOLOR, buf, p - buf);
|
||||||
}
|
}
|
||||||
|
@ -1344,15 +1352,20 @@ static void SendNameAndColor2(void)
|
||||||
CV_StealthSetValue(&cv_playercolor2, skincolor_blueteam);
|
CV_StealthSetValue(&cv_playercolor2, skincolor_blueteam);
|
||||||
}
|
}
|
||||||
|
|
||||||
// never allow the color "none"
|
// don't allow inaccessible colors
|
||||||
if (!cv_playercolor2.value)
|
if (!skincolors[cv_playercolor2.value].accessible)
|
||||||
{
|
{
|
||||||
if (players[secondplaya].skincolor)
|
if (players[secondplaya].skincolor && skincolors[players[secondplaya].skincolor].accessible)
|
||||||
CV_StealthSetValue(&cv_playercolor2, players[secondplaya].skincolor);
|
CV_StealthSetValue(&cv_playercolor2, players[secondplaya].skincolor);
|
||||||
else if (skins[players[secondplaya].skin].prefcolor)
|
else if (skincolors[atoi(cv_playercolor2.defaultvalue)].accessible)
|
||||||
|
CV_StealthSet(&cv_playercolor, cv_playercolor2.defaultvalue);
|
||||||
|
else if (skins[players[secondplaya].skin].prefcolor && skincolors[skins[players[secondplaya].skin].prefcolor].accessible)
|
||||||
CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin].prefcolor);
|
CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin].prefcolor);
|
||||||
else
|
else {
|
||||||
CV_StealthSet(&cv_playercolor2, cv_playercolor2.defaultvalue);
|
UINT16 i = 0;
|
||||||
|
while (i<numskincolors && !skincolors[i].accessible) i++;
|
||||||
|
CV_StealthSetValue(&cv_playercolor2, (i != numskincolors) ? i : SKINCOLOR_BLUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
players[secondplaya].availabilities = R_GetSkinAvailabilities();
|
players[secondplaya].availabilities = R_GetSkinAvailabilities();
|
||||||
|
@ -1405,7 +1418,7 @@ static void SendNameAndColor2(void)
|
||||||
{
|
{
|
||||||
CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin].prefcolor);
|
CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin].prefcolor);
|
||||||
|
|
||||||
players[secondplaya].skincolor = cv_playercolor2.value % MAXSKINCOLORS;
|
players[secondplaya].skincolor = cv_playercolor2.value % numskincolors;
|
||||||
|
|
||||||
if (players[secondplaya].mo)
|
if (players[secondplaya].mo)
|
||||||
players[secondplaya].mo->color = players[secondplaya].skincolor;
|
players[secondplaya].mo->color = players[secondplaya].skincolor;
|
||||||
|
@ -1428,7 +1441,8 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
||||||
{
|
{
|
||||||
player_t *p = &players[playernum];
|
player_t *p = &players[playernum];
|
||||||
char name[MAXPLAYERNAME+1];
|
char name[MAXPLAYERNAME+1];
|
||||||
UINT8 color, skin;
|
UINT16 color;
|
||||||
|
UINT8 skin;
|
||||||
|
|
||||||
#ifdef PARANOIA
|
#ifdef PARANOIA
|
||||||
if (playernum < 0 || playernum > MAXPLAYERS)
|
if (playernum < 0 || playernum > MAXPLAYERS)
|
||||||
|
@ -1447,7 +1461,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
||||||
|
|
||||||
READSTRINGN(*cp, name, MAXPLAYERNAME);
|
READSTRINGN(*cp, name, MAXPLAYERNAME);
|
||||||
p->availabilities = READUINT32(*cp);
|
p->availabilities = READUINT32(*cp);
|
||||||
color = READUINT8(*cp);
|
color = READUINT16(*cp);
|
||||||
skin = READUINT8(*cp);
|
skin = READUINT8(*cp);
|
||||||
|
|
||||||
// set name
|
// set name
|
||||||
|
@ -1455,9 +1469,9 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
||||||
SetPlayerName(playernum, name);
|
SetPlayerName(playernum, name);
|
||||||
|
|
||||||
// set color
|
// set color
|
||||||
p->skincolor = color % MAXSKINCOLORS;
|
p->skincolor = color % numskincolors;
|
||||||
if (p->mo)
|
if (p->mo)
|
||||||
p->mo->color = (UINT8)p->skincolor;
|
p->mo->color = (UINT16)p->skincolor;
|
||||||
|
|
||||||
// normal player colors
|
// normal player colors
|
||||||
if (server && (p != &players[consoleplayer] && p != &players[secondarydisplayplayer]))
|
if (server && (p != &players[consoleplayer] && p != &players[secondarydisplayplayer]))
|
||||||
|
@ -1474,8 +1488,8 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
||||||
kick = true;
|
kick = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't allow color "none"
|
// don't allow inaccessible colors
|
||||||
if (!p->skincolor)
|
if (skincolors[p->skincolor].accessible == false)
|
||||||
kick = true;
|
kick = true;
|
||||||
|
|
||||||
// availabilities
|
// availabilities
|
||||||
|
@ -4473,16 +4487,19 @@ static void Skin2_OnChange(void)
|
||||||
*/
|
*/
|
||||||
static void Color_OnChange(void)
|
static void Color_OnChange(void)
|
||||||
{
|
{
|
||||||
if (!Playing())
|
if (!Playing()) {
|
||||||
return; // do whatever you want
|
if (!cv_playercolor.value || !skincolors[cv_playercolor.value].accessible)
|
||||||
|
CV_StealthSetValue(&cv_playercolor, lastgoodcolor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (!(cv_debug || devparm) && !(multiplayer || netgame)) // In single player.
|
if (!(cv_debug || devparm) && !(multiplayer || netgame)) // In single player.
|
||||||
{
|
{
|
||||||
CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name);
|
CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!P_PlayerMoving(consoleplayer))
|
if (!P_PlayerMoving(consoleplayer) && skincolors[players[consoleplayer].skincolor].accessible == true)
|
||||||
{
|
{
|
||||||
// Color change menu scrolling fix is no longer necessary
|
// Color change menu scrolling fix is no longer necessary
|
||||||
SendNameAndColor();
|
SendNameAndColor();
|
||||||
|
@ -4493,6 +4510,8 @@ static void Color_OnChange(void)
|
||||||
players[consoleplayer].skincolor);
|
players[consoleplayer].skincolor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lastgoodcolor = cv_playercolor.value;
|
||||||
|
}
|
||||||
|
|
||||||
/** Sends a color change for the secondary splitscreen player, unless that
|
/** Sends a color change for the secondary splitscreen player, unless that
|
||||||
* player is moving.
|
* player is moving.
|
||||||
|
@ -4502,9 +4521,13 @@ static void Color_OnChange(void)
|
||||||
static void Color2_OnChange(void)
|
static void Color2_OnChange(void)
|
||||||
{
|
{
|
||||||
if (!Playing() || !splitscreen)
|
if (!Playing() || !splitscreen)
|
||||||
return; // do whatever you want
|
{
|
||||||
|
if (!cv_playercolor2.value || !skincolors[cv_playercolor2.value].accessible)
|
||||||
if (!P_PlayerMoving(secondarydisplayplayer))
|
CV_StealthSetValue(&cv_playercolor2, lastgoodcolor2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!P_PlayerMoving(secondarydisplayplayer) && skincolors[players[secondarydisplayplayer].skincolor].accessible == true)
|
||||||
{
|
{
|
||||||
// Color change menu scrolling fix is no longer necessary
|
// Color change menu scrolling fix is no longer necessary
|
||||||
SendNameAndColor2();
|
SendNameAndColor2();
|
||||||
|
@ -4515,6 +4538,8 @@ static void Color2_OnChange(void)
|
||||||
players[secondarydisplayplayer].skincolor);
|
players[secondarydisplayplayer].skincolor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lastgoodcolor2 = cv_playercolor2.value;
|
||||||
|
}
|
||||||
|
|
||||||
/** Displays the result of the chat being muted or unmuted.
|
/** Displays the result of the chat being muted or unmuted.
|
||||||
* The server or remote admin should already know and be able to talk
|
* The server or remote admin should already know and be able to talk
|
||||||
|
|
583
src/d_netfil.c
583
src/d_netfil.c
|
@ -56,7 +56,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
// Prototypes
|
// Prototypes
|
||||||
static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid);
|
static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid);
|
||||||
|
|
||||||
// Sender structure
|
// Sender structure
|
||||||
typedef struct filetx_s
|
typedef struct filetx_s
|
||||||
|
@ -69,7 +69,6 @@ typedef struct filetx_s
|
||||||
UINT32 size; // Size of the file
|
UINT32 size; // Size of the file
|
||||||
UINT8 fileid;
|
UINT8 fileid;
|
||||||
INT32 node; // Destination
|
INT32 node; // Destination
|
||||||
boolean textmode; // For files requested by Lua without the "b" option
|
|
||||||
struct filetx_s *next; // Next file in the list
|
struct filetx_s *next; // Next file in the list
|
||||||
} filetx_t;
|
} filetx_t;
|
||||||
|
|
||||||
|
@ -77,8 +76,13 @@ typedef struct filetx_s
|
||||||
typedef struct filetran_s
|
typedef struct filetran_s
|
||||||
{
|
{
|
||||||
filetx_t *txlist; // Linked list of all files for the node
|
filetx_t *txlist; // Linked list of all files for the node
|
||||||
|
UINT8 iteration;
|
||||||
|
UINT8 ackediteration;
|
||||||
UINT32 position; // The current position in the file
|
UINT32 position; // The current position in the file
|
||||||
|
boolean *ackedfragments;
|
||||||
|
UINT32 ackedsize;
|
||||||
FILE *currentfile; // The file currently being sent/received
|
FILE *currentfile; // The file currently being sent/received
|
||||||
|
tic_t dontsenduntil;
|
||||||
} filetran_t;
|
} filetran_t;
|
||||||
static filetran_t transfer[MAXNETNODES];
|
static filetran_t transfer[MAXNETNODES];
|
||||||
|
|
||||||
|
@ -88,8 +92,20 @@ static filetran_t transfer[MAXNETNODES];
|
||||||
// Receiver structure
|
// Receiver structure
|
||||||
INT32 fileneedednum; // Number of files needed to join the server
|
INT32 fileneedednum; // Number of files needed to join the server
|
||||||
fileneeded_t fileneeded[MAX_WADFILES]; // List of needed files
|
fileneeded_t fileneeded[MAX_WADFILES]; // List of needed files
|
||||||
|
static tic_t lasttimeackpacketsent = 0;
|
||||||
char downloaddir[512] = "DOWNLOAD";
|
char downloaddir[512] = "DOWNLOAD";
|
||||||
|
|
||||||
|
// For resuming failed downloads
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char filename[MAX_WADPATH];
|
||||||
|
UINT8 md5sum[16];
|
||||||
|
boolean *receivedfragments;
|
||||||
|
UINT32 fragmentsize;
|
||||||
|
UINT32 currentsize;
|
||||||
|
} pauseddownload_t;
|
||||||
|
static pauseddownload_t *pauseddownload = NULL;
|
||||||
|
|
||||||
#ifdef CLIENT_LOADINGSCREEN
|
#ifdef CLIENT_LOADINGSCREEN
|
||||||
// for cl loading screen
|
// for cl loading screen
|
||||||
INT32 lastfilenum = -1;
|
INT32 lastfilenum = -1;
|
||||||
|
@ -97,6 +113,7 @@ INT32 lastfilenum = -1;
|
||||||
|
|
||||||
luafiletransfer_t *luafiletransfers = NULL;
|
luafiletransfer_t *luafiletransfers = NULL;
|
||||||
boolean waitingforluafiletransfer = false;
|
boolean waitingforluafiletransfer = false;
|
||||||
|
boolean waitingforluafilecommand = false;
|
||||||
char luafiledir[256 + 16] = "luafiles";
|
char luafiledir[256 + 16] = "luafiles";
|
||||||
|
|
||||||
|
|
||||||
|
@ -159,25 +176,29 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr)
|
||||||
for (i = 0; i < fileneedednum; i++)
|
for (i = 0; i < fileneedednum; i++)
|
||||||
{
|
{
|
||||||
fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet
|
fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet
|
||||||
|
fileneeded[i].justdownloaded = false;
|
||||||
filestatus = READUINT8(p); // The first byte is the file status
|
filestatus = READUINT8(p); // The first byte is the file status
|
||||||
fileneeded[i].willsend = (UINT8)(filestatus >> 4);
|
fileneeded[i].willsend = (UINT8)(filestatus >> 4);
|
||||||
fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size
|
fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size
|
||||||
fileneeded[i].file = NULL; // The file isn't open yet
|
fileneeded[i].file = NULL; // The file isn't open yet
|
||||||
READSTRINGN(p, fileneeded[i].filename, MAX_WADPATH); // The next bytes are the file name
|
READSTRINGN(p, fileneeded[i].filename, MAX_WADPATH); // The next bytes are the file name
|
||||||
READMEM(p, fileneeded[i].md5sum, 16); // The last 16 bytes are the file checksum
|
READMEM(p, fileneeded[i].md5sum, 16); // The last 16 bytes are the file checksum
|
||||||
fileneeded[i].textmode = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CL_PrepareDownloadSaveGame(const char *tmpsave)
|
void CL_PrepareDownloadSaveGame(const char *tmpsave)
|
||||||
{
|
{
|
||||||
|
#ifdef CLIENT_LOADINGSCREEN
|
||||||
|
lastfilenum = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
fileneedednum = 1;
|
fileneedednum = 1;
|
||||||
fileneeded[0].status = FS_REQUESTED;
|
fileneeded[0].status = FS_REQUESTED;
|
||||||
|
fileneeded[0].justdownloaded = false;
|
||||||
fileneeded[0].totalsize = UINT32_MAX;
|
fileneeded[0].totalsize = UINT32_MAX;
|
||||||
fileneeded[0].file = NULL;
|
fileneeded[0].file = NULL;
|
||||||
memset(fileneeded[0].md5sum, 0, 16);
|
memset(fileneeded[0].md5sum, 0, 16);
|
||||||
strcpy(fileneeded[0].filename, tmpsave);
|
strcpy(fileneeded[0].filename, tmpsave);
|
||||||
fileneeded[0].textmode = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Checks the server to see if we CAN download all the files,
|
/** Checks the server to see if we CAN download all the files,
|
||||||
|
@ -246,6 +267,31 @@ boolean CL_CheckDownloadable(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns true if a needed file transfer can be resumed
|
||||||
|
*
|
||||||
|
* \param file The needed file to resume the transfer for
|
||||||
|
* \return True if the transfer can be resumed
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static boolean CL_CanResumeDownload(fileneeded_t *file)
|
||||||
|
{
|
||||||
|
return pauseddownload
|
||||||
|
&& !strcmp(pauseddownload->filename, file->filename) // Same name
|
||||||
|
&& !memcmp(pauseddownload->md5sum, file->md5sum, 16) // Same checksum
|
||||||
|
&& pauseddownload->fragmentsize == file->fragmentsize; // Same fragment size
|
||||||
|
}
|
||||||
|
|
||||||
|
void CL_AbortDownloadResume(void)
|
||||||
|
{
|
||||||
|
if (!pauseddownload)
|
||||||
|
return;
|
||||||
|
|
||||||
|
free(pauseddownload->receivedfragments);
|
||||||
|
remove(pauseddownload->filename);
|
||||||
|
free(pauseddownload);
|
||||||
|
pauseddownload = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/** Sends requests for files in the ::fileneeded table with a status of
|
/** Sends requests for files in the ::fileneeded table with a status of
|
||||||
* ::FS_NOTFOUND.
|
* ::FS_NOTFOUND.
|
||||||
*
|
*
|
||||||
|
@ -253,7 +299,7 @@ boolean CL_CheckDownloadable(void)
|
||||||
* \note Sends a PT_REQUESTFILE packet
|
* \note Sends a PT_REQUESTFILE packet
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
boolean CL_SendRequestFile(void)
|
boolean CL_SendFileRequest(void)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
INT32 i;
|
INT32 i;
|
||||||
|
@ -298,7 +344,7 @@ boolean CL_SendRequestFile(void)
|
||||||
|
|
||||||
// get request filepak and put it on the send queue
|
// get request filepak and put it on the send queue
|
||||||
// returns false if a requested file was not found or cannot be sent
|
// returns false if a requested file was not found or cannot be sent
|
||||||
boolean Got_RequestFilePak(INT32 node)
|
boolean PT_RequestFile(INT32 node)
|
||||||
{
|
{
|
||||||
char wad[MAX_WADPATH+1];
|
char wad[MAX_WADPATH+1];
|
||||||
UINT8 *p = netbuffer->u.textcmd;
|
UINT8 *p = netbuffer->u.textcmd;
|
||||||
|
@ -309,7 +355,7 @@ boolean Got_RequestFilePak(INT32 node)
|
||||||
if (id == 0xFF)
|
if (id == 0xFF)
|
||||||
break;
|
break;
|
||||||
READSTRINGN(p, wad, MAX_WADPATH);
|
READSTRINGN(p, wad, MAX_WADPATH);
|
||||||
if (!SV_SendFile(node, wad, id))
|
if (!AddFileToSendQueue(node, wad, id))
|
||||||
{
|
{
|
||||||
SV_AbortSendFiles(node);
|
SV_AbortSendFiles(node);
|
||||||
return false; // don't read the rest of the files
|
return false; // don't read the rest of the files
|
||||||
|
@ -462,8 +508,6 @@ void AddLuaFileTransfer(const char *filename, const char *mode)
|
||||||
luafiletransfer_t *filetransfer;
|
luafiletransfer_t *filetransfer;
|
||||||
static INT32 id;
|
static INT32 id;
|
||||||
|
|
||||||
//CONS_Printf("AddLuaFileTransfer \"%s\"\n", filename);
|
|
||||||
|
|
||||||
// Find the last transfer in the list and set a pointer to its "next" field
|
// Find the last transfer in the list and set a pointer to its "next" field
|
||||||
prevnext = &luafiletransfers;
|
prevnext = &luafiletransfers;
|
||||||
while (*prevnext)
|
while (*prevnext)
|
||||||
|
@ -493,26 +537,11 @@ void AddLuaFileTransfer(const char *filename, const char *mode)
|
||||||
|
|
||||||
strlcpy(filetransfer->mode, mode, sizeof(filetransfer->mode));
|
strlcpy(filetransfer->mode, mode, sizeof(filetransfer->mode));
|
||||||
|
|
||||||
if (server)
|
// Only if there is no transfer already going on
|
||||||
{
|
if (server && filetransfer == luafiletransfers)
|
||||||
INT32 i;
|
SV_PrepareSendLuaFile();
|
||||||
|
|
||||||
// Set status to "waiting" for everyone
|
|
||||||
for (i = 0; i < MAXNETNODES; i++)
|
|
||||||
filetransfer->nodestatus[i] = LFTNS_WAITING;
|
|
||||||
|
|
||||||
if (!luafiletransfers->next) // Only if there is no transfer already going on
|
|
||||||
{
|
|
||||||
if (FIL_ReadFileOK(filetransfer->realfilename))
|
|
||||||
SV_PrepareSendLuaFileToNextNode();
|
|
||||||
else
|
else
|
||||||
{
|
filetransfer->ongoing = false;
|
||||||
// Send a net command with 0 as its first byte to indicate the file couldn't be opened
|
|
||||||
UINT8 success = 0;
|
|
||||||
SendNetXCmd(XD_LUAFILE, &success, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the callback so it can be called once everyone has the file
|
// Store the callback so it can be called once everyone has the file
|
||||||
filetransfer->id = id;
|
filetransfer->id = id;
|
||||||
|
@ -526,7 +555,7 @@ void AddLuaFileTransfer(const char *filename, const char *mode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SV_PrepareSendLuaFileToNextNode(void)
|
static void SV_PrepareSendLuaFileToNextNode(void)
|
||||||
{
|
{
|
||||||
INT32 i;
|
INT32 i;
|
||||||
UINT8 success = 1;
|
UINT8 success = 1;
|
||||||
|
@ -550,6 +579,45 @@ void SV_PrepareSendLuaFileToNextNode(void)
|
||||||
SendNetXCmd(XD_LUAFILE, &success, 1);
|
SendNetXCmd(XD_LUAFILE, &success, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SV_PrepareSendLuaFile(void)
|
||||||
|
{
|
||||||
|
char *binfilename;
|
||||||
|
INT32 i;
|
||||||
|
|
||||||
|
luafiletransfers->ongoing = true;
|
||||||
|
|
||||||
|
// Set status to "waiting" for everyone
|
||||||
|
for (i = 0; i < MAXNETNODES; i++)
|
||||||
|
luafiletransfers->nodestatus[i] = LFTNS_WAITING;
|
||||||
|
|
||||||
|
if (FIL_ReadFileOK(luafiletransfers->realfilename))
|
||||||
|
{
|
||||||
|
// If opening in text mode, convert all newlines to LF
|
||||||
|
if (!strchr(luafiletransfers->mode, 'b'))
|
||||||
|
{
|
||||||
|
binfilename = strdup(va("%s" PATHSEP "$$$%d%d.tmp",
|
||||||
|
luafiledir, rand(), rand()));
|
||||||
|
if (!binfilename)
|
||||||
|
I_Error("SV_PrepareSendLuaFile: Out of memory\n");
|
||||||
|
|
||||||
|
if (!FIL_ConvertTextFileToBinary(luafiletransfers->realfilename, binfilename))
|
||||||
|
I_Error("SV_PrepareSendLuaFile: Failed to convert file newlines\n");
|
||||||
|
|
||||||
|
// Use the temporary file instead
|
||||||
|
free(luafiletransfers->realfilename);
|
||||||
|
luafiletransfers->realfilename = binfilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
SV_PrepareSendLuaFileToNextNode();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Send a net command with 0 as its first byte to indicate the file couldn't be opened
|
||||||
|
UINT8 success = 0;
|
||||||
|
SendNetXCmd(XD_LUAFILE, &success, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SV_HandleLuaFileSent(UINT8 node)
|
void SV_HandleLuaFileSent(UINT8 node)
|
||||||
{
|
{
|
||||||
luafiletransfers->nodestatus[node] = LFTNS_SENT;
|
luafiletransfers->nodestatus[node] = LFTNS_SENT;
|
||||||
|
@ -560,6 +628,10 @@ void RemoveLuaFileTransfer(void)
|
||||||
{
|
{
|
||||||
luafiletransfer_t *filetransfer = luafiletransfers;
|
luafiletransfer_t *filetransfer = luafiletransfers;
|
||||||
|
|
||||||
|
// If it was a temporary file, delete it
|
||||||
|
if (server && !strchr(filetransfer->mode, 'b'))
|
||||||
|
remove(filetransfer->realfilename);
|
||||||
|
|
||||||
RemoveLuaFileCallback(filetransfer->id);
|
RemoveLuaFileCallback(filetransfer->id);
|
||||||
|
|
||||||
luafiletransfers = filetransfer->next;
|
luafiletransfers = filetransfer->next;
|
||||||
|
@ -596,20 +668,28 @@ void CL_PrepareDownloadLuaFile(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (luafiletransfers->ongoing)
|
||||||
|
{
|
||||||
|
waitingforluafilecommand = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Tell the server we are ready to receive the file
|
// Tell the server we are ready to receive the file
|
||||||
netbuffer->packettype = PT_ASKLUAFILE;
|
netbuffer->packettype = PT_ASKLUAFILE;
|
||||||
HSendPacket(servernode, true, 0, 0);
|
HSendPacket(servernode, true, 0, 0);
|
||||||
|
|
||||||
fileneedednum = 1;
|
fileneedednum = 1;
|
||||||
fileneeded[0].status = FS_REQUESTED;
|
fileneeded[0].status = FS_REQUESTED;
|
||||||
|
fileneeded[0].justdownloaded = false;
|
||||||
fileneeded[0].totalsize = UINT32_MAX;
|
fileneeded[0].totalsize = UINT32_MAX;
|
||||||
fileneeded[0].file = NULL;
|
fileneeded[0].file = NULL;
|
||||||
memset(fileneeded[0].md5sum, 0, 16);
|
memset(fileneeded[0].md5sum, 0, 16);
|
||||||
strcpy(fileneeded[0].filename, luafiletransfers->realfilename);
|
strcpy(fileneeded[0].filename, luafiletransfers->realfilename);
|
||||||
fileneeded[0].textmode = !strchr(luafiletransfers->mode, 'b');
|
|
||||||
|
|
||||||
// Make sure all directories in the file path exist
|
// Make sure all directories in the file path exist
|
||||||
MakePathDirs(fileneeded[0].filename);
|
MakePathDirs(fileneeded[0].filename);
|
||||||
|
|
||||||
|
luafiletransfers->ongoing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Number of files to send
|
// Number of files to send
|
||||||
|
@ -620,12 +700,12 @@ static INT32 filestosend = 0;
|
||||||
*
|
*
|
||||||
* \param node The node to send the file to
|
* \param node The node to send the file to
|
||||||
* \param filename The file to send
|
* \param filename The file to send
|
||||||
* \param fileid ???
|
* \param fileid The index of the file in the list of added files
|
||||||
* \sa SV_SendRam
|
* \sa AddRamToSendQueue
|
||||||
* \sa SV_SendLuaFile
|
* \sa AddLuaFileToSendQueue
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid)
|
static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid)
|
||||||
{
|
{
|
||||||
filetx_t **q; // A pointer to the "next" field of the last file in the list
|
filetx_t **q; // A pointer to the "next" field of the last file in the list
|
||||||
filetx_t *p; // The new file request
|
filetx_t *p; // The new file request
|
||||||
|
@ -643,7 +723,7 @@ static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid)
|
||||||
// Allocate a file request and append it to the file list
|
// Allocate a file request and append it to the file list
|
||||||
p = *q = (filetx_t *)malloc(sizeof (filetx_t));
|
p = *q = (filetx_t *)malloc(sizeof (filetx_t));
|
||||||
if (!p)
|
if (!p)
|
||||||
I_Error("SV_SendFile: No more memory\n");
|
I_Error("AddFileToSendQueue: No more memory\n");
|
||||||
|
|
||||||
// Initialise with zeros
|
// Initialise with zeros
|
||||||
memset(p, 0, sizeof (filetx_t));
|
memset(p, 0, sizeof (filetx_t));
|
||||||
|
@ -651,7 +731,7 @@ static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid)
|
||||||
// Allocate the file name
|
// Allocate the file name
|
||||||
p->id.filename = (char *)malloc(MAX_WADPATH);
|
p->id.filename = (char *)malloc(MAX_WADPATH);
|
||||||
if (!p->id.filename)
|
if (!p->id.filename)
|
||||||
I_Error("SV_SendFile: No more memory\n");
|
I_Error("AddFileToSendQueue: No more memory\n");
|
||||||
|
|
||||||
// Set the file name and get rid of the path
|
// Set the file name and get rid of the path
|
||||||
strlcpy(p->id.filename, filename, MAX_WADPATH);
|
strlcpy(p->id.filename, filename, MAX_WADPATH);
|
||||||
|
@ -711,12 +791,12 @@ static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid)
|
||||||
* \param data The memory block to send
|
* \param data The memory block to send
|
||||||
* \param size The size of the block in bytes
|
* \param size The size of the block in bytes
|
||||||
* \param freemethod How to free the block after it has been sent
|
* \param freemethod How to free the block after it has been sent
|
||||||
* \param fileid ???
|
* \param fileid The index of the file in the list of added files
|
||||||
* \sa SV_SendFile
|
* \sa AddFileToSendQueue
|
||||||
* \sa SV_SendLuaFile
|
* \sa AddLuaFileToSendQueue
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void SV_SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod, UINT8 fileid)
|
void AddRamToSendQueue(INT32 node, void *data, size_t size, freemethod_t freemethod, UINT8 fileid)
|
||||||
{
|
{
|
||||||
filetx_t **q; // A pointer to the "next" field of the last file in the list
|
filetx_t **q; // A pointer to the "next" field of the last file in the list
|
||||||
filetx_t *p; // The new file request
|
filetx_t *p; // The new file request
|
||||||
|
@ -729,7 +809,7 @@ void SV_SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod, UI
|
||||||
// Allocate a file request and append it to the file list
|
// Allocate a file request and append it to the file list
|
||||||
p = *q = (filetx_t *)malloc(sizeof (filetx_t));
|
p = *q = (filetx_t *)malloc(sizeof (filetx_t));
|
||||||
if (!p)
|
if (!p)
|
||||||
I_Error("SV_SendRam: No more memory\n");
|
I_Error("AddRamToSendQueue: No more memory\n");
|
||||||
|
|
||||||
// Initialise with zeros
|
// Initialise with zeros
|
||||||
memset(p, 0, sizeof (filetx_t));
|
memset(p, 0, sizeof (filetx_t));
|
||||||
|
@ -749,11 +829,11 @@ void SV_SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod, UI
|
||||||
*
|
*
|
||||||
* \param node The node to send the file to
|
* \param node The node to send the file to
|
||||||
* \param filename The file to send
|
* \param filename The file to send
|
||||||
* \sa SV_SendFile
|
* \sa AddFileToSendQueue
|
||||||
* \sa SV_SendRam
|
* \sa AddRamToSendQueue
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
boolean SV_SendLuaFile(INT32 node, const char *filename, boolean textmode)
|
boolean AddLuaFileToSendQueue(INT32 node, const char *filename)
|
||||||
{
|
{
|
||||||
filetx_t **q; // A pointer to the "next" field of the last file in the list
|
filetx_t **q; // A pointer to the "next" field of the last file in the list
|
||||||
filetx_t *p; // The new file request
|
filetx_t *p; // The new file request
|
||||||
|
@ -770,7 +850,7 @@ boolean SV_SendLuaFile(INT32 node, const char *filename, boolean textmode)
|
||||||
// Allocate a file request and append it to the file list
|
// Allocate a file request and append it to the file list
|
||||||
p = *q = (filetx_t *)malloc(sizeof (filetx_t));
|
p = *q = (filetx_t *)malloc(sizeof (filetx_t));
|
||||||
if (!p)
|
if (!p)
|
||||||
I_Error("SV_SendLuaFile: No more memory\n");
|
I_Error("AddLuaFileToSendQueue: No more memory\n");
|
||||||
|
|
||||||
// Initialise with zeros
|
// Initialise with zeros
|
||||||
memset(p, 0, sizeof (filetx_t));
|
memset(p, 0, sizeof (filetx_t));
|
||||||
|
@ -778,15 +858,12 @@ boolean SV_SendLuaFile(INT32 node, const char *filename, boolean textmode)
|
||||||
// Allocate the file name
|
// Allocate the file name
|
||||||
p->id.filename = (char *)malloc(MAX_WADPATH); // !!!
|
p->id.filename = (char *)malloc(MAX_WADPATH); // !!!
|
||||||
if (!p->id.filename)
|
if (!p->id.filename)
|
||||||
I_Error("SV_SendLuaFile: No more memory\n");
|
I_Error("AddLuaFileToSendQueue: No more memory\n");
|
||||||
|
|
||||||
// Set the file name and get rid of the path
|
// Set the file name and get rid of the path
|
||||||
strlcpy(p->id.filename, filename, MAX_WADPATH); // !!!
|
strlcpy(p->id.filename, filename, MAX_WADPATH); // !!!
|
||||||
//nameonly(p->id.filename);
|
//nameonly(p->id.filename);
|
||||||
|
|
||||||
// Open in text mode if required by the Lua script
|
|
||||||
p->textmode = textmode;
|
|
||||||
|
|
||||||
DEBFILE(va("Sending Lua file %s to %d\n", filename, node));
|
DEBFILE(va("Sending Lua file %s to %d\n", filename, node));
|
||||||
p->ram = SF_FILE; // It's a file, we need to close it and free its name once we're done sending it
|
p->ram = SF_FILE; // It's a file, we need to close it and free its name once we're done sending it
|
||||||
p->next = NULL; // End of list
|
p->next = NULL; // End of list
|
||||||
|
@ -804,7 +881,8 @@ static void SV_EndFileSend(INT32 node)
|
||||||
{
|
{
|
||||||
filetx_t *p = transfer[node].txlist;
|
filetx_t *p = transfer[node].txlist;
|
||||||
|
|
||||||
// Free the file request according to the freemethod parameter used with SV_SendFile/Ram
|
// Free the file request according to the freemethod
|
||||||
|
// parameter used with AddFileToSendQueue/AddRamToSendQueue
|
||||||
switch (p->ram)
|
switch (p->ram)
|
||||||
{
|
{
|
||||||
case SF_FILE: // It's a file, close it and free its filename
|
case SF_FILE: // It's a file, close it and free its filename
|
||||||
|
@ -829,43 +907,32 @@ static void SV_EndFileSend(INT32 node)
|
||||||
|
|
||||||
// Indicate that the transmission is over
|
// Indicate that the transmission is over
|
||||||
transfer[node].currentfile = NULL;
|
transfer[node].currentfile = NULL;
|
||||||
|
if (transfer[node].ackedfragments)
|
||||||
|
free(transfer[node].ackedfragments);
|
||||||
|
transfer[node].ackedfragments = NULL;
|
||||||
|
|
||||||
filestosend--;
|
filestosend--;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PACKETPERTIC net_bandwidth/(TICRATE*software_MAXPACKETLENGTH)
|
#define PACKETPERTIC net_bandwidth/(TICRATE*software_MAXPACKETLENGTH)
|
||||||
|
#define FILEFRAGMENTSIZE (software_MAXPACKETLENGTH - (FILETXHEADER + BASEPACKETSIZE))
|
||||||
|
|
||||||
/** Handles file transmission
|
/** Handles file transmission
|
||||||
*
|
|
||||||
* \todo Use an acknowledging method more adapted to file transmission
|
|
||||||
* The current download speed suffers from lack of ack packets,
|
|
||||||
* especially when the one downloading has high latency
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void SV_FileSendTicker(void)
|
void FileSendTicker(void)
|
||||||
{
|
{
|
||||||
static INT32 currentnode = 0;
|
static INT32 currentnode = 0;
|
||||||
filetx_pak *p;
|
filetx_pak *p;
|
||||||
size_t size;
|
size_t fragmentsize;
|
||||||
filetx_t *f;
|
filetx_t *f;
|
||||||
INT32 packetsent, ram, i, j;
|
INT32 packetsent, ram, i, j;
|
||||||
INT32 maxpacketsent;
|
|
||||||
|
|
||||||
if (!filestosend) // No file to send
|
if (!filestosend) // No file to send
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (cv_downloadspeed.value) // New (and experimental) behavior
|
if (cv_downloadspeed.value) // New behavior
|
||||||
{
|
|
||||||
packetsent = cv_downloadspeed.value;
|
packetsent = cv_downloadspeed.value;
|
||||||
// Don't send more packets than we have free acks
|
|
||||||
#ifndef NONET
|
|
||||||
maxpacketsent = Net_GetFreeAcks(false) - 5; // Let 5 extra acks just in case
|
|
||||||
#else
|
|
||||||
maxpacketsent = 1;
|
|
||||||
#endif
|
|
||||||
if (packetsent > maxpacketsent && maxpacketsent > 0) // Send at least one packet
|
|
||||||
packetsent = maxpacketsent;
|
|
||||||
}
|
|
||||||
else // Old behavior
|
else // Old behavior
|
||||||
{
|
{
|
||||||
packetsent = PACKETPERTIC;
|
packetsent = PACKETPERTIC;
|
||||||
|
@ -882,11 +949,12 @@ void SV_FileSendTicker(void)
|
||||||
i = (i+1) % MAXNETNODES, j++)
|
i = (i+1) % MAXNETNODES, j++)
|
||||||
{
|
{
|
||||||
if (transfer[i].txlist)
|
if (transfer[i].txlist)
|
||||||
goto found;
|
break;
|
||||||
}
|
}
|
||||||
// no transfer to do
|
// no transfer to do
|
||||||
|
if (j >= MAXNETNODES)
|
||||||
I_Error("filestosend=%d but no file to send found\n", filestosend);
|
I_Error("filestosend=%d but no file to send found\n", filestosend);
|
||||||
found:
|
|
||||||
currentnode = (i+1) % MAXNETNODES;
|
currentnode = (i+1) % MAXNETNODES;
|
||||||
f = transfer[i].txlist;
|
f = transfer[i].txlist;
|
||||||
ram = f->ram;
|
ram = f->ram;
|
||||||
|
@ -899,7 +967,7 @@ void SV_FileSendTicker(void)
|
||||||
long filesize;
|
long filesize;
|
||||||
|
|
||||||
transfer[i].currentfile =
|
transfer[i].currentfile =
|
||||||
fopen(f->id.filename, f->textmode ? "r" : "rb");
|
fopen(f->id.filename, "rb");
|
||||||
|
|
||||||
if (!transfer[i].currentfile)
|
if (!transfer[i].currentfile)
|
||||||
I_Error("File %s does not exist",
|
I_Error("File %s does not exist",
|
||||||
|
@ -920,57 +988,232 @@ void SV_FileSendTicker(void)
|
||||||
}
|
}
|
||||||
else // Sending RAM
|
else // Sending RAM
|
||||||
transfer[i].currentfile = (FILE *)1; // Set currentfile to a non-null value to indicate that it is open
|
transfer[i].currentfile = (FILE *)1; // Set currentfile to a non-null value to indicate that it is open
|
||||||
|
|
||||||
|
transfer[i].iteration = 1;
|
||||||
|
transfer[i].ackediteration = 0;
|
||||||
transfer[i].position = 0;
|
transfer[i].position = 0;
|
||||||
|
transfer[i].ackedsize = 0;
|
||||||
|
|
||||||
|
transfer[i].ackedfragments = calloc(f->size / FILEFRAGMENTSIZE + 1, sizeof(*transfer[i].ackedfragments));
|
||||||
|
if (!transfer[i].ackedfragments)
|
||||||
|
I_Error("FileSendTicker: No more memory\n");
|
||||||
|
|
||||||
|
transfer[i].dontsenduntil = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the client hasn't acknowledged any fragment from the previous iteration,
|
||||||
|
// it is most likely because their acks haven't had enough time to reach the server
|
||||||
|
// yet, due to latency. In that case, we wait a little to avoid useless resend.
|
||||||
|
if (I_GetTime() < transfer[i].dontsenduntil)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Find the first non-acknowledged fragment
|
||||||
|
while (transfer[i].ackedfragments[transfer[i].position / FILEFRAGMENTSIZE])
|
||||||
|
{
|
||||||
|
transfer[i].position += FILEFRAGMENTSIZE;
|
||||||
|
if (transfer[i].position >= f->size)
|
||||||
|
{
|
||||||
|
if (transfer[i].ackediteration < transfer[i].iteration)
|
||||||
|
transfer[i].dontsenduntil = I_GetTime() + TICRATE / 2;
|
||||||
|
|
||||||
|
transfer[i].position = 0;
|
||||||
|
transfer[i].iteration++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build a packet containing a file fragment
|
// Build a packet containing a file fragment
|
||||||
p = &netbuffer->u.filetxpak;
|
p = &netbuffer->u.filetxpak;
|
||||||
size = software_MAXPACKETLENGTH - (FILETXHEADER + BASEPACKETSIZE);
|
fragmentsize = FILEFRAGMENTSIZE;
|
||||||
if (f->size-transfer[i].position < size)
|
if (f->size-transfer[i].position < fragmentsize)
|
||||||
size = f->size-transfer[i].position;
|
fragmentsize = f->size-transfer[i].position;
|
||||||
if (ram)
|
if (ram)
|
||||||
M_Memcpy(p->data, &f->id.ram[transfer[i].position], size);
|
M_Memcpy(p->data, &f->id.ram[transfer[i].position], fragmentsize);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size_t n = fread(p->data, 1, size, transfer[i].currentfile);
|
fseek(transfer[i].currentfile, transfer[i].position, SEEK_SET);
|
||||||
if (n != size) // Either an error or Windows turning CR-LF into LF
|
|
||||||
{
|
if (fread(p->data, 1, fragmentsize, transfer[i].currentfile) != fragmentsize)
|
||||||
if (f->textmode && feof(transfer[i].currentfile))
|
I_Error("FileSendTicker: can't read %s byte on %s at %d because %s", sizeu1(fragmentsize), f->id.filename, transfer[i].position, M_FileError(transfer[i].currentfile));
|
||||||
size = n;
|
|
||||||
else if (fread(p->data, 1, size, transfer[i].currentfile) != size)
|
|
||||||
I_Error("SV_FileSendTicker: can't read %s byte on %s at %d because %s", sizeu1(size), f->id.filename, transfer[i].position, M_FileError(transfer[i].currentfile));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
p->iteration = transfer[i].iteration;
|
||||||
p->position = LONG(transfer[i].position);
|
p->position = LONG(transfer[i].position);
|
||||||
// Put flag so receiver knows the total size
|
|
||||||
if (transfer[i].position + size == f->size || (f->textmode && feof(transfer[i].currentfile)))
|
|
||||||
p->position |= LONG(0x80000000);
|
|
||||||
p->fileid = f->fileid;
|
p->fileid = f->fileid;
|
||||||
p->size = SHORT((UINT16)size);
|
p->filesize = LONG(f->size);
|
||||||
|
p->size = SHORT((UINT16)FILEFRAGMENTSIZE);
|
||||||
|
|
||||||
// Send the packet
|
// Send the packet
|
||||||
if (HSendPacket(i, true, 0, FILETXHEADER + size)) // Reliable SEND
|
if (HSendPacket(i, false, 0, FILETXHEADER + fragmentsize)) // Don't use the default acknowledgement system
|
||||||
{ // Success
|
{ // Success
|
||||||
transfer[i].position = (UINT32)(transfer[i].position + size);
|
transfer[i].position = (UINT32)(transfer[i].position + fragmentsize);
|
||||||
if (transfer[i].position == f->size || (f->textmode && feof(transfer[i].currentfile))) // Finish?
|
if (transfer[i].position >= f->size)
|
||||||
SV_EndFileSend(i);
|
{
|
||||||
|
if (transfer[i].ackediteration < transfer[i].iteration)
|
||||||
|
transfer[i].dontsenduntil = I_GetTime() + TICRATE / 2;
|
||||||
|
|
||||||
|
transfer[i].position = 0;
|
||||||
|
transfer[i].iteration++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Not sent for some odd reason, retry at next call
|
{ // Not sent for some odd reason, retry at next call
|
||||||
if (!ram)
|
|
||||||
fseek(transfer[i].currentfile,transfer[i].position, SEEK_SET);
|
|
||||||
// Exit the while (can't send this one so why should i send the next?)
|
// Exit the while (can't send this one so why should i send the next?)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Got_Filetxpak(void)
|
void PT_FileAck(void)
|
||||||
|
{
|
||||||
|
fileack_pak *packet = &netbuffer->u.fileack;
|
||||||
|
INT32 node = doomcom->remotenode;
|
||||||
|
filetran_t *trans = &transfer[node];
|
||||||
|
INT32 i, j;
|
||||||
|
|
||||||
|
// Wrong file id? Ignore it, it's probably a late packet
|
||||||
|
if (!(trans->txlist && packet->fileid == trans->txlist->fileid))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (packet->numsegments * sizeof(*packet->segments) != doomcom->datalength - BASEPACKETSIZE - sizeof(*packet))
|
||||||
|
{
|
||||||
|
Net_CloseConnection(node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet->iteration > trans->ackediteration)
|
||||||
|
{
|
||||||
|
trans->ackediteration = packet->iteration;
|
||||||
|
if (trans->ackediteration >= trans->iteration - 1)
|
||||||
|
trans->dontsenduntil = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < packet->numsegments; i++)
|
||||||
|
{
|
||||||
|
fileacksegment_t *segment = &packet->segments[i];
|
||||||
|
|
||||||
|
for (j = 0; j < 32; j++)
|
||||||
|
if (LONG(segment->acks) & (1 << j))
|
||||||
|
{
|
||||||
|
if (LONG(segment->start) * FILEFRAGMENTSIZE >= trans->txlist->size)
|
||||||
|
{
|
||||||
|
Net_CloseConnection(node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!trans->ackedfragments[LONG(segment->start) + j])
|
||||||
|
{
|
||||||
|
trans->ackedfragments[LONG(segment->start) + j] = true;
|
||||||
|
trans->ackedsize += FILEFRAGMENTSIZE;
|
||||||
|
|
||||||
|
// If the last missing fragment was acked, finish!
|
||||||
|
if (trans->ackedsize == trans->txlist->size)
|
||||||
|
{
|
||||||
|
SV_EndFileSend(node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PT_FileReceived(void)
|
||||||
|
{
|
||||||
|
filetx_t *trans = transfer[doomcom->remotenode].txlist;
|
||||||
|
|
||||||
|
if (trans && netbuffer->u.filereceived == trans->fileid)
|
||||||
|
SV_EndFileSend(doomcom->remotenode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SendAckPacket(fileack_pak *packet, UINT8 fileid)
|
||||||
|
{
|
||||||
|
size_t packetsize;
|
||||||
|
INT32 i;
|
||||||
|
|
||||||
|
packetsize = sizeof(*packet) + packet->numsegments * sizeof(*packet->segments);
|
||||||
|
|
||||||
|
// Finalise the packet
|
||||||
|
packet->fileid = fileid;
|
||||||
|
for (i = 0; i < packet->numsegments; i++)
|
||||||
|
{
|
||||||
|
packet->segments[i].start = LONG(packet->segments[i].start);
|
||||||
|
packet->segments[i].acks = LONG(packet->segments[i].acks);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the packet
|
||||||
|
netbuffer->packettype = PT_FILEACK;
|
||||||
|
M_Memcpy(&netbuffer->u.fileack, packet, packetsize);
|
||||||
|
HSendPacket(servernode, false, 0, packetsize);
|
||||||
|
|
||||||
|
// Clear the packet
|
||||||
|
memset(packet, 0, sizeof(*packet) + 512);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AddFragmentToAckPacket(fileack_pak *packet, UINT8 iteration, UINT32 fragmentpos, UINT8 fileid)
|
||||||
|
{
|
||||||
|
fileacksegment_t *segment = &packet->segments[packet->numsegments - 1];
|
||||||
|
|
||||||
|
packet->iteration = max(packet->iteration, iteration);
|
||||||
|
|
||||||
|
if (packet->numsegments == 0
|
||||||
|
|| fragmentpos < segment->start
|
||||||
|
|| fragmentpos - segment->start >= 32)
|
||||||
|
{
|
||||||
|
// If the packet becomes too big, send it
|
||||||
|
if ((packet->numsegments + 1) * sizeof(*segment) > 512)
|
||||||
|
SendAckPacket(packet, fileid);
|
||||||
|
|
||||||
|
packet->numsegments++;
|
||||||
|
segment = &packet->segments[packet->numsegments - 1];
|
||||||
|
segment->start = fragmentpos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the bit that represents the fragment
|
||||||
|
segment->acks |= 1 << (fragmentpos - segment->start);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileReceiveTicker(void)
|
||||||
|
{
|
||||||
|
INT32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < fileneedednum; i++)
|
||||||
|
{
|
||||||
|
fileneeded_t *file = &fileneeded[i];
|
||||||
|
|
||||||
|
if (file->status == FS_DOWNLOADING)
|
||||||
|
{
|
||||||
|
if (lasttimeackpacketsent - I_GetTime() > TICRATE / 2)
|
||||||
|
SendAckPacket(file->ackpacket, i);
|
||||||
|
|
||||||
|
// When resuming a tranfer, start with telling
|
||||||
|
// the server what parts we already received
|
||||||
|
if (file->ackresendposition != UINT32_MAX && file->status == FS_DOWNLOADING)
|
||||||
|
{
|
||||||
|
// Acknowledge ~70 MB/s, whichs means the client sends ~18 KB/s
|
||||||
|
INT32 j;
|
||||||
|
for (j = 0; j < 2048; j++)
|
||||||
|
{
|
||||||
|
if (file->receivedfragments[file->ackresendposition])
|
||||||
|
AddFragmentToAckPacket(file->ackpacket, file->iteration, file->ackresendposition, i);
|
||||||
|
|
||||||
|
file->ackresendposition++;
|
||||||
|
if (file->ackresendposition * file->fragmentsize >= file->totalsize)
|
||||||
|
{
|
||||||
|
file->ackresendposition = UINT32_MAX;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PT_FileFragment(void)
|
||||||
{
|
{
|
||||||
INT32 filenum = netbuffer->u.filetxpak.fileid;
|
INT32 filenum = netbuffer->u.filetxpak.fileid;
|
||||||
fileneeded_t *file = &fileneeded[filenum];
|
fileneeded_t *file = &fileneeded[filenum];
|
||||||
|
UINT32 fragmentpos = LONG(netbuffer->u.filetxpak.position);
|
||||||
|
UINT16 fragmentsize = SHORT(netbuffer->u.filetxpak.size);
|
||||||
|
UINT16 boundedfragmentsize = doomcom->datalength - BASEPACKETSIZE - sizeof(netbuffer->u.filetxpak);
|
||||||
char *filename;
|
char *filename;
|
||||||
static INT32 filetime = 0;
|
|
||||||
|
|
||||||
filename = va("%s", file->filename);
|
filename = va("%s", file->filename);
|
||||||
nameonly(filename);
|
nameonly(filename);
|
||||||
|
@ -995,40 +1238,89 @@ void Got_Filetxpak(void)
|
||||||
if (file->status == FS_REQUESTED)
|
if (file->status == FS_REQUESTED)
|
||||||
{
|
{
|
||||||
if (file->file)
|
if (file->file)
|
||||||
I_Error("Got_Filetxpak: already open file\n");
|
I_Error("PT_FileFragment: already open file\n");
|
||||||
file->file = fopen(filename, file->textmode ? "w" : "wb");
|
|
||||||
|
file->status = FS_DOWNLOADING;
|
||||||
|
file->fragmentsize = fragmentsize;
|
||||||
|
file->iteration = 0;
|
||||||
|
|
||||||
|
file->ackpacket = calloc(1, sizeof(*file->ackpacket) + 512);
|
||||||
|
if (!file->ackpacket)
|
||||||
|
I_Error("FileSendTicker: No more memory\n");
|
||||||
|
|
||||||
|
if (CL_CanResumeDownload(file))
|
||||||
|
{
|
||||||
|
file->file = fopen(filename, "r+b");
|
||||||
|
if (!file->file)
|
||||||
|
I_Error("Can't reopen file %s: %s", filename, strerror(errno));
|
||||||
|
CONS_Printf("\r%s...\n", filename);
|
||||||
|
|
||||||
|
CONS_Printf("Resuming download...\n");
|
||||||
|
file->currentsize = pauseddownload->currentsize;
|
||||||
|
file->receivedfragments = pauseddownload->receivedfragments;
|
||||||
|
file->ackresendposition = 0;
|
||||||
|
|
||||||
|
free(pauseddownload);
|
||||||
|
pauseddownload = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CL_AbortDownloadResume();
|
||||||
|
|
||||||
|
file->file = fopen(filename, "wb");
|
||||||
if (!file->file)
|
if (!file->file)
|
||||||
I_Error("Can't create file %s: %s", filename, strerror(errno));
|
I_Error("Can't create file %s: %s", filename, strerror(errno));
|
||||||
|
|
||||||
CONS_Printf("\r%s...\n",filename);
|
CONS_Printf("\r%s...\n",filename);
|
||||||
|
|
||||||
file->currentsize = 0;
|
file->currentsize = 0;
|
||||||
file->status = FS_DOWNLOADING;
|
file->totalsize = LONG(netbuffer->u.filetxpak.filesize);
|
||||||
|
file->ackresendposition = UINT32_MAX; // Only used for resumed downloads
|
||||||
|
|
||||||
|
file->receivedfragments = calloc(file->totalsize / fragmentsize + 1, sizeof(*file->receivedfragments));
|
||||||
|
if (!file->receivedfragments)
|
||||||
|
I_Error("FileSendTicker: No more memory\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
lasttimeackpacketsent = I_GetTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file->status == FS_DOWNLOADING)
|
if (file->status == FS_DOWNLOADING)
|
||||||
{
|
{
|
||||||
UINT32 pos = LONG(netbuffer->u.filetxpak.position);
|
if (fragmentpos >= file->totalsize)
|
||||||
UINT16 size = SHORT(netbuffer->u.filetxpak.size);
|
I_Error("Invalid file fragment\n");
|
||||||
// Use a special trick to know when the file is complete (not always used)
|
|
||||||
// WARNING: file fragments can arrive out of order so don't stop yet!
|
file->iteration = max(file->iteration, netbuffer->u.filetxpak.iteration);
|
||||||
if (pos & 0x80000000)
|
|
||||||
|
if (!file->receivedfragments[fragmentpos / fragmentsize]) // Not received yet
|
||||||
{
|
{
|
||||||
pos &= ~0x80000000;
|
file->receivedfragments[fragmentpos / fragmentsize] = true;
|
||||||
file->totalsize = pos + size;
|
|
||||||
}
|
// We can receive packets in the wrong order, anyway all OSes support gaped files
|
||||||
// We can receive packet in the wrong order, anyway all os support gaped file
|
fseek(file->file, fragmentpos, SEEK_SET);
|
||||||
fseek(file->file, pos, SEEK_SET);
|
if (fragmentsize && fwrite(netbuffer->u.filetxpak.data, boundedfragmentsize, 1, file->file) != 1)
|
||||||
if (size && fwrite(netbuffer->u.filetxpak.data,size,1,file->file) != 1)
|
|
||||||
I_Error("Can't write to %s: %s\n",filename, M_FileError(file->file));
|
I_Error("Can't write to %s: %s\n",filename, M_FileError(file->file));
|
||||||
file->currentsize += size;
|
file->currentsize += boundedfragmentsize;
|
||||||
|
|
||||||
|
AddFragmentToAckPacket(file->ackpacket, file->iteration, fragmentpos / fragmentsize, filenum);
|
||||||
|
|
||||||
// Finished?
|
// Finished?
|
||||||
if (file->currentsize == file->totalsize)
|
if (file->currentsize == file->totalsize)
|
||||||
{
|
{
|
||||||
fclose(file->file);
|
fclose(file->file);
|
||||||
file->file = NULL;
|
file->file = NULL;
|
||||||
|
free(file->receivedfragments);
|
||||||
|
free(file->ackpacket);
|
||||||
file->status = FS_FOUND;
|
file->status = FS_FOUND;
|
||||||
|
file->justdownloaded = true;
|
||||||
CONS_Printf(M_GetText("Downloading %s...(done)\n"),
|
CONS_Printf(M_GetText("Downloading %s...(done)\n"),
|
||||||
filename);
|
filename);
|
||||||
|
|
||||||
|
// Tell the server we have received the file
|
||||||
|
netbuffer->packettype = PT_FILERECEIVED;
|
||||||
|
netbuffer->u.filereceived = filenum;
|
||||||
|
HSendPacket(servernode, true, 0, 1);
|
||||||
|
|
||||||
if (luafiletransfers)
|
if (luafiletransfers)
|
||||||
{
|
{
|
||||||
// Tell the server we have received the file
|
// Tell the server we have received the file
|
||||||
|
@ -1037,7 +1329,14 @@ void Got_Filetxpak(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else // Already received
|
||||||
|
{
|
||||||
|
// If they are sending us the fragment again, it's probably because
|
||||||
|
// they missed our previous ack, so we must re-acknowledge it
|
||||||
|
AddFragmentToAckPacket(file->ackpacket, file->iteration, fragmentpos / fragmentsize, filenum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!file->justdownloaded)
|
||||||
{
|
{
|
||||||
const char *s;
|
const char *s;
|
||||||
switch(file->status)
|
switch(file->status)
|
||||||
|
@ -1060,12 +1359,6 @@ void Got_Filetxpak(void)
|
||||||
}
|
}
|
||||||
I_Error("Received a file not requested (file id: %d, file status: %s)\n", filenum, s);
|
I_Error("Received a file not requested (file id: %d, file status: %s)\n", filenum, s);
|
||||||
}
|
}
|
||||||
// Send ack back quickly
|
|
||||||
if (++filetime == 3)
|
|
||||||
{
|
|
||||||
Net_SendAcks(servernode);
|
|
||||||
filetime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CLIENT_LOADINGSCREEN
|
#ifdef CLIENT_LOADINGSCREEN
|
||||||
lastfilenum = filenum;
|
lastfilenum = filenum;
|
||||||
|
@ -1078,7 +1371,7 @@ void Got_Filetxpak(void)
|
||||||
* \return True if the node is downloading a file
|
* \return True if the node is downloading a file
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
boolean SV_SendingFile(INT32 node)
|
boolean SendingFile(INT32 node)
|
||||||
{
|
{
|
||||||
return transfer[node].txlist != NULL;
|
return transfer[node].txlist != NULL;
|
||||||
}
|
}
|
||||||
|
@ -1107,12 +1400,62 @@ void CloseNetFile(void)
|
||||||
if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].file)
|
if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].file)
|
||||||
{
|
{
|
||||||
fclose(fileneeded[i].file);
|
fclose(fileneeded[i].file);
|
||||||
|
free(fileneeded[i].ackpacket);
|
||||||
|
|
||||||
|
if (!pauseddownload && i != 0) // 0 is either srb2.srb or the gamestate...
|
||||||
|
{
|
||||||
|
// Don't remove the file, save it for later in case we resume the download
|
||||||
|
pauseddownload = malloc(sizeof(*pauseddownload));
|
||||||
|
if (!pauseddownload)
|
||||||
|
I_Error("CloseNetFile: No more memory\n");
|
||||||
|
|
||||||
|
strcpy(pauseddownload->filename, fileneeded[i].filename);
|
||||||
|
memcpy(pauseddownload->md5sum, fileneeded[i].md5sum, 16);
|
||||||
|
pauseddownload->currentsize = fileneeded[i].currentsize;
|
||||||
|
pauseddownload->receivedfragments = fileneeded[i].receivedfragments;
|
||||||
|
pauseddownload->fragmentsize = fileneeded[i].fragmentsize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
free(fileneeded[i].receivedfragments);
|
||||||
// File is not complete delete it
|
// File is not complete delete it
|
||||||
remove(fileneeded[i].filename);
|
remove(fileneeded[i].filename);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remove PT_FILEFRAGMENT from acknowledge list
|
void Command_Downloads_f(void)
|
||||||
Net_AbortPacketType(PT_FILEFRAGMENT);
|
{
|
||||||
|
INT32 node;
|
||||||
|
|
||||||
|
for (node = 0; node < MAXNETNODES; node++)
|
||||||
|
if (transfer[node].txlist
|
||||||
|
&& transfer[node].txlist->ram == SF_FILE) // Node is downloading a file?
|
||||||
|
{
|
||||||
|
const char *name = transfer[node].txlist->id.filename;
|
||||||
|
UINT32 position = transfer[node].ackedsize;
|
||||||
|
UINT32 size = transfer[node].txlist->size;
|
||||||
|
char ratecolor;
|
||||||
|
|
||||||
|
// Avoid division by zero errors
|
||||||
|
if (!size)
|
||||||
|
size = 1;
|
||||||
|
|
||||||
|
name = &name[strlen(name) - nameonlylength(name)];
|
||||||
|
switch (4 * (position - 1) / size)
|
||||||
|
{
|
||||||
|
case 0: ratecolor = '\x85'; break;
|
||||||
|
case 1: ratecolor = '\x87'; break;
|
||||||
|
case 2: ratecolor = '\x82'; break;
|
||||||
|
case 3: ratecolor = '\x83'; break;
|
||||||
|
default: ratecolor = '\x80';
|
||||||
|
}
|
||||||
|
|
||||||
|
CONS_Printf("%2d %c%s ", node, ratecolor, name); // Node and file name
|
||||||
|
CONS_Printf("\x80%uK\x84/\x80%uK ", position / 1024, size / 1024); // Progress in kB
|
||||||
|
CONS_Printf("\x80(%c%u%%\x80) ", ratecolor, (UINT32)(100.0 * position / size)); // Progress in %
|
||||||
|
CONS_Printf("%s\n", I_GetNodeAddress(node)); // Address and newline
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Functions cut and pasted from Doomatic :)
|
// Functions cut and pasted from Doomatic :)
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#define __D_NETFIL__
|
#define __D_NETFIL__
|
||||||
|
|
||||||
#include "d_net.h"
|
#include "d_net.h"
|
||||||
|
#include "d_clisrv.h"
|
||||||
#include "w_wad.h"
|
#include "w_wad.h"
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
@ -39,12 +40,18 @@ typedef struct
|
||||||
UINT8 willsend; // Is the server willing to send it?
|
UINT8 willsend; // Is the server willing to send it?
|
||||||
char filename[MAX_WADPATH];
|
char filename[MAX_WADPATH];
|
||||||
UINT8 md5sum[16];
|
UINT8 md5sum[16];
|
||||||
|
filestatus_t status; // The value returned by recsearch
|
||||||
|
boolean justdownloaded; // To prevent late fragments from causing an I_Error
|
||||||
|
|
||||||
// Used only for download
|
// Used only for download
|
||||||
FILE *file;
|
FILE *file;
|
||||||
|
boolean *receivedfragments;
|
||||||
|
UINT32 fragmentsize;
|
||||||
|
UINT8 iteration;
|
||||||
|
fileack_pak *ackpacket;
|
||||||
UINT32 currentsize;
|
UINT32 currentsize;
|
||||||
UINT32 totalsize;
|
UINT32 totalsize;
|
||||||
filestatus_t status; // The value returned by recsearch
|
UINT32 ackresendposition; // Used when resuming downloads
|
||||||
boolean textmode; // For files requested by Lua without the "b" option
|
|
||||||
} fileneeded_t;
|
} fileneeded_t;
|
||||||
|
|
||||||
extern INT32 fileneedednum;
|
extern INT32 fileneedednum;
|
||||||
|
@ -61,16 +68,20 @@ void CL_PrepareDownloadSaveGame(const char *tmpsave);
|
||||||
|
|
||||||
INT32 CL_CheckFiles(void);
|
INT32 CL_CheckFiles(void);
|
||||||
void CL_LoadServerFiles(void);
|
void CL_LoadServerFiles(void);
|
||||||
void SV_SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod,
|
void AddRamToSendQueue(INT32 node, void *data, size_t size, freemethod_t freemethod,
|
||||||
UINT8 fileid);
|
UINT8 fileid);
|
||||||
|
|
||||||
void SV_FileSendTicker(void);
|
void FileSendTicker(void);
|
||||||
void Got_Filetxpak(void);
|
void PT_FileAck(void);
|
||||||
boolean SV_SendingFile(INT32 node);
|
void PT_FileReceived(void);
|
||||||
|
boolean SendingFile(INT32 node);
|
||||||
|
|
||||||
|
void FileReceiveTicker(void);
|
||||||
|
void PT_FileFragment(void);
|
||||||
|
|
||||||
boolean CL_CheckDownloadable(void);
|
boolean CL_CheckDownloadable(void);
|
||||||
boolean CL_SendRequestFile(void);
|
boolean CL_SendFileRequest(void);
|
||||||
boolean Got_RequestFilePak(INT32 node);
|
boolean PT_RequestFile(INT32 node);
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
@ -86,18 +97,19 @@ typedef struct luafiletransfer_s
|
||||||
char *realfilename;
|
char *realfilename;
|
||||||
char mode[4]; // rb+/wb+/ab+ + null character
|
char mode[4]; // rb+/wb+/ab+ + null character
|
||||||
INT32 id; // Callback ID
|
INT32 id; // Callback ID
|
||||||
|
boolean ongoing;
|
||||||
luafiletransfernodestatus_t nodestatus[MAXNETNODES];
|
luafiletransfernodestatus_t nodestatus[MAXNETNODES];
|
||||||
struct luafiletransfer_s *next;
|
struct luafiletransfer_s *next;
|
||||||
} luafiletransfer_t;
|
} luafiletransfer_t;
|
||||||
|
|
||||||
extern luafiletransfer_t *luafiletransfers;
|
extern luafiletransfer_t *luafiletransfers;
|
||||||
extern boolean waitingforluafiletransfer;
|
extern boolean waitingforluafiletransfer;
|
||||||
|
extern boolean waitingforluafilecommand;
|
||||||
extern char luafiledir[256 + 16];
|
extern char luafiledir[256 + 16];
|
||||||
|
|
||||||
void AddLuaFileTransfer(const char *filename, const char *mode);
|
void AddLuaFileTransfer(const char *filename, const char *mode);
|
||||||
void SV_PrepareSendLuaFileToNextNode(void);
|
void SV_PrepareSendLuaFile(void);
|
||||||
boolean SV_SendLuaFile(INT32 node, const char *filename, boolean textmode);
|
boolean AddLuaFileToSendQueue(INT32 node, const char *filename);
|
||||||
void SV_PrepareSendLuaFile(const char *filename);
|
|
||||||
void SV_HandleLuaFileSent(UINT8 node);
|
void SV_HandleLuaFileSent(UINT8 node);
|
||||||
void RemoveLuaFileTransfer(void);
|
void RemoveLuaFileTransfer(void);
|
||||||
void RemoveAllLuaFileTransfers(void);
|
void RemoveAllLuaFileTransfers(void);
|
||||||
|
@ -110,6 +122,9 @@ void MakePathDirs(char *path);
|
||||||
|
|
||||||
void SV_AbortSendFiles(INT32 node);
|
void SV_AbortSendFiles(INT32 node);
|
||||||
void CloseNetFile(void);
|
void CloseNetFile(void);
|
||||||
|
void CL_AbortDownloadResume(void);
|
||||||
|
|
||||||
|
void Command_Downloads_f(void);
|
||||||
|
|
||||||
boolean fileexist(char *filename, time_t ptime);
|
boolean fileexist(char *filename, time_t ptime);
|
||||||
|
|
||||||
|
|
|
@ -239,7 +239,8 @@ typedef enum
|
||||||
CR_MACESPIN,
|
CR_MACESPIN,
|
||||||
CR_MINECART,
|
CR_MINECART,
|
||||||
CR_ROLLOUT,
|
CR_ROLLOUT,
|
||||||
CR_PTERABYTE
|
CR_PTERABYTE,
|
||||||
|
CR_DUSTDEVIL
|
||||||
} carrytype_t; // pw_carry
|
} carrytype_t; // pw_carry
|
||||||
|
|
||||||
// Player powers. (don't edit this comment)
|
// Player powers. (don't edit this comment)
|
||||||
|
@ -331,6 +332,9 @@ typedef struct player_s
|
||||||
|
|
||||||
angle_t viewrollangle;
|
angle_t viewrollangle;
|
||||||
|
|
||||||
|
INT16 angleturn;
|
||||||
|
INT16 oldrelangleturn;
|
||||||
|
|
||||||
// Mouse aiming, where the guy is looking at!
|
// Mouse aiming, where the guy is looking at!
|
||||||
// It is updated with cmd->aiming.
|
// It is updated with cmd->aiming.
|
||||||
angle_t aiming;
|
angle_t aiming;
|
||||||
|
@ -365,7 +369,7 @@ typedef struct player_s
|
||||||
UINT16 flashpal;
|
UINT16 flashpal;
|
||||||
|
|
||||||
// Player skin colorshift, 0-15 for which color to draw player.
|
// Player skin colorshift, 0-15 for which color to draw player.
|
||||||
UINT8 skincolor;
|
UINT16 skincolor;
|
||||||
|
|
||||||
INT32 skin;
|
INT32 skin;
|
||||||
UINT32 availabilities;
|
UINT32 availabilities;
|
||||||
|
|
276
src/dehacked.c
276
src/dehacked.c
|
@ -56,10 +56,12 @@ int vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
|
||||||
// The crazy word-reading stuff uses these.
|
// The crazy word-reading stuff uses these.
|
||||||
static char *FREE_STATES[NUMSTATEFREESLOTS];
|
static char *FREE_STATES[NUMSTATEFREESLOTS];
|
||||||
static char *FREE_MOBJS[NUMMOBJFREESLOTS];
|
static char *FREE_MOBJS[NUMMOBJFREESLOTS];
|
||||||
|
static char *FREE_SKINCOLORS[NUMCOLORFREESLOTS];
|
||||||
static UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway.
|
static UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway.
|
||||||
#define initfreeslots() {\
|
#define initfreeslots() {\
|
||||||
memset(FREE_STATES,0,sizeof(char *) * NUMSTATEFREESLOTS);\
|
memset(FREE_STATES,0,sizeof(char *) * NUMSTATEFREESLOTS);\
|
||||||
memset(FREE_MOBJS,0,sizeof(char *) * NUMMOBJFREESLOTS);\
|
memset(FREE_MOBJS,0,sizeof(char *) * NUMMOBJFREESLOTS);\
|
||||||
|
memset(FREE_SKINCOLORS,0,sizeof(char *) * NUMCOLORFREESLOTS);\
|
||||||
memset(used_spr,0,sizeof(UINT8) * ((NUMSPRITEFREESLOTS / 8) + 1));\
|
memset(used_spr,0,sizeof(UINT8) * ((NUMSPRITEFREESLOTS / 8) + 1));\
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +79,7 @@ static hudnum_t get_huditem(const char *word);
|
||||||
static menutype_t get_menutype(const char *word);
|
static menutype_t get_menutype(const char *word);
|
||||||
//static INT16 get_gametype(const char *word);
|
//static INT16 get_gametype(const char *word);
|
||||||
//static powertype_t get_power(const char *word);
|
//static powertype_t get_power(const char *word);
|
||||||
|
skincolornum_t get_skincolor(const char *word);
|
||||||
|
|
||||||
boolean deh_loaded = false;
|
boolean deh_loaded = false;
|
||||||
static int dbg_line;
|
static int dbg_line;
|
||||||
|
@ -392,7 +395,7 @@ static void readPlayer(MYFILE *f, INT32 num)
|
||||||
// It works down here, though.
|
// It works down here, though.
|
||||||
{
|
{
|
||||||
INT32 numline = 0;
|
INT32 numline = 0;
|
||||||
for (i = 0; i < MAXLINELEN-1; i++)
|
for (i = 0; (size_t)i < sizeof(description[num].notes)-1; i++)
|
||||||
{
|
{
|
||||||
if (numline < 20 && description[num].notes[i] == '\n')
|
if (numline < 20 && description[num].notes[i] == '\n')
|
||||||
numline++;
|
numline++;
|
||||||
|
@ -449,7 +452,7 @@ static void readPlayer(MYFILE *f, INT32 num)
|
||||||
else if (fastcmp(word, "OPPOSITECOLOR") || fastcmp(word, "OPPOSITECOLOUR"))
|
else if (fastcmp(word, "OPPOSITECOLOR") || fastcmp(word, "OPPOSITECOLOUR"))
|
||||||
{
|
{
|
||||||
SLOTFOUND
|
SLOTFOUND
|
||||||
description[num].oppositecolor = (UINT8)get_number(word2);
|
description[num].oppositecolor = (UINT16)get_number(word2);
|
||||||
}
|
}
|
||||||
else if (fastcmp(word, "NAMETAG") || fastcmp(word, "TAGNAME"))
|
else if (fastcmp(word, "NAMETAG") || fastcmp(word, "TAGNAME"))
|
||||||
{
|
{
|
||||||
|
@ -459,12 +462,12 @@ static void readPlayer(MYFILE *f, INT32 num)
|
||||||
else if (fastcmp(word, "TAGTEXTCOLOR") || fastcmp(word, "TAGTEXTCOLOUR"))
|
else if (fastcmp(word, "TAGTEXTCOLOR") || fastcmp(word, "TAGTEXTCOLOUR"))
|
||||||
{
|
{
|
||||||
SLOTFOUND
|
SLOTFOUND
|
||||||
description[num].tagtextcolor = (UINT8)get_number(word2);
|
description[num].tagtextcolor = (UINT16)get_number(word2);
|
||||||
}
|
}
|
||||||
else if (fastcmp(word, "TAGOUTLINECOLOR") || fastcmp(word, "TAGOUTLINECOLOUR"))
|
else if (fastcmp(word, "TAGOUTLINECOLOR") || fastcmp(word, "TAGOUTLINECOLOUR"))
|
||||||
{
|
{
|
||||||
SLOTFOUND
|
SLOTFOUND
|
||||||
description[num].tagoutlinecolor = (UINT8)get_number(word2);
|
description[num].tagoutlinecolor = (UINT16)get_number(word2);
|
||||||
}
|
}
|
||||||
else if (fastcmp(word, "STATUS"))
|
else if (fastcmp(word, "STATUS"))
|
||||||
{
|
{
|
||||||
|
@ -571,6 +574,16 @@ static void readfreeslots(MYFILE *f)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (fastcmp(type, "SKINCOLOR"))
|
||||||
|
{
|
||||||
|
for (i = 0; i < NUMCOLORFREESLOTS; i++)
|
||||||
|
if (!FREE_SKINCOLORS[i]) {
|
||||||
|
FREE_SKINCOLORS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
|
||||||
|
strcpy(FREE_SKINCOLORS[i],word);
|
||||||
|
M_AddMenuColor(numskincolors++);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (fastcmp(type, "SPR2"))
|
else if (fastcmp(type, "SPR2"))
|
||||||
{
|
{
|
||||||
// Search if we already have an SPR2 by that name...
|
// Search if we already have an SPR2 by that name...
|
||||||
|
@ -753,6 +766,84 @@ static void readthing(MYFILE *f, INT32 num)
|
||||||
Z_Free(s);
|
Z_Free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void readskincolor(MYFILE *f, INT32 num)
|
||||||
|
{
|
||||||
|
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
|
||||||
|
char *word = s;
|
||||||
|
char *word2;
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
|
Color_cons_t[num].value = num;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (myfgets(s, MAXLINELEN, f))
|
||||||
|
{
|
||||||
|
if (s[0] == '\n')
|
||||||
|
break;
|
||||||
|
|
||||||
|
// First remove trailing newline, if there is one
|
||||||
|
tmp = strchr(s, '\n');
|
||||||
|
if (tmp)
|
||||||
|
*tmp = '\0';
|
||||||
|
|
||||||
|
tmp = strchr(s, '#');
|
||||||
|
if (tmp)
|
||||||
|
*tmp = '\0';
|
||||||
|
if (s == tmp)
|
||||||
|
continue; // Skip comment lines, but don't break.
|
||||||
|
|
||||||
|
// Get the part before the " = "
|
||||||
|
tmp = strchr(s, '=');
|
||||||
|
if (tmp)
|
||||||
|
*(tmp-1) = '\0';
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
strupr(word);
|
||||||
|
|
||||||
|
// Now get the part after
|
||||||
|
word2 = tmp += 2;
|
||||||
|
|
||||||
|
if (fastcmp(word, "NAME"))
|
||||||
|
{
|
||||||
|
deh_strlcpy(skincolors[num].name, word2,
|
||||||
|
sizeof (skincolors[num].name), va("Skincolor %d: name", num));
|
||||||
|
}
|
||||||
|
else if (fastcmp(word, "RAMP"))
|
||||||
|
{
|
||||||
|
UINT8 i;
|
||||||
|
tmp = strtok(word2,",");
|
||||||
|
for (i = 0; i < COLORRAMPSIZE; i++) {
|
||||||
|
skincolors[num].ramp[i] = (UINT8)get_number(tmp);
|
||||||
|
if ((tmp = strtok(NULL,",")) == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (fastcmp(word, "INVCOLOR"))
|
||||||
|
{
|
||||||
|
skincolors[num].invcolor = (UINT16)get_number(word2);
|
||||||
|
}
|
||||||
|
else if (fastcmp(word, "INVSHADE"))
|
||||||
|
{
|
||||||
|
skincolors[num].invshade = get_number(word2)%COLORRAMPSIZE;
|
||||||
|
}
|
||||||
|
else if (fastcmp(word, "CHATCOLOR"))
|
||||||
|
{
|
||||||
|
skincolors[num].chatcolor = get_number(word2);
|
||||||
|
}
|
||||||
|
else if (fastcmp(word, "ACCESSIBLE"))
|
||||||
|
{
|
||||||
|
if (num > FIRSTSUPERCOLOR)
|
||||||
|
skincolors[num].accessible = (boolean)(atoi(word2) || word2[0] == 'T' || word2[0] == 'Y');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
deh_warning("Skincolor %d: unknown word '%s'", num, word);
|
||||||
|
}
|
||||||
|
} while (!myfeof(f)); // finish when the line is empty
|
||||||
|
|
||||||
|
Z_Free(s);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HWRENDER
|
#ifdef HWRENDER
|
||||||
static void readlight(MYFILE *f, INT32 num)
|
static void readlight(MYFILE *f, INT32 num)
|
||||||
{
|
{
|
||||||
|
@ -1174,7 +1265,7 @@ static void readgametype(MYFILE *f, char *gtname)
|
||||||
// It works down here, though.
|
// It works down here, though.
|
||||||
{
|
{
|
||||||
INT32 numline = 0;
|
INT32 numline = 0;
|
||||||
for (i = 0; i < MAXLINELEN-1; i++)
|
for (i = 0; (size_t)i < sizeof(gtdescription)-1; i++)
|
||||||
{
|
{
|
||||||
if (numline < 20 && gtdescription[i] == '\n')
|
if (numline < 20 && gtdescription[i] == '\n')
|
||||||
numline++;
|
numline++;
|
||||||
|
@ -1557,7 +1648,7 @@ static void readlevelheader(MYFILE *f, INT32 num)
|
||||||
}
|
}
|
||||||
else if (fastcmp(word, "ACT"))
|
else if (fastcmp(word, "ACT"))
|
||||||
{
|
{
|
||||||
if (i >= 0 && i < 20) // 0 for no act number, TTL1 through TTL19
|
if (i >= 0 && i <= 99) // 0 for no act number
|
||||||
mapheaderinfo[num-1]->actnum = (UINT8)i;
|
mapheaderinfo[num-1]->actnum = (UINT8)i;
|
||||||
else
|
else
|
||||||
deh_warning("Level header %d: invalid act number %d", num, i);
|
deh_warning("Level header %d: invalid act number %d", num, i);
|
||||||
|
@ -1578,6 +1669,22 @@ static void readlevelheader(MYFILE *f, INT32 num)
|
||||||
|
|
||||||
mapheaderinfo[num-1]->nextlevel = (INT16)i;
|
mapheaderinfo[num-1]->nextlevel = (INT16)i;
|
||||||
}
|
}
|
||||||
|
else if (fastcmp(word, "MARATHONNEXT"))
|
||||||
|
{
|
||||||
|
if (fastcmp(word2, "TITLE")) i = 1100;
|
||||||
|
else if (fastcmp(word2, "EVALUATION")) i = 1101;
|
||||||
|
else if (fastcmp(word2, "CREDITS")) i = 1102;
|
||||||
|
else if (fastcmp(word2, "ENDING")) i = 1103;
|
||||||
|
else
|
||||||
|
// Support using the actual map name,
|
||||||
|
// i.e., MarathonNext = AB, MarathonNext = FZ, etc.
|
||||||
|
|
||||||
|
// Convert to map number
|
||||||
|
if (word2[0] >= 'A' && word2[0] <= 'Z' && word2[2] == '\0')
|
||||||
|
i = M_MapNumber(word2[0], word2[1]);
|
||||||
|
|
||||||
|
mapheaderinfo[num-1]->marathonnext = (INT16)i;
|
||||||
|
}
|
||||||
else if (fastcmp(word, "TYPEOFLEVEL"))
|
else if (fastcmp(word, "TYPEOFLEVEL"))
|
||||||
{
|
{
|
||||||
if (i) // it's just a number
|
if (i) // it's just a number
|
||||||
|
@ -2813,7 +2920,7 @@ static actionpointer_t actionpointers[] =
|
||||||
{{A_ThrownRing}, "A_THROWNRING"},
|
{{A_ThrownRing}, "A_THROWNRING"},
|
||||||
{{A_SetSolidSteam}, "A_SETSOLIDSTEAM"},
|
{{A_SetSolidSteam}, "A_SETSOLIDSTEAM"},
|
||||||
{{A_UnsetSolidSteam}, "A_UNSETSOLIDSTEAM"},
|
{{A_UnsetSolidSteam}, "A_UNSETSOLIDSTEAM"},
|
||||||
{{A_SignSpin}, "S_SIGNSPIN"},
|
{{A_SignSpin}, "A_SIGNSPIN"},
|
||||||
{{A_SignPlayer}, "A_SIGNPLAYER"},
|
{{A_SignPlayer}, "A_SIGNPLAYER"},
|
||||||
{{A_OverlayThink}, "A_OVERLAYTHINK"},
|
{{A_OverlayThink}, "A_OVERLAYTHINK"},
|
||||||
{{A_JetChase}, "A_JETCHASE"},
|
{{A_JetChase}, "A_JETCHASE"},
|
||||||
|
@ -3033,6 +3140,7 @@ static actionpointer_t actionpointers[] =
|
||||||
{{A_DragonbomberSpawn}, "A_DRAGONBOMERSPAWN"},
|
{{A_DragonbomberSpawn}, "A_DRAGONBOMERSPAWN"},
|
||||||
{{A_DragonWing}, "A_DRAGONWING"},
|
{{A_DragonWing}, "A_DRAGONWING"},
|
||||||
{{A_DragonSegment}, "A_DRAGONSEGMENT"},
|
{{A_DragonSegment}, "A_DRAGONSEGMENT"},
|
||||||
|
{{A_ChangeHeight}, "A_CHANGEHEIGHT"},
|
||||||
{{NULL}, "NONE"},
|
{{NULL}, "NONE"},
|
||||||
|
|
||||||
// This NULL entry must be the last in the list
|
// This NULL entry must be the last in the list
|
||||||
|
@ -3919,7 +4027,20 @@ static void readmaincfg(MYFILE *f)
|
||||||
else
|
else
|
||||||
value = get_number(word2);
|
value = get_number(word2);
|
||||||
|
|
||||||
spstage_start = (INT16)value;
|
spstage_start = spmarathon_start = (INT16)value;
|
||||||
|
}
|
||||||
|
else if (fastcmp(word, "SPMARATHON_START"))
|
||||||
|
{
|
||||||
|
// Support using the actual map name,
|
||||||
|
// i.e., Level AB, Level FZ, etc.
|
||||||
|
|
||||||
|
// Convert to map number
|
||||||
|
if (word2[0] >= 'A' && word2[0] <= 'Z')
|
||||||
|
value = M_MapNumber(word2[0], word2[1]);
|
||||||
|
else
|
||||||
|
value = get_number(word2);
|
||||||
|
|
||||||
|
spmarathon_start = (INT16)value;
|
||||||
}
|
}
|
||||||
else if (fastcmp(word, "SSTAGE_START"))
|
else if (fastcmp(word, "SSTAGE_START"))
|
||||||
{
|
{
|
||||||
|
@ -3951,19 +4072,19 @@ static void readmaincfg(MYFILE *f)
|
||||||
}
|
}
|
||||||
else if (fastcmp(word, "REDTEAM"))
|
else if (fastcmp(word, "REDTEAM"))
|
||||||
{
|
{
|
||||||
skincolor_redteam = (UINT8)get_number(word2);
|
skincolor_redteam = (UINT16)get_number(word2);
|
||||||
}
|
}
|
||||||
else if (fastcmp(word, "BLUETEAM"))
|
else if (fastcmp(word, "BLUETEAM"))
|
||||||
{
|
{
|
||||||
skincolor_blueteam = (UINT8)get_number(word2);
|
skincolor_blueteam = (UINT16)get_number(word2);
|
||||||
}
|
}
|
||||||
else if (fastcmp(word, "REDRING"))
|
else if (fastcmp(word, "REDRING"))
|
||||||
{
|
{
|
||||||
skincolor_redring = (UINT8)get_number(word2);
|
skincolor_redring = (UINT16)get_number(word2);
|
||||||
}
|
}
|
||||||
else if (fastcmp(word, "BLUERING"))
|
else if (fastcmp(word, "BLUERING"))
|
||||||
{
|
{
|
||||||
skincolor_bluering = (UINT8)get_number(word2);
|
skincolor_bluering = (UINT16)get_number(word2);
|
||||||
}
|
}
|
||||||
else if (fastcmp(word, "INVULNTICS"))
|
else if (fastcmp(word, "INVULNTICS"))
|
||||||
{
|
{
|
||||||
|
@ -4013,6 +4134,17 @@ static void readmaincfg(MYFILE *f)
|
||||||
introtoplay = 128;
|
introtoplay = 128;
|
||||||
introchanged = true;
|
introchanged = true;
|
||||||
}
|
}
|
||||||
|
else if (fastcmp(word, "CREDITSCUTSCENE"))
|
||||||
|
{
|
||||||
|
creditscutscene = (UINT8)get_number(word2);
|
||||||
|
// range check, you morons.
|
||||||
|
if (creditscutscene > 128)
|
||||||
|
creditscutscene = 128;
|
||||||
|
}
|
||||||
|
else if (fastcmp(word, "USEBLACKROCK"))
|
||||||
|
{
|
||||||
|
useBlackRock = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y');
|
||||||
|
}
|
||||||
else if (fastcmp(word, "LOOPTITLE"))
|
else if (fastcmp(word, "LOOPTITLE"))
|
||||||
{
|
{
|
||||||
looptitle = (value || word2[0] == 'T' || word2[0] == 'Y');
|
looptitle = (value || word2[0] == 'T' || word2[0] == 'Y');
|
||||||
|
@ -4114,13 +4246,6 @@ static void readmaincfg(MYFILE *f)
|
||||||
titlescrollyspeed = get_number(word2);
|
titlescrollyspeed = get_number(word2);
|
||||||
titlechanged = true;
|
titlechanged = true;
|
||||||
}
|
}
|
||||||
else if (fastcmp(word, "CREDITSCUTSCENE"))
|
|
||||||
{
|
|
||||||
creditscutscene = (UINT8)get_number(word2);
|
|
||||||
// range check, you morons.
|
|
||||||
if (creditscutscene > 128)
|
|
||||||
creditscutscene = 128;
|
|
||||||
}
|
|
||||||
else if (fastcmp(word, "DISABLESPEEDADJUST"))
|
else if (fastcmp(word, "DISABLESPEEDADJUST"))
|
||||||
{
|
{
|
||||||
disableSpeedAdjust = (value || word2[0] == 'T' || word2[0] == 'Y');
|
disableSpeedAdjust = (value || word2[0] == 'T' || word2[0] == 'Y');
|
||||||
|
@ -4177,6 +4302,9 @@ static void readmaincfg(MYFILE *f)
|
||||||
// can't use sprintf since there is %u in savegamename
|
// can't use sprintf since there is %u in savegamename
|
||||||
strcatbf(savegamename, srb2home, PATHSEP);
|
strcatbf(savegamename, srb2home, PATHSEP);
|
||||||
|
|
||||||
|
strcpy(liveeventbackup, va("live%s.bkp", timeattackfolder));
|
||||||
|
strcatbf(liveeventbackup, srb2home, PATHSEP);
|
||||||
|
|
||||||
gamedataadded = true;
|
gamedataadded = true;
|
||||||
titlechanged = true;
|
titlechanged = true;
|
||||||
}
|
}
|
||||||
|
@ -4555,6 +4683,18 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
|
||||||
ignorelines(f);
|
ignorelines(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (fastcmp(word, "SKINCOLOR") || fastcmp(word, "COLOR"))
|
||||||
|
{
|
||||||
|
if (i == 0 && word2[0] != '0') // If word2 isn't a number
|
||||||
|
i = get_skincolor(word2); // find a skincolor by name
|
||||||
|
if (i < numskincolors && i >= (INT32)SKINCOLOR_FIRSTFREESLOT)
|
||||||
|
readskincolor(f, i);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
deh_warning("Skincolor %d out of range (%d - %d)", i, SKINCOLOR_FIRSTFREESLOT, numskincolors-1);
|
||||||
|
ignorelines(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (fastcmp(word, "SPRITE2"))
|
else if (fastcmp(word, "SPRITE2"))
|
||||||
{
|
{
|
||||||
if (i == 0 && word2[0] != '0') // If word2 isn't a number
|
if (i == 0 && word2[0] != '0') // If word2 isn't a number
|
||||||
|
@ -5616,10 +5756,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
||||||
"S_FANG_PINCHPATHINGSTART1",
|
"S_FANG_PINCHPATHINGSTART1",
|
||||||
"S_FANG_PINCHPATHINGSTART2",
|
"S_FANG_PINCHPATHINGSTART2",
|
||||||
"S_FANG_PINCHPATHING",
|
"S_FANG_PINCHPATHING",
|
||||||
|
"S_FANG_PINCHBOUNCE0",
|
||||||
"S_FANG_PINCHBOUNCE1",
|
"S_FANG_PINCHBOUNCE1",
|
||||||
"S_FANG_PINCHBOUNCE2",
|
"S_FANG_PINCHBOUNCE2",
|
||||||
"S_FANG_PINCHBOUNCE3",
|
"S_FANG_PINCHBOUNCE3",
|
||||||
"S_FANG_PINCHBOUNCE4",
|
"S_FANG_PINCHBOUNCE4",
|
||||||
|
"S_FANG_PINCHFALL0",
|
||||||
"S_FANG_PINCHFALL1",
|
"S_FANG_PINCHFALL1",
|
||||||
"S_FANG_PINCHFALL2",
|
"S_FANG_PINCHFALL2",
|
||||||
"S_FANG_PINCHSKID1",
|
"S_FANG_PINCHSKID1",
|
||||||
|
@ -6231,6 +6373,14 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
||||||
"S_ROCKET",
|
"S_ROCKET",
|
||||||
|
|
||||||
"S_LASER",
|
"S_LASER",
|
||||||
|
"S_LASER2",
|
||||||
|
"S_LASERFLASH",
|
||||||
|
|
||||||
|
"S_LASERFLAME1",
|
||||||
|
"S_LASERFLAME2",
|
||||||
|
"S_LASERFLAME3",
|
||||||
|
"S_LASERFLAME4",
|
||||||
|
"S_LASERFLAME5",
|
||||||
|
|
||||||
"S_TORPEDO",
|
"S_TORPEDO",
|
||||||
|
|
||||||
|
@ -8991,8 +9141,6 @@ static const char *const ML_LIST[16] = {
|
||||||
"TFERLINE"
|
"TFERLINE"
|
||||||
};
|
};
|
||||||
|
|
||||||
// This DOES differ from r_draw's Color_Names, unfortunately.
|
|
||||||
// Also includes Super colors
|
|
||||||
static const char *COLOR_ENUMS[] = {
|
static const char *COLOR_ENUMS[] = {
|
||||||
"NONE", // SKINCOLOR_NONE,
|
"NONE", // SKINCOLOR_NONE,
|
||||||
|
|
||||||
|
@ -9230,6 +9378,7 @@ static const char *const MENUTYPES_LIST[] = {
|
||||||
"MP_CONNECT",
|
"MP_CONNECT",
|
||||||
"MP_ROOM",
|
"MP_ROOM",
|
||||||
"MP_PLAYERSETUP", // MP_PlayerSetupDef shared with SPLITSCREEN if #defined NONET
|
"MP_PLAYERSETUP", // MP_PlayerSetupDef shared with SPLITSCREEN if #defined NONET
|
||||||
|
"MP_SERVER_OPTIONS",
|
||||||
|
|
||||||
// Options
|
// Options
|
||||||
"OP_MAIN",
|
"OP_MAIN",
|
||||||
|
@ -9239,18 +9388,20 @@ static const char *const MENUTYPES_LIST[] = {
|
||||||
"OP_P1MOUSE",
|
"OP_P1MOUSE",
|
||||||
"OP_P1JOYSTICK",
|
"OP_P1JOYSTICK",
|
||||||
"OP_JOYSTICKSET", // OP_JoystickSetDef shared with P2
|
"OP_JOYSTICKSET", // OP_JoystickSetDef shared with P2
|
||||||
|
"OP_P1CAMERA",
|
||||||
|
|
||||||
"OP_P2CONTROLS",
|
"OP_P2CONTROLS",
|
||||||
"OP_P2MOUSE",
|
"OP_P2MOUSE",
|
||||||
"OP_P2JOYSTICK",
|
"OP_P2JOYSTICK",
|
||||||
|
"OP_P2CAMERA",
|
||||||
|
|
||||||
|
"OP_PLAYSTYLE",
|
||||||
|
|
||||||
"OP_VIDEO",
|
"OP_VIDEO",
|
||||||
"OP_VIDEOMODE",
|
"OP_VIDEOMODE",
|
||||||
"OP_COLOR",
|
"OP_COLOR",
|
||||||
"OP_OPENGL",
|
"OP_OPENGL",
|
||||||
"OP_OPENGL_LIGHTING",
|
"OP_OPENGL_LIGHTING",
|
||||||
"OP_OPENGL_FOG",
|
|
||||||
"OP_OPENGL_COLOR",
|
|
||||||
|
|
||||||
"OP_SOUND",
|
"OP_SOUND",
|
||||||
|
|
||||||
|
@ -9423,7 +9574,8 @@ struct {
|
||||||
|
|
||||||
// SKINCOLOR_ doesn't include these..!
|
// SKINCOLOR_ doesn't include these..!
|
||||||
{"MAXSKINCOLORS",MAXSKINCOLORS},
|
{"MAXSKINCOLORS",MAXSKINCOLORS},
|
||||||
{"MAXTRANSLATIONS",MAXTRANSLATIONS},
|
{"FIRSTSUPERCOLOR",FIRSTSUPERCOLOR},
|
||||||
|
{"NUMSUPERCOLORS",NUMSUPERCOLORS},
|
||||||
|
|
||||||
// Precipitation
|
// Precipitation
|
||||||
{"PRECIP_NONE",PRECIP_NONE},
|
{"PRECIP_NONE",PRECIP_NONE},
|
||||||
|
@ -9474,6 +9626,7 @@ struct {
|
||||||
{"CR_MINECART",CR_MINECART},
|
{"CR_MINECART",CR_MINECART},
|
||||||
{"CR_ROLLOUT",CR_ROLLOUT},
|
{"CR_ROLLOUT",CR_ROLLOUT},
|
||||||
{"CR_PTERABYTE",CR_PTERABYTE},
|
{"CR_PTERABYTE",CR_PTERABYTE},
|
||||||
|
{"CR_DUSTDEVIL",CR_DUSTDEVIL},
|
||||||
|
|
||||||
// Ring weapons (ringweapons_t)
|
// Ring weapons (ringweapons_t)
|
||||||
// Useful for A_GiveWeapon
|
// Useful for A_GiveWeapon
|
||||||
|
@ -9881,6 +10034,12 @@ struct {
|
||||||
{"TC_BLINK",TC_BLINK},
|
{"TC_BLINK",TC_BLINK},
|
||||||
{"TC_DASHMODE",TC_DASHMODE},
|
{"TC_DASHMODE",TC_DASHMODE},
|
||||||
|
|
||||||
|
// marathonmode flags
|
||||||
|
{"MA_INIT",MA_INIT},
|
||||||
|
{"MA_RUNNING",MA_RUNNING},
|
||||||
|
{"MA_NOCUTSCENES",MA_NOCUTSCENES},
|
||||||
|
{"MA_INGAME",MA_INGAME},
|
||||||
|
|
||||||
{NULL,0}
|
{NULL,0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9924,6 +10083,26 @@ static statenum_t get_state(const char *word)
|
||||||
return S_NULL;
|
return S_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skincolornum_t get_skincolor(const char *word)
|
||||||
|
{ // Returns the value of SKINCOLOR_ enumerations
|
||||||
|
skincolornum_t i;
|
||||||
|
if (*word >= '0' && *word <= '9')
|
||||||
|
return atoi(word);
|
||||||
|
if (fastncmp("SKINCOLOR_",word,10))
|
||||||
|
word += 10; // take off the SKINCOLOR_
|
||||||
|
for (i = 0; i < NUMCOLORFREESLOTS; i++) {
|
||||||
|
if (!FREE_SKINCOLORS[i])
|
||||||
|
break;
|
||||||
|
if (fastcmp(word, FREE_SKINCOLORS[i]))
|
||||||
|
return SKINCOLOR_FIRSTFREESLOT+i;
|
||||||
|
}
|
||||||
|
for (i = 0; i < SKINCOLOR_FIRSTFREESLOT; i++)
|
||||||
|
if (fastcmp(word, COLOR_ENUMS[i]))
|
||||||
|
return i;
|
||||||
|
deh_warning("Couldn't find skincolor named 'SKINCOLOR_%s'",word);
|
||||||
|
return SKINCOLOR_GREEN;
|
||||||
|
}
|
||||||
|
|
||||||
static spritenum_t get_sprite(const char *word)
|
static spritenum_t get_sprite(const char *word)
|
||||||
{ // Returns the value of SPR_ enumerations
|
{ // Returns the value of SPR_ enumerations
|
||||||
spritenum_t i;
|
spritenum_t i;
|
||||||
|
@ -10218,6 +10397,11 @@ static fixed_t find_const(const char **rword)
|
||||||
free(word);
|
free(word);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
else if (fastncmp("SKINCOLOR_",word,10)) {
|
||||||
|
r = get_skincolor(word);
|
||||||
|
free(word);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
else if (fastncmp("MT_",word,3)) {
|
else if (fastncmp("MT_",word,3)) {
|
||||||
r = get_mobjtype(word);
|
r = get_mobjtype(word);
|
||||||
free(word);
|
free(word);
|
||||||
|
@ -10286,17 +10470,6 @@ static fixed_t find_const(const char **rword)
|
||||||
free(word);
|
free(word);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
else if (fastncmp("SKINCOLOR_",word,10)) {
|
|
||||||
char *p = word+10;
|
|
||||||
for (i = 0; i < MAXTRANSLATIONS; i++)
|
|
||||||
if (fastcmp(p, COLOR_ENUMS[i])) {
|
|
||||||
free(word);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
const_warning("color",word);
|
|
||||||
free(word);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (fastncmp("GRADE_",word,6))
|
else if (fastncmp("GRADE_",word,6))
|
||||||
{
|
{
|
||||||
char *p = word+6;
|
char *p = word+6;
|
||||||
|
@ -10357,8 +10530,8 @@ void DEH_Check(void)
|
||||||
if (dehpowers != NUMPOWERS)
|
if (dehpowers != NUMPOWERS)
|
||||||
I_Error("You forgot to update the Dehacked powers list, you dolt!\n(%d powers defined, versus %s in the Dehacked list)\n", NUMPOWERS, sizeu1(dehpowers));
|
I_Error("You forgot to update the Dehacked powers list, you dolt!\n(%d powers defined, versus %s in the Dehacked list)\n", NUMPOWERS, sizeu1(dehpowers));
|
||||||
|
|
||||||
if (dehcolors != MAXTRANSLATIONS)
|
if (dehcolors != SKINCOLOR_FIRSTFREESLOT)
|
||||||
I_Error("You forgot to update the Dehacked colors list, you dolt!\n(%d colors defined, versus %s in the Dehacked list)\n", MAXTRANSLATIONS, sizeu1(dehcolors));
|
I_Error("You forgot to update the Dehacked colors list, you dolt!\n(%d colors defined, versus %s in the Dehacked list)\n", SKINCOLOR_FIRSTFREESLOT, sizeu1(dehcolors));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10466,6 +10639,22 @@ static inline int lib_freeslot(lua_State *L)
|
||||||
if (i == NUMMOBJFREESLOTS)
|
if (i == NUMMOBJFREESLOTS)
|
||||||
CONS_Alert(CONS_WARNING, "Ran out of free MobjType slots!\n");
|
CONS_Alert(CONS_WARNING, "Ran out of free MobjType slots!\n");
|
||||||
}
|
}
|
||||||
|
else if (fastcmp(type, "SKINCOLOR"))
|
||||||
|
{
|
||||||
|
skincolornum_t i;
|
||||||
|
for (i = 0; i < NUMCOLORFREESLOTS; i++)
|
||||||
|
if (!FREE_SKINCOLORS[i]) {
|
||||||
|
CONS_Printf("Skincolor SKINCOLOR_%s allocated.\n",word);
|
||||||
|
FREE_SKINCOLORS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
|
||||||
|
strcpy(FREE_SKINCOLORS[i],word);
|
||||||
|
M_AddMenuColor(numskincolors++);
|
||||||
|
lua_pushinteger(L, i);
|
||||||
|
r++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == NUMCOLORFREESLOTS)
|
||||||
|
CONS_Alert(CONS_WARNING, "Ran out of free skincolor slots!\n");
|
||||||
|
}
|
||||||
else if (fastcmp(type, "SPR2"))
|
else if (fastcmp(type, "SPR2"))
|
||||||
{
|
{
|
||||||
// Search if we already have an SPR2 by that name...
|
// Search if we already have an SPR2 by that name...
|
||||||
|
@ -10797,13 +10986,20 @@ static inline int lib_getenum(lua_State *L)
|
||||||
}
|
}
|
||||||
else if (fastncmp("SKINCOLOR_",word,10)) {
|
else if (fastncmp("SKINCOLOR_",word,10)) {
|
||||||
p = word+10;
|
p = word+10;
|
||||||
for (i = 0; i < MAXTRANSLATIONS; i++)
|
for (i = 0; i < NUMCOLORFREESLOTS; i++) {
|
||||||
|
if (!FREE_SKINCOLORS[i])
|
||||||
|
break;
|
||||||
|
if (fastcmp(p, FREE_SKINCOLORS[i])) {
|
||||||
|
lua_pushinteger(L, SKINCOLOR_FIRSTFREESLOT+i);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < SKINCOLOR_FIRSTFREESLOT; i++)
|
||||||
if (fastcmp(p, COLOR_ENUMS[i])) {
|
if (fastcmp(p, COLOR_ENUMS[i])) {
|
||||||
lua_pushinteger(L, i);
|
lua_pushinteger(L, i);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (mathlib) return luaL_error(L, "skincolor '%s' could not be found.\n", word);
|
return luaL_error(L, "skincolor '%s' could not be found.\n", word);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
else if (fastncmp("GRADE_",word,6))
|
else if (fastncmp("GRADE_",word,6))
|
||||||
{
|
{
|
||||||
|
|
|
@ -61,6 +61,8 @@
|
||||||
|
|
||||||
#include "../console.h"
|
#include "../console.h"
|
||||||
|
|
||||||
|
#include "../m_menu.h"
|
||||||
|
|
||||||
#ifdef __GNUG__
|
#ifdef __GNUG__
|
||||||
#pragma implementation "../i_system.h"
|
#pragma implementation "../i_system.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -555,6 +557,7 @@ void I_Error (const char *error, ...)
|
||||||
if (demorecording)
|
if (demorecording)
|
||||||
G_CheckDemoStatus();
|
G_CheckDemoStatus();
|
||||||
D_QuitNetGame ();
|
D_QuitNetGame ();
|
||||||
|
M_FreePlayerSetupColors();
|
||||||
|
|
||||||
if (shutdowning)
|
if (shutdowning)
|
||||||
{
|
{
|
||||||
|
@ -622,6 +625,7 @@ void I_Quit (void)
|
||||||
if (demorecording)
|
if (demorecording)
|
||||||
G_CheckDemoStatus();
|
G_CheckDemoStatus();
|
||||||
D_QuitNetGame ();
|
D_QuitNetGame ();
|
||||||
|
M_FreePlayerSetupColors();
|
||||||
I_ShutdownMusic();
|
I_ShutdownMusic();
|
||||||
I_ShutdownSound();
|
I_ShutdownSound();
|
||||||
I_ShutdownCD();
|
I_ShutdownCD();
|
||||||
|
|
|
@ -90,6 +90,9 @@ static unsigned long nombre = NEWTICRATE*10;
|
||||||
static void I_BlitScreenVesa1(void); //see later
|
static void I_BlitScreenVesa1(void); //see later
|
||||||
void I_FinishUpdate (void)
|
void I_FinishUpdate (void)
|
||||||
{
|
{
|
||||||
|
if (marathonmode)
|
||||||
|
SCR_DisplayMarathonInfo();
|
||||||
|
|
||||||
// draw captions if enabled
|
// draw captions if enabled
|
||||||
if (cv_closedcaptioning.value)
|
if (cv_closedcaptioning.value)
|
||||||
SCR_ClosedCaptions();
|
SCR_ClosedCaptions();
|
||||||
|
|
|
@ -208,10 +208,6 @@ typedef struct
|
||||||
|
|
||||||
#define ZSHIFT 4
|
#define ZSHIFT 4
|
||||||
|
|
||||||
extern const UINT8 Color_Index[MAXTRANSLATIONS-1][16];
|
|
||||||
extern const char *Color_Names[MAXSKINCOLORS + NUMSUPERCOLORS];
|
|
||||||
extern const UINT8 Color_Opposite[MAXSKINCOLORS - 1][2];
|
|
||||||
|
|
||||||
#define NUMMAPS 1035
|
#define NUMMAPS 1035
|
||||||
|
|
||||||
#endif // __DOOMDATA__
|
#endif // __DOOMDATA__
|
||||||
|
|
|
@ -143,9 +143,9 @@ extern char logfilename[1024];
|
||||||
// we use comprevision and compbranch instead.
|
// we use comprevision and compbranch instead.
|
||||||
#else
|
#else
|
||||||
#define VERSION 202 // Game version
|
#define VERSION 202 // Game version
|
||||||
#define SUBVERSION 2 // more precise version number
|
#define SUBVERSION 4 // more precise version number
|
||||||
#define VERSIONSTRING "v2.2.2"
|
#define VERSIONSTRING "v2.2.4"
|
||||||
#define VERSIONSTRINGW L"v2.2.2"
|
#define VERSIONSTRINGW L"v2.2.4"
|
||||||
// Hey! If you change this, add 1 to the MODVERSION below!
|
// Hey! If you change this, add 1 to the MODVERSION below!
|
||||||
// Otherwise we can't force updates!
|
// Otherwise we can't force updates!
|
||||||
#endif
|
#endif
|
||||||
|
@ -213,7 +213,7 @@ extern char logfilename[1024];
|
||||||
// it's only for detection of the version the player is using so the MS can alert them of an update.
|
// it's only for detection of the version the player is using so the MS can alert them of an update.
|
||||||
// Only set it higher, not lower, obviously.
|
// Only set it higher, not lower, obviously.
|
||||||
// Note that we use this to help keep internal testing in check; this is why v2.2.0 is not version "1".
|
// Note that we use this to help keep internal testing in check; this is why v2.2.0 is not version "1".
|
||||||
#define MODVERSION 42
|
#define MODVERSION 44
|
||||||
|
|
||||||
// To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically.
|
// To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically.
|
||||||
// Increment MINOREXECVERSION whenever a config change is needed that does not correspond
|
// Increment MINOREXECVERSION whenever a config change is needed that does not correspond
|
||||||
|
@ -239,6 +239,20 @@ extern char logfilename[1024];
|
||||||
#define PLAYERSMASK (MAXPLAYERS-1)
|
#define PLAYERSMASK (MAXPLAYERS-1)
|
||||||
#define MAXPLAYERNAME 21
|
#define MAXPLAYERNAME 21
|
||||||
|
|
||||||
|
#define COLORRAMPSIZE 16
|
||||||
|
#define MAXCOLORNAME 32
|
||||||
|
#define NUMCOLORFREESLOTS 1024
|
||||||
|
|
||||||
|
typedef struct skincolor_s
|
||||||
|
{
|
||||||
|
char name[MAXCOLORNAME+1]; // Skincolor name
|
||||||
|
UINT8 ramp[COLORRAMPSIZE]; // Colormap ramp
|
||||||
|
UINT16 invcolor; // Signpost color
|
||||||
|
UINT8 invshade; // Signpost color shade
|
||||||
|
UINT16 chatcolor; // Chat color
|
||||||
|
boolean accessible; // Accessible by the color command + setup menu
|
||||||
|
} skincolor_t;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
SKINCOLOR_NONE = 0,
|
SKINCOLOR_NONE = 0,
|
||||||
|
@ -317,12 +331,10 @@ typedef enum
|
||||||
SKINCOLOR_RASPBERRY,
|
SKINCOLOR_RASPBERRY,
|
||||||
SKINCOLOR_ROSY,
|
SKINCOLOR_ROSY,
|
||||||
|
|
||||||
// SKINCOLOR_? - one left before we bump up against 0x39, which isn't a HARD limit anymore but would be excessive
|
FIRSTSUPERCOLOR,
|
||||||
|
|
||||||
MAXSKINCOLORS,
|
|
||||||
|
|
||||||
// Super special awesome Super flashing colors!
|
// Super special awesome Super flashing colors!
|
||||||
SKINCOLOR_SUPERSILVER1 = MAXSKINCOLORS,
|
SKINCOLOR_SUPERSILVER1 = FIRSTSUPERCOLOR,
|
||||||
SKINCOLOR_SUPERSILVER2,
|
SKINCOLOR_SUPERSILVER2,
|
||||||
SKINCOLOR_SUPERSILVER3,
|
SKINCOLOR_SUPERSILVER3,
|
||||||
SKINCOLOR_SUPERSILVER4,
|
SKINCOLOR_SUPERSILVER4,
|
||||||
|
@ -376,9 +388,17 @@ typedef enum
|
||||||
SKINCOLOR_SUPERTAN4,
|
SKINCOLOR_SUPERTAN4,
|
||||||
SKINCOLOR_SUPERTAN5,
|
SKINCOLOR_SUPERTAN5,
|
||||||
|
|
||||||
MAXTRANSLATIONS,
|
SKINCOLOR_FIRSTFREESLOT,
|
||||||
NUMSUPERCOLORS = ((MAXTRANSLATIONS - MAXSKINCOLORS)/5)
|
SKINCOLOR_LASTFREESLOT = SKINCOLOR_FIRSTFREESLOT + NUMCOLORFREESLOTS - 1,
|
||||||
} skincolors_t;
|
|
||||||
|
MAXSKINCOLORS,
|
||||||
|
|
||||||
|
NUMSUPERCOLORS = ((SKINCOLOR_FIRSTFREESLOT - FIRSTSUPERCOLOR)/5)
|
||||||
|
} skincolornum_t;
|
||||||
|
|
||||||
|
extern UINT16 numskincolors;
|
||||||
|
|
||||||
|
extern skincolor_t skincolors[MAXSKINCOLORS];
|
||||||
|
|
||||||
// State updates, number of tics / second.
|
// State updates, number of tics / second.
|
||||||
// NOTE: used to setup the timer rate, see I_StartupTimer().
|
// NOTE: used to setup the timer rate, see I_StartupTimer().
|
||||||
|
@ -458,7 +478,8 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...) FUNCDEBUG;
|
||||||
|
|
||||||
// Things that used to be in dstrings.h
|
// Things that used to be in dstrings.h
|
||||||
#define SAVEGAMENAME "srb2sav"
|
#define SAVEGAMENAME "srb2sav"
|
||||||
char savegamename[256];
|
extern char savegamename[256];
|
||||||
|
extern char liveeventbackup[256];
|
||||||
|
|
||||||
// m_misc.h
|
// m_misc.h
|
||||||
#ifdef GETTEXT
|
#ifdef GETTEXT
|
||||||
|
@ -565,10 +586,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
|
||||||
// None of these that are disabled in the normal build are guaranteed to work perfectly
|
// None of these that are disabled in the normal build are guaranteed to work perfectly
|
||||||
// Compile them at your own risk!
|
// Compile them at your own risk!
|
||||||
|
|
||||||
/// Backwards compatibility with SRB2CB's slope linedef types.
|
|
||||||
/// \note A simple shim that prints a warning.
|
|
||||||
#define ESLOPE_TYPESHIM
|
|
||||||
|
|
||||||
/// Allows the use of devmode in multiplayer. AKA "fishcake"
|
/// Allows the use of devmode in multiplayer. AKA "fishcake"
|
||||||
//#define NETGAME_DEVMODE
|
//#define NETGAME_DEVMODE
|
||||||
|
|
||||||
|
@ -622,17 +639,13 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
|
||||||
/// SRB2CB itself ported this from PrBoom+
|
/// SRB2CB itself ported this from PrBoom+
|
||||||
#define NEWCLIP
|
#define NEWCLIP
|
||||||
|
|
||||||
|
/// OpenGL shaders
|
||||||
|
#define GL_SHADERS
|
||||||
|
|
||||||
/// Handle touching sector specials in P_PlayerAfterThink instead of P_PlayerThink.
|
/// Handle touching sector specials in P_PlayerAfterThink instead of P_PlayerThink.
|
||||||
/// \note Required for proper collision with moving sloped surfaces that have sector specials on them.
|
/// \note Required for proper collision with moving sloped surfaces that have sector specials on them.
|
||||||
#define SECTORSPECIALSAFTERTHINK
|
#define SECTORSPECIALSAFTERTHINK
|
||||||
|
|
||||||
/// FINALLY some real clipping that doesn't make walls dissappear AND speeds the game up
|
|
||||||
/// (that was the original comment from SRB2CB, sadly it is a lie and actually slows game down)
|
|
||||||
/// on the bright side it fixes some weird issues with translucent walls
|
|
||||||
/// \note SRB2CB port.
|
|
||||||
/// SRB2CB itself ported this from PrBoom+
|
|
||||||
#define NEWCLIP
|
|
||||||
|
|
||||||
/// Cache patches in Lua in a way that renderer switching will work flawlessly.
|
/// Cache patches in Lua in a way that renderer switching will work flawlessly.
|
||||||
//#define LUA_PATCH_SAFETY
|
//#define LUA_PATCH_SAFETY
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,19 @@ extern INT32 curWeather;
|
||||||
extern INT32 cursaveslot;
|
extern INT32 cursaveslot;
|
||||||
//extern INT16 lastmapsaved;
|
//extern INT16 lastmapsaved;
|
||||||
extern INT16 lastmaploaded;
|
extern INT16 lastmaploaded;
|
||||||
extern boolean gamecomplete;
|
extern UINT8 gamecomplete;
|
||||||
|
|
||||||
|
// Extra abilities/settings for skins (combinable stuff)
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MA_RUNNING = 1, // In action
|
||||||
|
MA_INIT = 1<<1, // Initialisation
|
||||||
|
MA_NOCUTSCENES = 1<<2, // No cutscenes
|
||||||
|
MA_INGAME = 1<<3 // Timer ignores loads
|
||||||
|
} marathonmode_t;
|
||||||
|
|
||||||
|
extern marathonmode_t marathonmode;
|
||||||
|
extern tic_t marathontime;
|
||||||
|
|
||||||
#define maxgameovers 13
|
#define maxgameovers 13
|
||||||
extern UINT8 numgameovers;
|
extern UINT8 numgameovers;
|
||||||
|
@ -127,7 +139,7 @@ extern INT32 displayplayer;
|
||||||
extern INT32 secondarydisplayplayer; // for splitscreen
|
extern INT32 secondarydisplayplayer; // for splitscreen
|
||||||
|
|
||||||
// Maps of special importance
|
// Maps of special importance
|
||||||
extern INT16 spstage_start;
|
extern INT16 spstage_start, spmarathon_start;
|
||||||
extern INT16 sstage_start, sstage_end, smpstage_start, smpstage_end;
|
extern INT16 sstage_start, sstage_end, smpstage_start, smpstage_end;
|
||||||
|
|
||||||
extern INT16 titlemap;
|
extern INT16 titlemap;
|
||||||
|
@ -145,7 +157,7 @@ extern INT32 tutorialanalog; // store cv_analog[0] user value
|
||||||
extern boolean looptitle;
|
extern boolean looptitle;
|
||||||
|
|
||||||
// CTF colors.
|
// CTF colors.
|
||||||
extern UINT8 skincolor_redteam, skincolor_blueteam, skincolor_redring, skincolor_bluering;
|
extern UINT16 skincolor_redteam, skincolor_blueteam, skincolor_redring, skincolor_bluering;
|
||||||
|
|
||||||
extern tic_t countdowntimer;
|
extern tic_t countdowntimer;
|
||||||
extern boolean countdowntimeup;
|
extern boolean countdowntimeup;
|
||||||
|
@ -289,6 +301,7 @@ typedef struct
|
||||||
UINT8 actnum; ///< Act number or 0 for none.
|
UINT8 actnum; ///< Act number or 0 for none.
|
||||||
UINT32 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.
|
||||||
|
INT16 marathonnext; ///< See nextlevel, but for Marathon mode. Necessary to support hub worlds ala SUGOI.
|
||||||
char keywords[33]; ///< Keywords separated by space to search for. 32 characters.
|
char keywords[33]; ///< Keywords separated by space to search for. 32 characters.
|
||||||
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.
|
||||||
|
@ -545,7 +558,7 @@ extern recorddata_t *mainrecords[NUMMAPS];
|
||||||
extern UINT8 mapvisited[NUMMAPS];
|
extern UINT8 mapvisited[NUMMAPS];
|
||||||
|
|
||||||
// Temporary holding place for nights data for the current map
|
// Temporary holding place for nights data for the current map
|
||||||
nightsdata_t ntemprecords;
|
extern nightsdata_t ntemprecords;
|
||||||
|
|
||||||
extern UINT32 token; ///< Number of tokens collected in a level
|
extern UINT32 token; ///< Number of tokens collected in a level
|
||||||
extern UINT32 tokenlist; ///< List of tokens collected
|
extern UINT32 tokenlist; ///< List of tokens collected
|
||||||
|
@ -575,11 +588,12 @@ extern UINT16 nightslinktics;
|
||||||
|
|
||||||
extern UINT8 introtoplay;
|
extern UINT8 introtoplay;
|
||||||
extern UINT8 creditscutscene;
|
extern UINT8 creditscutscene;
|
||||||
|
extern UINT8 useBlackRock;
|
||||||
|
|
||||||
extern UINT8 use1upSound;
|
extern UINT8 use1upSound;
|
||||||
extern UINT8 maxXtraLife; // Max extra lives from rings
|
extern UINT8 maxXtraLife; // Max extra lives from rings
|
||||||
extern UINT8 useContinues;
|
extern UINT8 useContinues;
|
||||||
#define continuesInSession (!multiplayer && (useContinues || ultimatemode || !(cursaveslot > 0)))
|
#define continuesInSession (!multiplayer && (ultimatemode || (useContinues && !marathonmode) || (!modeattacking && !(cursaveslot > 0))))
|
||||||
|
|
||||||
extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations
|
extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations
|
||||||
|
|
||||||
|
@ -620,6 +634,19 @@ extern mapthing_t *playerstarts[MAXPLAYERS]; // Cooperative
|
||||||
extern mapthing_t *bluectfstarts[MAXPLAYERS]; // CTF
|
extern mapthing_t *bluectfstarts[MAXPLAYERS]; // CTF
|
||||||
extern mapthing_t *redctfstarts[MAXPLAYERS]; // CTF
|
extern mapthing_t *redctfstarts[MAXPLAYERS]; // CTF
|
||||||
|
|
||||||
|
#define WAYPOINTSEQUENCESIZE 256
|
||||||
|
#define NUMWAYPOINTSEQUENCES 256
|
||||||
|
extern mobj_t *waypoints[NUMWAYPOINTSEQUENCES][WAYPOINTSEQUENCESIZE];
|
||||||
|
extern UINT16 numwaypoints[NUMWAYPOINTSEQUENCES];
|
||||||
|
|
||||||
|
void P_AddWaypoint(UINT8 sequence, UINT8 id, mobj_t *waypoint);
|
||||||
|
mobj_t *P_GetFirstWaypoint(UINT8 sequence);
|
||||||
|
mobj_t *P_GetLastWaypoint(UINT8 sequence);
|
||||||
|
mobj_t *P_GetPreviousWaypoint(mobj_t *current, boolean wrap);
|
||||||
|
mobj_t *P_GetNextWaypoint(mobj_t *current, boolean wrap);
|
||||||
|
mobj_t *P_GetClosestWaypoint(UINT8 sequence, mobj_t *mo);
|
||||||
|
boolean P_IsDegeneratedWaypointSequence(UINT8 sequence);
|
||||||
|
|
||||||
// =====================================
|
// =====================================
|
||||||
// Internal parameters, used for engine.
|
// Internal parameters, used for engine.
|
||||||
// =====================================
|
// =====================================
|
||||||
|
|
|
@ -16,6 +16,11 @@ tic_t I_GetTime(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int I_GetTimeMicros(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void I_Sleep(void){}
|
void I_Sleep(void){}
|
||||||
|
|
||||||
void I_GetEvent(void){}
|
void I_GetEvent(void){}
|
||||||
|
|
|
@ -1330,10 +1330,6 @@ void F_StartCredits(void)
|
||||||
// Just in case they're open ... somehow
|
// Just in case they're open ... somehow
|
||||||
M_ClearMenus(true);
|
M_ClearMenus(true);
|
||||||
|
|
||||||
// Save the second we enter the credits
|
|
||||||
if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && cursaveslot > 0)
|
|
||||||
G_SaveGame((UINT32)cursaveslot);
|
|
||||||
|
|
||||||
if (creditscutscene)
|
if (creditscutscene)
|
||||||
{
|
{
|
||||||
F_StartCustomCutscene(creditscutscene - 1, false, false);
|
F_StartCustomCutscene(creditscutscene - 1, false, false);
|
||||||
|
@ -1529,12 +1525,6 @@ void F_StartGameEvaluation(void)
|
||||||
// Just in case they're open ... somehow
|
// Just in case they're open ... somehow
|
||||||
M_ClearMenus(true);
|
M_ClearMenus(true);
|
||||||
|
|
||||||
// Save the second we enter the evaluation
|
|
||||||
// We need to do this again! Remember, it's possible a mod designed skipped
|
|
||||||
// the credits sequence!
|
|
||||||
if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && cursaveslot > 0)
|
|
||||||
G_SaveGame((UINT32)cursaveslot);
|
|
||||||
|
|
||||||
goodending = (ALL7EMERALDS(emeralds));
|
goodending = (ALL7EMERALDS(emeralds));
|
||||||
|
|
||||||
gameaction = ga_nothing;
|
gameaction = ga_nothing;
|
||||||
|
@ -1551,13 +1541,20 @@ void F_GameEvaluationDrawer(void)
|
||||||
angle_t fa;
|
angle_t fa;
|
||||||
INT32 eemeralds_cur;
|
INT32 eemeralds_cur;
|
||||||
char patchname[7] = "CEMGx0";
|
char patchname[7] = "CEMGx0";
|
||||||
const char* endingtext = (goodending ? "CONGRATULATIONS!" : "TRY AGAIN...");
|
const char* endingtext;
|
||||||
|
|
||||||
|
if (marathonmode)
|
||||||
|
endingtext = "THANKS FOR THE RUN!";
|
||||||
|
else if (goodending)
|
||||||
|
endingtext = "CONGRATULATIONS!";
|
||||||
|
else
|
||||||
|
endingtext = "TRY AGAIN...";
|
||||||
|
|
||||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||||
|
|
||||||
// Draw all the good crap here.
|
// Draw all the good crap here.
|
||||||
|
|
||||||
if (finalecount > 0)
|
if (finalecount > 0 && useBlackRock)
|
||||||
{
|
{
|
||||||
INT32 scale = FRACUNIT;
|
INT32 scale = FRACUNIT;
|
||||||
patch_t *rockpat;
|
patch_t *rockpat;
|
||||||
|
@ -1684,7 +1681,9 @@ void F_GameEvaluationTicker(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!goodending)
|
if (!useBlackRock)
|
||||||
|
;
|
||||||
|
else if (!goodending)
|
||||||
{
|
{
|
||||||
if (sparklloop)
|
if (sparklloop)
|
||||||
sparklloop--;
|
sparklloop--;
|
||||||
|
@ -1841,10 +1840,6 @@ void F_StartEnding(void)
|
||||||
// Just in case they're open ... somehow
|
// Just in case they're open ... somehow
|
||||||
M_ClearMenus(true);
|
M_ClearMenus(true);
|
||||||
|
|
||||||
// Save before the credits sequence.
|
|
||||||
if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && cursaveslot > 0)
|
|
||||||
G_SaveGame((UINT32)cursaveslot);
|
|
||||||
|
|
||||||
gameaction = ga_nothing;
|
gameaction = ga_nothing;
|
||||||
paused = false;
|
paused = false;
|
||||||
CON_ToggleOff();
|
CON_ToggleOff();
|
||||||
|
@ -2185,7 +2180,7 @@ void F_EndingDrawer(void)
|
||||||
for (i = 0; i < 7; ++i)
|
for (i = 0; i < 7; ++i)
|
||||||
{
|
{
|
||||||
UINT8* colormap;
|
UINT8* colormap;
|
||||||
skincolors_t col = SKINCOLOR_GREEN;
|
skincolornum_t col = SKINCOLOR_GREEN;
|
||||||
switch (i)
|
switch (i)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -3959,6 +3954,7 @@ static void F_AdvanceToNextScene(void)
|
||||||
animtimer = pictime = cutscenes[cutnum]->scene[scenenum].picduration[picnum];
|
animtimer = pictime = cutscenes[cutnum]->scene[scenenum].picduration[picnum];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See also G_AfterIntermission, the only other place which handles intra-map/ending transitions
|
||||||
void F_EndCutScene(void)
|
void F_EndCutScene(void)
|
||||||
{
|
{
|
||||||
cutsceneover = true; // do this first, just in case G_EndGame or something wants to turn it back false later
|
cutsceneover = true; // do this first, just in case G_EndGame or something wants to turn it back false later
|
||||||
|
|
|
@ -162,7 +162,9 @@ extern wipestyleflags_t wipestyleflags;
|
||||||
// Even my function names are borderline
|
// Even my function names are borderline
|
||||||
boolean F_ShouldColormapFade(void);
|
boolean F_ShouldColormapFade(void);
|
||||||
boolean F_TryColormapFade(UINT8 wipecolor);
|
boolean F_TryColormapFade(UINT8 wipecolor);
|
||||||
|
#ifndef NOWIPE
|
||||||
void F_DecideWipeStyle(void);
|
void F_DecideWipeStyle(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FADECOLORMAPDIV 8
|
#define FADECOLORMAPDIV 8
|
||||||
#define FADECOLORMAPROWS (256/FADECOLORMAPDIV)
|
#define FADECOLORMAPROWS (256/FADECOLORMAPDIV)
|
||||||
|
|
|
@ -464,6 +464,7 @@ void F_WipeEndScreen(void)
|
||||||
*/
|
*/
|
||||||
boolean F_ShouldColormapFade(void)
|
boolean F_ShouldColormapFade(void)
|
||||||
{
|
{
|
||||||
|
#ifndef NOWIPE
|
||||||
if ((wipestyleflags & (WSF_FADEIN|WSF_FADEOUT)) // only if one of those wipestyleflags are actually set
|
if ((wipestyleflags & (WSF_FADEIN|WSF_FADEOUT)) // only if one of those wipestyleflags are actually set
|
||||||
&& !(wipestyleflags & WSF_CROSSFADE)) // and if not crossfading
|
&& !(wipestyleflags & WSF_CROSSFADE)) // and if not crossfading
|
||||||
{
|
{
|
||||||
|
@ -479,11 +480,13 @@ boolean F_ShouldColormapFade(void)
|
||||||
// Menus
|
// Menus
|
||||||
|| gamestate == GS_TIMEATTACK);
|
|| gamestate == GS_TIMEATTACK);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Decides what wipe style to use.
|
/** Decides what wipe style to use.
|
||||||
*/
|
*/
|
||||||
|
#ifndef NOWIPE
|
||||||
void F_DecideWipeStyle(void)
|
void F_DecideWipeStyle(void)
|
||||||
{
|
{
|
||||||
// Set default wipe style
|
// Set default wipe style
|
||||||
|
@ -493,6 +496,7 @@ void F_DecideWipeStyle(void)
|
||||||
if (F_ShouldColormapFade())
|
if (F_ShouldColormapFade())
|
||||||
wipestyle = WIPESTYLE_COLORMAP;
|
wipestyle = WIPESTYLE_COLORMAP;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Attempt to run a colormap fade,
|
/** Attempt to run a colormap fade,
|
||||||
provided all the conditionals were properly met.
|
provided all the conditionals were properly met.
|
||||||
|
@ -501,6 +505,7 @@ void F_DecideWipeStyle(void)
|
||||||
*/
|
*/
|
||||||
boolean F_TryColormapFade(UINT8 wipecolor)
|
boolean F_TryColormapFade(UINT8 wipecolor)
|
||||||
{
|
{
|
||||||
|
#ifndef NOWIPE
|
||||||
if (F_ShouldColormapFade())
|
if (F_ShouldColormapFade())
|
||||||
{
|
{
|
||||||
#ifdef HWRENDER
|
#ifdef HWRENDER
|
||||||
|
@ -510,6 +515,7 @@ boolean F_TryColormapFade(UINT8 wipecolor)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
F_WipeColorFill(wipecolor);
|
F_WipeColorFill(wipecolor);
|
||||||
return false;
|
return false;
|
||||||
|
@ -608,6 +614,7 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
|
||||||
tic_t F_GetWipeLength(UINT8 wipetype)
|
tic_t F_GetWipeLength(UINT8 wipetype)
|
||||||
{
|
{
|
||||||
#ifdef NOWIPE
|
#ifdef NOWIPE
|
||||||
|
(void)wipetype;
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
static char lumpname[10] = "FADEmmss";
|
static char lumpname[10] = "FADEmmss";
|
||||||
|
@ -634,6 +641,7 @@ tic_t F_GetWipeLength(UINT8 wipetype)
|
||||||
boolean F_WipeExists(UINT8 wipetype)
|
boolean F_WipeExists(UINT8 wipetype)
|
||||||
{
|
{
|
||||||
#ifdef NOWIPE
|
#ifdef NOWIPE
|
||||||
|
(void)wipetype;
|
||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
static char lumpname[10] = "FADEmm00";
|
static char lumpname[10] = "FADEmm00";
|
||||||
|
|
229
src/g_demo.c
229
src/g_demo.c
|
@ -68,7 +68,7 @@ static struct {
|
||||||
UINT8 flags; // EZT flags
|
UINT8 flags; // EZT flags
|
||||||
|
|
||||||
// EZT_COLOR
|
// EZT_COLOR
|
||||||
UINT8 color, lastcolor;
|
UINT16 color, lastcolor;
|
||||||
|
|
||||||
// EZT_SCALE
|
// EZT_SCALE
|
||||||
fixed_t scale, lastscale;
|
fixed_t scale, lastscale;
|
||||||
|
@ -82,7 +82,8 @@ static struct {
|
||||||
// There is no conflict here.
|
// There is no conflict here.
|
||||||
typedef struct demoghost {
|
typedef struct demoghost {
|
||||||
UINT8 checksum[16];
|
UINT8 checksum[16];
|
||||||
UINT8 *buffer, *p, color, fadein;
|
UINT8 *buffer, *p, fadein;
|
||||||
|
UINT16 color;
|
||||||
UINT16 version;
|
UINT16 version;
|
||||||
mobj_t oldmo, *mo;
|
mobj_t oldmo, *mo;
|
||||||
struct demoghost *next;
|
struct demoghost *next;
|
||||||
|
@ -93,7 +94,7 @@ demoghost *ghosts = NULL;
|
||||||
// DEMO RECORDING
|
// DEMO RECORDING
|
||||||
//
|
//
|
||||||
|
|
||||||
#define DEMOVERSION 0x000c
|
#define DEMOVERSION 0x000d
|
||||||
#define DEMOHEADER "\xF0" "SRB2Replay" "\x0F"
|
#define DEMOHEADER "\xF0" "SRB2Replay" "\x0F"
|
||||||
|
|
||||||
#define DF_GHOST 0x01 // This demo contains ghost data too!
|
#define DF_GHOST 0x01 // This demo contains ghost data too!
|
||||||
|
@ -165,7 +166,6 @@ void G_LoadMetal(UINT8 **buffer)
|
||||||
void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
||||||
{
|
{
|
||||||
UINT8 ziptic;
|
UINT8 ziptic;
|
||||||
(void)playernum;
|
|
||||||
|
|
||||||
if (!demo_p || !demo_start)
|
if (!demo_p || !demo_start)
|
||||||
return;
|
return;
|
||||||
|
@ -183,6 +183,7 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
||||||
oldcmd.aiming = READINT16(demo_p);
|
oldcmd.aiming = READINT16(demo_p);
|
||||||
|
|
||||||
G_CopyTiccmd(cmd, &oldcmd, 1);
|
G_CopyTiccmd(cmd, &oldcmd, 1);
|
||||||
|
players[playernum].angleturn = cmd->angleturn;
|
||||||
|
|
||||||
if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER)
|
if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER)
|
||||||
{
|
{
|
||||||
|
@ -280,13 +281,13 @@ void G_GhostAddColor(ghostcolor_t color)
|
||||||
{
|
{
|
||||||
if (!demorecording || !(demoflags & DF_GHOST))
|
if (!demorecording || !(demoflags & DF_GHOST))
|
||||||
return;
|
return;
|
||||||
if (ghostext.lastcolor == (UINT8)color)
|
if (ghostext.lastcolor == (UINT16)color)
|
||||||
{
|
{
|
||||||
ghostext.flags &= ~EZT_COLOR;
|
ghostext.flags &= ~EZT_COLOR;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ghostext.flags |= EZT_COLOR;
|
ghostext.flags |= EZT_COLOR;
|
||||||
ghostext.color = (UINT8)color;
|
ghostext.color = (UINT16)color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void G_GhostAddScale(fixed_t scale)
|
void G_GhostAddScale(fixed_t scale)
|
||||||
|
@ -425,7 +426,7 @@ void G_WriteGhostTic(mobj_t *ghost)
|
||||||
WRITEUINT8(demo_p,ghostext.flags);
|
WRITEUINT8(demo_p,ghostext.flags);
|
||||||
if (ghostext.flags & EZT_COLOR)
|
if (ghostext.flags & EZT_COLOR)
|
||||||
{
|
{
|
||||||
WRITEUINT8(demo_p,ghostext.color);
|
WRITEUINT16(demo_p,ghostext.color);
|
||||||
ghostext.lastcolor = ghostext.color;
|
ghostext.lastcolor = ghostext.color;
|
||||||
}
|
}
|
||||||
if (ghostext.flags & EZT_SCALE)
|
if (ghostext.flags & EZT_SCALE)
|
||||||
|
@ -501,7 +502,7 @@ void G_WriteGhostTic(mobj_t *ghost)
|
||||||
WRITEUINT8(demo_p,ghost->player->followmobj->sprite2);
|
WRITEUINT8(demo_p,ghost->player->followmobj->sprite2);
|
||||||
WRITEUINT16(demo_p,ghost->player->followmobj->sprite);
|
WRITEUINT16(demo_p,ghost->player->followmobj->sprite);
|
||||||
WRITEUINT8(demo_p,(ghost->player->followmobj->frame & FF_FRAMEMASK));
|
WRITEUINT8(demo_p,(ghost->player->followmobj->frame & FF_FRAMEMASK));
|
||||||
WRITEUINT8(demo_p,ghost->player->followmobj->color);
|
WRITEUINT16(demo_p,ghost->player->followmobj->color);
|
||||||
|
|
||||||
*followtic_p = followtic;
|
*followtic_p = followtic;
|
||||||
}
|
}
|
||||||
|
@ -566,7 +567,7 @@ void G_ConsGhostTic(void)
|
||||||
{ // But wait, there's more!
|
{ // But wait, there's more!
|
||||||
UINT8 xziptic = READUINT8(demo_p);
|
UINT8 xziptic = READUINT8(demo_p);
|
||||||
if (xziptic & EZT_COLOR)
|
if (xziptic & EZT_COLOR)
|
||||||
demo_p++;
|
demo_p += (demoversion==0x000c) ? 1 : sizeof(UINT16);
|
||||||
if (xziptic & EZT_SCALE)
|
if (xziptic & EZT_SCALE)
|
||||||
demo_p += sizeof(fixed_t);
|
demo_p += sizeof(fixed_t);
|
||||||
if (xziptic & EZT_HIT)
|
if (xziptic & EZT_HIT)
|
||||||
|
@ -633,7 +634,7 @@ void G_ConsGhostTic(void)
|
||||||
demo_p++;
|
demo_p++;
|
||||||
demo_p += sizeof(UINT16);
|
demo_p += sizeof(UINT16);
|
||||||
demo_p++;
|
demo_p++;
|
||||||
demo_p++;
|
demo_p += (demoversion==0x000c) ? 1 : sizeof(UINT16);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-synchronise
|
// Re-synchronise
|
||||||
|
@ -731,7 +732,7 @@ void G_GhostTicker(void)
|
||||||
xziptic = READUINT8(g->p);
|
xziptic = READUINT8(g->p);
|
||||||
if (xziptic & EZT_COLOR)
|
if (xziptic & EZT_COLOR)
|
||||||
{
|
{
|
||||||
g->color = READUINT8(g->p);
|
g->color = (g->version==0x000c) ? READUINT8(g->p) : READUINT16(g->p);
|
||||||
switch(g->color)
|
switch(g->color)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
|
@ -764,7 +765,7 @@ void G_GhostTicker(void)
|
||||||
if (xziptic & EZT_THOKMASK)
|
if (xziptic & EZT_THOKMASK)
|
||||||
{ // Let's only spawn ONE of these per frame, thanks.
|
{ // Let's only spawn ONE of these per frame, thanks.
|
||||||
mobj_t *mobj;
|
mobj_t *mobj;
|
||||||
INT32 type = -1;
|
UINT32 type = MT_NULL;
|
||||||
if (g->mo->skin)
|
if (g->mo->skin)
|
||||||
{
|
{
|
||||||
skin_t *skin = (skin_t *)g->mo->skin;
|
skin_t *skin = (skin_t *)g->mo->skin;
|
||||||
|
@ -864,7 +865,7 @@ void G_GhostTicker(void)
|
||||||
g->mo->color += abs( ( (signed)( (unsigned)leveltime >> 1 ) % 9) - 4);
|
g->mo->color += abs( ( (signed)( (unsigned)leveltime >> 1 ) % 9) - 4);
|
||||||
break;
|
break;
|
||||||
case GHC_INVINCIBLE: // Mario invincibility (P_CheckInvincibilityTimer)
|
case GHC_INVINCIBLE: // Mario invincibility (P_CheckInvincibilityTimer)
|
||||||
g->mo->color = (UINT8)(SKINCOLOR_RUBY + (leveltime % (MAXSKINCOLORS - SKINCOLOR_RUBY))); // Passes through all saturated colours
|
g->mo->color = (UINT16)(SKINCOLOR_RUBY + (leveltime % (FIRSTSUPERCOLOR - SKINCOLOR_RUBY))); // Passes through all saturated colours
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -918,7 +919,7 @@ void G_GhostTicker(void)
|
||||||
follow->sprite = READUINT16(g->p);
|
follow->sprite = READUINT16(g->p);
|
||||||
follow->frame = (READUINT8(g->p)) | (g->mo->frame & FF_TRANSMASK);
|
follow->frame = (READUINT8(g->p)) | (g->mo->frame & FF_TRANSMASK);
|
||||||
follow->angle = g->mo->angle;
|
follow->angle = g->mo->angle;
|
||||||
follow->color = READUINT8(g->p);
|
follow->color = (g->version==0x000c) ? READUINT8(g->p) : READUINT16(g->p);
|
||||||
|
|
||||||
if (!(followtic & FZT_SPAWNED))
|
if (!(followtic & FZT_SPAWNED))
|
||||||
{
|
{
|
||||||
|
@ -996,7 +997,11 @@ void G_ReadMetalTic(mobj_t *metal)
|
||||||
// Read changes from the tic
|
// Read changes from the tic
|
||||||
if (ziptic & GZT_XYZ)
|
if (ziptic & GZT_XYZ)
|
||||||
{
|
{
|
||||||
P_TeleportMove(metal, READFIXED(metal_p), READFIXED(metal_p), READFIXED(metal_p));
|
// make sure the values are read in the right order
|
||||||
|
oldmetal.x = READFIXED(metal_p);
|
||||||
|
oldmetal.y = READFIXED(metal_p);
|
||||||
|
oldmetal.z = READFIXED(metal_p);
|
||||||
|
P_TeleportMove(metal, oldmetal.x, oldmetal.y, oldmetal.z);
|
||||||
oldmetal.x = metal->x;
|
oldmetal.x = metal->x;
|
||||||
oldmetal.y = metal->y;
|
oldmetal.y = metal->y;
|
||||||
oldmetal.z = metal->z;
|
oldmetal.z = metal->z;
|
||||||
|
@ -1051,7 +1056,7 @@ void G_ReadMetalTic(mobj_t *metal)
|
||||||
if (xziptic & EZT_THOKMASK)
|
if (xziptic & EZT_THOKMASK)
|
||||||
{ // Let's only spawn ONE of these per frame, thanks.
|
{ // Let's only spawn ONE of these per frame, thanks.
|
||||||
mobj_t *mobj;
|
mobj_t *mobj;
|
||||||
INT32 type = -1;
|
UINT32 type = MT_NULL;
|
||||||
if (metal->skin)
|
if (metal->skin)
|
||||||
{
|
{
|
||||||
skin_t *skin = (skin_t *)metal->skin;
|
skin_t *skin = (skin_t *)metal->skin;
|
||||||
|
@ -1158,7 +1163,7 @@ void G_ReadMetalTic(mobj_t *metal)
|
||||||
follow->sprite = READUINT16(metal_p);
|
follow->sprite = READUINT16(metal_p);
|
||||||
follow->frame = READUINT32(metal_p); // NOT & FF_FRAMEMASK here, so 32 bits
|
follow->frame = READUINT32(metal_p); // NOT & FF_FRAMEMASK here, so 32 bits
|
||||||
follow->angle = metal->angle;
|
follow->angle = metal->angle;
|
||||||
follow->color = READUINT8(metal_p);
|
follow->color = (metalversion==0x000c) ? READUINT8(metal_p) : READUINT16(metal_p);
|
||||||
|
|
||||||
if (!(followtic & FZT_SPAWNED))
|
if (!(followtic & FZT_SPAWNED))
|
||||||
{
|
{
|
||||||
|
@ -1340,7 +1345,7 @@ void G_WriteMetalTic(mobj_t *metal)
|
||||||
WRITEUINT8(demo_p,metal->player->followmobj->sprite2);
|
WRITEUINT8(demo_p,metal->player->followmobj->sprite2);
|
||||||
WRITEUINT16(demo_p,metal->player->followmobj->sprite);
|
WRITEUINT16(demo_p,metal->player->followmobj->sprite);
|
||||||
WRITEUINT32(demo_p,metal->player->followmobj->frame); // NOT & FF_FRAMEMASK here, so 32 bits
|
WRITEUINT32(demo_p,metal->player->followmobj->frame); // NOT & FF_FRAMEMASK here, so 32 bits
|
||||||
WRITEUINT8(demo_p,metal->player->followmobj->color);
|
WRITEUINT16(demo_p,metal->player->followmobj->color);
|
||||||
|
|
||||||
*followtic_p = followtic;
|
*followtic_p = followtic;
|
||||||
}
|
}
|
||||||
|
@ -1394,7 +1399,7 @@ void G_RecordMetal(void)
|
||||||
void G_BeginRecording(void)
|
void G_BeginRecording(void)
|
||||||
{
|
{
|
||||||
UINT8 i;
|
UINT8 i;
|
||||||
char name[16];
|
char name[MAXCOLORNAME+1];
|
||||||
player_t *player = &players[consoleplayer];
|
player_t *player = &players[consoleplayer];
|
||||||
|
|
||||||
if (demo_p)
|
if (demo_p)
|
||||||
|
@ -1457,12 +1462,12 @@ void G_BeginRecording(void)
|
||||||
demo_p += 16;
|
demo_p += 16;
|
||||||
|
|
||||||
// Color
|
// Color
|
||||||
for (i = 0; i < 16 && cv_playercolor.string[i]; i++)
|
for (i = 0; i < MAXCOLORNAME && cv_playercolor.string[i]; i++)
|
||||||
name[i] = cv_playercolor.string[i];
|
name[i] = cv_playercolor.string[i];
|
||||||
for (; i < 16; i++)
|
for (; i < MAXCOLORNAME; i++)
|
||||||
name[i] = '\0';
|
name[i] = '\0';
|
||||||
M_Memcpy(demo_p,name,16);
|
M_Memcpy(demo_p,name,MAXCOLORNAME);
|
||||||
demo_p += 16;
|
demo_p += MAXCOLORNAME;
|
||||||
|
|
||||||
// Stats
|
// Stats
|
||||||
WRITEUINT8(demo_p,player->charability);
|
WRITEUINT8(demo_p,player->charability);
|
||||||
|
@ -1622,7 +1627,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
||||||
c = READUINT8(p); // SUBVERSION
|
c = READUINT8(p); // SUBVERSION
|
||||||
I_Assert(c == SUBVERSION);
|
I_Assert(c == SUBVERSION);
|
||||||
s = READUINT16(p);
|
s = READUINT16(p);
|
||||||
I_Assert(s == DEMOVERSION);
|
I_Assert(s >= 0x000c);
|
||||||
p += 16; // demo checksum
|
p += 16; // demo checksum
|
||||||
I_Assert(!memcmp(p, "PLAY", 4));
|
I_Assert(!memcmp(p, "PLAY", 4));
|
||||||
p += 4; // PLAY
|
p += 4; // PLAY
|
||||||
|
@ -1671,6 +1676,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
||||||
switch(oldversion) // demoversion
|
switch(oldversion) // demoversion
|
||||||
{
|
{
|
||||||
case DEMOVERSION: // latest always supported
|
case DEMOVERSION: // latest always supported
|
||||||
|
case 0x000c: // all that changed between then and now was longer color name
|
||||||
break;
|
break;
|
||||||
// too old, cannot support.
|
// too old, cannot support.
|
||||||
default:
|
default:
|
||||||
|
@ -1744,15 +1750,15 @@ void G_DoPlayDemo(char *defdemoname)
|
||||||
{
|
{
|
||||||
UINT8 i;
|
UINT8 i;
|
||||||
lumpnum_t l;
|
lumpnum_t l;
|
||||||
char skin[17],color[17],*n,*pdemoname;
|
char skin[17],color[MAXCOLORNAME+1],*n,*pdemoname;
|
||||||
UINT8 version,subversion,charability,charability2,thrustfactor,accelstart,acceleration;
|
UINT8 version,subversion,charability,charability2,thrustfactor,accelstart,acceleration,cnamelen;
|
||||||
pflags_t pflags;
|
pflags_t pflags;
|
||||||
UINT32 randseed, followitem;
|
UINT32 randseed, followitem;
|
||||||
fixed_t camerascale,shieldscale,actionspd,mindash,maxdash,normalspeed,runspeed,jumpfactor,height,spinheight;
|
fixed_t camerascale,shieldscale,actionspd,mindash,maxdash,normalspeed,runspeed,jumpfactor,height,spinheight;
|
||||||
char msg[1024];
|
char msg[1024];
|
||||||
|
|
||||||
skin[16] = '\0';
|
skin[16] = '\0';
|
||||||
color[16] = '\0';
|
color[MAXCOLORNAME] = '\0';
|
||||||
|
|
||||||
n = defdemoname+strlen(defdemoname);
|
n = defdemoname+strlen(defdemoname);
|
||||||
while (*n != '/' && *n != '\\' && n != defdemoname)
|
while (*n != '/' && *n != '\\' && n != defdemoname)
|
||||||
|
@ -1810,6 +1816,11 @@ void G_DoPlayDemo(char *defdemoname)
|
||||||
switch(demoversion)
|
switch(demoversion)
|
||||||
{
|
{
|
||||||
case DEMOVERSION: // latest always supported
|
case DEMOVERSION: // latest always supported
|
||||||
|
cnamelen = MAXCOLORNAME;
|
||||||
|
break;
|
||||||
|
// all that changed between then and now was longer color name
|
||||||
|
case 0x000c:
|
||||||
|
cnamelen = 16;
|
||||||
break;
|
break;
|
||||||
// too old, cannot support.
|
// too old, cannot support.
|
||||||
default:
|
default:
|
||||||
|
@ -1876,8 +1887,8 @@ void G_DoPlayDemo(char *defdemoname)
|
||||||
demo_p += 16;
|
demo_p += 16;
|
||||||
|
|
||||||
// Color
|
// Color
|
||||||
M_Memcpy(color,demo_p,16);
|
M_Memcpy(color,demo_p,cnamelen);
|
||||||
demo_p += 16;
|
demo_p += cnamelen;
|
||||||
|
|
||||||
charability = READUINT8(demo_p);
|
charability = READUINT8(demo_p);
|
||||||
charability2 = READUINT8(demo_p);
|
charability2 = READUINT8(demo_p);
|
||||||
|
@ -1941,7 +1952,9 @@ void G_DoPlayDemo(char *defdemoname)
|
||||||
// Set skin
|
// Set skin
|
||||||
SetPlayerSkin(0, skin);
|
SetPlayerSkin(0, skin);
|
||||||
|
|
||||||
|
#ifdef HAVE_BLUA
|
||||||
LUAh_MapChange(gamemap);
|
LUAh_MapChange(gamemap);
|
||||||
|
#endif
|
||||||
displayplayer = consoleplayer = 0;
|
displayplayer = consoleplayer = 0;
|
||||||
memset(playeringame,0,sizeof(playeringame));
|
memset(playeringame,0,sizeof(playeringame));
|
||||||
playeringame[0] = true;
|
playeringame[0] = true;
|
||||||
|
@ -1949,8 +1962,9 @@ void G_DoPlayDemo(char *defdemoname)
|
||||||
G_InitNew(false, G_BuildMapName(gamemap), true, true, false);
|
G_InitNew(false, G_BuildMapName(gamemap), true, true, false);
|
||||||
|
|
||||||
// Set color
|
// Set color
|
||||||
for (i = 0; i < MAXSKINCOLORS; i++)
|
players[0].skincolor = skins[players[0].skin].prefcolor;
|
||||||
if (!stricmp(Color_Names[i],color))
|
for (i = 0; i < numskincolors; i++)
|
||||||
|
if (!stricmp(skincolors[i].name,color))
|
||||||
{
|
{
|
||||||
players[0].skincolor = i;
|
players[0].skincolor = i;
|
||||||
break;
|
break;
|
||||||
|
@ -1992,7 +2006,8 @@ void G_AddGhost(char *defdemoname)
|
||||||
{
|
{
|
||||||
INT32 i;
|
INT32 i;
|
||||||
lumpnum_t l;
|
lumpnum_t l;
|
||||||
char name[17],skin[17],color[17],*n,*pdemoname,md5[16];
|
char name[17],skin[17],color[MAXCOLORNAME+1],*n,*pdemoname,md5[16];
|
||||||
|
UINT8 cnamelen;
|
||||||
demoghost *gh;
|
demoghost *gh;
|
||||||
UINT8 flags;
|
UINT8 flags;
|
||||||
UINT8 *buffer,*p;
|
UINT8 *buffer,*p;
|
||||||
|
@ -2047,6 +2062,11 @@ void G_AddGhost(char *defdemoname)
|
||||||
switch(ghostversion)
|
switch(ghostversion)
|
||||||
{
|
{
|
||||||
case DEMOVERSION: // latest always supported
|
case DEMOVERSION: // latest always supported
|
||||||
|
cnamelen = MAXCOLORNAME;
|
||||||
|
break;
|
||||||
|
// all that changed between then and now was longer color name
|
||||||
|
case 0x000c:
|
||||||
|
cnamelen = 16;
|
||||||
break;
|
break;
|
||||||
// too old, cannot support.
|
// too old, cannot support.
|
||||||
default:
|
default:
|
||||||
|
@ -2109,8 +2129,8 @@ void G_AddGhost(char *defdemoname)
|
||||||
p += 16;
|
p += 16;
|
||||||
|
|
||||||
// Color
|
// Color
|
||||||
M_Memcpy(color, p,16);
|
M_Memcpy(color, p,cnamelen);
|
||||||
p += 16;
|
p += cnamelen;
|
||||||
|
|
||||||
// Ghosts do not have a player structure to put this in.
|
// Ghosts do not have a player structure to put this in.
|
||||||
p++; // charability
|
p++; // charability
|
||||||
|
@ -2198,10 +2218,10 @@ void G_AddGhost(char *defdemoname)
|
||||||
|
|
||||||
// Set color
|
// Set color
|
||||||
gh->mo->color = ((skin_t*)gh->mo->skin)->prefcolor;
|
gh->mo->color = ((skin_t*)gh->mo->skin)->prefcolor;
|
||||||
for (i = 0; i < MAXSKINCOLORS; i++)
|
for (i = 0; i < numskincolors; i++)
|
||||||
if (!stricmp(Color_Names[i],color))
|
if (!stricmp(skincolors[i].name,color))
|
||||||
{
|
{
|
||||||
gh->mo->color = (UINT8)i;
|
gh->mo->color = (UINT16)i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
gh->oldmo.color = gh->mo->color;
|
gh->oldmo.color = gh->mo->color;
|
||||||
|
@ -2292,6 +2312,7 @@ void G_DoPlayMetal(void)
|
||||||
switch(metalversion)
|
switch(metalversion)
|
||||||
{
|
{
|
||||||
case DEMOVERSION: // latest always supported
|
case DEMOVERSION: // latest always supported
|
||||||
|
case 0x000c: // all that changed between then and now was longer color name
|
||||||
break;
|
break;
|
||||||
// too old, cannot support.
|
// too old, cannot support.
|
||||||
default:
|
default:
|
||||||
|
@ -2332,6 +2353,38 @@ void G_DoneLevelLoad(void)
|
||||||
===================
|
===================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Writes the demo's checksum, or just random garbage if you can't do that for some reason.
|
||||||
|
static void WriteDemoChecksum(void)
|
||||||
|
{
|
||||||
|
UINT8 *p = demobuffer+16; // checksum position
|
||||||
|
#ifdef NOMD5
|
||||||
|
UINT8 i;
|
||||||
|
for (i = 0; i < 16; i++, p++)
|
||||||
|
*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
|
||||||
|
#else
|
||||||
|
md5_buffer((char *)p+16, demo_p - (p+16), p); // make a checksum of everything after the checksum in the file.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stops recording a demo.
|
||||||
|
static void G_StopDemoRecording(void)
|
||||||
|
{
|
||||||
|
boolean saved = false;
|
||||||
|
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
|
||||||
|
WriteDemoChecksum();
|
||||||
|
saved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file.
|
||||||
|
free(demobuffer);
|
||||||
|
demorecording = false;
|
||||||
|
|
||||||
|
if (modeattacking != ATTACKING_RECORD)
|
||||||
|
{
|
||||||
|
if (saved)
|
||||||
|
CONS_Printf(M_GetText("Demo %s recorded\n"), demoname);
|
||||||
|
else
|
||||||
|
CONS_Alert(CONS_WARNING, M_GetText("Demo %s not saved\n"), demoname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Stops metal sonic's demo. Separate from other functions because metal + replays can coexist
|
// Stops metal sonic's demo. Separate from other functions because metal + replays can coexist
|
||||||
void G_StopMetalDemo(void)
|
void G_StopMetalDemo(void)
|
||||||
{
|
{
|
||||||
|
@ -2349,20 +2402,8 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill)
|
||||||
boolean saved = false;
|
boolean saved = false;
|
||||||
if (demo_p)
|
if (demo_p)
|
||||||
{
|
{
|
||||||
UINT8 *p = demobuffer+16; // checksum position
|
WRITEUINT8(demo_p, (kill) ? METALDEATH : DEMOMARKER); // add the demo end (or metal death) marker
|
||||||
if (kill)
|
WriteDemoChecksum();
|
||||||
WRITEUINT8(demo_p, METALDEATH); // add the metal death marker
|
|
||||||
else
|
|
||||||
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
|
|
||||||
#ifdef NOMD5
|
|
||||||
{
|
|
||||||
UINT8 i;
|
|
||||||
for (i = 0; i < 16; i++, p++)
|
|
||||||
*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
md5_buffer((char *)p+16, demo_p - (p+16), (void *)p); // make a checksum of everything after the checksum in the file.
|
|
||||||
#endif
|
|
||||||
saved = FIL_WriteFile(va("%sMS.LMP", G_BuildMapName(gamemap)), demobuffer, demo_p - demobuffer); // finally output the file.
|
saved = FIL_WriteFile(va("%sMS.LMP", G_BuildMapName(gamemap)), demobuffer, demo_p - demobuffer); // finally output the file.
|
||||||
}
|
}
|
||||||
free(demobuffer);
|
free(demobuffer);
|
||||||
|
@ -2372,41 +2413,14 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill)
|
||||||
I_Error("Failed to save demo!");
|
I_Error("Failed to save demo!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset engine variable set for the demos
|
// Stops timing a demo.
|
||||||
// called from stopdemo command, map command, and g_checkdemoStatus.
|
static void G_StopTimingDemo(void)
|
||||||
void G_StopDemo(void)
|
|
||||||
{
|
|
||||||
Z_Free(demobuffer);
|
|
||||||
demobuffer = NULL;
|
|
||||||
demoplayback = false;
|
|
||||||
titledemo = false;
|
|
||||||
timingdemo = false;
|
|
||||||
singletics = false;
|
|
||||||
|
|
||||||
if (gamestate == GS_INTERMISSION)
|
|
||||||
Y_EndIntermission(); // cleanup
|
|
||||||
|
|
||||||
G_SetGamestate(GS_NULL);
|
|
||||||
wipegamestate = GS_NULL;
|
|
||||||
SV_StopServer();
|
|
||||||
SV_ResetServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean G_CheckDemoStatus(void)
|
|
||||||
{
|
|
||||||
boolean saved;
|
|
||||||
|
|
||||||
G_FreeGhosts();
|
|
||||||
|
|
||||||
// DO NOT end metal sonic demos here
|
|
||||||
|
|
||||||
if (timingdemo)
|
|
||||||
{
|
{
|
||||||
INT32 demotime;
|
INT32 demotime;
|
||||||
double f1, f2;
|
double f1, f2;
|
||||||
demotime = I_GetTime() - demostarttime;
|
demotime = I_GetTime() - demostarttime;
|
||||||
if (!demotime)
|
if (!demotime)
|
||||||
return true;
|
return;
|
||||||
G_StopDemo();
|
G_StopDemo();
|
||||||
timingdemo = false;
|
timingdemo = false;
|
||||||
f1 = (double)demotime;
|
f1 = (double)demotime;
|
||||||
|
@ -2454,6 +2468,37 @@ boolean G_CheckDemoStatus(void)
|
||||||
if (restorecv_vidwait != cv_vidwait.value)
|
if (restorecv_vidwait != cv_vidwait.value)
|
||||||
CV_SetValue(&cv_vidwait, restorecv_vidwait);
|
CV_SetValue(&cv_vidwait, restorecv_vidwait);
|
||||||
D_AdvanceDemo();
|
D_AdvanceDemo();
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset engine variable set for the demos
|
||||||
|
// called from stopdemo command, map command, and g_checkdemoStatus.
|
||||||
|
void G_StopDemo(void)
|
||||||
|
{
|
||||||
|
Z_Free(demobuffer);
|
||||||
|
demobuffer = NULL;
|
||||||
|
demoplayback = false;
|
||||||
|
titledemo = false;
|
||||||
|
timingdemo = false;
|
||||||
|
singletics = false;
|
||||||
|
|
||||||
|
if (gamestate == GS_INTERMISSION)
|
||||||
|
Y_EndIntermission(); // cleanup
|
||||||
|
|
||||||
|
G_SetGamestate(GS_NULL);
|
||||||
|
wipegamestate = GS_NULL;
|
||||||
|
SV_StopServer();
|
||||||
|
SV_ResetServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean G_CheckDemoStatus(void)
|
||||||
|
{
|
||||||
|
G_FreeGhosts();
|
||||||
|
|
||||||
|
// DO NOT end metal sonic demos here
|
||||||
|
|
||||||
|
if (timingdemo)
|
||||||
|
{
|
||||||
|
G_StopTimingDemo();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2473,27 +2518,7 @@ boolean G_CheckDemoStatus(void)
|
||||||
|
|
||||||
if (demorecording)
|
if (demorecording)
|
||||||
{
|
{
|
||||||
UINT8 *p = demobuffer+16; // checksum position
|
G_StopDemoRecording();
|
||||||
#ifdef NOMD5
|
|
||||||
UINT8 i;
|
|
||||||
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
|
|
||||||
for (i = 0; i < 16; i++, p++)
|
|
||||||
*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
|
|
||||||
#else
|
|
||||||
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
|
|
||||||
md5_buffer((char *)p+16, demo_p - (p+16), p); // make a checksum of everything after the checksum in the file.
|
|
||||||
#endif
|
|
||||||
saved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file.
|
|
||||||
free(demobuffer);
|
|
||||||
demorecording = false;
|
|
||||||
|
|
||||||
if (modeattacking != ATTACKING_RECORD)
|
|
||||||
{
|
|
||||||
if (saved)
|
|
||||||
CONS_Printf(M_GetText("Demo %s recorded\n"), demoname);
|
|
||||||
else
|
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Demo %s not saved\n"), demoname);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
173
src/g_game.c
173
src/g_game.c
|
@ -54,7 +54,7 @@ UINT8 ultimatemode = false;
|
||||||
|
|
||||||
boolean botingame;
|
boolean botingame;
|
||||||
UINT8 botskin;
|
UINT8 botskin;
|
||||||
UINT8 botcolor;
|
UINT16 botcolor;
|
||||||
|
|
||||||
JoyType_t Joystick;
|
JoyType_t Joystick;
|
||||||
JoyType_t Joystick2;
|
JoyType_t Joystick2;
|
||||||
|
@ -82,7 +82,10 @@ INT32 curWeather = PRECIP_NONE;
|
||||||
INT32 cursaveslot = 0; // Auto-save 1p savegame slot
|
INT32 cursaveslot = 0; // Auto-save 1p savegame slot
|
||||||
//INT16 lastmapsaved = 0; // Last map we auto-saved at
|
//INT16 lastmapsaved = 0; // Last map we auto-saved at
|
||||||
INT16 lastmaploaded = 0; // Last map the game loaded
|
INT16 lastmaploaded = 0; // Last map the game loaded
|
||||||
boolean gamecomplete = false;
|
UINT8 gamecomplete = 0;
|
||||||
|
|
||||||
|
marathonmode_t marathonmode = 0;
|
||||||
|
tic_t marathontime = 0;
|
||||||
|
|
||||||
UINT8 numgameovers = 0; // for startinglives balance
|
UINT8 numgameovers = 0; // for startinglives balance
|
||||||
SINT8 startinglivesbalance[maxgameovers+1] = {3, 5, 7, 9, 12, 15, 20, 25, 30, 40, 50, 75, 99, 0x7F};
|
SINT8 startinglivesbalance[maxgameovers+1] = {3, 5, 7, 9, 12, 15, 20, 25, 30, 40, 50, 75, 99, 0x7F};
|
||||||
|
@ -118,7 +121,7 @@ UINT32 ssspheres; // old special stage
|
||||||
INT16 lastmap; // last level you were at (returning from special stages)
|
INT16 lastmap; // last level you were at (returning from special stages)
|
||||||
tic_t timeinmap; // Ticker for time spent in level (used for levelcard display)
|
tic_t timeinmap; // Ticker for time spent in level (used for levelcard display)
|
||||||
|
|
||||||
INT16 spstage_start;
|
INT16 spstage_start, spmarathon_start;
|
||||||
INT16 sstage_start, sstage_end, smpstage_start, smpstage_end;
|
INT16 sstage_start, sstage_end, smpstage_start, smpstage_end;
|
||||||
|
|
||||||
INT16 titlemap = 0;
|
INT16 titlemap = 0;
|
||||||
|
@ -135,10 +138,10 @@ INT32 tutorialanalog = 0; // store cv_analog[0] user value
|
||||||
|
|
||||||
boolean looptitle = false;
|
boolean looptitle = false;
|
||||||
|
|
||||||
UINT8 skincolor_redteam = SKINCOLOR_RED;
|
UINT16 skincolor_redteam = SKINCOLOR_RED;
|
||||||
UINT8 skincolor_blueteam = SKINCOLOR_BLUE;
|
UINT16 skincolor_blueteam = SKINCOLOR_BLUE;
|
||||||
UINT8 skincolor_redring = SKINCOLOR_SALMON;
|
UINT16 skincolor_redring = SKINCOLOR_SALMON;
|
||||||
UINT8 skincolor_bluering = SKINCOLOR_CORNFLOWER;
|
UINT16 skincolor_bluering = SKINCOLOR_CORNFLOWER;
|
||||||
|
|
||||||
tic_t countdowntimer = 0;
|
tic_t countdowntimer = 0;
|
||||||
boolean countdowntimeup = false;
|
boolean countdowntimeup = false;
|
||||||
|
@ -223,6 +226,7 @@ UINT8 useContinues = 0; // Set to 1 to enable continues outside of no-save scena
|
||||||
|
|
||||||
UINT8 introtoplay;
|
UINT8 introtoplay;
|
||||||
UINT8 creditscutscene;
|
UINT8 creditscutscene;
|
||||||
|
UINT8 useBlackRock = 1;
|
||||||
|
|
||||||
// Emerald locations
|
// Emerald locations
|
||||||
mobj_t *hunt1;
|
mobj_t *hunt1;
|
||||||
|
@ -769,6 +773,8 @@ void G_SetGameModified(boolean silent)
|
||||||
// If in record attack recording, cancel it.
|
// If in record attack recording, cancel it.
|
||||||
if (modeattacking)
|
if (modeattacking)
|
||||||
M_EndModeAttackRun();
|
M_EndModeAttackRun();
|
||||||
|
else if (marathonmode)
|
||||||
|
Command_ExitGame_f();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Builds an original game map name from a map number.
|
/** Builds an original game map name from a map number.
|
||||||
|
@ -1065,6 +1071,7 @@ static fixed_t forwardmove[2] = {25<<FRACBITS>>16, 50<<FRACBITS>>16};
|
||||||
static fixed_t sidemove[2] = {25<<FRACBITS>>16, 50<<FRACBITS>>16}; // faster!
|
static fixed_t sidemove[2] = {25<<FRACBITS>>16, 50<<FRACBITS>>16}; // faster!
|
||||||
static fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn
|
static fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn
|
||||||
|
|
||||||
|
INT16 ticcmd_oldangleturn[2];
|
||||||
boolean ticcmd_centerviewdown[2]; // For simple controls, lock the camera behind the player
|
boolean ticcmd_centerviewdown[2]; // For simple controls, lock the camera behind the player
|
||||||
mobj_t *ticcmd_ztargetfocus[2]; // Locking onto an object?
|
mobj_t *ticcmd_ztargetfocus[2]; // Locking onto an object?
|
||||||
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
||||||
|
@ -1140,7 +1147,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
||||||
if (paused || P_AutoPause() || (gamestate == GS_LEVEL && (player->playerstate == PST_REBORN || ((gametyperules & GTR_TAG)
|
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)))))
|
||||||
{//@TODO splitscreen player
|
{//@TODO splitscreen player
|
||||||
cmd->angleturn = (INT16)(*myangle >> 16);
|
cmd->angleturn = ticcmd_oldangleturn[forplayer];
|
||||||
cmd->aiming = G_ClipAimingPitch(myaiming);
|
cmd->aiming = G_ClipAimingPitch(myaiming);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1361,7 +1368,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
||||||
if (controlstyle == CS_SIMPLE && !ticcmd_centerviewdown[forplayer] && !G_RingSlingerGametype())
|
if (controlstyle == CS_SIMPLE && !ticcmd_centerviewdown[forplayer] && !G_RingSlingerGametype())
|
||||||
{
|
{
|
||||||
CV_SetValue(&cv_directionchar[forplayer], 2);
|
CV_SetValue(&cv_directionchar[forplayer], 2);
|
||||||
*myangle = player->mo->angle;
|
cmd->angleturn = (INT16)((player->mo->angle - *myangle) >> 16);
|
||||||
*myaiming = 0;
|
*myaiming = 0;
|
||||||
|
|
||||||
if (cv_cam_lockonboss[forplayer].value)
|
if (cv_cam_lockonboss[forplayer].value)
|
||||||
|
@ -1430,7 +1437,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
||||||
else if (anglediff < -maxturn)
|
else if (anglediff < -maxturn)
|
||||||
anglediff = -maxturn;
|
anglediff = -maxturn;
|
||||||
|
|
||||||
*myangle += anglediff;
|
cmd->angleturn = (INT16)(cmd->angleturn + (anglediff >> 16));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1567,19 +1574,23 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
||||||
B_HandleFlightIndicator(player);
|
B_HandleFlightIndicator(player);
|
||||||
}
|
}
|
||||||
else if (player->bot == 2)
|
else if (player->bot == 2)
|
||||||
*myangle = localangle; // Fix offset angle for P2-controlled Tailsbot when P2's controls are set to non-Legacy
|
// Fix offset angle for P2-controlled Tailsbot when P2's controls are set to non-Legacy
|
||||||
|
cmd->angleturn = (INT16)((localangle - *myangle) >> 16);
|
||||||
|
|
||||||
|
*myangle += (cmd->angleturn<<16);
|
||||||
|
|
||||||
if (controlstyle == CS_LMAOGALOG) {
|
if (controlstyle == CS_LMAOGALOG) {
|
||||||
|
angle_t angle;
|
||||||
|
|
||||||
if (player->awayviewtics)
|
if (player->awayviewtics)
|
||||||
cmd->angleturn = (INT16)(player->awayviewmobj->angle >> 16);
|
angle = player->awayviewmobj->angle;
|
||||||
else
|
else
|
||||||
cmd->angleturn = (INT16)(thiscam->angle >> 16);
|
angle = thiscam->angle;
|
||||||
|
|
||||||
|
cmd->angleturn = (INT16)((angle - (ticcmd_oldangleturn[forplayer] << 16)) >> 16);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*myangle += (cmd->angleturn<<16);
|
|
||||||
cmd->angleturn = (INT16)(*myangle >> 16);
|
|
||||||
|
|
||||||
// Adjust camera angle by player input
|
// Adjust camera angle by player input
|
||||||
if (controlstyle == CS_SIMPLE && !forcestrafe && thiscam->chase && !turnheld[forplayer] && !ticcmd_centerviewdown[forplayer] && !player->climbing && player->powers[pw_carry] != CR_MINECART)
|
if (controlstyle == CS_SIMPLE && !forcestrafe && thiscam->chase && !turnheld[forplayer] && !ticcmd_centerviewdown[forplayer] && !player->climbing && player->powers[pw_carry] != CR_MINECART)
|
||||||
{
|
{
|
||||||
|
@ -1589,13 +1600,17 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
||||||
{
|
{
|
||||||
fixed_t sine = FINESINE((R_PointToAngle2(0, 0, player->rmomx, player->rmomy) - localangle)>>ANGLETOFINESHIFT);
|
fixed_t sine = FINESINE((R_PointToAngle2(0, 0, player->rmomx, player->rmomy) - localangle)>>ANGLETOFINESHIFT);
|
||||||
fixed_t factor;
|
fixed_t factor;
|
||||||
|
INT16 camadjust;
|
||||||
|
|
||||||
if ((sine > 0) == (cmd->sidemove > 0))
|
if ((sine > 0) == (cmd->sidemove > 0))
|
||||||
sine = 0; // Prevent jerking right when braking from going left, or vice versa
|
sine = 0; // Prevent jerking right when braking from going left, or vice versa
|
||||||
|
|
||||||
factor = min(40, FixedMul(player->speed, abs(sine))*2 / FRACUNIT);
|
factor = min(40, FixedMul(player->speed, abs(sine))*2 / FRACUNIT);
|
||||||
|
|
||||||
*myangle -= cmd->sidemove * factor * camadjustfactor;
|
camadjust = (cmd->sidemove * factor * camadjustfactor) >> 16;
|
||||||
|
|
||||||
|
*myangle -= camadjust << 16;
|
||||||
|
cmd->angleturn = (INT16)(cmd->angleturn - camadjust);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ticcmd_centerviewdown[forplayer] && (cv_cam_lockedinput[forplayer].value || (player->pflags & PF_STARTDASH)))
|
if (ticcmd_centerviewdown[forplayer] && (cv_cam_lockedinput[forplayer].value || (player->pflags & PF_STARTDASH)))
|
||||||
|
@ -1632,9 +1647,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
||||||
{
|
{
|
||||||
angle_t controlangle;
|
angle_t controlangle;
|
||||||
INT32 anglediff;
|
INT32 anglediff;
|
||||||
|
INT16 camadjust;
|
||||||
|
|
||||||
if ((cmd->forwardmove || cmd->sidemove) && !(player->pflags & PF_SPINNING))
|
if ((cmd->forwardmove || cmd->sidemove) && !(player->pflags & PF_SPINNING))
|
||||||
controlangle = (cmd->angleturn<<16) + R_PointToAngle2(0, 0, cmd->forwardmove << FRACBITS, -cmd->sidemove << FRACBITS);
|
controlangle = *myangle + R_PointToAngle2(0, 0, cmd->forwardmove << FRACBITS, -cmd->sidemove << FRACBITS);
|
||||||
else
|
else
|
||||||
controlangle = player->drawangle + drawangleoffset;
|
controlangle = player->drawangle + drawangleoffset;
|
||||||
|
|
||||||
|
@ -1651,7 +1667,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
||||||
anglediff = FixedMul(anglediff, sine);
|
anglediff = FixedMul(anglediff, sine);
|
||||||
}
|
}
|
||||||
|
|
||||||
*myangle += FixedMul(anglediff, camadjustfactor);
|
camadjust = FixedMul(anglediff, camadjustfactor) >> 16;
|
||||||
|
|
||||||
|
*myangle += camadjust << 16;
|
||||||
|
cmd->angleturn = (INT16)(cmd->angleturn + camadjust);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1665,6 +1684,9 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
||||||
LUAh_ViewpointSwitch(player, &players[consoleplayer], true);
|
LUAh_ViewpointSwitch(player, &players[consoleplayer], true);
|
||||||
displayplayer = consoleplayer;
|
displayplayer = consoleplayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd->angleturn = (INT16)(cmd->angleturn + ticcmd_oldangleturn[forplayer]);
|
||||||
|
ticcmd_oldangleturn[forplayer] = cmd->angleturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
ticcmd_t *G_CopyTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n)
|
ticcmd_t *G_CopyTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n)
|
||||||
|
@ -1866,6 +1888,7 @@ void G_StartTitleCard(void)
|
||||||
//
|
//
|
||||||
void G_PreLevelTitleCard(void)
|
void G_PreLevelTitleCard(void)
|
||||||
{
|
{
|
||||||
|
#ifndef NOWIPE
|
||||||
tic_t starttime = I_GetTime();
|
tic_t starttime = I_GetTime();
|
||||||
tic_t endtime = starttime + (PRELEVELTIME*NEWTICRATERATIO);
|
tic_t endtime = starttime + (PRELEVELTIME*NEWTICRATERATIO);
|
||||||
tic_t nowtime = starttime;
|
tic_t nowtime = starttime;
|
||||||
|
@ -1888,6 +1911,7 @@ void G_PreLevelTitleCard(void)
|
||||||
}
|
}
|
||||||
if (!cv_showhud.value)
|
if (!cv_showhud.value)
|
||||||
wipestyleflags = WSF_CROSSFADE;
|
wipestyleflags = WSF_CROSSFADE;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean titlecardforreload = false;
|
static boolean titlecardforreload = false;
|
||||||
|
@ -2161,6 +2185,10 @@ void G_Ticker(boolean run)
|
||||||
UINT32 i;
|
UINT32 i;
|
||||||
INT32 buf;
|
INT32 buf;
|
||||||
|
|
||||||
|
// see also SCR_DisplayMarathonInfo
|
||||||
|
if ((marathonmode & (MA_INIT|MA_INGAME)) == MA_INGAME && gamestate == GS_LEVEL)
|
||||||
|
marathontime++;
|
||||||
|
|
||||||
P_MapStart();
|
P_MapStart();
|
||||||
// do player reborns if needed
|
// do player reborns if needed
|
||||||
if (gamestate == GS_LEVEL)
|
if (gamestate == GS_LEVEL)
|
||||||
|
@ -2177,8 +2205,13 @@ void G_Ticker(boolean run)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Costs a life to retry ... unless the player in question is dead already.
|
// Costs a life to retry ... unless the player in question is dead already, or you haven't even touched the first starpost in marathon run.
|
||||||
if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES)
|
if (marathonmode && gamemap == spmarathon_start && !players[consoleplayer].starposttime)
|
||||||
|
{
|
||||||
|
marathonmode |= MA_INIT;
|
||||||
|
marathontime = 0;
|
||||||
|
}
|
||||||
|
else if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES)
|
||||||
players[consoleplayer].lives -= 1;
|
players[consoleplayer].lives -= 1;
|
||||||
|
|
||||||
G_DoReborn(consoleplayer);
|
G_DoReborn(consoleplayer);
|
||||||
|
@ -2205,11 +2238,16 @@ void G_Ticker(boolean run)
|
||||||
|
|
||||||
buf = gametic % BACKUPTICS;
|
buf = gametic % BACKUPTICS;
|
||||||
|
|
||||||
// read/write demo and check turbo cheat
|
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (playeringame[i])
|
if (playeringame[i])
|
||||||
|
{
|
||||||
G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1);
|
G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1);
|
||||||
|
|
||||||
|
players[i].angleturn += players[i].cmd.angleturn - players[i].oldrelangleturn;
|
||||||
|
players[i].oldrelangleturn = players[i].cmd.angleturn;
|
||||||
|
players[i].cmd.angleturn = players[i].angleturn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// do main actions
|
// do main actions
|
||||||
|
@ -2377,11 +2415,12 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
||||||
fixed_t height;
|
fixed_t height;
|
||||||
fixed_t spinheight;
|
fixed_t spinheight;
|
||||||
INT32 exiting;
|
INT32 exiting;
|
||||||
|
tic_t dashmode;
|
||||||
INT16 numboxes;
|
INT16 numboxes;
|
||||||
INT16 totalring;
|
INT16 totalring;
|
||||||
UINT8 laps;
|
UINT8 laps;
|
||||||
UINT8 mare;
|
UINT8 mare;
|
||||||
UINT8 skincolor;
|
UINT16 skincolor;
|
||||||
INT32 skin;
|
INT32 skin;
|
||||||
UINT32 availabilities;
|
UINT32 availabilities;
|
||||||
tic_t jointime;
|
tic_t jointime;
|
||||||
|
@ -2392,6 +2431,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
||||||
SINT8 pity;
|
SINT8 pity;
|
||||||
INT16 rings;
|
INT16 rings;
|
||||||
INT16 spheres;
|
INT16 spheres;
|
||||||
|
INT16 playerangleturn;
|
||||||
|
INT16 oldrelangleturn;
|
||||||
|
|
||||||
score = players[player].score;
|
score = players[player].score;
|
||||||
lives = players[player].lives;
|
lives = players[player].lives;
|
||||||
|
@ -2403,6 +2444,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
||||||
spectator = players[player].spectator;
|
spectator = players[player].spectator;
|
||||||
outofcoop = players[player].outofcoop;
|
outofcoop = players[player].outofcoop;
|
||||||
pflags = (players[player].pflags & (PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE|PF_TAGIT|PF_GAMETYPEOVER));
|
pflags = (players[player].pflags & (PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE|PF_TAGIT|PF_GAMETYPEOVER));
|
||||||
|
playerangleturn = players[player].angleturn;
|
||||||
|
oldrelangleturn = players[player].oldrelangleturn;
|
||||||
|
|
||||||
if (!betweenmaps)
|
if (!betweenmaps)
|
||||||
pflags |= (players[player].pflags & PF_FINISHED);
|
pflags |= (players[player].pflags & PF_FINISHED);
|
||||||
|
@ -2411,6 +2454,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
||||||
if (!(netgame || multiplayer))
|
if (!(netgame || multiplayer))
|
||||||
pflags |= (players[player].pflags & (PF_GODMODE|PF_NOCLIP|PF_INVIS));
|
pflags |= (players[player].pflags & (PF_GODMODE|PF_NOCLIP|PF_INVIS));
|
||||||
|
|
||||||
|
dashmode = players[player].dashmode;
|
||||||
|
|
||||||
numboxes = players[player].numboxes;
|
numboxes = players[player].numboxes;
|
||||||
laps = players[player].laps;
|
laps = players[player].laps;
|
||||||
totalring = players[player].totalring;
|
totalring = players[player].totalring;
|
||||||
|
@ -2474,6 +2519,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
||||||
p->quittime = quittime;
|
p->quittime = quittime;
|
||||||
p->spectator = spectator;
|
p->spectator = spectator;
|
||||||
p->outofcoop = outofcoop;
|
p->outofcoop = outofcoop;
|
||||||
|
p->angleturn = playerangleturn;
|
||||||
|
p->oldrelangleturn = oldrelangleturn;
|
||||||
|
|
||||||
// save player config truth reborn
|
// save player config truth reborn
|
||||||
p->skincolor = skincolor;
|
p->skincolor = skincolor;
|
||||||
|
@ -2509,6 +2556,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
||||||
p->spinheight = spinheight;
|
p->spinheight = spinheight;
|
||||||
p->exiting = exiting;
|
p->exiting = exiting;
|
||||||
|
|
||||||
|
p->dashmode = dashmode;
|
||||||
|
|
||||||
p->numboxes = numboxes;
|
p->numboxes = numboxes;
|
||||||
p->laps = laps;
|
p->laps = laps;
|
||||||
p->totalring = totalring;
|
p->totalring = totalring;
|
||||||
|
@ -2954,7 +3003,7 @@ void G_DoReborn(INT32 playernum)
|
||||||
players[i].starpostnum = 0;
|
players[i].starpostnum = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!countdowntimeup && (mapheaderinfo[gamemap-1]->levelflags & LF_NORELOAD))
|
if (!countdowntimeup && (mapheaderinfo[gamemap-1]->levelflags & LF_NORELOAD) && !(marathonmode & MA_INIT))
|
||||||
{
|
{
|
||||||
P_RespawnThings();
|
P_RespawnThings();
|
||||||
|
|
||||||
|
@ -3697,8 +3746,14 @@ static void G_DoCompleted(void)
|
||||||
// nextmap is 0-based, unlike gamemap
|
// nextmap is 0-based, unlike gamemap
|
||||||
if (nextmapoverride != 0)
|
if (nextmapoverride != 0)
|
||||||
nextmap = (INT16)(nextmapoverride-1);
|
nextmap = (INT16)(nextmapoverride-1);
|
||||||
|
else if (marathonmode && mapheaderinfo[gamemap-1]->marathonnext)
|
||||||
|
nextmap = (INT16)(mapheaderinfo[gamemap-1]->marathonnext-1);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
nextmap = (INT16)(mapheaderinfo[gamemap-1]->nextlevel-1);
|
nextmap = (INT16)(mapheaderinfo[gamemap-1]->nextlevel-1);
|
||||||
|
if (marathonmode && nextmap == spmarathon_start-1)
|
||||||
|
nextmap = 1100-1; // No infinite loop for you
|
||||||
|
}
|
||||||
|
|
||||||
// Remember last map for when you come out of the special stage.
|
// Remember last map for when you come out of the special stage.
|
||||||
if (!spec)
|
if (!spec)
|
||||||
|
@ -3722,10 +3777,12 @@ static void G_DoCompleted(void)
|
||||||
visitedmap[cm/8] |= (1<<(cm&7));
|
visitedmap[cm/8] |= (1<<(cm&7));
|
||||||
if (!mapheaderinfo[cm])
|
if (!mapheaderinfo[cm])
|
||||||
cm = -1; // guarantee error execution
|
cm = -1; // guarantee error execution
|
||||||
|
else if (marathonmode && mapheaderinfo[cm]->marathonnext)
|
||||||
|
cm = (INT16)(mapheaderinfo[cm]->marathonnext-1);
|
||||||
else
|
else
|
||||||
cm = (INT16)(mapheaderinfo[cm]->nextlevel-1);
|
cm = (INT16)(mapheaderinfo[cm]->nextlevel-1);
|
||||||
|
|
||||||
if (cm >= NUMMAPS || cm < 0) // out of range (either 1100-1102 or error)
|
if (cm >= NUMMAPS || cm < 0) // out of range (either 1100ish or error)
|
||||||
{
|
{
|
||||||
cm = nextmap; //Start the loop again so that the error checking below is executed.
|
cm = nextmap; //Start the loop again so that the error checking below is executed.
|
||||||
|
|
||||||
|
@ -3794,6 +3851,25 @@ static void G_DoCompleted(void)
|
||||||
if (nextmap < NUMMAPS && !mapheaderinfo[nextmap])
|
if (nextmap < NUMMAPS && !mapheaderinfo[nextmap])
|
||||||
P_AllocMapHeader(nextmap);
|
P_AllocMapHeader(nextmap);
|
||||||
|
|
||||||
|
// do this before going to the intermission or starting a custom cutscene, mostly for the sake of marathon mode but it also massively reduces redundant file save events in f_finale.c
|
||||||
|
if (nextmap >= 1100-1)
|
||||||
|
{
|
||||||
|
if (!gamecomplete)
|
||||||
|
gamecomplete = 2; // special temporary mode to prevent using SP level select in pause menu until the intermission is over without restricting it in every intermission
|
||||||
|
if (cursaveslot > 0)
|
||||||
|
{
|
||||||
|
if (marathonmode)
|
||||||
|
{
|
||||||
|
// don't keep a backup around when the run is done!
|
||||||
|
if (FIL_FileExists(liveeventbackup))
|
||||||
|
remove(liveeventbackup);
|
||||||
|
cursaveslot = 0;
|
||||||
|
}
|
||||||
|
else if ((!modifiedgame || savemoddata) && !(netgame || multiplayer))
|
||||||
|
G_SaveGame((UINT32)cursaveslot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the current gametype has no intermission screen set, then don't start it.
|
// If the current gametype has no intermission screen set, then don't start it.
|
||||||
Y_DetermineIntermissionType();
|
Y_DetermineIntermissionType();
|
||||||
|
|
||||||
|
@ -3810,6 +3886,7 @@ static void G_DoCompleted(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See also F_EndCutscene, the only other place which handles intra-map/ending transitions
|
||||||
void G_AfterIntermission(void)
|
void G_AfterIntermission(void)
|
||||||
{
|
{
|
||||||
Y_CleanupScreenBuffer();
|
Y_CleanupScreenBuffer();
|
||||||
|
@ -3820,9 +3897,12 @@ void G_AfterIntermission(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gamecomplete == 2) // special temporary mode to prevent using SP level select in pause menu until the intermission is over without restricting it in every intermission
|
||||||
|
gamecomplete = 1;
|
||||||
|
|
||||||
HU_ClearCEcho();
|
HU_ClearCEcho();
|
||||||
|
|
||||||
if ((gametyperules & GTR_CUTSCENES) && mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1) // Start a custom cutscene.
|
if ((gametyperules & GTR_CUTSCENES) && mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1 && !(marathonmode & MA_NOCUTSCENES)) // Start a custom cutscene.
|
||||||
F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false);
|
F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3963,7 +4043,7 @@ void G_EndGame(void)
|
||||||
void G_LoadGameSettings(void)
|
void G_LoadGameSettings(void)
|
||||||
{
|
{
|
||||||
// defaults
|
// defaults
|
||||||
spstage_start = 1;
|
spstage_start = spmarathon_start = 1;
|
||||||
sstage_start = 50;
|
sstage_start = 50;
|
||||||
sstage_end = 56; // 7 special stages in vanilla SRB2
|
sstage_end = 56; // 7 special stages in vanilla SRB2
|
||||||
sstage_end++; // plus one weirdo
|
sstage_end++; // plus one weirdo
|
||||||
|
@ -4283,6 +4363,9 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
|
||||||
startonmapnum = mapoverride;
|
startonmapnum = mapoverride;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (marathonmode)
|
||||||
|
strcpy(savename, liveeventbackup);
|
||||||
|
else
|
||||||
sprintf(savename, savegamename, slot);
|
sprintf(savename, savegamename, slot);
|
||||||
|
|
||||||
length = FIL_ReadFile(savename, &savebuffer);
|
length = FIL_ReadFile(savename, &savebuffer);
|
||||||
|
@ -4295,7 +4378,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
|
||||||
save_p = savebuffer;
|
save_p = savebuffer;
|
||||||
|
|
||||||
memset(vcheck, 0, sizeof (vcheck));
|
memset(vcheck, 0, sizeof (vcheck));
|
||||||
sprintf(vcheck, "version %d", VERSION);
|
sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION);
|
||||||
if (strcmp((const char *)save_p, (const char *)vcheck))
|
if (strcmp((const char *)save_p, (const char *)vcheck))
|
||||||
{
|
{
|
||||||
#ifdef SAVEGAME_OTHERVERSIONS
|
#ifdef SAVEGAME_OTHERVERSIONS
|
||||||
|
@ -4335,6 +4418,11 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
|
||||||
memset(&savedata, 0, sizeof(savedata));
|
memset(&savedata, 0, sizeof(savedata));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (marathonmode)
|
||||||
|
{
|
||||||
|
marathontime = READUINT32(save_p);
|
||||||
|
marathonmode |= READUINT8(save_p);
|
||||||
|
}
|
||||||
|
|
||||||
// done
|
// done
|
||||||
Z_Free(savebuffer);
|
Z_Free(savebuffer);
|
||||||
|
@ -4363,13 +4451,12 @@ void G_SaveGame(UINT32 slot)
|
||||||
char savename[256] = "";
|
char savename[256] = "";
|
||||||
const char *backup;
|
const char *backup;
|
||||||
|
|
||||||
|
if (marathonmode)
|
||||||
|
strcpy(savename, liveeventbackup);
|
||||||
|
else
|
||||||
sprintf(savename, savegamename, slot);
|
sprintf(savename, savegamename, slot);
|
||||||
backup = va("%s",savename);
|
backup = va("%s",savename);
|
||||||
|
|
||||||
// save during evaluation or credits? game's over, folks!
|
|
||||||
if (gamestate == GS_ENDING || gamestate == GS_CREDITS || gamestate == GS_EVALUATION)
|
|
||||||
gamecomplete = true;
|
|
||||||
|
|
||||||
gameaction = ga_nothing;
|
gameaction = ga_nothing;
|
||||||
{
|
{
|
||||||
char name[VERSIONSIZE];
|
char name[VERSIONSIZE];
|
||||||
|
@ -4383,10 +4470,15 @@ void G_SaveGame(UINT32 slot)
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(name, 0, sizeof (name));
|
memset(name, 0, sizeof (name));
|
||||||
sprintf(name, "version %d", VERSION);
|
sprintf(name, (marathonmode ? "back-up %d" : "version %d"), VERSION);
|
||||||
WRITEMEM(save_p, name, VERSIONSIZE);
|
WRITEMEM(save_p, name, VERSIONSIZE);
|
||||||
|
|
||||||
P_SaveGame();
|
P_SaveGame();
|
||||||
|
if (marathonmode)
|
||||||
|
{
|
||||||
|
WRITEUINT32(save_p, marathontime);
|
||||||
|
WRITEUINT8(save_p, (marathonmode & ~MA_INIT));
|
||||||
|
}
|
||||||
|
|
||||||
length = save_p - savebuffer;
|
length = save_p - savebuffer;
|
||||||
saved = FIL_WriteFile(backup, savebuffer, length);
|
saved = FIL_WriteFile(backup, savebuffer, length);
|
||||||
|
@ -4399,7 +4491,7 @@ void G_SaveGame(UINT32 slot)
|
||||||
if (cv_debug && saved)
|
if (cv_debug && saved)
|
||||||
CONS_Printf(M_GetText("Game saved.\n"));
|
CONS_Printf(M_GetText("Game saved.\n"));
|
||||||
else if (!saved)
|
else if (!saved)
|
||||||
CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, savegamename);
|
CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, (marathonmode ? liveeventbackup : savegamename));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BADSAVE goto cleanup;
|
#define BADSAVE goto cleanup;
|
||||||
|
@ -4412,6 +4504,9 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
|
||||||
char savename[255];
|
char savename[255];
|
||||||
const char *backup;
|
const char *backup;
|
||||||
|
|
||||||
|
if (marathonmode)
|
||||||
|
strcpy(savename, liveeventbackup);
|
||||||
|
else
|
||||||
sprintf(savename, savegamename, slot);
|
sprintf(savename, savegamename, slot);
|
||||||
backup = va("%s",savename);
|
backup = va("%s",savename);
|
||||||
|
|
||||||
|
@ -4431,7 +4526,7 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
|
||||||
save_p = savebuffer;
|
save_p = savebuffer;
|
||||||
// Version check
|
// Version check
|
||||||
memset(vcheck, 0, sizeof (vcheck));
|
memset(vcheck, 0, sizeof (vcheck));
|
||||||
sprintf(vcheck, "version %d", VERSION);
|
sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION);
|
||||||
if (strcmp((const char *)save_p, (const char *)vcheck)) BADSAVE
|
if (strcmp((const char *)save_p, (const char *)vcheck)) BADSAVE
|
||||||
save_p += VERSIONSIZE;
|
save_p += VERSIONSIZE;
|
||||||
|
|
||||||
|
@ -4498,7 +4593,7 @@ cleanup:
|
||||||
if (cv_debug && saved)
|
if (cv_debug && saved)
|
||||||
CONS_Printf(M_GetText("Game saved.\n"));
|
CONS_Printf(M_GetText("Game saved.\n"));
|
||||||
else if (!saved)
|
else if (!saved)
|
||||||
CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, savegamename);
|
CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, (marathonmode ? liveeventbackup : savegamename));
|
||||||
Z_Free(savebuffer);
|
Z_Free(savebuffer);
|
||||||
save_p = savebuffer = NULL;
|
save_p = savebuffer = NULL;
|
||||||
|
|
||||||
|
@ -4513,7 +4608,7 @@ cleanup:
|
||||||
//
|
//
|
||||||
void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, boolean SSSG, boolean FLS)
|
void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, boolean SSSG, boolean FLS)
|
||||||
{
|
{
|
||||||
UINT8 color = skins[pickedchar].prefcolor;
|
UINT16 color = skins[pickedchar].prefcolor;
|
||||||
paused = false;
|
paused = false;
|
||||||
|
|
||||||
if (demoplayback)
|
if (demoplayback)
|
||||||
|
@ -4636,7 +4731,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
|
||||||
automapactive = false;
|
automapactive = false;
|
||||||
imcontinuing = false;
|
imcontinuing = false;
|
||||||
|
|
||||||
if ((gametyperules & GTR_CUTSCENES) && !skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking) // Start a custom cutscene.
|
if ((gametyperules & GTR_CUTSCENES) && !skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking && !(marathonmode & MA_NOCUTSCENES)) // Start a custom cutscene.
|
||||||
F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer);
|
F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer);
|
||||||
else
|
else
|
||||||
G_DoLoadLevel(resetplayer);
|
G_DoLoadLevel(resetplayer);
|
||||||
|
@ -4667,7 +4762,7 @@ char *G_BuildMapTitle(INT32 mapnum)
|
||||||
{
|
{
|
||||||
size_t len = 1;
|
size_t len = 1;
|
||||||
const char *zonetext = NULL;
|
const char *zonetext = NULL;
|
||||||
const INT32 actnum = mapheaderinfo[mapnum-1]->actnum;
|
const UINT8 actnum = mapheaderinfo[mapnum-1]->actnum;
|
||||||
|
|
||||||
len += strlen(mapheaderinfo[mapnum-1]->lvlttl);
|
len += strlen(mapheaderinfo[mapnum-1]->lvlttl);
|
||||||
if (!(mapheaderinfo[mapnum-1]->levelflags & LF_NOZONE))
|
if (!(mapheaderinfo[mapnum-1]->levelflags & LF_NOZONE))
|
||||||
|
|
|
@ -93,6 +93,7 @@ typedef enum
|
||||||
// build an internal map name MAPxx from map number
|
// build an internal map name MAPxx from map number
|
||||||
const char *G_BuildMapName(INT32 map);
|
const char *G_BuildMapName(INT32 map);
|
||||||
|
|
||||||
|
extern INT16 ticcmd_oldangleturn[2];
|
||||||
extern boolean ticcmd_centerviewdown[2]; // For simple controls, lock the camera behind the player
|
extern boolean ticcmd_centerviewdown[2]; // For simple controls, lock the camera behind the player
|
||||||
extern mobj_t *ticcmd_ztargetfocus[2]; // Locking onto an object?
|
extern mobj_t *ticcmd_ztargetfocus[2]; // Locking onto an object?
|
||||||
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer);
|
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer);
|
||||||
|
|
|
@ -57,6 +57,7 @@ extern UINT8 ultimatemode; // was sk_insane
|
||||||
extern gameaction_t gameaction;
|
extern gameaction_t gameaction;
|
||||||
|
|
||||||
extern boolean botingame;
|
extern boolean botingame;
|
||||||
extern UINT8 botskin, botcolor;
|
extern UINT8 botskin;
|
||||||
|
extern UINT16 botcolor;
|
||||||
|
|
||||||
#endif //__G_STATE__
|
#endif //__G_STATE__
|
||||||
|
|
|
@ -1,20 +1,12 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
|
||||||
// Copyright (C) 2001 by DooM Legacy Team.
|
// Copyright (C) 2001 by DooM Legacy Team.
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software distributed under the
|
||||||
// modify it under the terms of the GNU General Public License
|
// terms of the GNU General Public License, version 2.
|
||||||
// as published by the Free Software Foundation; either version 2
|
// See the 'LICENSE' file for more details.
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hw3dsdrv.h
|
||||||
/// \brief 3D sound import/export prototypes for low-level hardware interface
|
/// \brief 3D sound import/export prototypes for low-level hardware interface
|
||||||
|
|
||||||
#ifndef __HW_3DS_DRV_H__
|
#ifndef __HW_3DS_DRV_H__
|
||||||
|
|
|
@ -1,19 +1,12 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
|
||||||
// Copyright (C) 2001 by DooM Legacy Team.
|
// Copyright (C) 2001 by DooM Legacy Team.
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software distributed under the
|
||||||
// modify it under the terms of the GNU General Public License
|
// terms of the GNU General Public License, version 2.
|
||||||
// as published by the Free Software Foundation; either version 2
|
// See the 'LICENSE' file for more details.
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hw3sound.c
|
||||||
/// \brief Hardware 3D sound general code
|
/// \brief Hardware 3D sound general code
|
||||||
|
|
||||||
#include "../doomdef.h"
|
#include "../doomdef.h"
|
||||||
|
|
|
@ -1,20 +1,12 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
|
||||||
// Copyright (C) 2001 by DooM Legacy Team.
|
// Copyright (C) 2001 by DooM Legacy Team.
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software distributed under the
|
||||||
// modify it under the terms of the GNU General Public License
|
// terms of the GNU General Public License, version 2.
|
||||||
// as published by the Free Software Foundation; either version 2
|
// See the 'LICENSE' file for more details.
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hw3sound.h
|
||||||
/// \brief High-level functions of hardware 3D sound
|
/// \brief High-level functions of hardware 3D sound
|
||||||
|
|
||||||
#ifndef __HW3_SOUND_H__
|
#ifndef __HW3_SOUND_H__
|
||||||
|
|
|
@ -0,0 +1,454 @@
|
||||||
|
// SONIC ROBO BLAST 2
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||||
|
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||||
|
//
|
||||||
|
// This program is free software distributed under the
|
||||||
|
// terms of the GNU General Public License, version 2.
|
||||||
|
// See the 'LICENSE' file for more details.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/// \file hw_batching.c
|
||||||
|
/// \brief Draw call batching and related things.
|
||||||
|
|
||||||
|
#ifdef HWRENDER
|
||||||
|
#include "hw_glob.h"
|
||||||
|
#include "hw_batching.h"
|
||||||
|
#include "../i_system.h"
|
||||||
|
|
||||||
|
// The texture for the next polygon given to HWR_ProcessPolygon.
|
||||||
|
// Set with HWR_SetCurrentTexture.
|
||||||
|
GLMipmap_t *current_texture = NULL;
|
||||||
|
|
||||||
|
boolean currently_batching = false;
|
||||||
|
|
||||||
|
FOutVector* finalVertexArray = NULL;// contains subset of sorted vertices and texture coordinates to be sent to gpu
|
||||||
|
UINT32* finalVertexIndexArray = NULL;// contains indexes for glDrawElements, taking into account fan->triangles conversion
|
||||||
|
// NOTE have this alloced as 3x finalVertexArray size
|
||||||
|
int finalVertexArrayAllocSize = 65536;
|
||||||
|
//GLubyte* colorArray = NULL;// contains color data to be sent to gpu, if needed
|
||||||
|
//int colorArrayAllocSize = 65536;
|
||||||
|
// not gonna use this for now, just sort by color and change state when it changes
|
||||||
|
// later maybe when using vertex attributes if it's needed
|
||||||
|
|
||||||
|
PolygonArrayEntry* polygonArray = NULL;// contains the polygon data from DrawPolygon, waiting to be processed
|
||||||
|
int polygonArraySize = 0;
|
||||||
|
UINT32* polygonIndexArray = NULL;// contains sorting pointers for polygonArray
|
||||||
|
int polygonArrayAllocSize = 65536;
|
||||||
|
|
||||||
|
FOutVector* unsortedVertexArray = NULL;// contains unsorted vertices and texture coordinates from DrawPolygon
|
||||||
|
int unsortedVertexArraySize = 0;
|
||||||
|
int unsortedVertexArrayAllocSize = 65536;
|
||||||
|
|
||||||
|
// Enables batching mode. HWR_ProcessPolygon will collect polygons instead of passing them directly to the rendering backend.
|
||||||
|
// Call HWR_RenderBatches to render all the collected geometry.
|
||||||
|
void HWR_StartBatching(void)
|
||||||
|
{
|
||||||
|
if (currently_batching)
|
||||||
|
I_Error("Repeat call to HWR_StartBatching without HWR_RenderBatches");
|
||||||
|
|
||||||
|
// init arrays if that has not been done yet
|
||||||
|
if (!finalVertexArray)
|
||||||
|
{
|
||||||
|
finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector));
|
||||||
|
finalVertexIndexArray = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32));
|
||||||
|
polygonArray = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry));
|
||||||
|
polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32));
|
||||||
|
unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector));
|
||||||
|
}
|
||||||
|
|
||||||
|
currently_batching = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This replaces the direct calls to pfnSetTexture in cases where batching is available.
|
||||||
|
// The texture selection is saved for the next HWR_ProcessPolygon call.
|
||||||
|
// Doing this was easier than getting a texture pointer to HWR_ProcessPolygon.
|
||||||
|
void HWR_SetCurrentTexture(GLMipmap_t *texture)
|
||||||
|
{
|
||||||
|
if (currently_batching)
|
||||||
|
{
|
||||||
|
current_texture = texture;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HWD.pfnSetTexture(texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If batching is enabled, this function collects the polygon data and the chosen texture
|
||||||
|
// for later use in HWR_RenderBatches. Otherwise the rendering backend is used to
|
||||||
|
// render the polygon immediately.
|
||||||
|
void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial)
|
||||||
|
{
|
||||||
|
if (currently_batching)
|
||||||
|
{
|
||||||
|
if (!pSurf)
|
||||||
|
I_Error("Got a null FSurfaceInfo in batching");// nulls should not come in the stuff that batching currently applies to
|
||||||
|
if (polygonArraySize == polygonArrayAllocSize)
|
||||||
|
{
|
||||||
|
PolygonArrayEntry* new_array;
|
||||||
|
// ran out of space, make new array double the size
|
||||||
|
polygonArrayAllocSize *= 2;
|
||||||
|
new_array = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry));
|
||||||
|
memcpy(new_array, polygonArray, polygonArraySize * sizeof(PolygonArrayEntry));
|
||||||
|
free(polygonArray);
|
||||||
|
polygonArray = new_array;
|
||||||
|
// also need to redo the index array, dont need to copy it though
|
||||||
|
free(polygonIndexArray);
|
||||||
|
polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32));
|
||||||
|
}
|
||||||
|
|
||||||
|
while (unsortedVertexArraySize + (int)iNumPts > unsortedVertexArrayAllocSize)
|
||||||
|
{
|
||||||
|
FOutVector* new_array;
|
||||||
|
// need more space for vertices in unsortedVertexArray
|
||||||
|
unsortedVertexArrayAllocSize *= 2;
|
||||||
|
new_array = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector));
|
||||||
|
memcpy(new_array, unsortedVertexArray, unsortedVertexArraySize * sizeof(FOutVector));
|
||||||
|
free(unsortedVertexArray);
|
||||||
|
unsortedVertexArray = new_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the polygon data to the arrays
|
||||||
|
|
||||||
|
polygonArray[polygonArraySize].surf = *pSurf;
|
||||||
|
polygonArray[polygonArraySize].vertsIndex = unsortedVertexArraySize;
|
||||||
|
polygonArray[polygonArraySize].numVerts = iNumPts;
|
||||||
|
polygonArray[polygonArraySize].polyFlags = PolyFlags;
|
||||||
|
polygonArray[polygonArraySize].texture = current_texture;
|
||||||
|
polygonArray[polygonArraySize].shader = shader;
|
||||||
|
polygonArray[polygonArraySize].horizonSpecial = horizonSpecial;
|
||||||
|
polygonArraySize++;
|
||||||
|
|
||||||
|
memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector));
|
||||||
|
unsortedVertexArraySize += iNumPts;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (shader)
|
||||||
|
HWD.pfnSetShader(shader);
|
||||||
|
HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int comparePolygons(const void *p1, const void *p2)
|
||||||
|
{
|
||||||
|
unsigned int index1 = *(const unsigned int*)p1;
|
||||||
|
unsigned int index2 = *(const unsigned int*)p2;
|
||||||
|
PolygonArrayEntry* poly1 = &polygonArray[index1];
|
||||||
|
PolygonArrayEntry* poly2 = &polygonArray[index2];
|
||||||
|
int diff;
|
||||||
|
INT64 diff64;
|
||||||
|
|
||||||
|
int shader1 = poly1->shader;
|
||||||
|
int shader2 = poly2->shader;
|
||||||
|
// make skywalls and horizon lines first in order
|
||||||
|
if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial)
|
||||||
|
shader1 = -1;
|
||||||
|
if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial)
|
||||||
|
shader2 = -1;
|
||||||
|
diff = shader1 - shader2;
|
||||||
|
if (diff != 0) return diff;
|
||||||
|
|
||||||
|
// skywalls and horizon lines must retain their order for horizon lines to work
|
||||||
|
if (shader1 == -1 && shader2 == -1)
|
||||||
|
return index1 - index2;
|
||||||
|
|
||||||
|
diff64 = poly1->texture - poly2->texture;
|
||||||
|
if (diff64 != 0) return diff64;
|
||||||
|
|
||||||
|
diff = poly1->polyFlags - poly2->polyFlags;
|
||||||
|
if (diff != 0) return diff;
|
||||||
|
|
||||||
|
diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba;
|
||||||
|
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
|
||||||
|
diff64 = poly1->surf.TintColor.rgba - poly2->surf.TintColor.rgba;
|
||||||
|
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
|
||||||
|
diff64 = poly1->surf.FadeColor.rgba - poly2->surf.FadeColor.rgba;
|
||||||
|
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
|
||||||
|
|
||||||
|
diff = poly1->surf.LightInfo.light_level - poly2->surf.LightInfo.light_level;
|
||||||
|
if (diff != 0) return diff;
|
||||||
|
diff = poly1->surf.LightInfo.fade_start - poly2->surf.LightInfo.fade_start;
|
||||||
|
if (diff != 0) return diff;
|
||||||
|
diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end;
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int comparePolygonsNoShaders(const void *p1, const void *p2)
|
||||||
|
{
|
||||||
|
unsigned int index1 = *(const unsigned int*)p1;
|
||||||
|
unsigned int index2 = *(const unsigned int*)p2;
|
||||||
|
PolygonArrayEntry* poly1 = &polygonArray[index1];
|
||||||
|
PolygonArrayEntry* poly2 = &polygonArray[index2];
|
||||||
|
int diff;
|
||||||
|
INT64 diff64;
|
||||||
|
|
||||||
|
GLMipmap_t *texture1 = poly1->texture;
|
||||||
|
GLMipmap_t *texture2 = poly2->texture;
|
||||||
|
if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial)
|
||||||
|
texture1 = NULL;
|
||||||
|
if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial)
|
||||||
|
texture2 = NULL;
|
||||||
|
diff64 = texture1 - texture2;
|
||||||
|
if (diff64 != 0) return diff64;
|
||||||
|
|
||||||
|
// skywalls and horizon lines must retain their order for horizon lines to work
|
||||||
|
if (texture1 == NULL && texture2 == NULL)
|
||||||
|
return index1 - index2;
|
||||||
|
|
||||||
|
diff = poly1->polyFlags - poly2->polyFlags;
|
||||||
|
if (diff != 0) return diff;
|
||||||
|
|
||||||
|
diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba;
|
||||||
|
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function organizes the geometry collected by HWR_ProcessPolygon calls into batches and uses
|
||||||
|
// the rendering backend to draw them.
|
||||||
|
void HWR_RenderBatches(void)
|
||||||
|
{
|
||||||
|
int finalVertexWritePos = 0;// position in finalVertexArray
|
||||||
|
int finalIndexWritePos = 0;// position in finalVertexIndexArray
|
||||||
|
|
||||||
|
int polygonReadPos = 0;// position in polygonIndexArray
|
||||||
|
|
||||||
|
int currentShader;
|
||||||
|
int nextShader = 0;
|
||||||
|
GLMipmap_t *currentTexture;
|
||||||
|
GLMipmap_t *nextTexture = NULL;
|
||||||
|
FBITFIELD currentPolyFlags = 0;
|
||||||
|
FBITFIELD nextPolyFlags = 0;
|
||||||
|
FSurfaceInfo currentSurfaceInfo;
|
||||||
|
FSurfaceInfo nextSurfaceInfo;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!currently_batching)
|
||||||
|
I_Error("HWR_RenderBatches called without starting batching");
|
||||||
|
|
||||||
|
nextSurfaceInfo.LightInfo.fade_end = 0;
|
||||||
|
nextSurfaceInfo.LightInfo.fade_start = 0;
|
||||||
|
nextSurfaceInfo.LightInfo.light_level = 0;
|
||||||
|
|
||||||
|
currently_batching = false;// no longer collecting batches
|
||||||
|
if (!polygonArraySize)
|
||||||
|
{
|
||||||
|
rs_hw_numpolys = rs_hw_numcalls = rs_hw_numshaders = rs_hw_numtextures = rs_hw_numpolyflags = rs_hw_numcolors = 0;
|
||||||
|
return;// nothing to draw
|
||||||
|
}
|
||||||
|
// init stats vars
|
||||||
|
rs_hw_numpolys = polygonArraySize;
|
||||||
|
rs_hw_numcalls = rs_hw_numverts = 0;
|
||||||
|
rs_hw_numshaders = rs_hw_numtextures = rs_hw_numpolyflags = rs_hw_numcolors = 1;
|
||||||
|
// init polygonIndexArray
|
||||||
|
for (i = 0; i < polygonArraySize; i++)
|
||||||
|
{
|
||||||
|
polygonIndexArray[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort polygons
|
||||||
|
rs_hw_batchsorttime = I_GetTimeMicros();
|
||||||
|
if (cv_grshaders.value && gr_shadersavailable)
|
||||||
|
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons);
|
||||||
|
else
|
||||||
|
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders);
|
||||||
|
rs_hw_batchsorttime = I_GetTimeMicros() - rs_hw_batchsorttime;
|
||||||
|
// sort order
|
||||||
|
// 1. shader
|
||||||
|
// 2. texture
|
||||||
|
// 3. polyflags
|
||||||
|
// 4. colors + light level
|
||||||
|
// not sure about what order of the last 2 should be, or if it even matters
|
||||||
|
|
||||||
|
rs_hw_batchdrawtime = I_GetTimeMicros();
|
||||||
|
|
||||||
|
currentShader = polygonArray[polygonIndexArray[0]].shader;
|
||||||
|
currentTexture = polygonArray[polygonIndexArray[0]].texture;
|
||||||
|
currentPolyFlags = polygonArray[polygonIndexArray[0]].polyFlags;
|
||||||
|
currentSurfaceInfo = polygonArray[polygonIndexArray[0]].surf;
|
||||||
|
// For now, will sort and track the colors. Vertex attributes could be used instead of uniforms
|
||||||
|
// and a color array could replace the color calls.
|
||||||
|
|
||||||
|
// set state for first batch
|
||||||
|
|
||||||
|
if (cv_grshaders.value && gr_shadersavailable)
|
||||||
|
{
|
||||||
|
HWD.pfnSetShader(currentShader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPolyFlags & PF_NoTexture)
|
||||||
|
currentTexture = NULL;
|
||||||
|
else
|
||||||
|
HWD.pfnSetTexture(currentTexture);
|
||||||
|
|
||||||
|
while (1)// note: remember handling notexture polyflag as having texture number 0 (also in comparePolygons)
|
||||||
|
{
|
||||||
|
int firstIndex;
|
||||||
|
int lastIndex;
|
||||||
|
|
||||||
|
boolean stopFlag = false;
|
||||||
|
boolean changeState = false;
|
||||||
|
boolean changeShader = false;
|
||||||
|
boolean changeTexture = false;
|
||||||
|
boolean changePolyFlags = false;
|
||||||
|
boolean changeSurfaceInfo = false;
|
||||||
|
|
||||||
|
// steps:
|
||||||
|
// write vertices
|
||||||
|
// check for changes or end, otherwise go back to writing
|
||||||
|
// changes will affect the next vars and the change bools
|
||||||
|
// end could set flag for stopping
|
||||||
|
// execute draw call
|
||||||
|
// could check ending flag here
|
||||||
|
// change states according to next vars and change bools, updating the current vars and reseting the bools
|
||||||
|
// reset write pos
|
||||||
|
// repeat loop
|
||||||
|
|
||||||
|
int index = polygonIndexArray[polygonReadPos++];
|
||||||
|
int numVerts = polygonArray[index].numVerts;
|
||||||
|
// before writing, check if there is enough room
|
||||||
|
// using 'while' instead of 'if' here makes sure that there will *always* be enough room.
|
||||||
|
// probably never will this loop run more than once though
|
||||||
|
while (finalVertexWritePos + numVerts > finalVertexArrayAllocSize)
|
||||||
|
{
|
||||||
|
FOutVector* new_array;
|
||||||
|
unsigned int* new_index_array;
|
||||||
|
finalVertexArrayAllocSize *= 2;
|
||||||
|
new_array = malloc(finalVertexArrayAllocSize * sizeof(FOutVector));
|
||||||
|
memcpy(new_array, finalVertexArray, finalVertexWritePos * sizeof(FOutVector));
|
||||||
|
free(finalVertexArray);
|
||||||
|
finalVertexArray = new_array;
|
||||||
|
// also increase size of index array, 3x of vertex array since
|
||||||
|
// going from fans to triangles increases vertex count to 3x
|
||||||
|
new_index_array = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32));
|
||||||
|
memcpy(new_index_array, finalVertexIndexArray, finalIndexWritePos * sizeof(UINT32));
|
||||||
|
free(finalVertexIndexArray);
|
||||||
|
finalVertexIndexArray = new_index_array;
|
||||||
|
}
|
||||||
|
// write the vertices of the polygon
|
||||||
|
memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[polygonArray[index].vertsIndex],
|
||||||
|
numVerts * sizeof(FOutVector));
|
||||||
|
// write the indexes, pointing to the fan vertexes but in triangles format
|
||||||
|
firstIndex = finalVertexWritePos;
|
||||||
|
lastIndex = finalVertexWritePos + numVerts;
|
||||||
|
finalVertexWritePos += 2;
|
||||||
|
while (finalVertexWritePos < lastIndex)
|
||||||
|
{
|
||||||
|
finalVertexIndexArray[finalIndexWritePos++] = firstIndex;
|
||||||
|
finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos - 1;
|
||||||
|
finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (polygonReadPos >= polygonArraySize)
|
||||||
|
{
|
||||||
|
stopFlag = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// check if a state change is required, set the change bools and next vars
|
||||||
|
int nextIndex = polygonIndexArray[polygonReadPos];
|
||||||
|
nextShader = polygonArray[nextIndex].shader;
|
||||||
|
nextTexture = polygonArray[nextIndex].texture;
|
||||||
|
nextPolyFlags = polygonArray[nextIndex].polyFlags;
|
||||||
|
nextSurfaceInfo = polygonArray[nextIndex].surf;
|
||||||
|
if (nextPolyFlags & PF_NoTexture)
|
||||||
|
nextTexture = 0;
|
||||||
|
if (currentShader != nextShader && cv_grshaders.value && gr_shadersavailable)
|
||||||
|
{
|
||||||
|
changeState = true;
|
||||||
|
changeShader = true;
|
||||||
|
}
|
||||||
|
if (currentTexture != nextTexture)
|
||||||
|
{
|
||||||
|
changeState = true;
|
||||||
|
changeTexture = true;
|
||||||
|
}
|
||||||
|
if (currentPolyFlags != nextPolyFlags)
|
||||||
|
{
|
||||||
|
changeState = true;
|
||||||
|
changePolyFlags = true;
|
||||||
|
}
|
||||||
|
if (cv_grshaders.value && gr_shadersavailable)
|
||||||
|
{
|
||||||
|
if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba ||
|
||||||
|
currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba ||
|
||||||
|
currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba ||
|
||||||
|
currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level ||
|
||||||
|
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
|
||||||
|
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end)
|
||||||
|
{
|
||||||
|
changeState = true;
|
||||||
|
changeSurfaceInfo = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba)
|
||||||
|
{
|
||||||
|
changeState = true;
|
||||||
|
changeSurfaceInfo = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changeState || stopFlag)
|
||||||
|
{
|
||||||
|
// execute draw call
|
||||||
|
HWD.pfnDrawIndexedTriangles(¤tSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray);
|
||||||
|
// update stats
|
||||||
|
rs_hw_numcalls++;
|
||||||
|
rs_hw_numverts += finalIndexWritePos;
|
||||||
|
// reset write positions
|
||||||
|
finalVertexWritePos = 0;
|
||||||
|
finalIndexWritePos = 0;
|
||||||
|
}
|
||||||
|
else continue;
|
||||||
|
|
||||||
|
// if we're here then either its time to stop or time to change state
|
||||||
|
if (stopFlag) break;
|
||||||
|
|
||||||
|
// change state according to change bools and next vars, update current vars and reset bools
|
||||||
|
if (changeShader)
|
||||||
|
{
|
||||||
|
HWD.pfnSetShader(nextShader);
|
||||||
|
currentShader = nextShader;
|
||||||
|
changeShader = false;
|
||||||
|
|
||||||
|
rs_hw_numshaders++;
|
||||||
|
}
|
||||||
|
if (changeTexture)
|
||||||
|
{
|
||||||
|
// texture should be already ready for use from calls to SetTexture during batch collection
|
||||||
|
HWD.pfnSetTexture(nextTexture);
|
||||||
|
currentTexture = nextTexture;
|
||||||
|
changeTexture = false;
|
||||||
|
|
||||||
|
rs_hw_numtextures++;
|
||||||
|
}
|
||||||
|
if (changePolyFlags)
|
||||||
|
{
|
||||||
|
currentPolyFlags = nextPolyFlags;
|
||||||
|
changePolyFlags = false;
|
||||||
|
|
||||||
|
rs_hw_numpolyflags++;
|
||||||
|
}
|
||||||
|
if (changeSurfaceInfo)
|
||||||
|
{
|
||||||
|
currentSurfaceInfo = nextSurfaceInfo;
|
||||||
|
changeSurfaceInfo = false;
|
||||||
|
|
||||||
|
rs_hw_numcolors++;
|
||||||
|
}
|
||||||
|
// and that should be it?
|
||||||
|
}
|
||||||
|
// reset the arrays (set sizes to 0)
|
||||||
|
polygonArraySize = 0;
|
||||||
|
unsortedVertexArraySize = 0;
|
||||||
|
|
||||||
|
rs_hw_batchdrawtime = I_GetTimeMicros() - rs_hw_batchdrawtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // HWRENDER
|
|
@ -0,0 +1,37 @@
|
||||||
|
// SONIC ROBO BLAST 2
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||||
|
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||||
|
//
|
||||||
|
// This program is free software distributed under the
|
||||||
|
// terms of the GNU General Public License, version 2.
|
||||||
|
// See the 'LICENSE' file for more details.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/// \file hw_batching.h
|
||||||
|
/// \brief Draw call batching and related things.
|
||||||
|
|
||||||
|
#ifndef __HWR_BATCHING_H__
|
||||||
|
#define __HWR_BATCHING_H__
|
||||||
|
|
||||||
|
#include "hw_defs.h"
|
||||||
|
#include "hw_data.h"
|
||||||
|
#include "hw_drv.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused
|
||||||
|
unsigned int vertsIndex;// location of verts in unsortedVertexArray
|
||||||
|
FUINT numVerts;
|
||||||
|
FBITFIELD polyFlags;
|
||||||
|
GLMipmap_t *texture;
|
||||||
|
int shader;
|
||||||
|
// this tells batching that the plane belongs to a horizon line and must be drawn in correct order with the skywalls
|
||||||
|
boolean horizonSpecial;
|
||||||
|
} PolygonArrayEntry;
|
||||||
|
|
||||||
|
void HWR_StartBatching(void);
|
||||||
|
void HWR_SetCurrentTexture(GLMipmap_t *texture);
|
||||||
|
void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial);
|
||||||
|
void HWR_RenderBatches(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,19 +1,12 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
|
||||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software distributed under the
|
||||||
// modify it under the terms of the GNU General Public License
|
// terms of the GNU General Public License, version 2.
|
||||||
// as published by the Free Software Foundation; either version 2
|
// See the 'LICENSE' file for more details.
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hw_bsp.c
|
||||||
/// \brief convert SRB2 map
|
/// \brief convert SRB2 map
|
||||||
|
|
||||||
#include "../doomdef.h"
|
#include "../doomdef.h"
|
||||||
|
|
|
@ -1,20 +1,13 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
|
||||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||||
|
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software distributed under the
|
||||||
// modify it under the terms of the GNU General Public License
|
// terms of the GNU General Public License, version 2.
|
||||||
// as published by the Free Software Foundation; either version 2
|
// See the 'LICENSE' file for more details.
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hw_cache.c
|
||||||
/// \brief load and convert graphics to the hardware format
|
/// \brief load and convert graphics to the hardware format
|
||||||
|
|
||||||
#include "../doomdef.h"
|
#include "../doomdef.h"
|
||||||
|
@ -22,6 +15,7 @@
|
||||||
#ifdef HWRENDER
|
#ifdef HWRENDER
|
||||||
#include "hw_glob.h"
|
#include "hw_glob.h"
|
||||||
#include "hw_drv.h"
|
#include "hw_drv.h"
|
||||||
|
#include "hw_batching.h"
|
||||||
|
|
||||||
#include "../doomstat.h" //gamemode
|
#include "../doomstat.h" //gamemode
|
||||||
#include "../i_video.h" //rendermode
|
#include "../i_video.h" //rendermode
|
||||||
|
@ -33,9 +27,6 @@
|
||||||
#include "../r_patch.h"
|
#include "../r_patch.h"
|
||||||
#include "../p_setup.h"
|
#include "../p_setup.h"
|
||||||
|
|
||||||
// Values set after a call to HWR_ResizeBlock()
|
|
||||||
static INT32 blocksize, blockwidth, blockheight;
|
|
||||||
|
|
||||||
INT32 patchformat = GR_TEXFMT_AP_88; // use alpha for holes
|
INT32 patchformat = GR_TEXFMT_AP_88; // use alpha for holes
|
||||||
INT32 textureformat = GR_TEXFMT_P_8; // use chromakey for hole
|
INT32 textureformat = GR_TEXFMT_P_8; // use chromakey for hole
|
||||||
|
|
||||||
|
@ -308,13 +299,13 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
|
||||||
if (pwidth <= 0 || pheight <= 0)
|
if (pwidth <= 0 || pheight <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ncols = (pwidth * pblockwidth) / pwidth;
|
ncols = pwidth;
|
||||||
|
|
||||||
// source advance
|
// source advance
|
||||||
xfrac = 0;
|
xfrac = 0;
|
||||||
xfracstep = (pwidth << FRACBITS) / pblockwidth;
|
xfracstep = FRACUNIT;
|
||||||
yfracstep = (pheight << FRACBITS) / pblockheight;
|
yfracstep = FRACUNIT;
|
||||||
scale_y = (pblockheight << FRACBITS) / pheight;
|
scale_y = FRACUNIT;
|
||||||
|
|
||||||
bpp = format2bpp[mipmap->grInfo.format];
|
bpp = format2bpp[mipmap->grInfo.format];
|
||||||
|
|
||||||
|
@ -322,7 +313,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
|
||||||
I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp);
|
I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp);
|
||||||
|
|
||||||
// NOTE: should this actually be pblockwidth*bpp?
|
// NOTE: should this actually be pblockwidth*bpp?
|
||||||
blockmodulo = blockwidth*bpp;
|
blockmodulo = pblockwidth*bpp;
|
||||||
|
|
||||||
// Draw each column to the block cache
|
// Draw each column to the block cache
|
||||||
for (; ncols--; block += bpp, xfrac += xfracstep)
|
for (; ncols--; block += bpp, xfrac += xfracstep)
|
||||||
|
@ -415,7 +406,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
|
||||||
I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp);
|
I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp);
|
||||||
|
|
||||||
// NOTE: should this actually be pblockwidth*bpp?
|
// NOTE: should this actually be pblockwidth*bpp?
|
||||||
blockmodulo = blockwidth*bpp;
|
blockmodulo = pblockwidth*bpp;
|
||||||
|
|
||||||
// Draw each column to the block cache
|
// Draw each column to the block cache
|
||||||
for (block += col*bpp; ncols--; block += bpp, xfrac += xfracstep)
|
for (block += col*bpp; ncols--; block += bpp, xfrac += xfracstep)
|
||||||
|
@ -433,142 +424,12 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// resize the patch to be 3dfx compliant
|
|
||||||
// set : blocksize = blockwidth * blockheight (no bpp used)
|
|
||||||
// blockwidth
|
|
||||||
// blockheight
|
|
||||||
//note : 8bit (1 byte per pixel) palettized format
|
|
||||||
static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight,
|
|
||||||
GrTexInfo *grInfo)
|
|
||||||
{
|
|
||||||
#ifdef GLIDE_API_COMPATIBILITY
|
|
||||||
// Build the full textures from patches.
|
|
||||||
static const GrLOD_t gr_lods[9] =
|
|
||||||
{
|
|
||||||
GR_LOD_LOG2_256,
|
|
||||||
GR_LOD_LOG2_128,
|
|
||||||
GR_LOD_LOG2_64,
|
|
||||||
GR_LOD_LOG2_32,
|
|
||||||
GR_LOD_LOG2_16,
|
|
||||||
GR_LOD_LOG2_8,
|
|
||||||
GR_LOD_LOG2_4,
|
|
||||||
GR_LOD_LOG2_2,
|
|
||||||
GR_LOD_LOG2_1
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
GrAspectRatio_t aspect;
|
|
||||||
float max_s;
|
|
||||||
float max_t;
|
|
||||||
} booring_aspect_t;
|
|
||||||
|
|
||||||
static const booring_aspect_t gr_aspects[8] =
|
|
||||||
{
|
|
||||||
{GR_ASPECT_LOG2_1x1, 255, 255},
|
|
||||||
{GR_ASPECT_LOG2_2x1, 255, 127},
|
|
||||||
{GR_ASPECT_LOG2_4x1, 255, 63},
|
|
||||||
{GR_ASPECT_LOG2_8x1, 255, 31},
|
|
||||||
|
|
||||||
{GR_ASPECT_LOG2_1x1, 255, 255},
|
|
||||||
{GR_ASPECT_LOG2_1x2, 127, 255},
|
|
||||||
{GR_ASPECT_LOG2_1x4, 63, 255},
|
|
||||||
{GR_ASPECT_LOG2_1x8, 31, 255}
|
|
||||||
};
|
|
||||||
|
|
||||||
INT32 j,k;
|
|
||||||
INT32 max,min;
|
|
||||||
#else
|
|
||||||
(void)grInfo;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// find a power of 2 width/height
|
|
||||||
if (cv_grrounddown.value)
|
|
||||||
{
|
|
||||||
blockwidth = 256;
|
|
||||||
while (originalwidth < blockwidth)
|
|
||||||
blockwidth >>= 1;
|
|
||||||
if (blockwidth < 1)
|
|
||||||
I_Error("3D GenerateTexture : too small");
|
|
||||||
|
|
||||||
blockheight = 256;
|
|
||||||
while (originalheight < blockheight)
|
|
||||||
blockheight >>= 1;
|
|
||||||
if (blockheight < 1)
|
|
||||||
I_Error("3D GenerateTexture : too small");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef GLIDE_API_COMPATIBILITY
|
|
||||||
//size up to nearest power of 2
|
|
||||||
blockwidth = 1;
|
|
||||||
while (blockwidth < originalwidth)
|
|
||||||
blockwidth <<= 1;
|
|
||||||
// scale down the original graphics to fit in 256
|
|
||||||
if (blockwidth > 2048)
|
|
||||||
blockwidth = 2048;
|
|
||||||
//I_Error("3D GenerateTexture : too big");
|
|
||||||
|
|
||||||
//size up to nearest power of 2
|
|
||||||
blockheight = 1;
|
|
||||||
while (blockheight < originalheight)
|
|
||||||
blockheight <<= 1;
|
|
||||||
// scale down the original graphics to fit in 256
|
|
||||||
if (blockheight > 2048)
|
|
||||||
blockheight = 2048;
|
|
||||||
//I_Error("3D GenerateTexture : too big");
|
|
||||||
#else
|
|
||||||
blockwidth = originalwidth;
|
|
||||||
blockheight = originalheight;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// do the boring LOD stuff.. blech!
|
|
||||||
#ifdef GLIDE_API_COMPATIBILITY
|
|
||||||
if (blockwidth >= blockheight)
|
|
||||||
{
|
|
||||||
max = blockwidth;
|
|
||||||
min = blockheight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
max = blockheight;
|
|
||||||
min = blockwidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (k = 2048, j = 0; k > max; j++)
|
|
||||||
k>>=1;
|
|
||||||
grInfo->smallLodLog2 = gr_lods[j];
|
|
||||||
grInfo->largeLodLog2 = gr_lods[j];
|
|
||||||
|
|
||||||
for (k = max, j = 0; k > min && j < 4; j++)
|
|
||||||
k>>=1;
|
|
||||||
// aspect ratio too small for 3Dfx (eg: 8x128 is 1x16 : use 1x8)
|
|
||||||
if (j == 4)
|
|
||||||
{
|
|
||||||
j = 3;
|
|
||||||
//CONS_Debug(DBG_RENDER, "HWR_ResizeBlock : bad aspect ratio %dx%d\n", blockwidth,blockheight);
|
|
||||||
if (blockwidth < blockheight)
|
|
||||||
blockwidth = max>>3;
|
|
||||||
else
|
|
||||||
blockheight = max>>3;
|
|
||||||
}
|
|
||||||
if (blockwidth < blockheight)
|
|
||||||
j += 4;
|
|
||||||
grInfo->aspectRatioLog2 = gr_aspects[j].aspect;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
blocksize = blockwidth * blockheight;
|
|
||||||
|
|
||||||
//CONS_Debug(DBG_RENDER, "Width is %d, Height is %d\n", blockwidth, blockheight);
|
|
||||||
}
|
|
||||||
|
|
||||||
static UINT8 *MakeBlock(GLMipmap_t *grMipmap)
|
static UINT8 *MakeBlock(GLMipmap_t *grMipmap)
|
||||||
{
|
{
|
||||||
UINT8 *block;
|
UINT8 *block;
|
||||||
INT32 bpp, i;
|
INT32 bpp, i;
|
||||||
UINT16 bu16 = ((0x00 <<8) | HWR_PATCHES_CHROMAKEY_COLORINDEX);
|
UINT16 bu16 = ((0x00 <<8) | HWR_PATCHES_CHROMAKEY_COLORINDEX);
|
||||||
|
INT32 blocksize = (grMipmap->width * grMipmap->height);
|
||||||
|
|
||||||
bpp = format2bpp[grMipmap->grInfo.format];
|
bpp = format2bpp[grMipmap->grInfo.format];
|
||||||
block = Z_Malloc(blocksize*bpp, PU_HWRCACHE, &(grMipmap->grInfo.data));
|
block = Z_Malloc(blocksize*bpp, PU_HWRCACHE, &(grMipmap->grInfo.data));
|
||||||
|
@ -599,6 +460,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex)
|
||||||
texpatch_t *patch;
|
texpatch_t *patch;
|
||||||
patch_t *realpatch;
|
patch_t *realpatch;
|
||||||
UINT8 *pdata;
|
UINT8 *pdata;
|
||||||
|
INT32 blockwidth, blockheight, blocksize;
|
||||||
|
|
||||||
INT32 i;
|
INT32 i;
|
||||||
boolean skyspecial = false; //poor hack for Legacy large skies..
|
boolean skyspecial = false; //poor hack for Legacy large skies..
|
||||||
|
@ -619,11 +481,13 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex)
|
||||||
else
|
else
|
||||||
grtex->mipmap.flags = TF_CHROMAKEYED | TF_WRAPXY;
|
grtex->mipmap.flags = TF_CHROMAKEYED | TF_WRAPXY;
|
||||||
|
|
||||||
HWR_ResizeBlock (texture->width, texture->height, &grtex->mipmap.grInfo);
|
grtex->mipmap.width = (UINT16)texture->width;
|
||||||
grtex->mipmap.width = (UINT16)blockwidth;
|
grtex->mipmap.height = (UINT16)texture->height;
|
||||||
grtex->mipmap.height = (UINT16)blockheight;
|
|
||||||
grtex->mipmap.grInfo.format = textureformat;
|
grtex->mipmap.grInfo.format = textureformat;
|
||||||
|
|
||||||
|
blockwidth = texture->width;
|
||||||
|
blockheight = texture->height;
|
||||||
|
blocksize = (blockwidth * blockheight);
|
||||||
block = MakeBlock(&grtex->mipmap);
|
block = MakeBlock(&grtex->mipmap);
|
||||||
|
|
||||||
if (skyspecial) //Hurdler: not efficient, but better than holes in the sky (and it's done only at level loading)
|
if (skyspecial) //Hurdler: not efficient, but better than holes in the sky (and it's done only at level loading)
|
||||||
|
@ -692,8 +556,6 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex)
|
||||||
// patch may be NULL if grMipmap has been initialised already and makebitmap is false
|
// patch may be NULL if grMipmap has been initialised already and makebitmap is false
|
||||||
void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap)
|
void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap)
|
||||||
{
|
{
|
||||||
INT32 newwidth, newheight;
|
|
||||||
|
|
||||||
#ifndef NO_PNG_LUMPS
|
#ifndef NO_PNG_LUMPS
|
||||||
// lump is a png so convert it
|
// lump is a png so convert it
|
||||||
size_t len = W_LumpLengthPwad(grPatch->wadnum, grPatch->lumpnum);
|
size_t len = W_LumpLengthPwad(grPatch->wadnum, grPatch->lumpnum);
|
||||||
|
@ -712,51 +574,32 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
|
||||||
grPatch->leftoffset = SHORT(patch->leftoffset);
|
grPatch->leftoffset = SHORT(patch->leftoffset);
|
||||||
grPatch->topoffset = SHORT(patch->topoffset);
|
grPatch->topoffset = SHORT(patch->topoffset);
|
||||||
|
|
||||||
// find the good 3dfx size (boring spec)
|
grMipmap->width = grMipmap->height = 1;
|
||||||
HWR_ResizeBlock (SHORT(patch->width), SHORT(patch->height), &grMipmap->grInfo);
|
while (grMipmap->width < grPatch->width) grMipmap->width <<= 1;
|
||||||
grMipmap->width = (UINT16)blockwidth;
|
while (grMipmap->height < grPatch->height) grMipmap->height <<= 1;
|
||||||
grMipmap->height = (UINT16)blockheight;
|
|
||||||
|
|
||||||
// no wrap around, no chroma key
|
// no wrap around, no chroma key
|
||||||
grMipmap->flags = 0;
|
grMipmap->flags = 0;
|
||||||
// setup the texture info
|
// setup the texture info
|
||||||
grMipmap->grInfo.format = patchformat;
|
grMipmap->grInfo.format = patchformat;
|
||||||
}
|
|
||||||
else
|
//grPatch->max_s = grPatch->max_t = 1.0f;
|
||||||
{
|
grPatch->max_s = (float)grPatch->width / (float)grMipmap->width;
|
||||||
blockwidth = grMipmap->width;
|
grPatch->max_t = (float)grPatch->height / (float)grMipmap->height;
|
||||||
blockheight = grMipmap->height;
|
|
||||||
blocksize = blockwidth * blockheight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Z_Free(grMipmap->grInfo.data);
|
Z_Free(grMipmap->grInfo.data);
|
||||||
grMipmap->grInfo.data = NULL;
|
grMipmap->grInfo.data = NULL;
|
||||||
|
|
||||||
// if rounddown, rounddown patches as well as textures
|
|
||||||
if (cv_grrounddown.value)
|
|
||||||
{
|
|
||||||
newwidth = blockwidth;
|
|
||||||
newheight = blockheight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// no rounddown, do not size up patches, so they don't look 'scaled'
|
|
||||||
newwidth = min(grPatch->width, blockwidth);
|
|
||||||
newheight = min(grPatch->height, blockheight);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (makebitmap)
|
if (makebitmap)
|
||||||
{
|
{
|
||||||
MakeBlock(grMipmap);
|
MakeBlock(grMipmap);
|
||||||
|
|
||||||
HWR_DrawPatchInCache(grMipmap,
|
HWR_DrawPatchInCache(grMipmap,
|
||||||
newwidth, newheight,
|
grMipmap->width, grMipmap->height,
|
||||||
grPatch->width, grPatch->height,
|
grPatch->width, grPatch->height,
|
||||||
patch);
|
patch);
|
||||||
}
|
}
|
||||||
|
|
||||||
grPatch->max_s = (float)newwidth / (float)blockwidth;
|
|
||||||
grPatch->max_t = (float)newheight / (float)blockheight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -896,9 +739,12 @@ GLTexture_t *HWR_GetTexture(INT32 tex)
|
||||||
if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded)
|
if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded)
|
||||||
HWR_GenerateTexture(tex, grtex);
|
HWR_GenerateTexture(tex, grtex);
|
||||||
|
|
||||||
// Tell the hardware driver to bind the current texture to the flat's mipmap
|
// If hardware does not have the texture, then call pfnSetTexture to upload it
|
||||||
|
if (!grtex->mipmap.downloaded)
|
||||||
HWD.pfnSetTexture(&grtex->mipmap);
|
HWD.pfnSetTexture(&grtex->mipmap);
|
||||||
|
|
||||||
|
HWR_SetCurrentTexture(&grtex->mipmap);
|
||||||
|
|
||||||
// The system-memory data can be purged now.
|
// The system-memory data can be purged now.
|
||||||
Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
|
Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
|
||||||
|
|
||||||
|
@ -910,11 +756,6 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
|
||||||
size_t size, pflatsize;
|
size_t size, pflatsize;
|
||||||
|
|
||||||
// setup the texture info
|
// setup the texture info
|
||||||
#ifdef GLIDE_API_COMPATIBILITY
|
|
||||||
grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64;
|
|
||||||
grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64;
|
|
||||||
grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
|
|
||||||
#endif
|
|
||||||
grMipmap->grInfo.format = GR_TEXFMT_P_8;
|
grMipmap->grInfo.format = GR_TEXFMT_P_8;
|
||||||
grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
|
grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
|
||||||
|
|
||||||
|
@ -957,15 +798,7 @@ static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum)
|
||||||
{
|
{
|
||||||
UINT8 *flat;
|
UINT8 *flat;
|
||||||
|
|
||||||
if (needpatchflush)
|
|
||||||
W_FlushCachedPatches();
|
|
||||||
|
|
||||||
// setup the texture info
|
// setup the texture info
|
||||||
#ifdef GLIDE_API_COMPATIBILITY
|
|
||||||
grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64;
|
|
||||||
grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64;
|
|
||||||
grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
|
|
||||||
#endif
|
|
||||||
grMipmap->grInfo.format = GR_TEXFMT_P_8;
|
grMipmap->grInfo.format = GR_TEXFMT_P_8;
|
||||||
grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
|
grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
|
||||||
|
|
||||||
|
@ -985,15 +818,16 @@ void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum)
|
||||||
if (flatlumpnum == LUMPERROR)
|
if (flatlumpnum == LUMPERROR)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (needpatchflush)
|
|
||||||
W_FlushCachedPatches();
|
|
||||||
|
|
||||||
grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap;
|
grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap;
|
||||||
if (!grmip->downloaded && !grmip->grInfo.data)
|
if (!grmip->downloaded && !grmip->grInfo.data)
|
||||||
HWR_CacheFlat(grmip, flatlumpnum);
|
HWR_CacheFlat(grmip, flatlumpnum);
|
||||||
|
|
||||||
|
// If hardware does not have the texture, then call pfnSetTexture to upload it
|
||||||
|
if (!grmip->downloaded)
|
||||||
HWD.pfnSetTexture(grmip);
|
HWD.pfnSetTexture(grmip);
|
||||||
|
|
||||||
|
HWR_SetCurrentTexture(grmip);
|
||||||
|
|
||||||
// The system-memory data can be purged now.
|
// The system-memory data can be purged now.
|
||||||
Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
|
Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
|
||||||
}
|
}
|
||||||
|
@ -1026,14 +860,17 @@ void HWR_GetLevelFlat(levelflat_t *levelflat)
|
||||||
if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded)
|
if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded)
|
||||||
HWR_CacheTextureAsFlat(&grtex->mipmap, texturenum);
|
HWR_CacheTextureAsFlat(&grtex->mipmap, texturenum);
|
||||||
|
|
||||||
// Tell the hardware driver to bind the current texture to the flat's mipmap
|
// If hardware does not have the texture, then call pfnSetTexture to upload it
|
||||||
|
if (!grtex->mipmap.downloaded)
|
||||||
HWD.pfnSetTexture(&grtex->mipmap);
|
HWD.pfnSetTexture(&grtex->mipmap);
|
||||||
|
|
||||||
|
HWR_SetCurrentTexture(&grtex->mipmap);
|
||||||
|
|
||||||
// The system-memory data can be purged now.
|
// The system-memory data can be purged now.
|
||||||
Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
|
Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
|
||||||
}
|
}
|
||||||
else // set no texture
|
else // set no texture
|
||||||
HWD.pfnSetTexture(NULL);
|
HWR_SetCurrentTexture(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1055,8 +892,12 @@ static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch)
|
||||||
Z_Free(patch);
|
Z_Free(patch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If hardware does not have the texture, then call pfnSetTexture to upload it
|
||||||
|
if (!grmip->downloaded)
|
||||||
HWD.pfnSetTexture(grmip);
|
HWD.pfnSetTexture(grmip);
|
||||||
|
|
||||||
|
HWR_SetCurrentTexture(grmip);
|
||||||
|
|
||||||
// The system-memory data can be purged now.
|
// The system-memory data can be purged now.
|
||||||
Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
|
Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
|
||||||
}
|
}
|
||||||
|
@ -1066,9 +907,6 @@ static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch)
|
||||||
// -----------------+
|
// -----------------+
|
||||||
void HWR_GetPatch(GLPatch_t *gpatch)
|
void HWR_GetPatch(GLPatch_t *gpatch)
|
||||||
{
|
{
|
||||||
if (needpatchflush)
|
|
||||||
W_FlushCachedPatches();
|
|
||||||
|
|
||||||
// is it in hardware cache
|
// is it in hardware cache
|
||||||
if (!gpatch->mipmap->downloaded && !gpatch->mipmap->grInfo.data)
|
if (!gpatch->mipmap->downloaded && !gpatch->mipmap->grInfo.data)
|
||||||
{
|
{
|
||||||
|
@ -1085,8 +923,12 @@ void HWR_GetPatch(GLPatch_t *gpatch)
|
||||||
Z_Free(ptr);
|
Z_Free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If hardware does not have the texture, then call pfnSetTexture to upload it
|
||||||
|
if (!gpatch->mipmap->downloaded)
|
||||||
HWD.pfnSetTexture(gpatch->mipmap);
|
HWD.pfnSetTexture(gpatch->mipmap);
|
||||||
|
|
||||||
|
HWR_SetCurrentTexture(gpatch->mipmap);
|
||||||
|
|
||||||
// The system-memory patch data can be purged now.
|
// The system-memory patch data can be purged now.
|
||||||
Z_ChangeTag(gpatch->mipmap->grInfo.data, PU_HWRCACHE_UNLOCKED);
|
Z_ChangeTag(gpatch->mipmap->grInfo.data, PU_HWRCACHE_UNLOCKED);
|
||||||
}
|
}
|
||||||
|
@ -1099,9 +941,6 @@ void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap)
|
||||||
{
|
{
|
||||||
GLMipmap_t *grmip, *newmip;
|
GLMipmap_t *grmip, *newmip;
|
||||||
|
|
||||||
if (needpatchflush)
|
|
||||||
W_FlushCachedPatches();
|
|
||||||
|
|
||||||
if (colormap == colormaps || colormap == NULL)
|
if (colormap == colormaps || colormap == NULL)
|
||||||
{
|
{
|
||||||
// Load the default (green) color in doom cache (temporary?) AND hardware cache
|
// Load the default (green) color in doom cache (temporary?) AND hardware cache
|
||||||
|
@ -1225,19 +1064,12 @@ static void HWR_DrawPicInCache(UINT8 *block, INT32 pblockwidth, INT32 pblockheig
|
||||||
// -----------------+
|
// -----------------+
|
||||||
GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
|
GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
|
||||||
{
|
{
|
||||||
GLPatch_t *grpatch;
|
GLPatch_t *grpatch = HWR_GetCachedGLPatch(lumpnum);
|
||||||
|
|
||||||
if (needpatchflush)
|
|
||||||
W_FlushCachedPatches();
|
|
||||||
|
|
||||||
grpatch = HWR_GetCachedGLPatch(lumpnum);
|
|
||||||
|
|
||||||
if (!grpatch->mipmap->downloaded && !grpatch->mipmap->grInfo.data)
|
if (!grpatch->mipmap->downloaded && !grpatch->mipmap->grInfo.data)
|
||||||
{
|
{
|
||||||
pic_t *pic;
|
pic_t *pic;
|
||||||
UINT8 *block;
|
UINT8 *block;
|
||||||
size_t len;
|
size_t len;
|
||||||
INT32 newwidth, newheight;
|
|
||||||
|
|
||||||
pic = W_CacheLumpNum(lumpnum, PU_CACHE);
|
pic = W_CacheLumpNum(lumpnum, PU_CACHE);
|
||||||
grpatch->width = SHORT(pic->width);
|
grpatch->width = SHORT(pic->width);
|
||||||
|
@ -1247,10 +1079,8 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
|
||||||
grpatch->leftoffset = 0;
|
grpatch->leftoffset = 0;
|
||||||
grpatch->topoffset = 0;
|
grpatch->topoffset = 0;
|
||||||
|
|
||||||
// find the good 3dfx size (boring spec)
|
grpatch->mipmap->width = (UINT16)grpatch->width;
|
||||||
HWR_ResizeBlock (grpatch->width, grpatch->height, &grpatch->mipmap->grInfo);
|
grpatch->mipmap->height = (UINT16)grpatch->height;
|
||||||
grpatch->mipmap->width = (UINT16)blockwidth;
|
|
||||||
grpatch->mipmap->height = (UINT16)blockheight;
|
|
||||||
|
|
||||||
if (pic->mode == PALETTE)
|
if (pic->mode == PALETTE)
|
||||||
grpatch->mipmap->grInfo.format = textureformat; // can be set by driver
|
grpatch->mipmap->grInfo.format = textureformat; // can be set by driver
|
||||||
|
@ -1262,30 +1092,16 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
|
||||||
// allocate block
|
// allocate block
|
||||||
block = MakeBlock(grpatch->mipmap);
|
block = MakeBlock(grpatch->mipmap);
|
||||||
|
|
||||||
// if rounddown, rounddown patches as well as textures
|
if (grpatch->width == SHORT(pic->width) &&
|
||||||
if (cv_grrounddown.value)
|
grpatch->height == SHORT(pic->height) &&
|
||||||
{
|
|
||||||
newwidth = blockwidth;
|
|
||||||
newheight = blockheight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// no rounddown, do not size up patches, so they don't look 'scaled'
|
|
||||||
newwidth = min(SHORT(pic->width),blockwidth);
|
|
||||||
newheight = min(SHORT(pic->height),blockheight);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (grpatch->width == blockwidth &&
|
|
||||||
grpatch->height == blockheight &&
|
|
||||||
format2bpp[grpatch->mipmap->grInfo.format] == format2bpp[picmode2GR[pic->mode]])
|
format2bpp[grpatch->mipmap->grInfo.format] == format2bpp[picmode2GR[pic->mode]])
|
||||||
{
|
{
|
||||||
// no conversion needed
|
// no conversion needed
|
||||||
M_Memcpy(grpatch->mipmap->grInfo.data, pic->data,len);
|
M_Memcpy(grpatch->mipmap->grInfo.data, pic->data,len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
HWR_DrawPicInCache(block, newwidth, newheight,
|
HWR_DrawPicInCache(block, SHORT(pic->width), SHORT(pic->height),
|
||||||
blockwidth*format2bpp[grpatch->mipmap->grInfo.format],
|
SHORT(pic->width)*format2bpp[grpatch->mipmap->grInfo.format],
|
||||||
pic,
|
pic,
|
||||||
format2bpp[grpatch->mipmap->grInfo.format]);
|
format2bpp[grpatch->mipmap->grInfo.format]);
|
||||||
|
|
||||||
|
@ -1293,8 +1109,7 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
|
||||||
Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED);
|
Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED);
|
||||||
|
|
||||||
grpatch->mipmap->flags = 0;
|
grpatch->mipmap->flags = 0;
|
||||||
grpatch->max_s = (float)newwidth / (float)blockwidth;
|
grpatch->max_s = grpatch->max_t = 1.0f;
|
||||||
grpatch->max_t = (float)newheight / (float)blockheight;
|
|
||||||
}
|
}
|
||||||
HWD.pfnSetTexture(grpatch->mipmap);
|
HWD.pfnSetTexture(grpatch->mipmap);
|
||||||
//CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grpatch->mipmap.grInfo.data, grpatch->mipmap.downloaded);
|
//CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grpatch->mipmap.grInfo.data, grpatch->mipmap.downloaded);
|
||||||
|
@ -1330,7 +1145,7 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32
|
||||||
{
|
{
|
||||||
INT32 i,j;
|
INT32 i,j;
|
||||||
fixed_t posx, posy, stepx, stepy;
|
fixed_t posx, posy, stepx, stepy;
|
||||||
UINT8 *block = mipmap->grInfo.data; // places the data directly into here, it already has the space allocated from HWR_ResizeBlock
|
UINT8 *block = mipmap->grInfo.data; // places the data directly into here
|
||||||
UINT8 *flat;
|
UINT8 *flat;
|
||||||
UINT8 *dest, *src, texel;
|
UINT8 *dest, *src, texel;
|
||||||
RGBA_t col;
|
RGBA_t col;
|
||||||
|
@ -1345,7 +1160,7 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32
|
||||||
for (j = 0; j < pblockheight; j++)
|
for (j = 0; j < pblockheight; j++)
|
||||||
{
|
{
|
||||||
posx = 0;
|
posx = 0;
|
||||||
dest = &block[j*blockwidth]; // 1bpp
|
dest = &block[j*(mipmap->width)]; // 1bpp
|
||||||
src = &flat[(posy>>FRACBITS)*SHORT(fmwidth)];
|
src = &flat[(posy>>FRACBITS)*SHORT(fmwidth)];
|
||||||
for (i = 0; i < pblockwidth;i++)
|
for (i = 0; i < pblockwidth;i++)
|
||||||
{
|
{
|
||||||
|
@ -1399,14 +1214,12 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Thankfully, this will still work for this scenario
|
// Thankfully, this will still work for this scenario
|
||||||
HWR_ResizeBlock(fmwidth, fmheight, &grMipmap->grInfo);
|
grMipmap->width = fmwidth;
|
||||||
|
grMipmap->height = fmheight;
|
||||||
grMipmap->width = blockwidth;
|
|
||||||
grMipmap->height = blockheight;
|
|
||||||
|
|
||||||
MakeBlock(grMipmap);
|
MakeBlock(grMipmap);
|
||||||
|
|
||||||
HWR_DrawFadeMaskInCache(grMipmap, blockwidth, blockheight, fademasklumpnum, fmwidth, fmheight);
|
HWR_DrawFadeMaskInCache(grMipmap, fmwidth, fmheight, fademasklumpnum, fmwidth, fmheight);
|
||||||
|
|
||||||
// I DO need to convert this because it isn't power of 2 and we need the alpha
|
// I DO need to convert this because it isn't power of 2 and we need the alpha
|
||||||
}
|
}
|
||||||
|
@ -1414,13 +1227,7 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum)
|
||||||
|
|
||||||
void HWR_GetFadeMask(lumpnum_t fademasklumpnum)
|
void HWR_GetFadeMask(lumpnum_t fademasklumpnum)
|
||||||
{
|
{
|
||||||
GLMipmap_t *grmip;
|
GLMipmap_t *grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap;
|
||||||
|
|
||||||
if (needpatchflush)
|
|
||||||
W_FlushCachedPatches();
|
|
||||||
|
|
||||||
grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap;
|
|
||||||
|
|
||||||
if (!grmip->downloaded && !grmip->grInfo.data)
|
if (!grmip->downloaded && !grmip->grInfo.data)
|
||||||
HWR_CacheFadeMask(grmip, fademasklumpnum);
|
HWR_CacheFadeMask(grmip, fademasklumpnum);
|
||||||
|
|
||||||
|
|
|
@ -78,8 +78,8 @@
|
||||||
#include "r_opengl/r_opengl.h"
|
#include "r_opengl/r_opengl.h"
|
||||||
|
|
||||||
#ifdef HAVE_SPHEREFRUSTRUM
|
#ifdef HAVE_SPHEREFRUSTRUM
|
||||||
static GLfloat viewMatrix[16];
|
static GLdouble viewMatrix[16];
|
||||||
static GLfloat projMatrix[16];
|
static GLdouble projMatrix[16];
|
||||||
float frustum[6][4];
|
float frustum[6][4];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -320,12 +320,12 @@ void gld_clipper_Clear(void)
|
||||||
|
|
||||||
#define RMUL (1.6f/1.333333f)
|
#define RMUL (1.6f/1.333333f)
|
||||||
|
|
||||||
angle_t gld_FrustumAngle(void)
|
angle_t gld_FrustumAngle(angle_t tiltangle)
|
||||||
{
|
{
|
||||||
double floatangle;
|
double floatangle;
|
||||||
angle_t a1;
|
angle_t a1;
|
||||||
|
|
||||||
float tilt = (float)fabs(((double)(int)aimingangle) / ANG1);
|
float tilt = (float)fabs(((double)(int)tiltangle) / ANG1);
|
||||||
|
|
||||||
// NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function
|
// NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function
|
||||||
|
|
||||||
|
@ -339,7 +339,7 @@ angle_t gld_FrustumAngle(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the pitch is larger than this you can look all around at a FOV of 90
|
// If the pitch is larger than this you can look all around at a FOV of 90
|
||||||
if (abs((signed)aimingangle) > 46 * ANG1)
|
if (abs((signed)tiltangle) > 46 * ANG1)
|
||||||
return 0xffffffff;
|
return 0xffffffff;
|
||||||
|
|
||||||
// ok, this is a gross hack that barely works...
|
// ok, this is a gross hack that barely works...
|
||||||
|
@ -352,7 +352,7 @@ angle_t gld_FrustumAngle(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SRB2CB I don't think used any of this stuff, let's disable for now since SRB2 probably doesn't want it either
|
// SRB2CB I don't think used any of this stuff, let's disable for now since SRB2 probably doesn't want it either
|
||||||
// compiler complains about (p)glGetDoublev anyway, in case anyone wants this
|
// compiler complains about (p)glGetFloatv anyway, in case anyone wants this
|
||||||
// only r_opengl.c can use the base gl funcs as it turns out, that's a problem for whoever wants sphere frustum checks
|
// only r_opengl.c can use the base gl funcs as it turns out, that's a problem for whoever wants sphere frustum checks
|
||||||
// btw to renable define HAVE_SPHEREFRUSTRUM in hw_clip.h
|
// btw to renable define HAVE_SPHEREFRUSTRUM in hw_clip.h
|
||||||
#ifdef HAVE_SPHEREFRUSTRUM
|
#ifdef HAVE_SPHEREFRUSTRUM
|
||||||
|
@ -381,7 +381,7 @@ void gld_FrustrumSetup(void)
|
||||||
float t;
|
float t;
|
||||||
float clip[16];
|
float clip[16];
|
||||||
|
|
||||||
pglGeFloatv(GL_PROJECTION_MATRIX, projMatrix);
|
pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix);
|
||||||
pglGetFloatv(GL_MODELVIEW_MATRIX, viewMatrix);
|
pglGetFloatv(GL_MODELVIEW_MATRIX, viewMatrix);
|
||||||
|
|
||||||
clip[0] = CALCMATRIX(0, 0, 1, 4, 2, 8, 3, 12);
|
clip[0] = CALCMATRIX(0, 0, 1, 4, 2, 8, 3, 12);
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
boolean gld_clipper_SafeCheckRange(angle_t startAngle, angle_t endAngle);
|
boolean gld_clipper_SafeCheckRange(angle_t startAngle, angle_t endAngle);
|
||||||
void gld_clipper_SafeAddClipRange(angle_t startangle, angle_t endangle);
|
void gld_clipper_SafeAddClipRange(angle_t startangle, angle_t endangle);
|
||||||
void gld_clipper_Clear(void);
|
void gld_clipper_Clear(void);
|
||||||
angle_t gld_FrustumAngle(void);
|
angle_t gld_FrustumAngle(angle_t tiltangle);
|
||||||
#ifdef HAVE_SPHEREFRUSTRUM
|
#ifdef HAVE_SPHEREFRUSTRUM
|
||||||
void gld_FrustrumSetup(void);
|
void gld_FrustrumSetup(void);
|
||||||
boolean gld_SphereInFrustum(float x, float y, float z, float radius);
|
boolean gld_SphereInFrustum(float x, float y, float z, float radius);
|
||||||
|
|
|
@ -1,21 +1,14 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
|
||||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||||
|
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software distributed under the
|
||||||
// modify it under the terms of the GNU General Public License
|
// terms of the GNU General Public License, version 2.
|
||||||
// as published by the Free Software Foundation; either version 2
|
// See the 'LICENSE' file for more details.
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hw_data.h
|
||||||
/// \brief defines structures and exports for the standard 3D driver DLL used by Doom Legacy
|
/// \brief defines structures and exports for the hardware interface used by Sonic Robo Blast 2
|
||||||
|
|
||||||
#ifndef _HWR_DATA_
|
#ifndef _HWR_DATA_
|
||||||
#define _HWR_DATA_
|
#define _HWR_DATA_
|
||||||
|
|
|
@ -1,24 +1,19 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
|
||||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||||
|
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software distributed under the
|
||||||
// modify it under the terms of the GNU General Public License
|
// terms of the GNU General Public License, version 2.
|
||||||
// as published by the Free Software Foundation; either version 2
|
// See the 'LICENSE' file for more details.
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hw_defs.h
|
||||||
/// \brief 3D hardware renderer definitions
|
/// \brief 3D hardware renderer definitions
|
||||||
|
|
||||||
#ifndef _HWR_DEFS_
|
#ifndef _HWR_DEFS_
|
||||||
#define _HWR_DEFS_
|
#define _HWR_DEFS_
|
||||||
#include "../doomtype.h"
|
#include "../doomtype.h"
|
||||||
|
#include "../r_defs.h"
|
||||||
|
|
||||||
#define ZCLIP_PLANE 4.0f // Used for the actual game drawing
|
#define ZCLIP_PLANE 4.0f // Used for the actual game drawing
|
||||||
#define NZCLIP_PLANE 0.9f // Seems to be only used for the HUD and screen textures
|
#define NZCLIP_PLANE 0.9f // Seems to be only used for the HUD and screen textures
|
||||||
|
@ -85,13 +80,15 @@ typedef struct FVector
|
||||||
FLOAT x,y,z;
|
FLOAT x,y,z;
|
||||||
} FVector;
|
} FVector;
|
||||||
|
|
||||||
// 3D model vector (coords + texture coords)
|
// ======================
|
||||||
typedef struct
|
// wallVert3D
|
||||||
{
|
// ----------------------
|
||||||
//FVector Point;
|
// :crab: IS GONE! :crab:
|
||||||
FLOAT x,y,z;
|
// ======================
|
||||||
FLOAT s,t,w; // texture coordinates
|
|
||||||
} v3d_t, wallVert3D;
|
// -----------
|
||||||
|
// structures
|
||||||
|
// -----------
|
||||||
|
|
||||||
//Hurdler: Transform (coords + angles)
|
//Hurdler: Transform (coords + angles)
|
||||||
//BP: transform order : scale(rotation_x(rotation_y(translation(v))))
|
//BP: transform order : scale(rotation_x(rotation_y(translation(v))))
|
||||||
|
@ -123,15 +120,16 @@ typedef struct
|
||||||
#ifdef USE_FTRANSFORM_MIRROR
|
#ifdef USE_FTRANSFORM_MIRROR
|
||||||
boolean mirror; // SRB2Kart: Encore Mode
|
boolean mirror; // SRB2Kart: Encore Mode
|
||||||
#endif
|
#endif
|
||||||
|
boolean shearing; // 14042019
|
||||||
|
float viewaiming; // 17052019
|
||||||
} FTransform;
|
} FTransform;
|
||||||
|
|
||||||
// Transformed vector, as passed to HWR API
|
// Transformed vector, as passed to HWR API
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
FLOAT x,y,z;
|
FLOAT x,y,z;
|
||||||
FUINT argb; // flat-shaded color
|
FLOAT s; // s texture ordinate (s over w)
|
||||||
FLOAT sow; // s texture ordinate (s over w)
|
FLOAT t; // t texture ordinate (t over w)
|
||||||
FLOAT tow; // t texture ordinate (t over w)
|
|
||||||
} FOutVector;
|
} FOutVector;
|
||||||
|
|
||||||
|
|
||||||
|
@ -162,10 +160,10 @@ enum EPolyFlags
|
||||||
PF_Invisible = 0x00000400, // Disable write to color buffer
|
PF_Invisible = 0x00000400, // Disable write to color buffer
|
||||||
PF_Decal = 0x00000800, // Enable polygon offset
|
PF_Decal = 0x00000800, // Enable polygon offset
|
||||||
PF_Modulated = 0x00001000, // Modulation (multiply output with constant ARGB)
|
PF_Modulated = 0x00001000, // Modulation (multiply output with constant ARGB)
|
||||||
// When set, pass the color constant into the FSurfaceInfo -> FlatColor
|
// When set, pass the color constant into the FSurfaceInfo -> PolyColor
|
||||||
PF_NoTexture = 0x00002000, // Use the small white texture
|
PF_NoTexture = 0x00002000, // Use the small white texture
|
||||||
PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona
|
PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona
|
||||||
PF_Unused = 0x00008000, // Unused
|
PF_Ripple = 0x00008000, // Water shader effect
|
||||||
PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y
|
PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y
|
||||||
PF_ForceWrapX = 0x00020000, // Force repeat texture on X
|
PF_ForceWrapX = 0x00020000, // Force repeat texture on X
|
||||||
PF_ForceWrapY = 0x00040000, // Force repeat texture on Y
|
PF_ForceWrapY = 0x00040000, // Force repeat texture on Y
|
||||||
|
@ -178,7 +176,6 @@ enum EPolyFlags
|
||||||
enum ESurfFlags
|
enum ESurfFlags
|
||||||
{
|
{
|
||||||
SF_DYNLIGHT = 0x00000001,
|
SF_DYNLIGHT = 0x00000001,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ETextureFlags
|
enum ETextureFlags
|
||||||
|
@ -190,38 +187,36 @@ enum ETextureFlags
|
||||||
TF_TRANSPARENT = 0x00000040, // texture with some alpha == 0
|
TF_TRANSPARENT = 0x00000040, // texture with some alpha == 0
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef TODO
|
|
||||||
struct FTextureInfo
|
|
||||||
{
|
|
||||||
FUINT Width; // Pixels
|
|
||||||
FUINT Height; // Pixels
|
|
||||||
FUBYTE *TextureData; // Image data
|
|
||||||
FUINT Format; // FORMAT_RGB, ALPHA ...
|
|
||||||
FBITFIELD Flags; // Flags to tell driver about texture (see ETextureFlags)
|
|
||||||
void DriverExtra; // (OpenGL texture object nr, ...)
|
|
||||||
// chromakey enabled,...
|
|
||||||
|
|
||||||
struct FTextureInfo *Next; // Manage list of downloaded textures.
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
typedef struct GLMipmap_s FTextureInfo;
|
typedef struct GLMipmap_s FTextureInfo;
|
||||||
#endif
|
|
||||||
|
// jimita 14032019
|
||||||
|
struct FLightInfo
|
||||||
|
{
|
||||||
|
FUINT light_level;
|
||||||
|
FUINT fade_start;
|
||||||
|
FUINT fade_end;
|
||||||
|
};
|
||||||
|
typedef struct FLightInfo FLightInfo;
|
||||||
|
|
||||||
// Description of a renderable surface
|
// Description of a renderable surface
|
||||||
struct FSurfaceInfo
|
struct FSurfaceInfo
|
||||||
{
|
{
|
||||||
FUINT PolyFlags; // Surface flags -- UNUSED YET --
|
FUINT PolyFlags;
|
||||||
RGBA_t FlatColor; // Flat-shaded color used with PF_Modulated mode
|
RGBA_t PolyColor;
|
||||||
|
RGBA_t TintColor;
|
||||||
|
RGBA_t FadeColor;
|
||||||
|
FLightInfo LightInfo; // jimita 14032019
|
||||||
};
|
};
|
||||||
typedef struct FSurfaceInfo FSurfaceInfo;
|
typedef struct FSurfaceInfo FSurfaceInfo;
|
||||||
|
|
||||||
|
#define GL_DEFAULTMIX 0x00000000
|
||||||
|
#define GL_DEFAULTFOG 0xFF000000
|
||||||
|
|
||||||
//Hurdler: added for backward compatibility
|
//Hurdler: added for backward compatibility
|
||||||
enum hwdsetspecialstate
|
enum hwdsetspecialstate
|
||||||
{
|
{
|
||||||
HWD_SET_MODEL_LIGHTING = 1,
|
HWD_SET_MODEL_LIGHTING = 1,
|
||||||
HWD_SET_FOG_MODE,
|
HWD_SET_SHADERS,
|
||||||
HWD_SET_FOG_COLOR,
|
|
||||||
HWD_SET_FOG_DENSITY,
|
|
||||||
HWD_SET_TEXTUREFILTERMODE,
|
HWD_SET_TEXTUREFILTERMODE,
|
||||||
HWD_SET_TEXTUREANISOTROPICMODE,
|
HWD_SET_TEXTUREANISOTROPICMODE,
|
||||||
HWD_NUMSTATE
|
HWD_NUMSTATE
|
||||||
|
@ -229,6 +224,15 @@ enum hwdsetspecialstate
|
||||||
|
|
||||||
typedef enum hwdsetspecialstate hwdspecialstate_t;
|
typedef enum hwdsetspecialstate hwdspecialstate_t;
|
||||||
|
|
||||||
|
// Lactozilla: Shader info
|
||||||
|
// Generally set at the start of the frame.
|
||||||
|
enum hwdshaderinfo
|
||||||
|
{
|
||||||
|
HWD_SHADERINFO_LEVELTIME = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum hwdshaderinfo hwdshaderinfo_t;
|
||||||
|
|
||||||
enum hwdfiltermode
|
enum hwdfiltermode
|
||||||
{
|
{
|
||||||
HWD_SET_TEXTUREFILTER_POINTSAMPLED,
|
HWD_SET_TEXTUREFILTER_POINTSAMPLED,
|
||||||
|
|
|
@ -1,19 +1,12 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2005 by Sonic Team Junior.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2005 by SRB2 Jr. Team.
|
// This program is free software distributed under the
|
||||||
//
|
// terms of the GNU General Public License, version 2.
|
||||||
// This program is free software; you can redistribute it and/or
|
// See the 'LICENSE' file for more details.
|
||||||
// modify it under the terms of the GNU General Public License
|
|
||||||
// as published by the Free Software Foundation; either version 2
|
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hw_dll.h
|
||||||
/// \brief Win32 DLL and Shared Objects API definitions
|
/// \brief Win32 DLL and Shared Objects API definitions
|
||||||
|
|
||||||
#ifndef __HWR_DLL_H__
|
#ifndef __HWR_DLL_H__
|
||||||
|
@ -54,8 +47,6 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void (*I_Error_t) (const char *error, ...) FUNCIERROR;
|
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// MATHS
|
// MATHS
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
@ -63,7 +54,7 @@ typedef void (*I_Error_t) (const char *error, ...) FUNCIERROR;
|
||||||
// Constants
|
// Constants
|
||||||
#define DEGREE (0.017453292519943295769236907684883l) // 2*PI/360
|
#define DEGREE (0.017453292519943295769236907684883l) // 2*PI/360
|
||||||
|
|
||||||
void DBG_Printf(const char *lpFmt, ...) /*FUNCPRINTF*/;
|
void GL_DBG_Printf(const char *format, ...) /*FUNCPRINTF*/;
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
|
||||||
|
|
|
@ -1,19 +1,13 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
|
||||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||||
|
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software distributed under the
|
||||||
// modify it under the terms of the GNU General Public License
|
// terms of the GNU General Public License, version 2.
|
||||||
// as published by the Free Software Foundation; either version 2
|
// See the 'LICENSE' file for more details.
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hw_draw.c
|
||||||
/// \brief miscellaneous drawing (mainly 2d)
|
/// \brief miscellaneous drawing (mainly 2d)
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
@ -23,6 +17,7 @@
|
||||||
#include "../doomdef.h"
|
#include "../doomdef.h"
|
||||||
|
|
||||||
#ifdef HWRENDER
|
#ifdef HWRENDER
|
||||||
|
#include "hw_main.h"
|
||||||
#include "hw_glob.h"
|
#include "hw_glob.h"
|
||||||
#include "hw_drv.h"
|
#include "hw_drv.h"
|
||||||
|
|
||||||
|
@ -43,9 +38,6 @@
|
||||||
#define O_BINARY 0
|
#define O_BINARY 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float gr_patch_scalex;
|
|
||||||
float gr_patch_scaley;
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
#endif
|
#endif
|
||||||
|
@ -65,9 +57,6 @@ typedef struct
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
#endif
|
#endif
|
||||||
typedef UINT8 GLRGB[3];
|
|
||||||
|
|
||||||
#define BLENDMODE PF_Translucent
|
|
||||||
|
|
||||||
static UINT8 softwaretranstogl[11] = { 0, 25, 51, 76,102,127,153,178,204,229,255};
|
static UINT8 softwaretranstogl[11] = { 0, 25, 51, 76,102,127,153,178,204,229,255};
|
||||||
static UINT8 softwaretranstogl_hi[11] = { 0, 51,102,153,204,255,255,255,255,255,255};
|
static UINT8 softwaretranstogl_hi[11] = { 0, 51,102,153,204,255,255,255,255,255,255};
|
||||||
|
@ -121,12 +110,12 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option)
|
||||||
|
|
||||||
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
||||||
|
|
||||||
v[0].sow = v[3].sow = 0.0f;
|
v[0].s = v[3].s = 0.0f;
|
||||||
v[2].sow = v[1].sow = gpatch->max_s;
|
v[2].s = v[1].s = gpatch->max_s;
|
||||||
v[0].tow = v[1].tow = 0.0f;
|
v[0].t = v[1].t = 0.0f;
|
||||||
v[2].tow = v[3].tow = gpatch->max_t;
|
v[2].t = v[3].t = gpatch->max_t;
|
||||||
|
|
||||||
flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest;
|
flags = PF_Translucent|PF_NoDepthTest;
|
||||||
|
|
||||||
if (option & V_WRAPX)
|
if (option & V_WRAPX)
|
||||||
flags |= PF_ForceWrapX;
|
flags |= PF_ForceWrapX;
|
||||||
|
@ -356,19 +345,19 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
|
||||||
|
|
||||||
if (option & V_FLIP)
|
if (option & V_FLIP)
|
||||||
{
|
{
|
||||||
v[0].sow = v[3].sow = gpatch->max_s;
|
v[0].s = v[3].s = gpatch->max_s;
|
||||||
v[2].sow = v[1].sow = 0.0f;
|
v[2].s = v[1].s = 0.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
v[0].sow = v[3].sow = 0.0f;
|
v[0].s = v[3].s = 0.0f;
|
||||||
v[2].sow = v[1].sow = gpatch->max_s;
|
v[2].s = v[1].s = gpatch->max_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
v[0].tow = v[1].tow = 0.0f;
|
v[0].t = v[1].t = 0.0f;
|
||||||
v[2].tow = v[3].tow = gpatch->max_t;
|
v[2].t = v[3].t = gpatch->max_t;
|
||||||
|
|
||||||
flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest;
|
flags = PF_Translucent|PF_NoDepthTest;
|
||||||
|
|
||||||
if (option & V_WRAPX)
|
if (option & V_WRAPX)
|
||||||
flags |= PF_ForceWrapX;
|
flags |= PF_ForceWrapX;
|
||||||
|
@ -379,11 +368,11 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
|
||||||
if (alphalevel)
|
if (alphalevel)
|
||||||
{
|
{
|
||||||
FSurfaceInfo Surf;
|
FSurfaceInfo Surf;
|
||||||
Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff;
|
Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff;
|
||||||
if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[st_translucency];
|
if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency];
|
||||||
else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[st_translucency];
|
else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency];
|
||||||
else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[st_translucency];
|
else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency];
|
||||||
else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel];
|
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
|
||||||
flags |= PF_Modulated;
|
flags |= PF_Modulated;
|
||||||
HWD.pfnDrawPolygon(&Surf, v, 4, flags);
|
HWD.pfnDrawPolygon(&Surf, v, 4, flags);
|
||||||
}
|
}
|
||||||
|
@ -514,19 +503,19 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
|
||||||
|
|
||||||
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
||||||
|
|
||||||
v[0].sow = v[3].sow = ((sx )/(float)SHORT(gpatch->width) )*gpatch->max_s;
|
v[0].s = v[3].s = ((sx )/(float)SHORT(gpatch->width) )*gpatch->max_s;
|
||||||
if (sx + w > SHORT(gpatch->width))
|
if (sx + w > SHORT(gpatch->width))
|
||||||
v[2].sow = v[1].sow = gpatch->max_s;
|
v[2].s = v[1].s = gpatch->max_s;
|
||||||
else
|
else
|
||||||
v[2].sow = v[1].sow = ((sx+w)/(float)SHORT(gpatch->width) )*gpatch->max_s;
|
v[2].s = v[1].s = ((sx+w)/(float)SHORT(gpatch->width) )*gpatch->max_s;
|
||||||
|
|
||||||
v[0].tow = v[1].tow = ((sy )/(float)SHORT(gpatch->height))*gpatch->max_t;
|
v[0].t = v[1].t = ((sy )/(float)SHORT(gpatch->height))*gpatch->max_t;
|
||||||
if (sy + h > SHORT(gpatch->height))
|
if (sy + h > SHORT(gpatch->height))
|
||||||
v[2].tow = v[3].tow = gpatch->max_t;
|
v[2].t = v[3].t = gpatch->max_t;
|
||||||
else
|
else
|
||||||
v[2].tow = v[3].tow = ((sy+h)/(float)SHORT(gpatch->height))*gpatch->max_t;
|
v[2].t = v[3].t = ((sy+h)/(float)SHORT(gpatch->height))*gpatch->max_t;
|
||||||
|
|
||||||
flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest;
|
flags = PF_Translucent|PF_NoDepthTest;
|
||||||
|
|
||||||
if (option & V_WRAPX)
|
if (option & V_WRAPX)
|
||||||
flags |= PF_ForceWrapX;
|
flags |= PF_ForceWrapX;
|
||||||
|
@ -537,11 +526,11 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
|
||||||
if (alphalevel)
|
if (alphalevel)
|
||||||
{
|
{
|
||||||
FSurfaceInfo Surf;
|
FSurfaceInfo Surf;
|
||||||
Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff;
|
Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff;
|
||||||
if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[st_translucency];
|
if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency];
|
||||||
else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[st_translucency];
|
else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency];
|
||||||
else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[st_translucency];
|
else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency];
|
||||||
else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel];
|
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
|
||||||
flags |= PF_Modulated;
|
flags |= PF_Modulated;
|
||||||
HWD.pfnDrawPolygon(&Surf, v, 4, flags);
|
HWD.pfnDrawPolygon(&Surf, v, 4, flags);
|
||||||
}
|
}
|
||||||
|
@ -569,10 +558,10 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
|
||||||
|
|
||||||
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
||||||
|
|
||||||
v[0].sow = v[3].sow = 0;
|
v[0].s = v[3].s = 0;
|
||||||
v[2].sow = v[1].sow = patch->max_s;
|
v[2].s = v[1].s = patch->max_s;
|
||||||
v[0].tow = v[1].tow = 0;
|
v[0].t = v[1].t = 0;
|
||||||
v[2].tow = v[3].tow = patch->max_t;
|
v[2].t = v[3].t = patch->max_t;
|
||||||
|
|
||||||
|
|
||||||
//Hurdler: Boris, the same comment as above... but maybe for pics
|
//Hurdler: Boris, the same comment as above... but maybe for pics
|
||||||
|
@ -581,7 +570,7 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
|
||||||
// But then, the question is: why not 0 instead of PF_Masked ?
|
// But then, the question is: why not 0 instead of PF_Masked ?
|
||||||
// or maybe PF_Environment ??? (like what I said above)
|
// or maybe PF_Environment ??? (like what I said above)
|
||||||
// BP: PF_Environment don't change anything ! and 0 is undifined
|
// BP: PF_Environment don't change anything ! and 0 is undifined
|
||||||
HWD.pfnDrawPolygon(NULL, v, 4, BLENDMODE | PF_NoDepthTest | PF_Clip | PF_NoZClip);
|
HWD.pfnDrawPolygon(NULL, v, 4, PF_Translucent | PF_NoDepthTest | PF_Clip | PF_NoZClip);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
@ -644,10 +633,10 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum
|
||||||
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
||||||
|
|
||||||
// flat is 64x64 lod and texture offsets are [0.0, 1.0]
|
// flat is 64x64 lod and texture offsets are [0.0, 1.0]
|
||||||
v[0].sow = v[3].sow = (float)((x & flatflag)/dflatsize);
|
v[0].s = v[3].s = (float)((x & flatflag)/dflatsize);
|
||||||
v[2].sow = v[1].sow = (float)(v[0].sow + w/dflatsize);
|
v[2].s = v[1].s = (float)(v[0].s + w/dflatsize);
|
||||||
v[0].tow = v[1].tow = (float)((y & flatflag)/dflatsize);
|
v[0].t = v[1].t = (float)((y & flatflag)/dflatsize);
|
||||||
v[2].tow = v[3].tow = (float)(v[0].tow + h/dflatsize);
|
v[2].t = v[3].t = (float)(v[0].t + h/dflatsize);
|
||||||
|
|
||||||
HWR_LiterallyGetFlat(flatlumpnum);
|
HWR_LiterallyGetFlat(flatlumpnum);
|
||||||
|
|
||||||
|
@ -679,20 +668,20 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength)
|
||||||
v[2].y = v[3].y = 1.0f;
|
v[2].y = v[3].y = 1.0f;
|
||||||
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
||||||
|
|
||||||
v[0].sow = v[3].sow = 0.0f;
|
v[0].s = v[3].s = 0.0f;
|
||||||
v[2].sow = v[1].sow = 1.0f;
|
v[2].s = v[1].s = 1.0f;
|
||||||
v[0].tow = v[1].tow = 1.0f;
|
v[0].t = v[1].t = 1.0f;
|
||||||
v[2].tow = v[3].tow = 0.0f;
|
v[2].t = v[3].t = 0.0f;
|
||||||
|
|
||||||
if (color & 0xFF00) // Do COLORMAP fade.
|
if (color & 0xFF00) // Do COLORMAP fade.
|
||||||
{
|
{
|
||||||
Surf.FlatColor.rgba = UINT2RGBA(0x01010160);
|
Surf.PolyColor.rgba = UINT2RGBA(0x01010160);
|
||||||
Surf.FlatColor.s.alpha = (strength*8);
|
Surf.PolyColor.s.alpha = (strength*8);
|
||||||
}
|
}
|
||||||
else // Do TRANSMAP** fade.
|
else // Do TRANSMAP** fade.
|
||||||
{
|
{
|
||||||
Surf.FlatColor.rgba = V_GetColor(color).rgba;
|
Surf.PolyColor.rgba = V_GetColor(color).rgba;
|
||||||
Surf.FlatColor.s.alpha = softwaretranstogl[strength];
|
Surf.PolyColor.s.alpha = softwaretranstogl[strength];
|
||||||
}
|
}
|
||||||
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
||||||
}
|
}
|
||||||
|
@ -850,24 +839,22 @@ void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 ac
|
||||||
v[0].y = v[1].y = fy;
|
v[0].y = v[1].y = fy;
|
||||||
v[2].y = v[3].y = fy - fh;
|
v[2].y = v[3].y = fy - fh;
|
||||||
|
|
||||||
//Hurdler: do we still use this argb color? if not, we should remove it
|
|
||||||
v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //;
|
|
||||||
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
||||||
|
|
||||||
v[0].sow = v[3].sow = 0.0f;
|
v[0].s = v[3].s = 0.0f;
|
||||||
v[2].sow = v[1].sow = 1.0f;
|
v[2].s = v[1].s = 1.0f;
|
||||||
v[0].tow = v[1].tow = 0.0f;
|
v[0].t = v[1].t = 0.0f;
|
||||||
v[2].tow = v[3].tow = 1.0f;
|
v[2].t = v[3].t = 1.0f;
|
||||||
|
|
||||||
if (actualcolor & 0xFF00) // Do COLORMAP fade.
|
if (actualcolor & 0xFF00) // Do COLORMAP fade.
|
||||||
{
|
{
|
||||||
Surf.FlatColor.rgba = UINT2RGBA(0x01010160);
|
Surf.PolyColor.rgba = UINT2RGBA(0x01010160);
|
||||||
Surf.FlatColor.s.alpha = (strength*8);
|
Surf.PolyColor.s.alpha = (strength*8);
|
||||||
}
|
}
|
||||||
else // Do TRANSMAP** fade.
|
else // Do TRANSMAP** fade.
|
||||||
{
|
{
|
||||||
Surf.FlatColor.rgba = V_GetColor(actualcolor).rgba;
|
Surf.PolyColor.rgba = V_GetColor(actualcolor).rgba;
|
||||||
Surf.FlatColor.s.alpha = softwaretranstogl[strength];
|
Surf.PolyColor.s.alpha = softwaretranstogl[strength];
|
||||||
}
|
}
|
||||||
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
||||||
}
|
}
|
||||||
|
@ -888,13 +875,13 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height)
|
||||||
v[2].y = v[3].y = 1.0f;
|
v[2].y = v[3].y = 1.0f;
|
||||||
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
||||||
|
|
||||||
v[0].sow = v[3].sow = 0.0f;
|
v[0].s = v[3].s = 0.0f;
|
||||||
v[2].sow = v[1].sow = 1.0f;
|
v[2].s = v[1].s = 1.0f;
|
||||||
v[0].tow = v[1].tow = 1.0f;
|
v[0].t = v[1].t = 1.0f;
|
||||||
v[2].tow = v[3].tow = 0.0f;
|
v[2].t = v[3].t = 0.0f;
|
||||||
|
|
||||||
Surf.FlatColor.rgba = UINT2RGBA(color);
|
Surf.PolyColor.rgba = UINT2RGBA(color);
|
||||||
Surf.FlatColor.s.alpha = 0x80;
|
Surf.PolyColor.s.alpha = 0x80;
|
||||||
|
|
||||||
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
||||||
}
|
}
|
||||||
|
@ -904,7 +891,11 @@ void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight)
|
||||||
{
|
{
|
||||||
FOutVector v[4];
|
FOutVector v[4];
|
||||||
FSurfaceInfo Surf;
|
FSurfaceInfo Surf;
|
||||||
INT32 height = (boxheight * 4) + (boxheight/2)*5; // 4 lines of space plus gaps between and some leeway
|
INT32 height;
|
||||||
|
if (boxheight < 0)
|
||||||
|
height = -boxheight;
|
||||||
|
else
|
||||||
|
height = (boxheight * 4) + (boxheight/2)*5; // 4 lines of space plus gaps between and some leeway
|
||||||
|
|
||||||
// setup some neat-o translucency effect
|
// setup some neat-o translucency effect
|
||||||
|
|
||||||
|
@ -914,13 +905,13 @@ void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight)
|
||||||
v[2].y = v[3].y = -1.0f+((height<<1)/(float)vid.height);
|
v[2].y = v[3].y = -1.0f+((height<<1)/(float)vid.height);
|
||||||
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
||||||
|
|
||||||
v[0].sow = v[3].sow = 0.0f;
|
v[0].s = v[3].s = 0.0f;
|
||||||
v[2].sow = v[1].sow = 1.0f;
|
v[2].s = v[1].s = 1.0f;
|
||||||
v[0].tow = v[1].tow = 1.0f;
|
v[0].t = v[1].t = 1.0f;
|
||||||
v[2].tow = v[3].tow = 0.0f;
|
v[2].t = v[3].t = 0.0f;
|
||||||
|
|
||||||
Surf.FlatColor.rgba = UINT2RGBA(color);
|
Surf.PolyColor.rgba = UINT2RGBA(color);
|
||||||
Surf.FlatColor.s.alpha = (color == 0 ? 0xC0 : 0x80); // make black darker, like software
|
Surf.PolyColor.s.alpha = (color == 0 ? 0xC0 : 0x80); // make black darker, like software
|
||||||
|
|
||||||
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
||||||
}
|
}
|
||||||
|
@ -1232,17 +1223,15 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32
|
||||||
v[0].y = v[1].y = fy;
|
v[0].y = v[1].y = fy;
|
||||||
v[2].y = v[3].y = fy - fh;
|
v[2].y = v[3].y = fy - fh;
|
||||||
|
|
||||||
//Hurdler: do we still use this argb color? if not, we should remove it
|
|
||||||
v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //;
|
|
||||||
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
||||||
|
|
||||||
v[0].sow = v[3].sow = 0.0f;
|
v[0].s = v[3].s = 0.0f;
|
||||||
v[2].sow = v[1].sow = 1.0f;
|
v[2].s = v[1].s = 1.0f;
|
||||||
v[0].tow = v[1].tow = 0.0f;
|
v[0].t = v[1].t = 0.0f;
|
||||||
v[2].tow = v[3].tow = 1.0f;
|
v[2].t = v[3].t = 1.0f;
|
||||||
|
|
||||||
Surf.FlatColor.rgba = UINT2RGBA(actualcolor);
|
Surf.PolyColor.rgba = UINT2RGBA(actualcolor);
|
||||||
Surf.FlatColor.s.alpha = 0x80;
|
Surf.PolyColor.s.alpha = 0x80;
|
||||||
|
|
||||||
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
||||||
}
|
}
|
||||||
|
@ -1412,16 +1401,14 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
|
||||||
v[0].y = v[1].y = fy;
|
v[0].y = v[1].y = fy;
|
||||||
v[2].y = v[3].y = fy - fh;
|
v[2].y = v[3].y = fy - fh;
|
||||||
|
|
||||||
//Hurdler: do we still use this argb color? if not, we should remove it
|
|
||||||
v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //;
|
|
||||||
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
||||||
|
|
||||||
v[0].sow = v[3].sow = 0.0f;
|
v[0].s = v[3].s = 0.0f;
|
||||||
v[2].sow = v[1].sow = 1.0f;
|
v[2].s = v[1].s = 1.0f;
|
||||||
v[0].tow = v[1].tow = 0.0f;
|
v[0].t = v[1].t = 0.0f;
|
||||||
v[2].tow = v[3].tow = 1.0f;
|
v[2].t = v[3].t = 1.0f;
|
||||||
|
|
||||||
Surf.FlatColor = V_GetColor(color);
|
Surf.PolyColor = V_GetColor(color);
|
||||||
|
|
||||||
HWD.pfnDrawPolygon(&Surf, v, 4,
|
HWD.pfnDrawPolygon(&Surf, v, 4,
|
||||||
PF_Modulated|PF_NoTexture|PF_NoDepthTest);
|
PF_Modulated|PF_NoTexture|PF_NoDepthTest);
|
||||||
|
|
|
@ -1,20 +1,13 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
|
||||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||||
|
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software distributed under the
|
||||||
// modify it under the terms of the GNU General Public License
|
// terms of the GNU General Public License, version 2.
|
||||||
// as published by the Free Software Foundation; either version 2
|
// See the 'LICENSE' file for more details.
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hw_drv.h
|
||||||
/// \brief imports/exports for the 3D hardware low-level interface API
|
/// \brief imports/exports for the 3D hardware low-level interface API
|
||||||
|
|
||||||
#ifndef __HWR_DRV_H__
|
#ifndef __HWR_DRV_H__
|
||||||
|
@ -32,7 +25,7 @@
|
||||||
// STANDARD DLL EXPORTS
|
// STANDARD DLL EXPORTS
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
EXPORT boolean HWRAPI(Init) (I_Error_t ErrorFunction);
|
EXPORT boolean HWRAPI(Init) (void);
|
||||||
#ifndef HAVE_SDL
|
#ifndef HAVE_SDL
|
||||||
EXPORT void HWRAPI(Shutdown) (void);
|
EXPORT void HWRAPI(Shutdown) (void);
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,10 +36,12 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal);
|
||||||
EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl);
|
EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl);
|
||||||
EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color);
|
EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color);
|
||||||
EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags);
|
EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags);
|
||||||
|
EXPORT void HWRAPI(DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, UINT32 *IndexArray);
|
||||||
EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform);
|
EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform);
|
||||||
EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags);
|
EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags);
|
||||||
EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor);
|
EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor);
|
||||||
EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo);
|
EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo);
|
||||||
|
EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *TexInfo);
|
||||||
EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data);
|
EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data);
|
||||||
EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip);
|
EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip);
|
||||||
EXPORT void HWRAPI(ClearMipMapCache) (void);
|
EXPORT void HWRAPI(ClearMipMapCache) (void);
|
||||||
|
@ -55,14 +50,11 @@ EXPORT void HWRAPI(ClearMipMapCache) (void);
|
||||||
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
|
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
|
||||||
|
|
||||||
//Hurdler: added for new development
|
//Hurdler: added for new development
|
||||||
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color);
|
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface);
|
||||||
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
|
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
|
||||||
EXPORT void HWRAPI(SetTransform) (FTransform *ptransform);
|
EXPORT void HWRAPI(SetTransform) (FTransform *ptransform);
|
||||||
EXPORT INT32 HWRAPI(GetTextureUsed) (void);
|
EXPORT INT32 HWRAPI(GetTextureUsed) (void);
|
||||||
EXPORT INT32 HWRAPI(GetRenderVersion) (void);
|
|
||||||
|
|
||||||
#define SCREENVERTS 10
|
|
||||||
EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
|
|
||||||
EXPORT void HWRAPI(FlushScreenTextures) (void);
|
EXPORT void HWRAPI(FlushScreenTextures) (void);
|
||||||
EXPORT void HWRAPI(StartScreenWipe) (void);
|
EXPORT void HWRAPI(StartScreenWipe) (void);
|
||||||
EXPORT void HWRAPI(EndScreenWipe) (void);
|
EXPORT void HWRAPI(EndScreenWipe) (void);
|
||||||
|
@ -71,6 +63,20 @@ EXPORT void HWRAPI(DrawIntermissionBG) (void);
|
||||||
EXPORT void HWRAPI(MakeScreenTexture) (void);
|
EXPORT void HWRAPI(MakeScreenTexture) (void);
|
||||||
EXPORT void HWRAPI(MakeScreenFinalTexture) (void);
|
EXPORT void HWRAPI(MakeScreenFinalTexture) (void);
|
||||||
EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height);
|
EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height);
|
||||||
|
|
||||||
|
#define SCREENVERTS 10
|
||||||
|
EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
|
||||||
|
|
||||||
|
// jimita
|
||||||
|
EXPORT boolean HWRAPI(LoadShaders) (void);
|
||||||
|
EXPORT void HWRAPI(KillShaders) (void);
|
||||||
|
EXPORT void HWRAPI(SetShader) (int shader);
|
||||||
|
EXPORT void HWRAPI(UnSetShader) (void);
|
||||||
|
|
||||||
|
EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value);
|
||||||
|
EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment);
|
||||||
|
EXPORT boolean HWRAPI(InitCustomShaders) (void);
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// HWR DRIVER OBJECT, FOR CLIENT PROGRAM
|
// HWR DRIVER OBJECT, FOR CLIENT PROGRAM
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
@ -84,10 +90,12 @@ struct hwdriver_s
|
||||||
FinishUpdate pfnFinishUpdate;
|
FinishUpdate pfnFinishUpdate;
|
||||||
Draw2DLine pfnDraw2DLine;
|
Draw2DLine pfnDraw2DLine;
|
||||||
DrawPolygon pfnDrawPolygon;
|
DrawPolygon pfnDrawPolygon;
|
||||||
|
DrawIndexedTriangles pfnDrawIndexedTriangles;
|
||||||
RenderSkyDome pfnRenderSkyDome;
|
RenderSkyDome pfnRenderSkyDome;
|
||||||
SetBlend pfnSetBlend;
|
SetBlend pfnSetBlend;
|
||||||
ClearBuffer pfnClearBuffer;
|
ClearBuffer pfnClearBuffer;
|
||||||
SetTexture pfnSetTexture;
|
SetTexture pfnSetTexture;
|
||||||
|
UpdateTexture pfnUpdateTexture;
|
||||||
ReadRect pfnReadRect;
|
ReadRect pfnReadRect;
|
||||||
GClipRect pfnGClipRect;
|
GClipRect pfnGClipRect;
|
||||||
ClearMipMapCache pfnClearMipMapCache;
|
ClearMipMapCache pfnClearMipMapCache;
|
||||||
|
@ -96,7 +104,6 @@ struct hwdriver_s
|
||||||
CreateModelVBOs pfnCreateModelVBOs;
|
CreateModelVBOs pfnCreateModelVBOs;
|
||||||
SetTransform pfnSetTransform;
|
SetTransform pfnSetTransform;
|
||||||
GetTextureUsed pfnGetTextureUsed;
|
GetTextureUsed pfnGetTextureUsed;
|
||||||
GetRenderVersion pfnGetRenderVersion;
|
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
GetModeList pfnGetModeList;
|
GetModeList pfnGetModeList;
|
||||||
#endif
|
#endif
|
||||||
|
@ -112,13 +119,19 @@ struct hwdriver_s
|
||||||
MakeScreenTexture pfnMakeScreenTexture;
|
MakeScreenTexture pfnMakeScreenTexture;
|
||||||
MakeScreenFinalTexture pfnMakeScreenFinalTexture;
|
MakeScreenFinalTexture pfnMakeScreenFinalTexture;
|
||||||
DrawScreenFinalTexture pfnDrawScreenFinalTexture;
|
DrawScreenFinalTexture pfnDrawScreenFinalTexture;
|
||||||
|
|
||||||
|
LoadShaders pfnLoadShaders;
|
||||||
|
KillShaders pfnKillShaders;
|
||||||
|
SetShader pfnSetShader;
|
||||||
|
UnSetShader pfnUnSetShader;
|
||||||
|
|
||||||
|
SetShaderInfo pfnSetShaderInfo;
|
||||||
|
LoadCustomShader pfnLoadCustomShader;
|
||||||
|
InitCustomShaders pfnInitCustomShaders;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct hwdriver_s hwdriver;
|
extern struct hwdriver_s hwdriver;
|
||||||
|
|
||||||
//Hurdler: 16/10/99: added for OpenGL gamma correction
|
|
||||||
//extern RGBA_t gamma_correction;
|
|
||||||
|
|
||||||
#define HWD hwdriver
|
#define HWD hwdriver
|
||||||
|
|
||||||
#endif //not defined _CREATE_DLL_
|
#endif //not defined _CREATE_DLL_
|
||||||
|
|
|
@ -1,19 +1,12 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
|
||||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software distributed under the
|
||||||
// modify it under the terms of the GNU General Public License
|
// terms of the GNU General Public License, version 2.
|
||||||
// as published by the Free Software Foundation; either version 2
|
// See the 'LICENSE' file for more details.
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hw_glide.h
|
||||||
/// \brief Declaration needed by Glide renderer
|
/// \brief Declaration needed by Glide renderer
|
||||||
/// !!! To be replaced by our own def in the future !!!
|
/// !!! To be replaced by our own def in the future !!!
|
||||||
|
|
||||||
|
@ -25,26 +18,6 @@
|
||||||
typedef unsigned long FxU32;
|
typedef unsigned long FxU32;
|
||||||
typedef long FxI32;
|
typedef long FxI32;
|
||||||
|
|
||||||
typedef FxI32 GrAspectRatio_t;
|
|
||||||
#define GR_ASPECT_LOG2_8x1 3 /* 8W x 1H */
|
|
||||||
#define GR_ASPECT_LOG2_4x1 2 /* 4W x 1H */
|
|
||||||
#define GR_ASPECT_LOG2_2x1 1 /* 2W x 1H */
|
|
||||||
#define GR_ASPECT_LOG2_1x1 0 /* 1W x 1H */
|
|
||||||
#define GR_ASPECT_LOG2_1x2 -1 /* 1W x 2H */
|
|
||||||
#define GR_ASPECT_LOG2_1x4 -2 /* 1W x 4H */
|
|
||||||
#define GR_ASPECT_LOG2_1x8 -3 /* 1W x 8H */
|
|
||||||
|
|
||||||
typedef FxI32 GrLOD_t;
|
|
||||||
#define GR_LOD_LOG2_256 0x8
|
|
||||||
#define GR_LOD_LOG2_128 0x7
|
|
||||||
#define GR_LOD_LOG2_64 0x6
|
|
||||||
#define GR_LOD_LOG2_32 0x5
|
|
||||||
#define GR_LOD_LOG2_16 0x4
|
|
||||||
#define GR_LOD_LOG2_8 0x3
|
|
||||||
#define GR_LOD_LOG2_4 0x2
|
|
||||||
#define GR_LOD_LOG2_2 0x1
|
|
||||||
#define GR_LOD_LOG2_1 0x0
|
|
||||||
|
|
||||||
typedef FxI32 GrTextureFormat_t;
|
typedef FxI32 GrTextureFormat_t;
|
||||||
#define GR_TEXFMT_ALPHA_8 0x2 /* (0..0xFF) alpha */
|
#define GR_TEXFMT_ALPHA_8 0x2 /* (0..0xFF) alpha */
|
||||||
#define GR_TEXFMT_INTENSITY_8 0x3 /* (0..0xFF) intensity */
|
#define GR_TEXFMT_INTENSITY_8 0x3 /* (0..0xFF) intensity */
|
||||||
|
@ -59,11 +32,6 @@ typedef FxI32 GrTextureFormat_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
#ifdef GLIDE_API_COMPATIBILITY
|
|
||||||
GrLOD_t smallLodLog2;
|
|
||||||
GrLOD_t largeLodLog2;
|
|
||||||
GrAspectRatio_t aspectRatioLog2;
|
|
||||||
#endif
|
|
||||||
GrTextureFormat_t format;
|
GrTextureFormat_t format;
|
||||||
void *data;
|
void *data;
|
||||||
} GrTexInfo;
|
} GrTexInfo;
|
||||||
|
|
|
@ -1,20 +1,13 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
|
||||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||||
|
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software distributed under the
|
||||||
// modify it under the terms of the GNU General Public License
|
// terms of the GNU General Public License, version 2.
|
||||||
// as published by the Free Software Foundation; either version 2
|
// See the 'LICENSE' file for more details.
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hw_glob.h
|
||||||
/// \brief globals (shared data & code) for hw_ modules
|
/// \brief globals (shared data & code) for hw_ modules
|
||||||
|
|
||||||
#ifndef _HWR_GLOB_H_
|
#ifndef _HWR_GLOB_H_
|
||||||
|
@ -118,11 +111,6 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
|
||||||
// --------
|
// --------
|
||||||
// hw_draw.c
|
// hw_draw.c
|
||||||
// --------
|
// --------
|
||||||
extern float gr_patch_scalex;
|
|
||||||
extern float gr_patch_scaley;
|
|
||||||
|
|
||||||
extern consvar_t cv_grrounddown; // on/off
|
|
||||||
|
|
||||||
extern INT32 patchformat;
|
extern INT32 patchformat;
|
||||||
extern INT32 textureformat;
|
extern INT32 textureformat;
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,13 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
|
||||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||||
|
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software distributed under the
|
||||||
// modify it under the terms of the GNU General Public License
|
// terms of the GNU General Public License, version 2.
|
||||||
// as published by the Free Software Foundation; either version 2
|
// See the 'LICENSE' file for more details.
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hw_light.c
|
||||||
/// \brief Corona/Dynamic/Static lighting add on by Hurdler
|
/// \brief Corona/Dynamic/Static lighting add on by Hurdler
|
||||||
/// !!! Under construction !!!
|
/// !!! Under construction !!!
|
||||||
|
|
||||||
|
@ -298,6 +292,8 @@ light_t *t_lspr[NUMSPRITES] =
|
||||||
|
|
||||||
// Projectiles
|
// Projectiles
|
||||||
&lspr[NOLIGHT], // SPR_MISL
|
&lspr[NOLIGHT], // SPR_MISL
|
||||||
|
&lspr[SMALLREDBALL_L], // SPR_LASR
|
||||||
|
&lspr[REDSHINE_L], // SPR_LASF
|
||||||
&lspr[NOLIGHT], // SPR_TORP
|
&lspr[NOLIGHT], // SPR_TORP
|
||||||
&lspr[NOLIGHT], // SPR_ENRG
|
&lspr[NOLIGHT], // SPR_ENRG
|
||||||
&lspr[NOLIGHT], // SPR_MINE
|
&lspr[NOLIGHT], // SPR_MINE
|
||||||
|
@ -877,19 +873,19 @@ void HWR_WallLighting(FOutVector *wlVerts)
|
||||||
#endif
|
#endif
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
wlVerts[i].sow = (float)(0.5f + d[i]*s);
|
wlVerts[i].s = (float)(0.5f + d[i]*s);
|
||||||
wlVerts[i].tow = (float)(0.5f + (wlVerts[i].y-LIGHT_POS(j).y)*s*1.2f);
|
wlVerts[i].t = (float)(0.5f + (wlVerts[i].y-LIGHT_POS(j).y)*s*1.2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
HWR_SetLight();
|
HWR_SetLight();
|
||||||
|
|
||||||
Surf.FlatColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color);
|
Surf.PolyColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color);
|
||||||
#ifdef DL_HIGH_QUALITY
|
#ifdef DL_HIGH_QUALITY
|
||||||
Surf.FlatColor.s.alpha = (UINT8)((1-dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha);
|
Surf.PolyColor.s.alpha = (UINT8)((1-dist_p2d/DL_SQRRADIUS(j))*Surf.PolyColor.s.alpha);
|
||||||
#endif
|
#endif
|
||||||
// next state is null so fade out with alpha
|
// next state is null so fade out with alpha
|
||||||
if (dynlights->mo[j]->state->nextstate == S_NULL)
|
if (dynlights->mo[j]->state->nextstate == S_NULL)
|
||||||
Surf.FlatColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha);
|
Surf.PolyColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.PolyColor.s.alpha);
|
||||||
|
|
||||||
HWD.pfnDrawPolygon (&Surf, wlVerts, 4, LIGHTMAPFLAGS);
|
HWD.pfnDrawPolygon (&Surf, wlVerts, 4, LIGHTMAPFLAGS);
|
||||||
|
|
||||||
|
@ -946,19 +942,19 @@ void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts)
|
||||||
#endif
|
#endif
|
||||||
for (i = 0; i < nrClipVerts; i++)
|
for (i = 0; i < nrClipVerts; i++)
|
||||||
{
|
{
|
||||||
clVerts[i].sow = 0.5f + (clVerts[i].x-LIGHT_POS(j).x)*s;
|
clVerts[i].s = 0.5f + (clVerts[i].x-LIGHT_POS(j).x)*s;
|
||||||
clVerts[i].tow = 0.5f + (clVerts[i].z-LIGHT_POS(j).z)*s*1.2f;
|
clVerts[i].t = 0.5f + (clVerts[i].z-LIGHT_POS(j).z)*s*1.2f;
|
||||||
}
|
}
|
||||||
|
|
||||||
HWR_SetLight();
|
HWR_SetLight();
|
||||||
|
|
||||||
Surf.FlatColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color);
|
Surf.PolyColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color);
|
||||||
#ifdef DL_HIGH_QUALITY
|
#ifdef DL_HIGH_QUALITY
|
||||||
Surf.FlatColor.s.alpha = (unsigned char)((1 - dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha);
|
Surf.PolyColor.s.alpha = (unsigned char)((1 - dist_p2d/DL_SQRRADIUS(j))*Surf.PolyColor.s.alpha);
|
||||||
#endif
|
#endif
|
||||||
// next state is null so fade out with alpha
|
// next state is null so fade out with alpha
|
||||||
if ((dynlights->mo[j]->state->nextstate == S_NULL))
|
if ((dynlights->mo[j]->state->nextstate == S_NULL))
|
||||||
Surf.FlatColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha);
|
Surf.PolyColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.PolyColor.s.alpha);
|
||||||
|
|
||||||
HWD.pfnDrawPolygon (&Surf, clVerts, nrClipVerts, LIGHTMAPFLAGS);
|
HWD.pfnDrawPolygon (&Surf, clVerts, nrClipVerts, LIGHTMAPFLAGS);
|
||||||
|
|
||||||
|
@ -1025,11 +1021,11 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gr_vissprite_t *spr)
|
||||||
// more realistique corona !
|
// more realistique corona !
|
||||||
if (cz >= 255*8+250)
|
if (cz >= 255*8+250)
|
||||||
return;
|
return;
|
||||||
Surf.FlatColor.rgba = p_lspr->corona_color;
|
Surf.PolyColor.rgba = p_lspr->corona_color;
|
||||||
if (cz > 250.0f)
|
if (cz > 250.0f)
|
||||||
Surf.FlatColor.s.alpha = 0xff-((int)cz-250)/8;
|
Surf.PolyColor.s.alpha = 0xff-((int)cz-250)/8;
|
||||||
else
|
else
|
||||||
Surf.FlatColor.s.alpha = 0xff;
|
Surf.PolyColor.s.alpha = 0xff;
|
||||||
|
|
||||||
// do not be hide by sprite of the light itself !
|
// do not be hide by sprite of the light itself !
|
||||||
cz = cz - 2.0f;
|
cz = cz - 2.0f;
|
||||||
|
@ -1041,19 +1037,19 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gr_vissprite_t *spr)
|
||||||
// car comme l'offset est minime sa ce voit pas !
|
// car comme l'offset est minime sa ce voit pas !
|
||||||
light[0].x = cx-size; light[0].z = cz;
|
light[0].x = cx-size; light[0].z = cz;
|
||||||
light[0].y = cy-size*1.33f+p_lspr->light_yoffset;
|
light[0].y = cy-size*1.33f+p_lspr->light_yoffset;
|
||||||
light[0].sow = 0.0f; light[0].tow = 0.0f;
|
light[0].s = 0.0f; light[0].t = 0.0f;
|
||||||
|
|
||||||
light[1].x = cx+size; light[1].z = cz;
|
light[1].x = cx+size; light[1].z = cz;
|
||||||
light[1].y = cy-size*1.33f+p_lspr->light_yoffset;
|
light[1].y = cy-size*1.33f+p_lspr->light_yoffset;
|
||||||
light[1].sow = 1.0f; light[1].tow = 0.0f;
|
light[1].s = 1.0f; light[1].t = 0.0f;
|
||||||
|
|
||||||
light[2].x = cx+size; light[2].z = cz;
|
light[2].x = cx+size; light[2].z = cz;
|
||||||
light[2].y = cy+size*1.33f+p_lspr->light_yoffset;
|
light[2].y = cy+size*1.33f+p_lspr->light_yoffset;
|
||||||
light[2].sow = 1.0f; light[2].tow = 1.0f;
|
light[2].s = 1.0f; light[2].t = 1.0f;
|
||||||
|
|
||||||
light[3].x = cx-size; light[3].z = cz;
|
light[3].x = cx-size; light[3].z = cz;
|
||||||
light[3].y = cy+size*1.33f+p_lspr->light_yoffset;
|
light[3].y = cy+size*1.33f+p_lspr->light_yoffset;
|
||||||
light[3].sow = 0.0f; light[3].tow = 1.0f;
|
light[3].s = 0.0f; light[3].t = 1.0f;
|
||||||
|
|
||||||
HWR_GetPic(coronalumpnum); /// \todo use different coronas
|
HWR_GetPic(coronalumpnum); /// \todo use different coronas
|
||||||
|
|
||||||
|
@ -1099,11 +1095,11 @@ void HWR_DrawCoronas(void)
|
||||||
// more realistique corona !
|
// more realistique corona !
|
||||||
if (cz >= 255*8+250)
|
if (cz >= 255*8+250)
|
||||||
continue;
|
continue;
|
||||||
Surf.FlatColor.rgba = p_lspr->corona_color;
|
Surf.PolyColor.rgba = p_lspr->corona_color;
|
||||||
if (cz > 250.0f)
|
if (cz > 250.0f)
|
||||||
Surf.FlatColor.s.alpha = (UINT8)(0xff-(UINT8)(((int)cz-250)/8));
|
Surf.PolyColor.s.alpha = (UINT8)(0xff-(UINT8)(((int)cz-250)/8));
|
||||||
else
|
else
|
||||||
Surf.FlatColor.s.alpha = 0xff;
|
Surf.PolyColor.s.alpha = 0xff;
|
||||||
|
|
||||||
switch (p_lspr->type)
|
switch (p_lspr->type)
|
||||||
{
|
{
|
||||||
|
@ -1111,7 +1107,7 @@ void HWR_DrawCoronas(void)
|
||||||
size = p_lspr->corona_radius * ((cz+120.0f)/950.0f); // d'ou vienne ces constante ?
|
size = p_lspr->corona_radius * ((cz+120.0f)/950.0f); // d'ou vienne ces constante ?
|
||||||
break;
|
break;
|
||||||
case ROCKET_SPR:
|
case ROCKET_SPR:
|
||||||
Surf.FlatColor.s.alpha = (UINT8)((M_RandomByte()>>1)&0xff);
|
Surf.PolyColor.s.alpha = (UINT8)((M_RandomByte()>>1)&0xff);
|
||||||
// don't need a break
|
// don't need a break
|
||||||
case CORONA_SPR:
|
case CORONA_SPR:
|
||||||
size = p_lspr->corona_radius * ((cz+60.0f)/100.0f); // d'ou vienne ces constante ?
|
size = p_lspr->corona_radius * ((cz+60.0f)/100.0f); // d'ou vienne ces constante ?
|
||||||
|
@ -1131,19 +1127,19 @@ void HWR_DrawCoronas(void)
|
||||||
|
|
||||||
light[0].x = cx-size; light[0].z = cz;
|
light[0].x = cx-size; light[0].z = cz;
|
||||||
light[0].y = cy-size*1.33f;
|
light[0].y = cy-size*1.33f;
|
||||||
light[0].sow = 0.0f; light[0].tow = 0.0f;
|
light[0].s = 0.0f; light[0].t = 0.0f;
|
||||||
|
|
||||||
light[1].x = cx+size; light[1].z = cz;
|
light[1].x = cx+size; light[1].z = cz;
|
||||||
light[1].y = cy-size*1.33f;
|
light[1].y = cy-size*1.33f;
|
||||||
light[1].sow = 1.0f; light[1].tow = 0.0f;
|
light[1].s = 1.0f; light[1].t = 0.0f;
|
||||||
|
|
||||||
light[2].x = cx+size; light[2].z = cz;
|
light[2].x = cx+size; light[2].z = cz;
|
||||||
light[2].y = cy+size*1.33f;
|
light[2].y = cy+size*1.33f;
|
||||||
light[2].sow = 1.0f; light[2].tow = 1.0f;
|
light[2].s = 1.0f; light[2].t = 1.0f;
|
||||||
|
|
||||||
light[3].x = cx-size; light[3].z = cz;
|
light[3].x = cx-size; light[3].z = cz;
|
||||||
light[3].y = cy+size*1.33f;
|
light[3].y = cy+size*1.33f;
|
||||||
light[3].sow = 0.0f; light[3].tow = 1.0f;
|
light[3].s = 0.0f; light[3].t = 1.0f;
|
||||||
|
|
||||||
HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_NoDepthTest | PF_Corona);
|
HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_NoDepthTest | PF_Corona);
|
||||||
}
|
}
|
||||||
|
@ -1252,11 +1248,6 @@ static void HWR_SetLight(void)
|
||||||
lightmappatch.height = 128;
|
lightmappatch.height = 128;
|
||||||
lightmappatch.mipmap->width = 128;
|
lightmappatch.mipmap->width = 128;
|
||||||
lightmappatch.mipmap->height = 128;
|
lightmappatch.mipmap->height = 128;
|
||||||
#ifdef GLIDE_API_COMPATIBILITY
|
|
||||||
lightmappatch.mipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_128;
|
|
||||||
lightmappatch.mipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_128;
|
|
||||||
lightmappatch.mipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
|
|
||||||
#endif
|
|
||||||
lightmappatch.mipmap->flags = 0; //TF_WRAPXY; // DEBUG: view the overdraw !
|
lightmappatch.mipmap->flags = 0; //TF_WRAPXY; // DEBUG: view the overdraw !
|
||||||
}
|
}
|
||||||
HWD.pfnSetTexture(lightmappatch.mipmap);
|
HWD.pfnSetTexture(lightmappatch.mipmap);
|
||||||
|
|
|
@ -1,19 +1,13 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
|
||||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||||
|
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software distributed under the
|
||||||
// modify it under the terms of the GNU General Public License
|
// terms of the GNU General Public License, version 2.
|
||||||
// as published by the Free Software Foundation; either version 2
|
// See the 'LICENSE' file for more details.
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hw_light.h
|
||||||
/// \brief Dynamic lighting & coronas add on by Hurdler
|
/// \brief Dynamic lighting & coronas add on by Hurdler
|
||||||
|
|
||||||
#ifndef _HW_LIGHTS_
|
#ifndef _HW_LIGHTS_
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,20 +1,13 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
|
||||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||||
|
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software distributed under the
|
||||||
// modify it under the terms of the GNU General Public License
|
// terms of the GNU General Public License, version 2.
|
||||||
// as published by the Free Software Foundation; either version 2
|
// See the 'LICENSE' file for more details.
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hw_main.h
|
||||||
/// \brief 3D render mode functions
|
/// \brief 3D render mode functions
|
||||||
|
|
||||||
#ifndef __HWR_MAIN_H__
|
#ifndef __HWR_MAIN_H__
|
||||||
|
@ -73,8 +66,11 @@ void HWR_MakeScreenFinalTexture(void);
|
||||||
void HWR_DrawScreenFinalTexture(int width, int height);
|
void HWR_DrawScreenFinalTexture(int width, int height);
|
||||||
|
|
||||||
// This stuff is put here so MD2's can use them
|
// This stuff is put here so MD2's can use them
|
||||||
UINT32 HWR_Lighting(INT32 light, UINT32 color, UINT32 fadecolor, boolean fogblockpoly, boolean plane);
|
void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap);
|
||||||
FUNCMATH UINT8 LightLevelToLum(INT32 l);
|
UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work
|
||||||
|
|
||||||
|
void HWR_ReadShaders(UINT16 wadnum, boolean PK3);
|
||||||
|
boolean HWR_LoadShaders(void);
|
||||||
|
|
||||||
extern CV_PossibleValue_t granisotropicmode_cons_t[];
|
extern CV_PossibleValue_t granisotropicmode_cons_t[];
|
||||||
|
|
||||||
|
@ -84,21 +80,23 @@ extern consvar_t cv_grstaticlighting;
|
||||||
extern consvar_t cv_grcoronas;
|
extern consvar_t cv_grcoronas;
|
||||||
extern consvar_t cv_grcoronasize;
|
extern consvar_t cv_grcoronasize;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern consvar_t cv_grshaders;
|
||||||
extern consvar_t cv_grmodels;
|
extern consvar_t cv_grmodels;
|
||||||
extern consvar_t cv_grmodelinterpolation;
|
extern consvar_t cv_grmodelinterpolation;
|
||||||
extern consvar_t cv_grmodellighting;
|
extern consvar_t cv_grmodellighting;
|
||||||
extern consvar_t cv_grfog;
|
|
||||||
extern consvar_t cv_grfogcolor;
|
|
||||||
extern consvar_t cv_grfogdensity;
|
|
||||||
extern consvar_t cv_grsoftwarefog;
|
|
||||||
extern consvar_t cv_grfiltermode;
|
extern consvar_t cv_grfiltermode;
|
||||||
extern consvar_t cv_granisotropicmode;
|
extern consvar_t cv_granisotropicmode;
|
||||||
extern consvar_t cv_grcorrecttricks;
|
extern consvar_t cv_grcorrecttricks;
|
||||||
extern consvar_t cv_fovchange;
|
extern consvar_t cv_fovchange;
|
||||||
extern consvar_t cv_grsolvetjoin;
|
extern consvar_t cv_grsolvetjoin;
|
||||||
|
extern consvar_t cv_grshearing;
|
||||||
extern consvar_t cv_grspritebillboarding;
|
extern consvar_t cv_grspritebillboarding;
|
||||||
extern consvar_t cv_grskydome;
|
extern consvar_t cv_grskydome;
|
||||||
extern consvar_t cv_grfakecontrast;
|
extern consvar_t cv_grfakecontrast;
|
||||||
|
extern consvar_t cv_grslopecontrast;
|
||||||
|
|
||||||
|
extern consvar_t cv_grbatching;
|
||||||
|
|
||||||
extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy;
|
extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy;
|
||||||
|
|
||||||
|
@ -108,4 +106,24 @@ extern float gr_viewwindowx, gr_basewindowcentery;
|
||||||
extern fixed_t *hwbbox;
|
extern fixed_t *hwbbox;
|
||||||
extern FTransform atransform;
|
extern FTransform atransform;
|
||||||
|
|
||||||
|
|
||||||
|
// Render stats
|
||||||
|
extern int rs_hw_nodesorttime;
|
||||||
|
extern int rs_hw_nodedrawtime;
|
||||||
|
extern int rs_hw_spritesorttime;
|
||||||
|
extern int rs_hw_spritedrawtime;
|
||||||
|
|
||||||
|
// Render stats for batching
|
||||||
|
extern int rs_hw_numpolys;
|
||||||
|
extern int rs_hw_numverts;
|
||||||
|
extern int rs_hw_numcalls;
|
||||||
|
extern int rs_hw_numshaders;
|
||||||
|
extern int rs_hw_numtextures;
|
||||||
|
extern int rs_hw_numpolyflags;
|
||||||
|
extern int rs_hw_numcolors;
|
||||||
|
extern int rs_hw_batchsorttime;
|
||||||
|
extern int rs_hw_batchdrawtime;
|
||||||
|
|
||||||
|
extern boolean gr_shadersavailable;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,23 +1,16 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
|
||||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||||
|
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software distributed under the
|
||||||
// modify it under the terms of the GNU General Public License
|
// terms of the GNU General Public License, version 2.
|
||||||
// as published by the Free Software Foundation; either version 2
|
// See the 'LICENSE' file for more details.
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hw_md2.c
|
||||||
/// \brief MD2 Handling
|
/// \brief 3D Model Handling
|
||||||
/// Inspired from md2.c by Mete Ciragan (mete@swissquake.ch)
|
/// Inspired from md2.c by Mete Ciragan (mete@swissquake.ch)
|
||||||
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -382,7 +375,10 @@ static void md2_loadTexture(md2_t *model)
|
||||||
#endif
|
#endif
|
||||||
grpatch->mipmap->grInfo.format = PCX_Load(filename, &w, &h, grpatch);
|
grpatch->mipmap->grInfo.format = PCX_Load(filename, &w, &h, grpatch);
|
||||||
if (grpatch->mipmap->grInfo.format == 0)
|
if (grpatch->mipmap->grInfo.format == 0)
|
||||||
|
{
|
||||||
|
model->notexturefile = true; // mark it so its not searched for again repeatedly
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
grpatch->mipmap->downloaded = 0;
|
grpatch->mipmap->downloaded = 0;
|
||||||
grpatch->mipmap->flags = 0;
|
grpatch->mipmap->flags = 0;
|
||||||
|
@ -400,13 +396,6 @@ static void md2_loadTexture(md2_t *model)
|
||||||
V_CubeApply(&image->s.red, &image->s.green, &image->s.blue);
|
V_CubeApply(&image->s.red, &image->s.green, &image->s.blue);
|
||||||
image++;
|
image++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GLIDE_API_COMPATIBILITY
|
|
||||||
// not correct!
|
|
||||||
grpatch->mipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_256;
|
|
||||||
grpatch->mipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_256;
|
|
||||||
grpatch->mipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
HWD.pfnSetTexture(grpatch->mipmap);
|
HWD.pfnSetTexture(grpatch->mipmap);
|
||||||
}
|
}
|
||||||
|
@ -444,6 +433,7 @@ static void md2_loadBlendTexture(md2_t *model)
|
||||||
grpatch->mipmap->grInfo.format = PCX_Load(filename, &w, &h, grpatch);
|
grpatch->mipmap->grInfo.format = PCX_Load(filename, &w, &h, grpatch);
|
||||||
if (grpatch->mipmap->grInfo.format == 0)
|
if (grpatch->mipmap->grInfo.format == 0)
|
||||||
{
|
{
|
||||||
|
model->noblendfile = true; // mark it so its not searched for again repeatedly
|
||||||
Z_Free(filename);
|
Z_Free(filename);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -455,13 +445,6 @@ static void md2_loadBlendTexture(md2_t *model)
|
||||||
grpatch->height = (INT16)h;
|
grpatch->height = (INT16)h;
|
||||||
grpatch->mipmap->width = (UINT16)w;
|
grpatch->mipmap->width = (UINT16)w;
|
||||||
grpatch->mipmap->height = (UINT16)h;
|
grpatch->mipmap->height = (UINT16)h;
|
||||||
|
|
||||||
#ifdef GLIDE_API_COMPATIBILITY
|
|
||||||
// not correct!
|
|
||||||
grpatch->mipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_256;
|
|
||||||
grpatch->mipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_256;
|
|
||||||
grpatch->mipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
HWD.pfnSetTexture(grpatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary
|
HWD.pfnSetTexture(grpatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary
|
||||||
|
|
||||||
|
@ -486,6 +469,8 @@ void HWR_InitModels(void)
|
||||||
md2_playermodels[s].scale = -1.0f;
|
md2_playermodels[s].scale = -1.0f;
|
||||||
md2_playermodels[s].model = NULL;
|
md2_playermodels[s].model = NULL;
|
||||||
md2_playermodels[s].grpatch = NULL;
|
md2_playermodels[s].grpatch = NULL;
|
||||||
|
md2_playermodels[s].notexturefile = false;
|
||||||
|
md2_playermodels[s].noblendfile = false;
|
||||||
md2_playermodels[s].skin = -1;
|
md2_playermodels[s].skin = -1;
|
||||||
md2_playermodels[s].notfound = true;
|
md2_playermodels[s].notfound = true;
|
||||||
md2_playermodels[s].error = false;
|
md2_playermodels[s].error = false;
|
||||||
|
@ -495,6 +480,8 @@ void HWR_InitModels(void)
|
||||||
md2_models[i].scale = -1.0f;
|
md2_models[i].scale = -1.0f;
|
||||||
md2_models[i].model = NULL;
|
md2_models[i].model = NULL;
|
||||||
md2_models[i].grpatch = NULL;
|
md2_models[i].grpatch = NULL;
|
||||||
|
md2_models[i].notexturefile = false;
|
||||||
|
md2_models[i].noblendfile = false;
|
||||||
md2_models[i].skin = -1;
|
md2_models[i].skin = -1;
|
||||||
md2_models[i].notfound = true;
|
md2_models[i].notfound = true;
|
||||||
md2_models[i].error = false;
|
md2_models[i].error = false;
|
||||||
|
@ -677,12 +664,12 @@ spritemodelfound:
|
||||||
#define SETBRIGHTNESS(brightness,r,g,b) \
|
#define SETBRIGHTNESS(brightness,r,g,b) \
|
||||||
brightness = (UINT8)(((1063*(UINT16)(r))/5000) + ((3576*(UINT16)(g))/5000) + ((361*(UINT16)(b))/5000))
|
brightness = (UINT8)(((1063*(UINT16)(r))/5000) + ((3576*(UINT16)(g))/5000) + ((361*(UINT16)(b))/5000))
|
||||||
|
|
||||||
static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolors_t color)
|
static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolornum_t color)
|
||||||
{
|
{
|
||||||
UINT16 w = gpatch->width, h = gpatch->height;
|
UINT16 w = gpatch->width, h = gpatch->height;
|
||||||
UINT32 size = w*h;
|
UINT32 size = w*h;
|
||||||
RGBA_t *image, *blendimage, *cur, blendcolor;
|
RGBA_t *image, *blendimage, *cur, blendcolor;
|
||||||
UINT8 translation[16]; // First the color index
|
UINT16 translation[16]; // First the color index
|
||||||
UINT8 cutoff[16]; // Brightness cutoff before using the next color
|
UINT8 cutoff[16]; // Brightness cutoff before using the next color
|
||||||
UINT8 translen = 0;
|
UINT8 translen = 0;
|
||||||
UINT8 i;
|
UINT8 i;
|
||||||
|
@ -718,16 +705,16 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
|
||||||
if (skinnum == TC_METALSONIC)
|
if (skinnum == TC_METALSONIC)
|
||||||
color = SKINCOLOR_COBALT;
|
color = SKINCOLOR_COBALT;
|
||||||
|
|
||||||
if (color != SKINCOLOR_NONE)
|
if (color != SKINCOLOR_NONE && color < numskincolors)
|
||||||
{
|
{
|
||||||
UINT8 numdupes = 1;
|
UINT8 numdupes = 1;
|
||||||
|
|
||||||
translation[translen] = Color_Index[color-1][0];
|
translation[translen] = skincolors[color].ramp[0];
|
||||||
cutoff[translen] = 255;
|
cutoff[translen] = 255;
|
||||||
|
|
||||||
for (i = 1; i < 16; i++)
|
for (i = 1; i < 16; i++)
|
||||||
{
|
{
|
||||||
if (translation[translen] == Color_Index[color-1][i])
|
if (translation[translen] == skincolors[color].ramp[i])
|
||||||
{
|
{
|
||||||
numdupes++;
|
numdupes++;
|
||||||
continue;
|
continue;
|
||||||
|
@ -741,7 +728,7 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
|
||||||
numdupes = 1;
|
numdupes = 1;
|
||||||
translen++;
|
translen++;
|
||||||
|
|
||||||
translation[translen] = (UINT8)Color_Index[color-1][i];
|
translation[translen] = (UINT16)skincolors[color].ramp[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
translen++;
|
translen++;
|
||||||
|
@ -949,11 +936,19 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
|
||||||
|
|
||||||
blendcolor = V_GetColor(translation[firsti]);
|
blendcolor = V_GetColor(translation[firsti]);
|
||||||
|
|
||||||
|
if (secondi >= translen)
|
||||||
|
mul = 0;
|
||||||
|
|
||||||
if (mul > 0) // If it's 0, then we only need the first color.
|
if (mul > 0) // If it's 0, then we only need the first color.
|
||||||
{
|
{
|
||||||
if (secondi >= translen) // blend to black
|
#if 0
|
||||||
|
if (secondi >= translen)
|
||||||
|
{
|
||||||
|
// blend to black
|
||||||
nextcolor = V_GetColor(31);
|
nextcolor = V_GetColor(31);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
nextcolor = V_GetColor(translation[secondi]);
|
nextcolor = V_GetColor(translation[secondi]);
|
||||||
|
|
||||||
// Find difference between points
|
// Find difference between points
|
||||||
|
@ -1043,7 +1038,7 @@ skippixel:
|
||||||
|
|
||||||
#undef SETBRIGHTNESS
|
#undef SETBRIGHTNESS
|
||||||
|
|
||||||
static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT32 skinnum, const UINT8 *colormap, skincolors_t color)
|
static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT32 skinnum, const UINT8 *colormap, skincolornum_t color)
|
||||||
{
|
{
|
||||||
// mostly copied from HWR_GetMappedPatch, hence the similarities and comment
|
// mostly copied from HWR_GetMappedPatch, hence the similarities and comment
|
||||||
GLMipmap_t *grmip, *newmip;
|
GLMipmap_t *grmip, *newmip;
|
||||||
|
@ -1188,15 +1183,14 @@ static UINT8 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t
|
||||||
|
|
||||||
boolean HWR_DrawModel(gr_vissprite_t *spr)
|
boolean HWR_DrawModel(gr_vissprite_t *spr)
|
||||||
{
|
{
|
||||||
FSurfaceInfo Surf;
|
md2_t *md2;
|
||||||
|
|
||||||
char filename[64];
|
char filename[64];
|
||||||
INT32 frame = 0;
|
INT32 frame = 0;
|
||||||
INT32 nextFrame = -1;
|
INT32 nextFrame = -1;
|
||||||
UINT8 spr2 = 0;
|
UINT8 spr2 = 0;
|
||||||
FTransform p;
|
FTransform p;
|
||||||
md2_t *md2;
|
FSurfaceInfo Surf;
|
||||||
UINT8 color[4];
|
|
||||||
|
|
||||||
if (!cv_grmodels.value)
|
if (!cv_grmodels.value)
|
||||||
return false;
|
return false;
|
||||||
|
@ -1235,13 +1229,10 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
|
||||||
colormap = sector->extra_colormap;
|
colormap = sector->extra_colormap;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (colormap)
|
HWR_Lighting(&Surf, lightlevel, colormap);
|
||||||
Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false);
|
|
||||||
else
|
|
||||||
Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Surf.FlatColor.rgba = 0xFFFFFFFF;
|
Surf.PolyColor.rgba = 0xFFFFFFFF;
|
||||||
|
|
||||||
// Look at HWR_ProjectSprite for more
|
// Look at HWR_ProjectSprite for more
|
||||||
{
|
{
|
||||||
|
@ -1263,11 +1254,11 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
|
||||||
//durs = tics;
|
//durs = tics;
|
||||||
|
|
||||||
if (spr->mobj->flags2 & MF2_SHADOW)
|
if (spr->mobj->flags2 & MF2_SHADOW)
|
||||||
Surf.FlatColor.s.alpha = 0x40;
|
Surf.PolyColor.s.alpha = 0x40;
|
||||||
else if (spr->mobj->frame & FF_TRANSMASK)
|
else if (spr->mobj->frame & FF_TRANSMASK)
|
||||||
HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
|
HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
|
||||||
else
|
else
|
||||||
Surf.FlatColor.s.alpha = 0xFF;
|
Surf.PolyColor.s.alpha = 0xFF;
|
||||||
|
|
||||||
// dont forget to enabled the depth test because we can't do this like
|
// dont forget to enabled the depth test because we can't do this like
|
||||||
// before: polygons models are not sorted
|
// before: polygons models are not sorted
|
||||||
|
@ -1315,12 +1306,14 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
|
||||||
finalscale = md2->scale;
|
finalscale = md2->scale;
|
||||||
//Hurdler: arf, I don't like that implementation at all... too much crappy
|
//Hurdler: arf, I don't like that implementation at all... too much crappy
|
||||||
gpatch = md2->grpatch;
|
gpatch = md2->grpatch;
|
||||||
if (!gpatch || !gpatch->mipmap->grInfo.format || !gpatch->mipmap->downloaded)
|
if (!gpatch || ((!gpatch->mipmap->grInfo.format || !gpatch->mipmap->downloaded) && !md2->notexturefile))
|
||||||
md2_loadTexture(md2);
|
md2_loadTexture(md2);
|
||||||
gpatch = md2->grpatch; // Load it again, because it isn't being loaded into gpatch after md2_loadtexture...
|
gpatch = md2->grpatch; // Load it again, because it isn't being loaded into gpatch after md2_loadtexture...
|
||||||
|
|
||||||
if ((gpatch && gpatch->mipmap->grInfo.format) // don't load the blend texture if the base texture isn't available
|
if ((gpatch && gpatch->mipmap->grInfo.format) // don't load the blend texture if the base texture isn't available
|
||||||
&& (!md2->blendgrpatch || !((GLPatch_t *)md2->blendgrpatch)->mipmap->grInfo.format || !((GLPatch_t *)md2->blendgrpatch)->mipmap->downloaded))
|
&& (!md2->blendgrpatch
|
||||||
|
|| ((!((GLPatch_t *)md2->blendgrpatch)->mipmap->grInfo.format || !((GLPatch_t *)md2->blendgrpatch)->mipmap->downloaded)
|
||||||
|
&& !md2->noblendfile)))
|
||||||
md2_loadBlendTexture(md2);
|
md2_loadBlendTexture(md2);
|
||||||
|
|
||||||
if (gpatch && gpatch->mipmap->grInfo.format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture
|
if (gpatch && gpatch->mipmap->grInfo.format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture
|
||||||
|
@ -1336,7 +1329,7 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
|
||||||
else
|
else
|
||||||
skinnum = TC_BOSS;
|
skinnum = TC_BOSS;
|
||||||
}
|
}
|
||||||
else if ((skincolors_t)spr->mobj->color != SKINCOLOR_NONE)
|
else if ((skincolornum_t)spr->mobj->color != SKINCOLOR_NONE)
|
||||||
{
|
{
|
||||||
if (spr->mobj->colorized)
|
if (spr->mobj->colorized)
|
||||||
skinnum = TC_RAINBOW;
|
skinnum = TC_RAINBOW;
|
||||||
|
@ -1356,7 +1349,7 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translation or skin number found
|
// Translation or skin number found
|
||||||
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolors_t)spr->mobj->color);
|
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolornum_t)spr->mobj->color);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1512,11 +1505,6 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
color[0] = Surf.FlatColor.s.red;
|
|
||||||
color[1] = Surf.FlatColor.s.green;
|
|
||||||
color[2] = Surf.FlatColor.s.blue;
|
|
||||||
color[3] = Surf.FlatColor.s.alpha;
|
|
||||||
|
|
||||||
// SRB2CBTODO: MD2 scaling support
|
// SRB2CBTODO: MD2 scaling support
|
||||||
finalscale *= FIXED_TO_FLOAT(spr->mobj->scale);
|
finalscale *= FIXED_TO_FLOAT(spr->mobj->scale);
|
||||||
|
|
||||||
|
@ -1525,7 +1513,8 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
|
||||||
p.mirror = atransform.mirror; // from Kart
|
p.mirror = atransform.mirror; // from Kart
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, color);
|
HWD.pfnSetShader(4); // model shader
|
||||||
|
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, &Surf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,21 +1,14 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
|
||||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||||
|
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software distributed under the
|
||||||
// modify it under the terms of the GNU General Public License
|
// terms of the GNU General Public License, version 2.
|
||||||
// as published by the Free Software Foundation; either version 2
|
// See the 'LICENSE' file for more details.
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hw_md2.h
|
||||||
/// \brief MD2 Handling
|
/// \brief 3D Model Handling
|
||||||
/// Inspired from md2.h by Mete Ciragan (mete@swissquake.ch)
|
/// Inspired from md2.h by Mete Ciragan (mete@swissquake.ch)
|
||||||
|
|
||||||
#ifndef _HW_MD2_H_
|
#ifndef _HW_MD2_H_
|
||||||
|
@ -35,7 +28,9 @@ typedef struct
|
||||||
float offset;
|
float offset;
|
||||||
model_t *model;
|
model_t *model;
|
||||||
void *grpatch;
|
void *grpatch;
|
||||||
|
boolean notexturefile; // true if texture file was not found
|
||||||
void *blendgrpatch;
|
void *blendgrpatch;
|
||||||
|
boolean noblendfile; // true if blend texture file was not found
|
||||||
boolean notfound;
|
boolean notfound;
|
||||||
INT32 skin;
|
INT32 skin;
|
||||||
boolean error;
|
boolean error;
|
||||||
|
|
|
@ -1,19 +1,12 @@
|
||||||
// Emacs style mode select -*- C++ -*-
|
// SONIC ROBO BLAST 2
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2005 by Sonic Team Junior.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2005 by SRB2 Jr. Team.
|
// This program is free software distributed under the
|
||||||
//
|
// terms of the GNU General Public License, version 2.
|
||||||
// This program is free software; you can redistribute it and/or
|
// See the 'LICENSE' file for more details.
|
||||||
// modify it under the terms of the GNU General Public License
|
|
||||||
// as published by the Free Software Foundation; either version 2
|
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file
|
/// \file hws_data.h
|
||||||
/// \brief 3D sound definitions
|
/// \brief 3D sound definitions
|
||||||
|
|
||||||
#ifndef __HWS_DATA_H__
|
#ifndef __HWS_DATA_H__
|
||||||
|
|
|
@ -206,7 +206,7 @@ int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepth
|
||||||
|
|
||||||
if (iLastPFD)
|
if (iLastPFD)
|
||||||
{
|
{
|
||||||
DBG_Printf("WARNING : SetPixelFormat() called twise not supported by all drivers !\n");
|
GL_DBG_Printf("WARNING : SetPixelFormat() called twise not supported by all drivers !\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the pixel format only if different than the current
|
// set the pixel format only if different than the current
|
||||||
|
@ -215,17 +215,17 @@ int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepth
|
||||||
else
|
else
|
||||||
iLastPFD = iPFD;
|
iLastPFD = iPFD;
|
||||||
|
|
||||||
DBG_Printf("SetupPixelFormat() - %d ColorBits - %d StencilBits - %d DepthBits\n",
|
GL_DBG_Printf("SetupPixelFormat() - %d ColorBits - %d StencilBits - %d DepthBits\n",
|
||||||
WantColorBits, WantStencilBits, WantDepthBits);
|
WantColorBits, WantStencilBits, WantDepthBits);
|
||||||
|
|
||||||
nPixelFormat = ChoosePixelFormat(hDC, &pfd);
|
nPixelFormat = ChoosePixelFormat(hDC, &pfd);
|
||||||
|
|
||||||
if (nPixelFormat == 0)
|
if (nPixelFormat == 0)
|
||||||
DBG_Printf("ChoosePixelFormat() FAILED\n");
|
GL_DBG_Printf("ChoosePixelFormat() FAILED\n");
|
||||||
|
|
||||||
if (SetPixelFormat(hDC, nPixelFormat, &pfd) == 0)
|
if (SetPixelFormat(hDC, nPixelFormat, &pfd) == 0)
|
||||||
{
|
{
|
||||||
DBG_Printf("SetPixelFormat() FAILED\n");
|
GL_DBG_Printf("SetPixelFormat() FAILED\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +243,7 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode)
|
||||||
BOOL WantFullScreen = !(lvid->u.windowed); //(lvid->u.windowed ? 0 : CDS_FULLSCREEN);
|
BOOL WantFullScreen = !(lvid->u.windowed); //(lvid->u.windowed ? 0 : CDS_FULLSCREEN);
|
||||||
|
|
||||||
UNREFERENCED_PARAMETER(pcurrentmode);
|
UNREFERENCED_PARAMETER(pcurrentmode);
|
||||||
DBG_Printf ("SetMode(): %dx%d %d bits (%s)\n",
|
GL_DBG_Printf ("SetMode(): %dx%d %d bits (%s)\n",
|
||||||
lvid->width, lvid->height, lvid->bpp*8,
|
lvid->width, lvid->height, lvid->bpp*8,
|
||||||
WantFullScreen ? "fullscreen" : "windowed");
|
WantFullScreen ? "fullscreen" : "windowed");
|
||||||
|
|
||||||
|
@ -301,7 +301,7 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode)
|
||||||
hDC = GetDC(hWnd);
|
hDC = GetDC(hWnd);
|
||||||
if (!hDC)
|
if (!hDC)
|
||||||
{
|
{
|
||||||
DBG_Printf("GetDC() FAILED\n");
|
GL_DBG_Printf("GetDC() FAILED\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,12 +321,12 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode)
|
||||||
hGLRC = pwglCreateContext(hDC);
|
hGLRC = pwglCreateContext(hDC);
|
||||||
if (!hGLRC)
|
if (!hGLRC)
|
||||||
{
|
{
|
||||||
DBG_Printf("pwglCreateContext() FAILED\n");
|
GL_DBG_Printf("pwglCreateContext() FAILED\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!pwglMakeCurrent(hDC, hGLRC))
|
if (!pwglMakeCurrent(hDC, hGLRC))
|
||||||
{
|
{
|
||||||
DBG_Printf("wglMakeCurrent() FAILED\n");
|
GL_DBG_Printf("wglMakeCurrent() FAILED\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -337,15 +337,15 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode)
|
||||||
//BP: why don't we make it earlier ?
|
//BP: why don't we make it earlier ?
|
||||||
//Hurdler: we cannot do that before intialising gl context
|
//Hurdler: we cannot do that before intialising gl context
|
||||||
renderer = (LPCSTR)pglGetString(GL_RENDERER);
|
renderer = (LPCSTR)pglGetString(GL_RENDERER);
|
||||||
DBG_Printf("Vendor : %s\n", pglGetString(GL_VENDOR));
|
GL_DBG_Printf("Vendor : %s\n", pglGetString(GL_VENDOR));
|
||||||
DBG_Printf("Renderer : %s\n", renderer);
|
GL_DBG_Printf("Renderer : %s\n", renderer);
|
||||||
DBG_Printf("Version : %s\n", pglGetString(GL_VERSION));
|
GL_DBG_Printf("Version : %s\n", pglGetString(GL_VERSION));
|
||||||
DBG_Printf("Extensions : %s\n", gl_extensions);
|
GL_DBG_Printf("Extensions : %s\n", gl_extensions);
|
||||||
|
|
||||||
// BP: disable advenced feature that don't work on somes hardware
|
// BP: disable advenced feature that don't work on somes hardware
|
||||||
// Hurdler: Now works on G400 with bios 1.6 and certified drivers 6.04
|
// Hurdler: Now works on G400 with bios 1.6 and certified drivers 6.04
|
||||||
if (strstr(renderer, "810")) oglflags |= GLF_NOZBUFREAD;
|
if (strstr(renderer, "810")) oglflags |= GLF_NOZBUFREAD;
|
||||||
DBG_Printf("oglflags : 0x%X\n", oglflags);
|
GL_DBG_Printf("oglflags : 0x%X\n", oglflags);
|
||||||
|
|
||||||
#ifdef USE_WGL_SWAP
|
#ifdef USE_WGL_SWAP
|
||||||
if (isExtAvailable("WGL_EXT_swap_control",gl_extensions))
|
if (isExtAvailable("WGL_EXT_swap_control",gl_extensions))
|
||||||
|
@ -386,7 +386,7 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode)
|
||||||
// -----------------+
|
// -----------------+
|
||||||
static void UnSetRes(void)
|
static void UnSetRes(void)
|
||||||
{
|
{
|
||||||
DBG_Printf("UnSetRes()\n");
|
GL_DBG_Printf("UnSetRes()\n");
|
||||||
|
|
||||||
pwglMakeCurrent(hDC, NULL);
|
pwglMakeCurrent(hDC, NULL);
|
||||||
pwglDeleteContext(hGLRC);
|
pwglDeleteContext(hGLRC);
|
||||||
|
@ -437,7 +437,7 @@ EXPORT void HWRAPI(GetModeList) (vmode_t** pvidmodes, INT32 *numvidmodes)
|
||||||
video_modes[iMode].misc = 0;
|
video_modes[iMode].misc = 0;
|
||||||
video_modes[iMode].name = malloc(12 * sizeof (CHAR));
|
video_modes[iMode].name = malloc(12 * sizeof (CHAR));
|
||||||
sprintf(video_modes[iMode].name, "%dx%d", (INT32)Tmp.dmPelsWidth, (INT32)Tmp.dmPelsHeight);
|
sprintf(video_modes[iMode].name, "%dx%d", (INT32)Tmp.dmPelsWidth, (INT32)Tmp.dmPelsHeight);
|
||||||
DBG_Printf ("Mode: %s\n", video_modes[iMode].name);
|
GL_DBG_Printf ("Mode: %s\n", video_modes[iMode].name);
|
||||||
video_modes[iMode].width = Tmp.dmPelsWidth;
|
video_modes[iMode].width = Tmp.dmPelsWidth;
|
||||||
video_modes[iMode].height = Tmp.dmPelsHeight;
|
video_modes[iMode].height = Tmp.dmPelsHeight;
|
||||||
video_modes[iMode].bytesperpixel = Tmp.dmBitsPerPel/8;
|
video_modes[iMode].bytesperpixel = Tmp.dmBitsPerPel/8;
|
||||||
|
@ -474,7 +474,7 @@ EXPORT void HWRAPI(GetModeList) (vmode_t** pvidmodes, INT32 *numvidmodes)
|
||||||
HDC bpphdc;
|
HDC bpphdc;
|
||||||
INT32 iBitsPerPel;
|
INT32 iBitsPerPel;
|
||||||
|
|
||||||
DBG_Printf ("HWRAPI GetModeList()\n");
|
GL_DBG_Printf ("HWRAPI GetModeList()\n");
|
||||||
|
|
||||||
bpphdc = GetDC(NULL); // on obtient le bpp actuel
|
bpphdc = GetDC(NULL); // on obtient le bpp actuel
|
||||||
iBitsPerPel = GetDeviceCaps(bpphdc, BITSPIXEL);
|
iBitsPerPel = GetDeviceCaps(bpphdc, BITSPIXEL);
|
||||||
|
@ -490,7 +490,7 @@ EXPORT void HWRAPI(GetModeList) (vmode_t** pvidmodes, INT32 *numvidmodes)
|
||||||
video_modes[i].misc = 0;
|
video_modes[i].misc = 0;
|
||||||
video_modes[i].name = malloc(12 * sizeof (CHAR));
|
video_modes[i].name = malloc(12 * sizeof (CHAR));
|
||||||
sprintf(video_modes[i].name, "%dx%d", res[i][0], res[i][1]);
|
sprintf(video_modes[i].name, "%dx%d", res[i][0], res[i][1]);
|
||||||
DBG_Printf ("Mode: %s\n", video_modes[i].name);
|
GL_DBG_Printf ("Mode: %s\n", video_modes[i].name);
|
||||||
video_modes[i].width = res[i][0];
|
video_modes[i].width = res[i][0];
|
||||||
video_modes[i].height = res[i][1];
|
video_modes[i].height = res[i][1];
|
||||||
video_modes[i].bytesperpixel = iBitsPerPel/8;
|
video_modes[i].bytesperpixel = iBitsPerPel/8;
|
||||||
|
@ -511,9 +511,9 @@ EXPORT void HWRAPI(Shutdown) (void)
|
||||||
#ifdef DEBUG_TO_FILE
|
#ifdef DEBUG_TO_FILE
|
||||||
long nb_centiemes;
|
long nb_centiemes;
|
||||||
|
|
||||||
DBG_Printf ("HWRAPI Shutdown()\n");
|
GL_DBG_Printf ("HWRAPI Shutdown()\n");
|
||||||
nb_centiemes = ((clock()-my_clock)*100)/CLOCKS_PER_SEC;
|
nb_centiemes = ((clock()-my_clock)*100)/CLOCKS_PER_SEC;
|
||||||
DBG_Printf("Nb frames: %li; Nb sec: %2.2f -> %2.1f fps\n",
|
GL_DBG_Printf("Nb frames: %li; Nb sec: %2.2f -> %2.1f fps\n",
|
||||||
nb_frames, nb_centiemes/100.0f, (100*nb_frames)/(double)nb_centiemes);
|
nb_frames, nb_centiemes/100.0f, (100*nb_frames)/(double)nb_centiemes);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -530,7 +530,7 @@ EXPORT void HWRAPI(Shutdown) (void)
|
||||||
}
|
}
|
||||||
FreeLibrary(GLU32);
|
FreeLibrary(GLU32);
|
||||||
FreeLibrary(OGL32);
|
FreeLibrary(OGL32);
|
||||||
DBG_Printf ("HWRAPI Shutdown(DONE)\n");
|
GL_DBG_Printf ("HWRAPI Shutdown(DONE)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------+
|
// -----------------+
|
||||||
|
@ -543,7 +543,7 @@ EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl)
|
||||||
#else
|
#else
|
||||||
UNREFERENCED_PARAMETER(waitvbl);
|
UNREFERENCED_PARAMETER(waitvbl);
|
||||||
#endif
|
#endif
|
||||||
// DBG_Printf ("FinishUpdate()\n");
|
// GL_DBG_Printf ("FinishUpdate()\n");
|
||||||
#ifdef DEBUG_TO_FILE
|
#ifdef DEBUG_TO_FILE
|
||||||
if ((++nb_frames)==2) // on ne commence pas <20> la premi<6D>re frame
|
if ((++nb_frames)==2) // on ne commence pas <20> la premi<6D>re frame
|
||||||
my_clock = clock();
|
my_clock = clock();
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -70,10 +70,6 @@
|
||||||
extern FILE *gllogstream;
|
extern FILE *gllogstream;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DRIVER_STRING
|
|
||||||
#define DRIVER_STRING "HWRAPI Init(): SRB2 OpenGL renderer" // Tails
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// PROTOS
|
// PROTOS
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
@ -81,13 +77,11 @@ extern FILE *gllogstream;
|
||||||
boolean LoadGL(void);
|
boolean LoadGL(void);
|
||||||
void *GetGLFunc(const char *proc);
|
void *GetGLFunc(const char *proc);
|
||||||
boolean SetupGLfunc(void);
|
boolean SetupGLfunc(void);
|
||||||
boolean SetupGLFunc13(void);
|
void SetupGLFunc4(void);
|
||||||
void Flush(void);
|
void Flush(void);
|
||||||
INT32 isExtAvailable(const char *extension, const GLubyte *start);
|
INT32 isExtAvailable(const char *extension, const GLubyte *start);
|
||||||
int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepthBits);
|
|
||||||
void SetModelView(GLint w, GLint h);
|
void SetModelView(GLint w, GLint h);
|
||||||
void SetStates(void);
|
void SetStates(void);
|
||||||
FUNCMATH float byteasfloat(UINT8 fbyte);
|
|
||||||
|
|
||||||
#ifndef GL_EXT_texture_filter_anisotropic
|
#ifndef GL_EXT_texture_filter_anisotropic
|
||||||
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
|
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
|
||||||
|
@ -123,7 +117,10 @@ static PFNglEnableClientState pglEnableClientState;
|
||||||
// GLOBAL
|
// GLOBAL
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
|
extern const GLubyte *gl_version;
|
||||||
|
extern const GLubyte *gl_renderer;
|
||||||
extern const GLubyte *gl_extensions;
|
extern const GLubyte *gl_extensions;
|
||||||
|
|
||||||
extern RGBA_t myPaletteData[];
|
extern RGBA_t myPaletteData[];
|
||||||
extern GLint screen_width;
|
extern GLint screen_width;
|
||||||
extern GLint screen_height;
|
extern GLint screen_height;
|
||||||
|
|
141
src/hu_stuff.c
141
src/hu_stuff.c
|
@ -68,7 +68,7 @@ patch_t *nightsnum[10]; // 0-9
|
||||||
// Level title and credits fonts
|
// Level title and credits fonts
|
||||||
patch_t *lt_font[LT_FONTSIZE];
|
patch_t *lt_font[LT_FONTSIZE];
|
||||||
patch_t *cred_font[CRED_FONTSIZE];
|
patch_t *cred_font[CRED_FONTSIZE];
|
||||||
patch_t *ttlnum[20]; // act numbers (0-19)
|
patch_t *ttlnum[10]; // act numbers (0-9)
|
||||||
|
|
||||||
// Name tag fonts
|
// Name tag fonts
|
||||||
patch_t *ntb_font[NT_FONTSIZE];
|
patch_t *ntb_font[NT_FONTSIZE];
|
||||||
|
@ -243,7 +243,7 @@ void HU_LoadGraphics(void)
|
||||||
tallinfin = (patch_t *)W_CachePatchName("STTINFIN", PU_HUDGFX);
|
tallinfin = (patch_t *)W_CachePatchName("STTINFIN", PU_HUDGFX);
|
||||||
|
|
||||||
// cache act numbers for level titles
|
// cache act numbers for level titles
|
||||||
for (i = 0; i < 20; i++)
|
for (i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
sprintf(buffer, "TTL%.2d", i);
|
sprintf(buffer, "TTL%.2d", i);
|
||||||
ttlnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
ttlnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||||
|
@ -755,113 +755,40 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const UINT8 color = players[playernum].skincolor;
|
UINT16 chatcolor = skincolors[players[playernum].skincolor].chatcolor;
|
||||||
|
|
||||||
|
if (!chatcolor || chatcolor%0x1000 || chatcolor>V_INVERTMAP)
|
||||||
|
cstart = "\x80";
|
||||||
|
else if (chatcolor == V_MAGENTAMAP)
|
||||||
|
cstart = "\x81";
|
||||||
|
else if (chatcolor == V_YELLOWMAP)
|
||||||
|
cstart = "\x82";
|
||||||
|
else if (chatcolor == V_GREENMAP)
|
||||||
cstart = "\x83";
|
cstart = "\x83";
|
||||||
|
else if (chatcolor == V_BLUEMAP)
|
||||||
// Follow palette order at r_draw.c Color_Names
|
cstart = "\x84";
|
||||||
switch (color)
|
else if (chatcolor == V_REDMAP)
|
||||||
{
|
cstart = "\x85";
|
||||||
default:
|
else if (chatcolor == V_GRAYMAP)
|
||||||
case SKINCOLOR_WHITE:
|
cstart = "\x86";
|
||||||
case SKINCOLOR_BONE:
|
else if (chatcolor == V_ORANGEMAP)
|
||||||
case SKINCOLOR_CLOUDY:
|
cstart = "\x87";
|
||||||
case SKINCOLOR_GREY:
|
else if (chatcolor == V_SKYMAP)
|
||||||
case SKINCOLOR_SILVER:
|
cstart = "\x88";
|
||||||
case SKINCOLOR_AETHER:
|
else if (chatcolor == V_PURPLEMAP)
|
||||||
case SKINCOLOR_SLATE:
|
cstart = "\x89";
|
||||||
cstart = "\x80"; // white
|
else if (chatcolor == V_AQUAMAP)
|
||||||
break;
|
cstart = "\x8a";
|
||||||
case SKINCOLOR_CARBON:
|
else if (chatcolor == V_PERIDOTMAP)
|
||||||
case SKINCOLOR_JET:
|
cstart = "\x8b";
|
||||||
case SKINCOLOR_BLACK:
|
else if (chatcolor == V_AZUREMAP)
|
||||||
cstart = "\x86"; // V_GRAYMAP
|
cstart = "\x8c";
|
||||||
break;
|
else if (chatcolor == V_BROWNMAP)
|
||||||
case SKINCOLOR_PINK:
|
cstart = "\x8d";
|
||||||
case SKINCOLOR_RUBY:
|
else if (chatcolor == V_ROSYMAP)
|
||||||
case SKINCOLOR_SALMON:
|
cstart = "\x8e";
|
||||||
case SKINCOLOR_RED:
|
else if (chatcolor == V_INVERTMAP)
|
||||||
case SKINCOLOR_CRIMSON:
|
cstart = "\x8f";
|
||||||
case SKINCOLOR_FLAME:
|
|
||||||
case SKINCOLOR_KETCHUP:
|
|
||||||
cstart = "\x85"; // V_REDMAP
|
|
||||||
break;
|
|
||||||
case SKINCOLOR_YOGURT:
|
|
||||||
case SKINCOLOR_BROWN:
|
|
||||||
case SKINCOLOR_BRONZE:
|
|
||||||
case SKINCOLOR_TAN:
|
|
||||||
case SKINCOLOR_BEIGE:
|
|
||||||
case SKINCOLOR_QUAIL:
|
|
||||||
cstart = "\x8d"; // V_BROWNMAP
|
|
||||||
break;
|
|
||||||
case SKINCOLOR_MOSS:
|
|
||||||
case SKINCOLOR_GREEN:
|
|
||||||
case SKINCOLOR_FOREST:
|
|
||||||
case SKINCOLOR_EMERALD:
|
|
||||||
case SKINCOLOR_MINT:
|
|
||||||
cstart = "\x83"; // V_GREENMAP
|
|
||||||
break;
|
|
||||||
case SKINCOLOR_AZURE:
|
|
||||||
cstart = "\x8c"; // V_AZUREMAP
|
|
||||||
break;
|
|
||||||
case SKINCOLOR_LAVENDER:
|
|
||||||
case SKINCOLOR_PASTEL:
|
|
||||||
case SKINCOLOR_PURPLE:
|
|
||||||
cstart = "\x89"; // V_PURPLEMAP
|
|
||||||
break;
|
|
||||||
case SKINCOLOR_PEACHY:
|
|
||||||
case SKINCOLOR_LILAC:
|
|
||||||
case SKINCOLOR_PLUM:
|
|
||||||
case SKINCOLOR_ROSY:
|
|
||||||
cstart = "\x8e"; // V_ROSYMAP
|
|
||||||
break;
|
|
||||||
case SKINCOLOR_SUNSET:
|
|
||||||
case SKINCOLOR_COPPER:
|
|
||||||
case SKINCOLOR_APRICOT:
|
|
||||||
case SKINCOLOR_ORANGE:
|
|
||||||
case SKINCOLOR_RUST:
|
|
||||||
cstart = "\x87"; // V_ORANGEMAP
|
|
||||||
break;
|
|
||||||
case SKINCOLOR_GOLD:
|
|
||||||
case SKINCOLOR_SANDY:
|
|
||||||
case SKINCOLOR_YELLOW:
|
|
||||||
case SKINCOLOR_OLIVE:
|
|
||||||
cstart = "\x82"; // V_YELLOWMAP
|
|
||||||
break;
|
|
||||||
case SKINCOLOR_LIME:
|
|
||||||
case SKINCOLOR_PERIDOT:
|
|
||||||
case SKINCOLOR_APPLE:
|
|
||||||
cstart = "\x8b"; // V_PERIDOTMAP
|
|
||||||
break;
|
|
||||||
case SKINCOLOR_SEAFOAM:
|
|
||||||
case SKINCOLOR_AQUA:
|
|
||||||
cstart = "\x8a"; // V_AQUAMAP
|
|
||||||
break;
|
|
||||||
case SKINCOLOR_TEAL:
|
|
||||||
case SKINCOLOR_WAVE:
|
|
||||||
case SKINCOLOR_CYAN:
|
|
||||||
case SKINCOLOR_SKY:
|
|
||||||
case SKINCOLOR_CERULEAN:
|
|
||||||
case SKINCOLOR_ICY:
|
|
||||||
case SKINCOLOR_SAPPHIRE:
|
|
||||||
case SKINCOLOR_VAPOR:
|
|
||||||
cstart = "\x88"; // V_SKYMAP
|
|
||||||
break;
|
|
||||||
case SKINCOLOR_CORNFLOWER:
|
|
||||||
case SKINCOLOR_BLUE:
|
|
||||||
case SKINCOLOR_COBALT:
|
|
||||||
case SKINCOLOR_DUSK:
|
|
||||||
case SKINCOLOR_BLUEBELL:
|
|
||||||
cstart = "\x84"; // V_BLUEMAP
|
|
||||||
break;
|
|
||||||
case SKINCOLOR_BUBBLEGUM:
|
|
||||||
case SKINCOLOR_MAGENTA:
|
|
||||||
case SKINCOLOR_NEON:
|
|
||||||
case SKINCOLOR_VIOLET:
|
|
||||||
case SKINCOLOR_RASPBERRY:
|
|
||||||
cstart = "\x81"; // V_MAGENTAMAP
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
prefix = cstart;
|
prefix = cstart;
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ extern patch_t *lt_font[LT_FONTSIZE];
|
||||||
extern patch_t *cred_font[CRED_FONTSIZE];
|
extern patch_t *cred_font[CRED_FONTSIZE];
|
||||||
extern patch_t *ntb_font[NT_FONTSIZE];
|
extern patch_t *ntb_font[NT_FONTSIZE];
|
||||||
extern patch_t *nto_font[NT_FONTSIZE];
|
extern patch_t *nto_font[NT_FONTSIZE];
|
||||||
extern patch_t *ttlnum[20];
|
extern patch_t *ttlnum[10];
|
||||||
extern patch_t *emeraldpics[3][8];
|
extern patch_t *emeraldpics[3][8];
|
||||||
extern patch_t *rflagico;
|
extern patch_t *rflagico;
|
||||||
extern patch_t *bflagico;
|
extern patch_t *bflagico;
|
||||||
|
|
|
@ -46,6 +46,8 @@ UINT32 I_GetFreeMem(UINT32 *total);
|
||||||
*/
|
*/
|
||||||
tic_t I_GetTime(void);
|
tic_t I_GetTime(void);
|
||||||
|
|
||||||
|
int I_GetTimeMicros(void);// provides microsecond counter for render stats
|
||||||
|
|
||||||
/** \brief The I_Sleep function
|
/** \brief The I_Sleep function
|
||||||
|
|
||||||
\return void
|
\return void
|
||||||
|
|
|
@ -487,7 +487,7 @@ static void cleanupnodes(void)
|
||||||
|
|
||||||
// Why can't I start at zero?
|
// Why can't I start at zero?
|
||||||
for (j = 1; j < MAXNETNODES; j++)
|
for (j = 1; j < MAXNETNODES; j++)
|
||||||
if (!(nodeingame[j] || SV_SendingFile(j)))
|
if (!(nodeingame[j] || SendingFile(j)))
|
||||||
nodeconnected[j] = false;
|
nodeconnected[j] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
195
src/info.c
195
src/info.c
|
@ -20,6 +20,7 @@
|
||||||
#include "m_misc.h"
|
#include "m_misc.h"
|
||||||
#include "z_zone.h"
|
#include "z_zone.h"
|
||||||
#include "d_player.h"
|
#include "d_player.h"
|
||||||
|
#include "v_video.h" // V_*MAP constants
|
||||||
#include "lzf.h"
|
#include "lzf.h"
|
||||||
#ifdef HWRENDER
|
#ifdef HWRENDER
|
||||||
#include "hardware/hw_light.h"
|
#include "hardware/hw_light.h"
|
||||||
|
@ -187,6 +188,8 @@ char sprnames[NUMSPRITES + 1][5] =
|
||||||
|
|
||||||
// Projectiles
|
// Projectiles
|
||||||
"MISL",
|
"MISL",
|
||||||
|
"LASR", // GFZ3 laser
|
||||||
|
"LASF", // GFZ3 laser flames
|
||||||
"TORP", // Torpedo
|
"TORP", // Torpedo
|
||||||
"ENRG", // Energy ball
|
"ENRG", // Energy ball
|
||||||
"MINE", // Skim mine
|
"MINE", // Skim mine
|
||||||
|
@ -1427,11 +1430,13 @@ state_t states[NUMSTATES] =
|
||||||
|
|
||||||
{SPR_FANG, 8, 0, {A_PrepareRepeat}, 1, 0, S_FANG_PINCHPATHINGSTART2}, // S_FANG_PINCHPATHINGSTART1
|
{SPR_FANG, 8, 0, {A_PrepareRepeat}, 1, 0, S_FANG_PINCHPATHINGSTART2}, // S_FANG_PINCHPATHINGSTART1
|
||||||
{SPR_FANG, 8, 0, {A_PlayActiveSound}, 0, 0, S_FANG_PINCHPATHING}, // S_FANG_PINCHPATHINGSTART2
|
{SPR_FANG, 8, 0, {A_PlayActiveSound}, 0, 0, S_FANG_PINCHPATHING}, // S_FANG_PINCHPATHINGSTART2
|
||||||
{SPR_FANG, 8, 0, {A_Boss5FindWaypoint}, 1, 0, S_FANG_PINCHBOUNCE1}, // S_FANG_PINCHPATHING
|
{SPR_FANG, 8, 0, {A_Boss5FindWaypoint}, 1, 0, S_FANG_PINCHBOUNCE0}, // S_FANG_PINCHPATHING
|
||||||
|
{SPR_FANG, 8, 0, {A_SetObjectFlags}, MF_NOCLIP|MF_NOCLIPHEIGHT, 2, S_FANG_PINCHBOUNCE1}, // S_FANG_PINCHBOUNCE0
|
||||||
{SPR_FANG, 8, 2, {A_Thrust}, 0, 1, S_FANG_PINCHBOUNCE2}, // S_FANG_PINCHBOUNCE1
|
{SPR_FANG, 8, 2, {A_Thrust}, 0, 1, S_FANG_PINCHBOUNCE2}, // S_FANG_PINCHBOUNCE1
|
||||||
{SPR_FANG, 9, 2, {NULL}, 0, 0, S_FANG_PINCHBOUNCE3}, // S_FANG_PINCHBOUNCE2
|
{SPR_FANG, 9, 2, {NULL}, 0, 0, S_FANG_PINCHBOUNCE3}, // S_FANG_PINCHBOUNCE2
|
||||||
{SPR_FANG, 10, 2, {A_Boss5Jump}, 0, 0, S_FANG_PINCHBOUNCE4}, // S_FANG_PINCHBOUNCE3
|
{SPR_FANG, 10, 2, {A_Boss5Jump}, 0, 0, S_FANG_PINCHBOUNCE4}, // S_FANG_PINCHBOUNCE3
|
||||||
{SPR_FANG, 10, 1, {A_Boss5CheckFalling}, S_FANG_PINCHSKID1, S_FANG_PINCHFALL1, S_FANG_PINCHBOUNCE4}, // S_FANG_PINCHBOUNCE4
|
{SPR_FANG, 10, 1, {A_Boss5CheckFalling}, S_FANG_PINCHSKID1, S_FANG_PINCHFALL0, S_FANG_PINCHBOUNCE4}, // S_FANG_PINCHBOUNCE4
|
||||||
|
{SPR_FANG, 12, 0, {A_SetObjectFlags}, MF_NOCLIP|MF_NOCLIPHEIGHT, 1, S_FANG_PINCHFALL1}, // S_FANG_PINCHFALL0
|
||||||
{SPR_FANG, 12, 1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL2}, // S_FANG_PINCHFALL1
|
{SPR_FANG, 12, 1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL2}, // S_FANG_PINCHFALL1
|
||||||
{SPR_FANG, 13, 1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL1}, // S_FANG_PINCHFALL2
|
{SPR_FANG, 13, 1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL1}, // S_FANG_PINCHFALL2
|
||||||
{SPR_FANG, 4, 0, {A_PlayAttackSound}, 0, 0, S_FANG_PINCHSKID2}, // S_FANG_PINCHSKID1
|
{SPR_FANG, 4, 0, {A_PlayAttackSound}, 0, 0, S_FANG_PINCHSKID2}, // S_FANG_PINCHSKID1
|
||||||
|
@ -2058,7 +2063,15 @@ state_t states[NUMSTATES] =
|
||||||
|
|
||||||
{SPR_MISL, FF_FULLBRIGHT, 1, {A_SmokeTrailer}, MT_SMOKE, 0, S_ROCKET}, // S_ROCKET
|
{SPR_MISL, FF_FULLBRIGHT, 1, {A_SmokeTrailer}, MT_SMOKE, 0, S_ROCKET}, // S_ROCKET
|
||||||
|
|
||||||
{SPR_MISL, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LASER
|
{SPR_LASR, FF_FULLBRIGHT|0, 2, {NULL}, 0, 0, S_NULL}, // S_LASER
|
||||||
|
{SPR_LASR, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_NULL}, // S_LASER2
|
||||||
|
{SPR_LASR, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_NULL}, // S_LASERFLASH
|
||||||
|
|
||||||
|
{SPR_LASF, FF_FULLBRIGHT|0, 2, {NULL}, 0, 0, S_LASERFLAME2}, // S_LASERFLAME1
|
||||||
|
{SPR_LASF, FF_FULLBRIGHT|1, 1, {A_ChangeHeight}, 156*FRACUNIT, 3, S_LASERFLAME3}, // S_LASERFLAME2
|
||||||
|
{SPR_LASF, FF_FULLBRIGHT|2, 0, {A_ChangeHeight}, 32*FRACUNIT, 3, S_LASERFLAME4}, // S_LASERFLAME3
|
||||||
|
{SPR_LASF, FF_ANIMATE|FF_PAPERSPRITE|FF_FULLBRIGHT|2, 4, {NULL}, 1, 2, S_LASERFLAME5}, // S_LASERFLAME4
|
||||||
|
{SPR_LASF, FF_ANIMATE|FF_PAPERSPRITE|FF_FULLBRIGHT|4, 28, {NULL}, 2, 2, S_NULL}, // S_LASERFLAME5
|
||||||
|
|
||||||
{SPR_TORP, 0, 1, {A_SmokeTrailer}, MT_SMOKE, 0, S_TORPEDO}, // S_TORPEDO
|
{SPR_TORP, 0, 1, {A_SmokeTrailer}, MT_SMOKE, 0, S_TORPEDO}, // S_TORPEDO
|
||||||
|
|
||||||
|
@ -5665,28 +5678,28 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
|
|
||||||
{ // MT_EGGMOBILE_FIRE
|
{ // MT_EGGMOBILE_FIRE
|
||||||
-1, // doomednum
|
-1, // doomednum
|
||||||
S_SPINFIRE1, // spawnstate
|
S_LASERFLAME1, // spawnstate
|
||||||
1, // spawnhealth
|
1, // spawnhealth
|
||||||
S_NULL, // seestate
|
S_NULL, // seestate
|
||||||
sfx_None, // seesound
|
sfx_s3kc2s, // seesound
|
||||||
8, // reactiontime
|
8, // reactiontime
|
||||||
sfx_None, // attacksound
|
sfx_None, // attacksound
|
||||||
S_NULL, // painstate
|
S_NULL, // painstate
|
||||||
0, // painchance
|
0, // painchance
|
||||||
sfx_None, // painsound
|
sfx_s3k8d, // painsound
|
||||||
S_NULL, // meleestate
|
S_NULL, // meleestate
|
||||||
S_NULL, // missilestate
|
S_NULL, // missilestate
|
||||||
S_NULL, // deathstate
|
S_NULL, // deathstate
|
||||||
S_NULL, // xdeathstate
|
S_NULL, // xdeathstate
|
||||||
sfx_None, // deathsound
|
sfx_None, // deathsound
|
||||||
0, // speed
|
0, // speed
|
||||||
8*FRACUNIT, // radius
|
24*FRACUNIT, // radius
|
||||||
14*FRACUNIT, // height
|
84*FRACUNIT, // height
|
||||||
0, // display offset
|
0, // display offset
|
||||||
DMG_FIRE, // mass
|
DMG_FIRE, // mass
|
||||||
1, // damage
|
1, // damage
|
||||||
sfx_None, // activesound
|
sfx_None, // activesound
|
||||||
MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY|MF_FIRE, // flags
|
MF_NOGRAVITY|MF_FIRE|MF_PAIN, // flags
|
||||||
S_NULL // raisestate
|
S_NULL // raisestate
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -9637,8 +9650,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
S_NULL, // painstate
|
S_NULL, // painstate
|
||||||
0, // painchance
|
0, // painchance
|
||||||
sfx_None, // painsound
|
sfx_None, // painsound
|
||||||
S_NULL, // meleestate
|
S_LASERFLASH, // meleestate
|
||||||
S_NULL, // missilestate
|
S_LASER2, // missilestate
|
||||||
S_NULL, // deathstate
|
S_NULL, // deathstate
|
||||||
S_NULL, // xdeathstate
|
S_NULL, // xdeathstate
|
||||||
sfx_None, // deathsound
|
sfx_None, // deathsound
|
||||||
|
@ -9649,7 +9662,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
0, // mass
|
0, // mass
|
||||||
20, // damage
|
20, // damage
|
||||||
sfx_None, // activesound
|
sfx_None, // activesound
|
||||||
MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY, // flags
|
MF_MISSILE|MF_NOGRAVITY, // flags
|
||||||
S_NULL // raisestate
|
S_NULL // raisestate
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -21606,8 +21619,140 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
skincolor_t skincolors[MAXSKINCOLORS] = {
|
||||||
|
{"None", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_NONE
|
||||||
|
|
||||||
/** Patches the mobjinfo table and state table.
|
// Greyscale ranges
|
||||||
|
{"White", {0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x11}, SKINCOLOR_BLACK, 5, 0, true}, // SKINCOLOR_WHITE
|
||||||
|
{"Bone", {0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x05, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x12}, SKINCOLOR_JET, 7, 0, true}, // SKINCOLOR_BONE
|
||||||
|
{"Cloudy", {0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14}, SKINCOLOR_CARBON, 7, 0, true}, // SKINCOLOR_CLOUDY
|
||||||
|
{"Grey", {0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18}, SKINCOLOR_AETHER, 12, 0, true}, // SKINCOLOR_GREY
|
||||||
|
{"Silver", {0x02, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x1f}, SKINCOLOR_SLATE, 12, 0, true}, // SKINCOLOR_SILVER
|
||||||
|
{"Carbon", {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x16, 0x17, 0x17, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1c, 0x1d}, SKINCOLOR_CLOUDY, 7, V_GRAYMAP, true}, // SKINCOLOR_CARBON
|
||||||
|
{"Jet", {0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1a, 0x1b, 0x1c, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f}, SKINCOLOR_BONE, 7, V_GRAYMAP, true}, // SKINCOLOR_JET
|
||||||
|
{"Black", {0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1b, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f}, SKINCOLOR_WHITE, 7, V_GRAYMAP, true}, // SKINCOLOR_BLACK
|
||||||
|
|
||||||
|
// Desaturated
|
||||||
|
{"Aether", {0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x91, 0x91, 0x91, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf}, SKINCOLOR_GREY, 15, 0, true}, // SKINCOLOR_AETHER
|
||||||
|
{"Slate", {0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0xaa, 0xaa, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_SILVER, 12, 0, true}, // SKINCOLOR_SLATE
|
||||||
|
{"Bluebell", {0x90, 0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0xac, 0xac, 0xad, 0xad, 0xa8, 0xa8, 0xa9, 0xfd, 0xfe}, SKINCOLOR_COPPER, 4, V_BLUEMAP, true}, // SKINCOLOR_BLUEBELL
|
||||||
|
{"Pink", {0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, SKINCOLOR_AZURE, 9, V_REDMAP, true}, // SKINCOLOR_PINK
|
||||||
|
{"Yogurt", {0xd0, 0x30, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe3, 0xe6, 0xe8, 0xe9}, SKINCOLOR_RUST, 7, V_BROWNMAP, true}, // SKINCOLOR_YOGURT
|
||||||
|
{"Brown", {0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef}, SKINCOLOR_TAN, 2, V_BROWNMAP, true}, // SKINCOLOR_BROWN
|
||||||
|
{"Bronze", {0xde, 0xe0, 0xe1, 0xe4, 0xe7, 0xe9, 0xeb, 0xec, 0xed, 0xed, 0xed, 0x19, 0x19, 0x1b, 0x1d, 0x1e}, SKINCOLOR_KETCHUP, 0, V_BROWNMAP, true}, // SKINCOLOR_BRONZE
|
||||||
|
{"Tan", {0x51, 0x51, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0xf5, 0xf5, 0xf9, 0xf9, 0xed, 0xed}, SKINCOLOR_BROWN, 12, V_BROWNMAP, true}, // SKINCOLOR_TAN
|
||||||
|
{"Beige", {0x54, 0x55, 0x56, 0x56, 0xf2, 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfb, 0xed, 0xed}, SKINCOLOR_MOSS, 5, V_BROWNMAP, true}, // SKINCOLOR_BEIGE
|
||||||
|
{"Moss", {0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f}, SKINCOLOR_BEIGE, 13, V_GREENMAP, true}, // SKINCOLOR_MOSS
|
||||||
|
{"Azure", {0x90, 0x90, 0x91, 0x91, 0xaa, 0xaa, 0xab, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf}, SKINCOLOR_PINK, 5, V_AZUREMAP, true}, // SKINCOLOR_AZURE
|
||||||
|
{"Lavender", {0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7}, SKINCOLOR_GOLD, 4, V_PURPLEMAP, true}, // SKINCOLOR_LAVENDER
|
||||||
|
|
||||||
|
// Viv's vivid colours (toast 21/07/17)
|
||||||
|
{"Ruby", {0xb0, 0xb0, 0xc9, 0xca, 0xcc, 0x26, 0x27, 0x28, 0x29, 0x2a, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfd}, SKINCOLOR_EMERALD, 10, V_REDMAP, true}, // SKINCOLOR_RUBY
|
||||||
|
{"Salmon", {0xd0, 0xd0, 0xd1, 0xd2, 0x20, 0x21, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e}, SKINCOLOR_FOREST, 6, V_REDMAP, true}, // SKINCOLOR_SALMON
|
||||||
|
{"Red", {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, SKINCOLOR_GREEN, 10, V_REDMAP, true}, // SKINCOLOR_RED
|
||||||
|
{"Crimson", {0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c, 0x2d, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x1f}, SKINCOLOR_ICY, 10, V_REDMAP, true}, // SKINCOLOR_CRIMSON
|
||||||
|
{"Flame", {0x31, 0x32, 0x33, 0x36, 0x22, 0x22, 0x25, 0x25, 0x25, 0xcd, 0xcf, 0xcf, 0xc5, 0xc5, 0xc7, 0xc7}, SKINCOLOR_PURPLE, 8, V_REDMAP, true}, // SKINCOLOR_FLAME
|
||||||
|
{"Ketchup", {0x48, 0x49, 0x40, 0x33, 0x34, 0x36, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2b, 0x2c, 0x47, 0x2e, 0x2f}, SKINCOLOR_BRONZE, 8, V_REDMAP, true}, // SKINCOLOR_KETCHUP
|
||||||
|
{"Peachy", {0xd0, 0x30, 0x31, 0x31, 0x32, 0x32, 0xdc, 0xdc, 0xdc, 0xd3, 0xd4, 0xd4, 0xcc, 0xcd, 0xce, 0xcf}, SKINCOLOR_TEAL, 7, V_ROSYMAP, true}, // SKINCOLOR_PEACHY
|
||||||
|
{"Quail", {0xd8, 0xd9, 0xdb, 0xdc, 0xde, 0xdf, 0xd5, 0xd5, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0x1d, 0x1f}, SKINCOLOR_WAVE, 5, V_BROWNMAP, true}, // SKINCOLOR_QUAIL
|
||||||
|
{"Sunset", {0x51, 0x52, 0x40, 0x40, 0x34, 0x36, 0xd5, 0xd5, 0xd6, 0xd7, 0xcf, 0xcf, 0xc6, 0xc6, 0xc7, 0xfe}, SKINCOLOR_SAPPHIRE, 5, V_ORANGEMAP, true}, // SKINCOLOR_SUNSET
|
||||||
|
{"Copper", {0x58, 0x54, 0x40, 0x34, 0x35, 0x38, 0x3a, 0x3c, 0x3d, 0x2a, 0x2b, 0x2c, 0x2c, 0xba, 0xba, 0xbb}, SKINCOLOR_BLUEBELL, 5, V_ORANGEMAP, true}, // SKINCOLOR_COPPER
|
||||||
|
{"Apricot", {0x00, 0xd8, 0xd9, 0xda, 0xdb, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e}, SKINCOLOR_CYAN, 4, V_ORANGEMAP, true}, // SKINCOLOR_APRICOT
|
||||||
|
{"Orange", {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x2c}, SKINCOLOR_BLUE, 4, V_ORANGEMAP, true}, // SKINCOLOR_ORANGE
|
||||||
|
{"Rust", {0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3f, 0x2c, 0x2d, 0x47, 0x2e, 0x2f, 0x2f}, SKINCOLOR_YOGURT, 8, V_ORANGEMAP, true}, // SKINCOLOR_RUST
|
||||||
|
{"Gold", {0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, SKINCOLOR_LAVENDER, 10, V_YELLOWMAP, true}, // SKINCOLOR_GOLD
|
||||||
|
{"Sandy", {0x53, 0x40, 0x41, 0x42, 0x43, 0xe6, 0xe9, 0xe9, 0xea, 0xec, 0xec, 0xc6, 0xc6, 0xc7, 0xc7, 0xfe}, SKINCOLOR_SKY, 8, V_YELLOWMAP, true}, // SKINCOLOR_SANDY
|
||||||
|
{"Yellow", {0x52, 0x53, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4e, 0x4f, 0xed}, SKINCOLOR_CORNFLOWER, 8, V_YELLOWMAP, true}, // SKINCOLOR_YELLOW
|
||||||
|
{"Olive", {0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0xe7, 0xe7, 0xe9, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7, 0xfd}, SKINCOLOR_DUSK, 3, V_YELLOWMAP, true}, // SKINCOLOR_OLIVE
|
||||||
|
{"Lime", {0x50, 0x51, 0x52, 0x53, 0x48, 0xbc, 0xbd, 0xbe, 0xbe, 0xbf, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_MAGENTA, 9, V_PERIDOTMAP, true}, // SKINCOLOR_LIME
|
||||||
|
{"Peridot", {0x58, 0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf, 0x5e, 0x5e, 0x5f, 0x5f, 0x77, 0x77}, SKINCOLOR_COBALT, 2, V_PERIDOTMAP, true}, // SKINCOLOR_PERIDOT
|
||||||
|
{"Apple", {0x49, 0x49, 0xbc, 0xbd, 0xbe, 0xbe, 0xbe, 0x67, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6d}, SKINCOLOR_RASPBERRY, 13, V_PERIDOTMAP, true}, // SKINCOLOR_APPLE
|
||||||
|
{"Green", {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_RED, 6, V_GREENMAP, true}, // SKINCOLOR_GREEN
|
||||||
|
{"Forest", {0x65, 0x66, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f}, SKINCOLOR_SALMON, 9, V_GREENMAP, true}, // SKINCOLOR_FOREST
|
||||||
|
{"Emerald", {0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, SKINCOLOR_RUBY, 4, V_GREENMAP, true}, // SKINCOLOR_EMERALD
|
||||||
|
{"Mint", {0x00, 0x00, 0x58, 0x58, 0x59, 0x62, 0x62, 0x62, 0x64, 0x67, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a}, SKINCOLOR_VIOLET, 5, V_GREENMAP, true}, // SKINCOLOR_MINT
|
||||||
|
{"Seafoam", {0x01, 0x58, 0x59, 0x5a, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0xfd, 0xfd}, SKINCOLOR_PLUM, 6, V_AQUAMAP, true}, // SKINCOLOR_SEAFOAM
|
||||||
|
{"Aqua", {0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x76, 0x77}, SKINCOLOR_ROSY, 7, V_AQUAMAP, true}, // SKINCOLOR_AQUA
|
||||||
|
{"Teal", {0x78, 0x78, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0x8a}, SKINCOLOR_PEACHY, 7, V_SKYMAP, true}, // SKINCOLOR_TEAL
|
||||||
|
{"Wave", {0x00, 0x78, 0x78, 0x79, 0x8d, 0x87, 0x88, 0x89, 0x89, 0xae, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_QUAIL, 5, V_SKYMAP, true}, // SKINCOLOR_WAVE
|
||||||
|
{"Cyan", {0x80, 0x81, 0xff, 0xff, 0x83, 0x83, 0x8d, 0x8d, 0x8d, 0x8e, 0x7e, 0x7f, 0x76, 0x76, 0x77, 0x6e}, SKINCOLOR_APRICOT, 6, V_SKYMAP, true}, // SKINCOLOR_CYAN
|
||||||
|
{"Sky", {0x80, 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x85, 0x85, 0x86, 0x87, 0x88, 0x89, 0x89, 0x8a, 0x8b}, SKINCOLOR_SANDY, 1, V_SKYMAP, true}, // SKINCOLOR_SKY
|
||||||
|
{"Cerulean", {0x85, 0x86, 0x87, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0xfd, 0xfd, 0xfd, 0x1f, 0x1f, 0x1f}, SKINCOLOR_NEON, 4, V_SKYMAP, true}, // SKINCOLOR_CERULEAN
|
||||||
|
{"Icy", {0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x83, 0x83, 0x86, 0x87, 0x95, 0x95, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_CRIMSON, 0, V_SKYMAP, true}, // SKINCOLOR_ICY
|
||||||
|
{"Sapphire", {0x80, 0x83, 0x86, 0x87, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_SUNSET, 5, V_SKYMAP, true}, // SKINCOLOR_SAPPHIRE
|
||||||
|
{"Cornflower", {0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x9a, 0x9c, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e}, SKINCOLOR_YELLOW, 4, V_BLUEMAP, true}, // SKINCOLOR_CORNFLOWER
|
||||||
|
{"Blue", {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_ORANGE, 5, V_BLUEMAP, true}, // SKINCOLOR_BLUE
|
||||||
|
{"Cobalt", {0x93, 0x94, 0x95, 0x96, 0x98, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfd, 0xfe, 0xfe}, SKINCOLOR_PERIDOT, 5, V_BLUEMAP, true}, // SKINCOLOR_COBALT
|
||||||
|
{"Vapor", {0x80, 0x81, 0x83, 0x86, 0x94, 0x94, 0xa3, 0xa3, 0xa4, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_LILAC, 4, V_SKYMAP, true}, // SKINCOLOR_VAPOR
|
||||||
|
{"Dusk", {0x92, 0x93, 0x94, 0x94, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_OLIVE, 0, V_BLUEMAP, true}, // SKINCOLOR_DUSK
|
||||||
|
{"Pastel", {0x90, 0x90, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, SKINCOLOR_BUBBLEGUM, 9, V_PURPLEMAP, true}, // SKINCOLOR_PASTEL
|
||||||
|
{"Purple", {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_FLAME, 7, V_PURPLEMAP, true}, // SKINCOLOR_PURPLE
|
||||||
|
{"Bubblegum", {0x00, 0xd0, 0xd0, 0xc8, 0xc8, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, SKINCOLOR_PASTEL, 8, V_MAGENTAMAP, true}, // SKINCOLOR_BUBBLEGUM
|
||||||
|
{"Magenta", {0xb3, 0xb3, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb}, SKINCOLOR_LIME, 6, V_MAGENTAMAP, true}, // SKINCOLOR_MAGENTA
|
||||||
|
{"Neon", {0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb, 0xc7, 0xc7, 0x1d, 0x1d, 0x1e}, SKINCOLOR_CERULEAN, 2, V_MAGENTAMAP, true}, // SKINCOLOR_NEON
|
||||||
|
{"Violet", {0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, SKINCOLOR_MINT, 6, V_MAGENTAMAP, true}, // SKINCOLOR_VIOLET
|
||||||
|
{"Lilac", {0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xfe, 0x1f}, SKINCOLOR_VAPOR, 4, V_ROSYMAP, true}, // SKINCOLOR_LILAC
|
||||||
|
{"Plum", {0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, SKINCOLOR_MINT, 7, V_ROSYMAP, true}, // SKINCOLOR_PLUM
|
||||||
|
{"Raspberry", {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE, 13, V_MAGENTAMAP, true}, // SKINCOLOR_RASPBERRY
|
||||||
|
{"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_ROSY
|
||||||
|
|
||||||
|
// super
|
||||||
|
{"Super Silver 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03}, SKINCOLOR_BLACK, 15, 0, false}, // SKINCOLOR_SUPERSILVER1
|
||||||
|
{"Super Silver 2", {0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07}, SKINCOLOR_BLACK, 6, 0, false}, // SKINCOLOR_SUPERSILVER2
|
||||||
|
{"Super Silver 3", {0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x09, 0x0b}, SKINCOLOR_BLACK, 5, 0, false}, // SKINCOLOR_SUPERSILVER3
|
||||||
|
{"Super Silver 4", {0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11}, SKINCOLOR_BLACK, 5, V_GRAYMAP, false}, // SKINCOLOR_SUPERSILVER4
|
||||||
|
{"Super Silver 5", {0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, 0x13}, SKINCOLOR_BLACK, 5, V_GRAYMAP, false}, // SKINCOLOR_SUPERSILVER5
|
||||||
|
|
||||||
|
{"Super Red 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2}, SKINCOLOR_CYAN, 15, 0, false}, // SKINCOLOR_SUPERRED1
|
||||||
|
{"Super Red 2", {0x00, 0x00, 0x00, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd2, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21}, SKINCOLOR_CYAN, 14, V_ROSYMAP, false}, // SKINCOLOR_SUPERRED2
|
||||||
|
{"Super Red 3", {0x00, 0x00, 0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23}, SKINCOLOR_CYAN, 13, V_REDMAP, false}, // SKINCOLOR_SUPERRED3
|
||||||
|
{"Super Red 4", {0x00, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24}, SKINCOLOR_CYAN, 11, V_REDMAP, false}, // SKINCOLOR_SUPERRED4
|
||||||
|
{"Super Red 5", {0xd0, 0xd1, 0xd2, 0xd2, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25}, SKINCOLOR_CYAN, 10, V_REDMAP, false}, // SKINCOLOR_SUPERRED5
|
||||||
|
|
||||||
|
{"Super Orange 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x30, 0x31, 0x32, 0x33, 0x34}, SKINCOLOR_SAPPHIRE, 15, 0, false}, // SKINCOLOR_SUPERORANGE1
|
||||||
|
{"Super Orange 2", {0x00, 0x00, 0x00, 0x00, 0xd0, 0xd0, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x34}, SKINCOLOR_SAPPHIRE, 12, V_ORANGEMAP, false}, // SKINCOLOR_SUPERORANGE2
|
||||||
|
{"Super Orange 3", {0x00, 0x00, 0xd0, 0xd0, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35}, SKINCOLOR_SAPPHIRE, 9, V_ORANGEMAP, false}, // SKINCOLOR_SUPERORANGE3
|
||||||
|
{"Super Orange 4", {0x00, 0xd0, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x44, 0x45, 0x46}, SKINCOLOR_SAPPHIRE, 4, V_ORANGEMAP, false}, // SKINCOLOR_SUPERORANGE4
|
||||||
|
{"Super Orange 5", {0xd0, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x44, 0x45, 0x46, 0x47}, SKINCOLOR_SAPPHIRE, 3, V_ORANGEMAP, false}, // SKINCOLOR_SUPERORANGE5
|
||||||
|
|
||||||
|
{"Super Gold 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x51, 0x52, 0x53, 0x48}, SKINCOLOR_CORNFLOWER, 15, 0, false}, // SKINCOLOR_SUPERGOLD1
|
||||||
|
{"Super Gold 2", {0x00, 0x50, 0x51, 0x52, 0x53, 0x53, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41}, SKINCOLOR_CORNFLOWER, 9, V_YELLOWMAP, false}, // SKINCOLOR_SUPERGOLD2
|
||||||
|
{"Super Gold 3", {0x51, 0x52, 0x53, 0x53, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43}, SKINCOLOR_CORNFLOWER, 8, V_YELLOWMAP, false}, // SKINCOLOR_SUPERGOLD3
|
||||||
|
{"Super Gold 4", {0x53, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46}, SKINCOLOR_CORNFLOWER, 8, V_YELLOWMAP, false}, // SKINCOLOR_SUPERGOLD4
|
||||||
|
{"Super Gold 5", {0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47}, SKINCOLOR_CORNFLOWER, 8, V_YELLOWMAP, false}, // SKINCOLOR_SUPERGOLD5
|
||||||
|
|
||||||
|
{"Super Peridot 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x58, 0x58, 0xbc, 0xbc, 0xbc}, SKINCOLOR_COBALT, 15, 0, false}, // SKINCOLOR_SUPERPERIDOT1
|
||||||
|
{"Super Peridot 2", {0x00, 0x58, 0x58, 0x58, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe}, SKINCOLOR_COBALT, 4, V_PERIDOTMAP, false}, // SKINCOLOR_SUPERPERIDOT2
|
||||||
|
{"Super Peridot 3", {0x58, 0x58, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf}, SKINCOLOR_COBALT, 3, V_PERIDOTMAP, false}, // SKINCOLOR_SUPERPERIDOT3
|
||||||
|
{"Super Peridot 4", {0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf, 0x5e, 0x5e, 0x5f}, SKINCOLOR_COBALT, 3, V_PERIDOTMAP, false}, // SKINCOLOR_SUPERPERIDOT4
|
||||||
|
{"Super Peridot 5", {0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf, 0x5e, 0x5e, 0x5f, 0x77}, SKINCOLOR_COBALT, 3, V_PERIDOTMAP, false}, // SKINCOLOR_SUPERPERIDOT5
|
||||||
|
|
||||||
|
{"Super Sky 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x81, 0x82, 0x83, 0x84}, SKINCOLOR_RUST, 15, 0, false}, // SKINCOLOR_SUPERSKY1
|
||||||
|
{"Super Sky 2", {0x00, 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86}, SKINCOLOR_RUST, 4, V_SKYMAP, false}, // SKINCOLOR_SUPERSKY2
|
||||||
|
{"Super Sky 3", {0x81, 0x82, 0x83, 0x83, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87}, SKINCOLOR_RUST, 3, V_SKYMAP, false}, // SKINCOLOR_SUPERSKY3
|
||||||
|
{"Super Sky 4", {0x83, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x88, 0x89, 0x8a}, SKINCOLOR_RUST, 3, V_SKYMAP, false}, // SKINCOLOR_SUPERSKY4
|
||||||
|
{"Super Sky 5", {0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x88, 0x89, 0x8a, 0x8b}, SKINCOLOR_RUST, 3, V_SKYMAP, false}, // SKINCOLOR_SUPERSKY5
|
||||||
|
|
||||||
|
{"Super Purple 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90, 0xa0, 0xa0, 0xa1, 0xa2}, SKINCOLOR_EMERALD, 15, 0, false}, // SKINCOLOR_SUPERPURPLE1
|
||||||
|
{"Super Purple 2", {0x00, 0x90, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5}, SKINCOLOR_EMERALD, 4, V_PURPLEMAP, false}, // SKINCOLOR_SUPERPURPLE2
|
||||||
|
{"Super Purple 3", {0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa6, 0xa6}, SKINCOLOR_EMERALD, 0, V_PURPLEMAP, false}, // SKINCOLOR_SUPERPURPLE3
|
||||||
|
{"Super Purple 4", {0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa9}, SKINCOLOR_EMERALD, 0, V_PURPLEMAP, false}, // SKINCOLOR_SUPERPURPLE4
|
||||||
|
{"Super Purple 5", {0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa9, 0xfd}, SKINCOLOR_EMERALD, 0, V_PURPLEMAP, false}, // SKINCOLOR_SUPERPURPLE5
|
||||||
|
|
||||||
|
{"Super Rust 1", {0x00, 0xd0, 0xd0, 0xd0, 0x30, 0x30, 0x31, 0x32, 0x33, 0x37, 0x3a, 0x44, 0x45, 0x46, 0x47, 0x2e}, SKINCOLOR_CYAN, 14, V_ORANGEMAP, false}, // SKINCOLOR_SUPERRUST1
|
||||||
|
{"Super Rust 2", {0x30, 0x31, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38, 0x3a, 0x44, 0x45, 0x46, 0x47, 0x47, 0x2e}, SKINCOLOR_CYAN, 10, V_ORANGEMAP, false}, // SKINCOLOR_SUPERRUST2
|
||||||
|
{"Super Rust 3", {0x31, 0x32, 0x33, 0x34, 0x36, 0x37, 0x38, 0x3a, 0x44, 0x45, 0x45, 0x46, 0x46, 0x47, 0x2e, 0x2e}, SKINCOLOR_CYAN, 9, V_ORANGEMAP, false}, // SKINCOLOR_SUPERRUST3
|
||||||
|
{"Super Rust 4", {0x48, 0x40, 0x41, 0x42, 0x43, 0x44, 0x44, 0x45, 0x45, 0x46, 0x46, 0x47, 0x47, 0x2e, 0x2e, 0x2e}, SKINCOLOR_CYAN, 8, V_ORANGEMAP, false}, // SKINCOLOR_SUPERRUST4
|
||||||
|
{"Super Rust 5", {0x41, 0x42, 0x43, 0x43, 0x44, 0x44, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee, 0xee, 0xef, 0xef}, SKINCOLOR_CYAN, 8, V_ORANGEMAP, false}, // SKINCOLOR_SUPERRUST5
|
||||||
|
|
||||||
|
{"Super Tan 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52}, SKINCOLOR_BROWN, 14, 0, false}, // SKINCOLOR_SUPERTAN1
|
||||||
|
{"Super Tan 2", {0x00, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5}, SKINCOLOR_BROWN, 13, V_BROWNMAP, false}, // SKINCOLOR_SUPERTAN2
|
||||||
|
{"Super Tan 3", {0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9}, SKINCOLOR_BROWN, 12, V_BROWNMAP, false}, // SKINCOLOR_SUPERTAN3
|
||||||
|
{"Super Tan 4", {0x51, 0x52, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9, 0xfb, 0xed}, SKINCOLOR_BROWN, 11, V_BROWNMAP, false}, // SKINCOLOR_SUPERTAN4
|
||||||
|
{"Super Tan 5", {0x52, 0x52, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9, 0xfb, 0xed, 0xee, 0xef, 0xef}, SKINCOLOR_BROWN, 10, V_BROWNMAP, false} // SKINCOLOR_SUPERTAN5
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Patches the mobjinfo, state, and skincolor tables.
|
||||||
* Free slots are emptied out and set to initial values.
|
* Free slots are emptied out and set to initial values.
|
||||||
*/
|
*/
|
||||||
void P_PatchInfoTables(void)
|
void P_PatchInfoTables(void)
|
||||||
|
@ -21635,6 +21780,11 @@ void P_PatchInfoTables(void)
|
||||||
sprnames[i][0] = '\0'; // i == NUMSPRITES
|
sprnames[i][0] = '\0'; // i == NUMSPRITES
|
||||||
memset(&states[S_FIRSTFREESLOT], 0, sizeof (state_t) * NUMSTATEFREESLOTS);
|
memset(&states[S_FIRSTFREESLOT], 0, sizeof (state_t) * NUMSTATEFREESLOTS);
|
||||||
memset(&mobjinfo[MT_FIRSTFREESLOT], 0, sizeof (mobjinfo_t) * NUMMOBJFREESLOTS);
|
memset(&mobjinfo[MT_FIRSTFREESLOT], 0, sizeof (mobjinfo_t) * NUMMOBJFREESLOTS);
|
||||||
|
memset(&skincolors[SKINCOLOR_FIRSTFREESLOT], 0, sizeof (skincolor_t) * NUMCOLORFREESLOTS);
|
||||||
|
for (i = SKINCOLOR_FIRSTFREESLOT; i <= SKINCOLOR_LASTFREESLOT; i++) {
|
||||||
|
skincolors[i].accessible = false;
|
||||||
|
skincolors[i].name[0] = '\0';
|
||||||
|
}
|
||||||
for (i = MT_FIRSTFREESLOT; i <= MT_LASTFREESLOT; i++)
|
for (i = MT_FIRSTFREESLOT; i <= MT_LASTFREESLOT; i++)
|
||||||
mobjinfo[i].doomednum = -1;
|
mobjinfo[i].doomednum = -1;
|
||||||
}
|
}
|
||||||
|
@ -21643,7 +21793,8 @@ void P_PatchInfoTables(void)
|
||||||
static char *sprnamesbackup;
|
static char *sprnamesbackup;
|
||||||
static state_t *statesbackup;
|
static state_t *statesbackup;
|
||||||
static mobjinfo_t *mobjinfobackup;
|
static mobjinfo_t *mobjinfobackup;
|
||||||
static size_t sprnamesbackupsize, statesbackupsize, mobjinfobackupsize;
|
static skincolor_t *skincolorsbackup;
|
||||||
|
static size_t sprnamesbackupsize, statesbackupsize, mobjinfobackupsize, skincolorsbackupsize;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void P_BackupTables(void)
|
void P_BackupTables(void)
|
||||||
|
@ -21653,6 +21804,7 @@ void P_BackupTables(void)
|
||||||
sprnamesbackup = Z_Malloc(sizeof(sprnames), PU_STATIC, NULL);
|
sprnamesbackup = Z_Malloc(sizeof(sprnames), PU_STATIC, NULL);
|
||||||
statesbackup = Z_Malloc(sizeof(states), PU_STATIC, NULL);
|
statesbackup = Z_Malloc(sizeof(states), PU_STATIC, NULL);
|
||||||
mobjinfobackup = Z_Malloc(sizeof(mobjinfo), PU_STATIC, NULL);
|
mobjinfobackup = Z_Malloc(sizeof(mobjinfo), PU_STATIC, NULL);
|
||||||
|
skincolorsbackup = Z_Malloc(sizeof(skincolors), PU_STATIC, NULL);
|
||||||
|
|
||||||
// Sprite names
|
// Sprite names
|
||||||
sprnamesbackupsize = lzf_compress(sprnames, sizeof(sprnames), sprnamesbackup, sizeof(sprnames));
|
sprnamesbackupsize = lzf_compress(sprnames, sizeof(sprnames), sprnamesbackup, sizeof(sprnames));
|
||||||
|
@ -21674,6 +21826,13 @@ void P_BackupTables(void)
|
||||||
mobjinfobackup = Z_Realloc(mobjinfobackup, mobjinfobackupsize, PU_STATIC, NULL);
|
mobjinfobackup = Z_Realloc(mobjinfobackup, mobjinfobackupsize, PU_STATIC, NULL);
|
||||||
else
|
else
|
||||||
M_Memcpy(mobjinfobackup, mobjinfo, sizeof(mobjinfo));
|
M_Memcpy(mobjinfobackup, mobjinfo, sizeof(mobjinfo));
|
||||||
|
|
||||||
|
//Skincolor info
|
||||||
|
skincolorsbackupsize = lzf_compress(skincolors, sizeof(skincolors), skincolorsbackup, sizeof(skincolors));
|
||||||
|
if (skincolorsbackupsize > 0)
|
||||||
|
skincolorsbackup = Z_Realloc(skincolorsbackup, skincolorsbackupsize, PU_STATIC, NULL);
|
||||||
|
else
|
||||||
|
M_Memcpy(skincolorsbackup, skincolors, sizeof(skincolors));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21706,5 +21865,13 @@ void P_ResetData(INT32 flags)
|
||||||
else
|
else
|
||||||
M_Memcpy(mobjinfo, mobjinfobackup, sizeof(mobjinfobackup));
|
M_Memcpy(mobjinfo, mobjinfobackup, sizeof(mobjinfobackup));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & 8)
|
||||||
|
{
|
||||||
|
if (skincolorsbackupsize > 0)
|
||||||
|
lzf_decompress(skincolorsbackup, skincolorsbackupsize, skincolors, sizeof(skincolors));
|
||||||
|
else
|
||||||
|
M_Memcpy(skincolors, skincolorsbackup, sizeof(skincolorsbackup));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
13
src/info.h
13
src/info.h
|
@ -284,6 +284,7 @@ void A_RolloutRock();
|
||||||
void A_DragonbomberSpawn();
|
void A_DragonbomberSpawn();
|
||||||
void A_DragonWing();
|
void A_DragonWing();
|
||||||
void A_DragonSegment();
|
void A_DragonSegment();
|
||||||
|
void A_ChangeHeight();
|
||||||
|
|
||||||
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1
|
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1
|
||||||
#define NUMMOBJFREESLOTS 512
|
#define NUMMOBJFREESLOTS 512
|
||||||
|
@ -451,6 +452,8 @@ typedef enum sprite
|
||||||
|
|
||||||
// Projectiles
|
// Projectiles
|
||||||
SPR_MISL,
|
SPR_MISL,
|
||||||
|
SPR_LASR, // GFZ3 laser
|
||||||
|
SPR_LASF, // GFZ3 laser flames
|
||||||
SPR_TORP, // Torpedo
|
SPR_TORP, // Torpedo
|
||||||
SPR_ENRG, // Energy ball
|
SPR_ENRG, // Energy ball
|
||||||
SPR_MINE, // Skim mine
|
SPR_MINE, // Skim mine
|
||||||
|
@ -1605,10 +1608,12 @@ typedef enum state
|
||||||
S_FANG_PINCHPATHINGSTART1,
|
S_FANG_PINCHPATHINGSTART1,
|
||||||
S_FANG_PINCHPATHINGSTART2,
|
S_FANG_PINCHPATHINGSTART2,
|
||||||
S_FANG_PINCHPATHING,
|
S_FANG_PINCHPATHING,
|
||||||
|
S_FANG_PINCHBOUNCE0,
|
||||||
S_FANG_PINCHBOUNCE1,
|
S_FANG_PINCHBOUNCE1,
|
||||||
S_FANG_PINCHBOUNCE2,
|
S_FANG_PINCHBOUNCE2,
|
||||||
S_FANG_PINCHBOUNCE3,
|
S_FANG_PINCHBOUNCE3,
|
||||||
S_FANG_PINCHBOUNCE4,
|
S_FANG_PINCHBOUNCE4,
|
||||||
|
S_FANG_PINCHFALL0,
|
||||||
S_FANG_PINCHFALL1,
|
S_FANG_PINCHFALL1,
|
||||||
S_FANG_PINCHFALL2,
|
S_FANG_PINCHFALL2,
|
||||||
S_FANG_PINCHSKID1,
|
S_FANG_PINCHSKID1,
|
||||||
|
@ -2220,6 +2225,14 @@ typedef enum state
|
||||||
S_ROCKET,
|
S_ROCKET,
|
||||||
|
|
||||||
S_LASER,
|
S_LASER,
|
||||||
|
S_LASER2,
|
||||||
|
S_LASERFLASH,
|
||||||
|
|
||||||
|
S_LASERFLAME1,
|
||||||
|
S_LASERFLAME2,
|
||||||
|
S_LASERFLAME3,
|
||||||
|
S_LASERFLAME4,
|
||||||
|
S_LASERFLAME5,
|
||||||
|
|
||||||
S_TORPEDO,
|
S_TORPEDO,
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "fastcmp.h"
|
#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
|
||||||
#include "p_slopes.h" // P_GetZAt
|
#include "p_slopes.h" // P_GetSlopeZAt
|
||||||
#include "z_zone.h"
|
#include "z_zone.h"
|
||||||
#include "r_main.h"
|
#include "r_main.h"
|
||||||
#include "r_draw.h"
|
#include "r_draw.h"
|
||||||
|
@ -27,6 +27,7 @@
|
||||||
#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
|
||||||
|
#include "m_menu.h" // Player Setup menu color stuff
|
||||||
|
|
||||||
#include "lua_script.h"
|
#include "lua_script.h"
|
||||||
#include "lua_libs.h"
|
#include "lua_libs.h"
|
||||||
|
@ -144,6 +145,8 @@ static const struct {
|
||||||
{META_STATE, "state_t"},
|
{META_STATE, "state_t"},
|
||||||
{META_MOBJINFO, "mobjinfo_t"},
|
{META_MOBJINFO, "mobjinfo_t"},
|
||||||
{META_SFXINFO, "sfxinfo_t"},
|
{META_SFXINFO, "sfxinfo_t"},
|
||||||
|
{META_SKINCOLOR, "skincolor_t"},
|
||||||
|
{META_COLORRAMP, "skincolor_t.ramp"},
|
||||||
{META_SPRITEINFO, "spriteinfo_t"},
|
{META_SPRITEINFO, "spriteinfo_t"},
|
||||||
{META_PIVOTLIST, "spriteframepivot_t[]"},
|
{META_PIVOTLIST, "spriteframepivot_t[]"},
|
||||||
{META_FRAMEPIVOT, "spriteframepivot_t"},
|
{META_FRAMEPIVOT, "spriteframepivot_t"},
|
||||||
|
@ -252,6 +255,43 @@ static int lib_reserveLuabanks(lua_State *L)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// M_MENU
|
||||||
|
//////////////
|
||||||
|
|
||||||
|
static int lib_pMoveColorBefore(lua_State *L)
|
||||||
|
{
|
||||||
|
UINT16 color = (UINT16)luaL_checkinteger(L, 1);
|
||||||
|
UINT16 targ = (UINT16)luaL_checkinteger(L, 2);
|
||||||
|
|
||||||
|
NOHUD
|
||||||
|
M_MoveColorBefore(color, targ);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lib_pMoveColorAfter(lua_State *L)
|
||||||
|
{
|
||||||
|
UINT16 color = (UINT16)luaL_checkinteger(L, 1);
|
||||||
|
UINT16 targ = (UINT16)luaL_checkinteger(L, 2);
|
||||||
|
|
||||||
|
NOHUD
|
||||||
|
M_MoveColorAfter(color, targ);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lib_pGetColorBefore(lua_State *L)
|
||||||
|
{
|
||||||
|
UINT16 color = (UINT16)luaL_checkinteger(L, 1);
|
||||||
|
lua_pushinteger(L, M_GetColorBefore(color));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lib_pGetColorAfter(lua_State *L)
|
||||||
|
{
|
||||||
|
UINT16 color = (UINT16)luaL_checkinteger(L, 1);
|
||||||
|
lua_pushinteger(L, M_GetColorAfter(color));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// M_RANDOM
|
// M_RANDOM
|
||||||
//////////////
|
//////////////
|
||||||
|
|
||||||
|
@ -2184,14 +2224,20 @@ static int lib_evStartCrumble(lua_State *L)
|
||||||
|
|
||||||
static int lib_pGetZAt(lua_State *L)
|
static int lib_pGetZAt(lua_State *L)
|
||||||
{
|
{
|
||||||
pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE));
|
|
||||||
fixed_t x = luaL_checkfixed(L, 2);
|
fixed_t x = luaL_checkfixed(L, 2);
|
||||||
fixed_t y = luaL_checkfixed(L, 3);
|
fixed_t y = luaL_checkfixed(L, 3);
|
||||||
//HUDSAFE
|
//HUDSAFE
|
||||||
if (!slope)
|
if (lua_isnil(L, 1))
|
||||||
return LUA_ErrInvalid(L, "pslope_t");
|
{
|
||||||
|
fixed_t z = luaL_checkfixed(L, 4);
|
||||||
|
lua_pushfixed(L, P_GetZAt(NULL, x, y, z));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE));
|
||||||
|
lua_pushfixed(L, P_GetSlopeZAt(slope, x, y));
|
||||||
|
}
|
||||||
|
|
||||||
lua_pushfixed(L, P_GetZAt(slope, x, y));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2382,10 +2428,10 @@ static int lib_rGetColorByName(lua_State *L)
|
||||||
// SKINCOLOR_GREEN > "Green" for example
|
// SKINCOLOR_GREEN > "Green" for example
|
||||||
static int lib_rGetNameByColor(lua_State *L)
|
static int lib_rGetNameByColor(lua_State *L)
|
||||||
{
|
{
|
||||||
UINT8 colornum = (UINT8)luaL_checkinteger(L, 1);
|
UINT16 colornum = (UINT16)luaL_checkinteger(L, 1);
|
||||||
if (!colornum || colornum >= MAXSKINCOLORS)
|
if (!colornum || colornum >= numskincolors)
|
||||||
return luaL_error(L, "skincolor %d out of range (1 - %d).", colornum, MAXSKINCOLORS-1);
|
return luaL_error(L, "skincolor %d out of range (1 - %d).", colornum, numskincolors-1);
|
||||||
lua_pushstring(L, Color_Names[colornum]);
|
lua_pushstring(L, skincolors[colornum].name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2458,6 +2504,20 @@ static int lib_sStopSound(lua_State *L)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lib_sStopSoundByID(lua_State *L)
|
||||||
|
{
|
||||||
|
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||||
|
sfxenum_t sound_id = luaL_checkinteger(L, 2);
|
||||||
|
//NOHUD
|
||||||
|
if (!origin)
|
||||||
|
return LUA_ErrInvalid(L, "mobj_t");
|
||||||
|
if (sound_id >= NUMSFX)
|
||||||
|
return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1);
|
||||||
|
|
||||||
|
S_StopSoundByID(origin, sound_id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int lib_sChangeMusic(lua_State *L)
|
static int lib_sChangeMusic(lua_State *L)
|
||||||
{
|
{
|
||||||
#ifdef MUSICSLOT_COMPATIBILITY
|
#ifdef MUSICSLOT_COMPATIBILITY
|
||||||
|
@ -2878,15 +2938,50 @@ static int lib_gAddGametype(lua_State *L)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int Lcheckmapnumber (lua_State *L, int idx, const char *fun)
|
||||||
|
{
|
||||||
|
if (ISINLEVEL)
|
||||||
|
return luaL_optinteger(L, idx, gamemap);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (lua_isnoneornil(L, idx))
|
||||||
|
{
|
||||||
|
return luaL_error(L,
|
||||||
|
"%s can only be used without a parameter while in a level.",
|
||||||
|
fun
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return luaL_checkinteger(L, idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int lib_gBuildMapName(lua_State *L)
|
static int lib_gBuildMapName(lua_State *L)
|
||||||
{
|
{
|
||||||
INT32 map = luaL_optinteger(L, 1, gamemap);
|
INT32 map = Lcheckmapnumber(L, 1, "G_BuildMapName");
|
||||||
//HUDSAFE
|
//HUDSAFE
|
||||||
INLEVEL
|
|
||||||
lua_pushstring(L, G_BuildMapName(map));
|
lua_pushstring(L, G_BuildMapName(map));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lib_gBuildMapTitle(lua_State *L)
|
||||||
|
{
|
||||||
|
INT32 map = Lcheckmapnumber(L, 1, "G_BuildMapTitle");
|
||||||
|
char *name;
|
||||||
|
if (map < 1 || map > NUMMAPS)
|
||||||
|
{
|
||||||
|
return luaL_error(L,
|
||||||
|
"map number %d out of range (1 - %d)",
|
||||||
|
map,
|
||||||
|
NUMMAPS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
name = G_BuildMapTitle(map);
|
||||||
|
lua_pushstring(L, name);
|
||||||
|
Z_Free(name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int lib_gDoReborn(lua_State *L)
|
static int lib_gDoReborn(lua_State *L)
|
||||||
{
|
{
|
||||||
INT32 playernum = luaL_checkinteger(L, 1);
|
INT32 playernum = luaL_checkinteger(L, 1);
|
||||||
|
@ -3081,6 +3176,12 @@ static luaL_Reg lib[] = {
|
||||||
{"IsPlayerAdmin", lib_isPlayerAdmin},
|
{"IsPlayerAdmin", lib_isPlayerAdmin},
|
||||||
{"reserveLuabanks", lib_reserveLuabanks},
|
{"reserveLuabanks", lib_reserveLuabanks},
|
||||||
|
|
||||||
|
// m_menu
|
||||||
|
{"M_MoveColorAfter",lib_pMoveColorAfter},
|
||||||
|
{"M_MoveColorBefore",lib_pMoveColorBefore},
|
||||||
|
{"M_GetColorAfter",lib_pGetColorAfter},
|
||||||
|
{"M_GetColorBefore",lib_pGetColorBefore},
|
||||||
|
|
||||||
// m_random
|
// m_random
|
||||||
{"P_RandomFixed",lib_pRandomFixed},
|
{"P_RandomFixed",lib_pRandomFixed},
|
||||||
{"P_RandomByte",lib_pRandomByte},
|
{"P_RandomByte",lib_pRandomByte},
|
||||||
|
@ -3261,6 +3362,7 @@ static luaL_Reg lib[] = {
|
||||||
{"S_StartSound",lib_sStartSound},
|
{"S_StartSound",lib_sStartSound},
|
||||||
{"S_StartSoundAtVolume",lib_sStartSoundAtVolume},
|
{"S_StartSoundAtVolume",lib_sStartSoundAtVolume},
|
||||||
{"S_StopSound",lib_sStopSound},
|
{"S_StopSound",lib_sStopSound},
|
||||||
|
{"S_StopSoundByID",lib_sStopSoundByID},
|
||||||
{"S_ChangeMusic",lib_sChangeMusic},
|
{"S_ChangeMusic",lib_sChangeMusic},
|
||||||
{"S_SpeedMusic",lib_sSpeedMusic},
|
{"S_SpeedMusic",lib_sSpeedMusic},
|
||||||
{"S_StopMusic",lib_sStopMusic},
|
{"S_StopMusic",lib_sStopMusic},
|
||||||
|
@ -3279,6 +3381,7 @@ static luaL_Reg lib[] = {
|
||||||
// g_game
|
// g_game
|
||||||
{"G_AddGametype", lib_gAddGametype},
|
{"G_AddGametype", lib_gAddGametype},
|
||||||
{"G_BuildMapName",lib_gBuildMapName},
|
{"G_BuildMapName",lib_gBuildMapName},
|
||||||
|
{"G_BuildMapTitle",lib_gBuildMapTitle},
|
||||||
{"G_DoReborn",lib_gDoReborn},
|
{"G_DoReborn",lib_gDoReborn},
|
||||||
{"G_SetCustomExitVars",lib_gSetCustomExitVars},
|
{"G_SetCustomExitVars",lib_gSetCustomExitVars},
|
||||||
{"G_EnoughPlayersFinished",lib_gEnoughPlayersFinished},
|
{"G_EnoughPlayersFinished",lib_gEnoughPlayersFinished},
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -878,8 +878,8 @@ static int libd_drawNameTag(lua_State *L)
|
||||||
INT32 y;
|
INT32 y;
|
||||||
const char *str;
|
const char *str;
|
||||||
INT32 flags;
|
INT32 flags;
|
||||||
UINT8 basecolor;
|
UINT16 basecolor;
|
||||||
UINT8 outlinecolor;
|
UINT16 outlinecolor;
|
||||||
UINT8 *basecolormap = NULL;
|
UINT8 *basecolormap = NULL;
|
||||||
UINT8 *outlinecolormap = NULL;
|
UINT8 *outlinecolormap = NULL;
|
||||||
|
|
||||||
|
@ -908,8 +908,8 @@ static int libd_drawScaledNameTag(lua_State *L)
|
||||||
const char *str;
|
const char *str;
|
||||||
INT32 flags;
|
INT32 flags;
|
||||||
fixed_t scale;
|
fixed_t scale;
|
||||||
UINT8 basecolor;
|
UINT16 basecolor;
|
||||||
UINT8 outlinecolor;
|
UINT16 outlinecolor;
|
||||||
UINT8 *basecolormap = NULL;
|
UINT8 *basecolormap = NULL;
|
||||||
UINT8 *outlinecolormap = NULL;
|
UINT8 *outlinecolormap = NULL;
|
||||||
|
|
||||||
|
@ -966,7 +966,7 @@ static int libd_nameTagWidth(lua_State *L)
|
||||||
static int libd_getColormap(lua_State *L)
|
static int libd_getColormap(lua_State *L)
|
||||||
{
|
{
|
||||||
INT32 skinnum = TC_DEFAULT;
|
INT32 skinnum = TC_DEFAULT;
|
||||||
skincolors_t color = luaL_optinteger(L, 2, 0);
|
skincolornum_t color = luaL_optinteger(L, 2, 0);
|
||||||
UINT8* colormap = NULL;
|
UINT8* colormap = NULL;
|
||||||
HUDONLY
|
HUDONLY
|
||||||
if (lua_isnoneornil(L, 1))
|
if (lua_isnoneornil(L, 1))
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
#include "lua_libs.h"
|
#include "lua_libs.h"
|
||||||
#include "lua_hud.h" // hud_running errors
|
#include "lua_hud.h" // hud_running errors
|
||||||
|
|
||||||
|
extern CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1];
|
||||||
|
extern void R_FlushTranslationColormapCache(void);
|
||||||
|
|
||||||
boolean LUA_CallAction(const char *action, mobj_t *actor);
|
boolean LUA_CallAction(const char *action, mobj_t *actor);
|
||||||
state_t *astate;
|
state_t *astate;
|
||||||
|
|
||||||
|
@ -1465,6 +1468,229 @@ static int lib_luabankslen(lua_State *L)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
// SKINCOLOR INFO //
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
// Arbitrary skincolors[] table index -> skincolor_t *
|
||||||
|
static int lib_getSkinColor(lua_State *L)
|
||||||
|
{
|
||||||
|
UINT32 i;
|
||||||
|
lua_remove(L, 1);
|
||||||
|
|
||||||
|
i = luaL_checkinteger(L, 1);
|
||||||
|
if (!i || i >= numskincolors)
|
||||||
|
return luaL_error(L, "skincolors[] index %d out of range (1 - %d)", i, numskincolors-1);
|
||||||
|
LUA_PushUserdata(L, &skincolors[i], META_SKINCOLOR);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set the entire c->ramp array
|
||||||
|
static void setRamp(lua_State *L, skincolor_t* c) {
|
||||||
|
UINT32 i;
|
||||||
|
lua_pushnil(L);
|
||||||
|
for (i=0; i<COLORRAMPSIZE; i++) {
|
||||||
|
if (lua_objlen(L,-2)<COLORRAMPSIZE) {
|
||||||
|
luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' must be %d entries long; got %d.", COLORRAMPSIZE, lua_objlen(L,-2));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (lua_next(L, -2) != 0) {
|
||||||
|
c->ramp[i] = lua_isnumber(L,-1) ? (UINT8)luaL_checkinteger(L,-1) : 120;
|
||||||
|
lua_pop(L, 1);
|
||||||
|
} else
|
||||||
|
c->ramp[i] = 120;
|
||||||
|
}
|
||||||
|
lua_pop(L,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lua table full of data -> skincolors[]
|
||||||
|
static int lib_setSkinColor(lua_State *L)
|
||||||
|
{
|
||||||
|
UINT32 j;
|
||||||
|
skincolor_t *info;
|
||||||
|
UINT16 cnum; //skincolor num
|
||||||
|
lua_remove(L, 1); // don't care about skincolors[] userdata.
|
||||||
|
{
|
||||||
|
cnum = (UINT16)luaL_checkinteger(L, 1);
|
||||||
|
if (cnum < SKINCOLOR_FIRSTFREESLOT || cnum >= numskincolors)
|
||||||
|
return luaL_error(L, "skincolors[] index %d out of range (%d - %d)", cnum, SKINCOLOR_FIRSTFREESLOT, numskincolors-1);
|
||||||
|
info = &skincolors[cnum]; // get the skincolor to assign to.
|
||||||
|
}
|
||||||
|
luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table.
|
||||||
|
lua_remove(L, 1); // pop skincolor num, don't need it any more.
|
||||||
|
lua_settop(L, 1); // cut the stack here. the only thing left now is the table of data we're assigning to the skincolor.
|
||||||
|
|
||||||
|
if (hud_running)
|
||||||
|
return luaL_error(L, "Do not alter skincolors in HUD rendering code!");
|
||||||
|
|
||||||
|
// clear the skincolor to start with, in case of missing table elements
|
||||||
|
memset(info,0,sizeof(skincolor_t));
|
||||||
|
|
||||||
|
Color_cons_t[cnum].value = cnum;
|
||||||
|
lua_pushnil(L);
|
||||||
|
while (lua_next(L, 1)) {
|
||||||
|
lua_Integer i = 0;
|
||||||
|
const char *str = NULL;
|
||||||
|
if (lua_isnumber(L, 2))
|
||||||
|
i = lua_tointeger(L, 2);
|
||||||
|
else
|
||||||
|
str = luaL_checkstring(L, 2);
|
||||||
|
|
||||||
|
if (i == 1 || (str && fastcmp(str,"name"))) {
|
||||||
|
const char* n = luaL_checkstring(L, 3);
|
||||||
|
strlcpy(info->name, n, MAXCOLORNAME+1);
|
||||||
|
if (strlen(n) > MAXCOLORNAME)
|
||||||
|
CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') longer than %d chars; shortened to %s.\n", n, MAXCOLORNAME, info->name);
|
||||||
|
} else if (i == 2 || (str && fastcmp(str,"ramp"))) {
|
||||||
|
if (!lua_istable(L, 3) && luaL_checkudata(L, 3, META_COLORRAMP) == NULL)
|
||||||
|
return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' must be a table or array.");
|
||||||
|
else if (lua_istable(L, 3))
|
||||||
|
setRamp(L, info);
|
||||||
|
else
|
||||||
|
for (j=0; j<COLORRAMPSIZE; j++)
|
||||||
|
info->ramp[j] = (*((UINT8 **)luaL_checkudata(L, 3, META_COLORRAMP)))[j];
|
||||||
|
R_FlushTranslationColormapCache();
|
||||||
|
} else if (i == 3 || (str && fastcmp(str,"invcolor")))
|
||||||
|
info->invcolor = (UINT16)luaL_checkinteger(L, 3);
|
||||||
|
else if (i == 4 || (str && fastcmp(str,"invshade")))
|
||||||
|
info->invshade = (UINT8)luaL_checkinteger(L, 3)%COLORRAMPSIZE;
|
||||||
|
else if (i == 5 || (str && fastcmp(str,"chatcolor")))
|
||||||
|
info->chatcolor = (UINT16)luaL_checkinteger(L, 3);
|
||||||
|
else if (i == 6 || (str && fastcmp(str,"accessible"))) {
|
||||||
|
boolean v = lua_isboolean(L,3) ? lua_toboolean(L, 3) : true;
|
||||||
|
if (cnum < FIRSTSUPERCOLOR && v != skincolors[cnum].accessible)
|
||||||
|
return luaL_error(L, "skincolors[] index %d is a standard color; accessibility changes are prohibited.", i);
|
||||||
|
else
|
||||||
|
info->accessible = v;
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #skincolors -> numskincolors
|
||||||
|
static int lib_skincolorslen(lua_State *L)
|
||||||
|
{
|
||||||
|
lua_pushinteger(L, numskincolors);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skincolor_t *, field -> number
|
||||||
|
static int skincolor_get(lua_State *L)
|
||||||
|
{
|
||||||
|
skincolor_t *info = *((skincolor_t **)luaL_checkudata(L, 1, META_SKINCOLOR));
|
||||||
|
const char *field = luaL_checkstring(L, 2);
|
||||||
|
|
||||||
|
I_Assert(info != NULL);
|
||||||
|
I_Assert(info >= skincolors);
|
||||||
|
|
||||||
|
if (fastcmp(field,"name"))
|
||||||
|
lua_pushstring(L, info->name);
|
||||||
|
else if (fastcmp(field,"ramp"))
|
||||||
|
LUA_PushUserdata(L, info->ramp, META_COLORRAMP);
|
||||||
|
else if (fastcmp(field,"invcolor"))
|
||||||
|
lua_pushinteger(L, info->invcolor);
|
||||||
|
else if (fastcmp(field,"invshade"))
|
||||||
|
lua_pushinteger(L, info->invshade);
|
||||||
|
else if (fastcmp(field,"chatcolor"))
|
||||||
|
lua_pushinteger(L, info->chatcolor);
|
||||||
|
else if (fastcmp(field,"accessible"))
|
||||||
|
lua_pushboolean(L, info->accessible);
|
||||||
|
else
|
||||||
|
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "skincolor_t", field);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skincolor_t *, field, number -> skincolors[]
|
||||||
|
static int skincolor_set(lua_State *L)
|
||||||
|
{
|
||||||
|
UINT32 i;
|
||||||
|
skincolor_t *info = *((skincolor_t **)luaL_checkudata(L, 1, META_SKINCOLOR));
|
||||||
|
const char *field = luaL_checkstring(L, 2);
|
||||||
|
|
||||||
|
I_Assert(info != NULL);
|
||||||
|
I_Assert(info >= skincolors);
|
||||||
|
|
||||||
|
if (info-skincolors < SKINCOLOR_FIRSTFREESLOT || info-skincolors >= numskincolors)
|
||||||
|
return luaL_error(L, "skincolors[] index %d out of range (%d - %d)", info-skincolors, SKINCOLOR_FIRSTFREESLOT, numskincolors-1);
|
||||||
|
|
||||||
|
if (fastcmp(field,"name")) {
|
||||||
|
const char* n = luaL_checkstring(L, 3);
|
||||||
|
if (strchr(n, ' ') != NULL)
|
||||||
|
CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') contains spaces.\n", n);
|
||||||
|
strlcpy(info->name, n, MAXCOLORNAME+1);
|
||||||
|
if (strlen(n) > MAXCOLORNAME)
|
||||||
|
CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') longer than %d chars; clipped to %s.\n", n, MAXCOLORNAME, info->name);
|
||||||
|
} else if (fastcmp(field,"ramp")) {
|
||||||
|
if (!lua_istable(L, 3) && luaL_checkudata(L, 3, META_COLORRAMP) == NULL)
|
||||||
|
return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' must be a table or array.");
|
||||||
|
else if (lua_istable(L, 3))
|
||||||
|
setRamp(L, info);
|
||||||
|
else
|
||||||
|
for (i=0; i<COLORRAMPSIZE; i++)
|
||||||
|
info->ramp[i] = (*((UINT8 **)luaL_checkudata(L, 3, META_COLORRAMP)))[i];
|
||||||
|
R_FlushTranslationColormapCache();
|
||||||
|
} else if (fastcmp(field,"invcolor"))
|
||||||
|
info->invcolor = (UINT16)luaL_checkinteger(L, 3);
|
||||||
|
else if (fastcmp(field,"invshade"))
|
||||||
|
info->invshade = (UINT8)luaL_checkinteger(L, 3)%COLORRAMPSIZE;
|
||||||
|
else if (fastcmp(field,"chatcolor"))
|
||||||
|
info->chatcolor = (UINT16)luaL_checkinteger(L, 3);
|
||||||
|
else if (fastcmp(field,"accessible"))
|
||||||
|
info->accessible = lua_isboolean(L,3);
|
||||||
|
else
|
||||||
|
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "skincolor_t", field);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skincolor_t * -> SKINCOLOR_*
|
||||||
|
static int skincolor_num(lua_State *L)
|
||||||
|
{
|
||||||
|
skincolor_t *info = *((skincolor_t **)luaL_checkudata(L, 1, META_SKINCOLOR));
|
||||||
|
|
||||||
|
I_Assert(info != NULL);
|
||||||
|
I_Assert(info >= skincolors);
|
||||||
|
|
||||||
|
lua_pushinteger(L, info-skincolors);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ramp, n -> ramp[n]
|
||||||
|
static int colorramp_get(lua_State *L)
|
||||||
|
{
|
||||||
|
UINT8 *colorramp = *((UINT8 **)luaL_checkudata(L, 1, META_COLORRAMP));
|
||||||
|
UINT32 n = luaL_checkinteger(L, 2);
|
||||||
|
if (n >= COLORRAMPSIZE)
|
||||||
|
return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' index %d out of range (0 - %d)", n, COLORRAMPSIZE-1);
|
||||||
|
lua_pushinteger(L, colorramp[n]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ramp, n, value -> ramp[n] = value
|
||||||
|
static int colorramp_set(lua_State *L)
|
||||||
|
{
|
||||||
|
UINT8 *colorramp = *((UINT8 **)luaL_checkudata(L, 1, META_COLORRAMP));
|
||||||
|
UINT16 cnum = (UINT16)(((uint8_t*)colorramp - (uint8_t*)(skincolors[0].ramp))/sizeof(skincolor_t));
|
||||||
|
UINT32 n = luaL_checkinteger(L, 2);
|
||||||
|
UINT8 i = (UINT8)luaL_checkinteger(L, 3);
|
||||||
|
if (cnum < SKINCOLOR_FIRSTFREESLOT || cnum >= numskincolors)
|
||||||
|
return luaL_error(L, "skincolors[] index %d out of range (%d - %d)", cnum, SKINCOLOR_FIRSTFREESLOT, numskincolors-1);
|
||||||
|
if (n >= COLORRAMPSIZE)
|
||||||
|
return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' index %d out of range (0 - %d)", n, COLORRAMPSIZE-1);
|
||||||
|
if (hud_running)
|
||||||
|
return luaL_error(L, "Do not alter skincolor_t in HUD rendering code!");
|
||||||
|
colorramp[n] = i;
|
||||||
|
R_FlushTranslationColormapCache();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #ramp -> COLORRAMPSIZE
|
||||||
|
static int colorramp_len(lua_State *L)
|
||||||
|
{
|
||||||
|
lua_pushinteger(L, COLORRAMPSIZE);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//
|
//
|
||||||
// Now push all these functions into the Lua state!
|
// Now push all these functions into the Lua state!
|
||||||
|
@ -1502,6 +1728,28 @@ int LUA_InfoLib(lua_State *L)
|
||||||
lua_setfield(L, -2, "__len");
|
lua_setfield(L, -2, "__len");
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
luaL_newmetatable(L, META_SKINCOLOR);
|
||||||
|
lua_pushcfunction(L, skincolor_get);
|
||||||
|
lua_setfield(L, -2, "__index");
|
||||||
|
|
||||||
|
lua_pushcfunction(L, skincolor_set);
|
||||||
|
lua_setfield(L, -2, "__newindex");
|
||||||
|
|
||||||
|
lua_pushcfunction(L, skincolor_num);
|
||||||
|
lua_setfield(L, -2, "__len");
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
luaL_newmetatable(L, META_COLORRAMP);
|
||||||
|
lua_pushcfunction(L, colorramp_get);
|
||||||
|
lua_setfield(L, -2, "__index");
|
||||||
|
|
||||||
|
lua_pushcfunction(L, colorramp_set);
|
||||||
|
lua_setfield(L, -2, "__newindex");
|
||||||
|
|
||||||
|
lua_pushcfunction(L, colorramp_len);
|
||||||
|
lua_setfield(L, -2, "__len");
|
||||||
|
lua_pop(L,1);
|
||||||
|
|
||||||
luaL_newmetatable(L, META_SFXINFO);
|
luaL_newmetatable(L, META_SFXINFO);
|
||||||
lua_pushcfunction(L, sfxinfo_get);
|
lua_pushcfunction(L, sfxinfo_get);
|
||||||
lua_setfield(L, -2, "__index");
|
lua_setfield(L, -2, "__index");
|
||||||
|
@ -1605,6 +1853,19 @@ int LUA_InfoLib(lua_State *L)
|
||||||
lua_setmetatable(L, -2);
|
lua_setmetatable(L, -2);
|
||||||
lua_setglobal(L, "mobjinfo");
|
lua_setglobal(L, "mobjinfo");
|
||||||
|
|
||||||
|
lua_newuserdata(L, 0);
|
||||||
|
lua_createtable(L, 0, 2);
|
||||||
|
lua_pushcfunction(L, lib_getSkinColor);
|
||||||
|
lua_setfield(L, -2, "__index");
|
||||||
|
|
||||||
|
lua_pushcfunction(L, lib_setSkinColor);
|
||||||
|
lua_setfield(L, -2, "__newindex");
|
||||||
|
|
||||||
|
lua_pushcfunction(L, lib_skincolorslen);
|
||||||
|
lua_setfield(L, -2, "__len");
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
lua_setglobal(L, "skincolors");
|
||||||
|
|
||||||
lua_newuserdata(L, 0);
|
lua_newuserdata(L, 0);
|
||||||
lua_createtable(L, 0, 2);
|
lua_createtable(L, 0, 2);
|
||||||
lua_pushcfunction(L, lib_getSfxInfo);
|
lua_pushcfunction(L, lib_getSfxInfo);
|
||||||
|
|
|
@ -20,6 +20,8 @@ extern lua_State *gL;
|
||||||
#define META_STATE "STATE_T*"
|
#define META_STATE "STATE_T*"
|
||||||
#define META_MOBJINFO "MOBJINFO_T*"
|
#define META_MOBJINFO "MOBJINFO_T*"
|
||||||
#define META_SFXINFO "SFXINFO_T*"
|
#define META_SFXINFO "SFXINFO_T*"
|
||||||
|
#define META_SKINCOLOR "SKINCOLOR_T*"
|
||||||
|
#define META_COLORRAMP "SKINCOLOR_T*RAMP"
|
||||||
#define META_SPRITEINFO "SPRITEINFO_T*"
|
#define META_SPRITEINFO "SPRITEINFO_T*"
|
||||||
#define META_PIVOTLIST "SPRITEFRAMEPIVOT_T[]"
|
#define META_PIVOTLIST "SPRITEFRAMEPIVOT_T[]"
|
||||||
#define META_FRAMEPIVOT "SPRITEFRAMEPIVOT_T*"
|
#define META_FRAMEPIVOT "SPRITEFRAMEPIVOT_T*"
|
||||||
|
|
|
@ -139,6 +139,7 @@ static const char *const side_opt[] = {
|
||||||
"toptexture",
|
"toptexture",
|
||||||
"bottomtexture",
|
"bottomtexture",
|
||||||
"midtexture",
|
"midtexture",
|
||||||
|
"line",
|
||||||
"sector",
|
"sector",
|
||||||
"special",
|
"special",
|
||||||
"repeatcnt",
|
"repeatcnt",
|
||||||
|
@ -2009,6 +2010,8 @@ static int mapheaderinfo_get(lua_State *L)
|
||||||
lua_pushinteger(L, header->typeoflevel);
|
lua_pushinteger(L, header->typeoflevel);
|
||||||
else if (fastcmp(field,"nextlevel"))
|
else if (fastcmp(field,"nextlevel"))
|
||||||
lua_pushinteger(L, header->nextlevel);
|
lua_pushinteger(L, header->nextlevel);
|
||||||
|
else if (fastcmp(field,"marathonnext"))
|
||||||
|
lua_pushinteger(L, header->marathonnext);
|
||||||
else if (fastcmp(field,"keywords"))
|
else if (fastcmp(field,"keywords"))
|
||||||
lua_pushstring(L, header->keywords);
|
lua_pushstring(L, header->keywords);
|
||||||
else if (fastcmp(field,"musname"))
|
else if (fastcmp(field,"musname"))
|
||||||
|
|
|
@ -113,7 +113,8 @@ static int lib_fixeddiv(lua_State *L)
|
||||||
|
|
||||||
static int lib_fixedrem(lua_State *L)
|
static int lib_fixedrem(lua_State *L)
|
||||||
{
|
{
|
||||||
lua_pushfixed(L, FixedRem(luaL_checkfixed(L, 1), luaL_checkfixed(L, 2)));
|
LUA_Deprecated(L, "FixedRem(a, b)", "a % b");
|
||||||
|
lua_pushfixed(L, luaL_checkfixed(L, 1) % luaL_checkfixed(L, 2));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,15 +173,14 @@ static int lib_all7emeralds(lua_State *L)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whee, special Lua-exclusive function for making use of Color_Opposite[]
|
|
||||||
// Returns both color and signpost shade numbers!
|
// Returns both color and signpost shade numbers!
|
||||||
static int lib_coloropposite(lua_State *L)
|
static int lib_coloropposite(lua_State *L)
|
||||||
{
|
{
|
||||||
UINT8 colornum = (UINT8)luaL_checkinteger(L, 1);
|
UINT16 colornum = (UINT16)luaL_checkinteger(L, 1);
|
||||||
if (!colornum || colornum >= MAXSKINCOLORS)
|
if (!colornum || colornum >= numskincolors)
|
||||||
return luaL_error(L, "skincolor %d out of range (1 - %d).", colornum, MAXSKINCOLORS-1);
|
return luaL_error(L, "skincolor %d out of range (1 - %d).", colornum, numskincolors-1);
|
||||||
lua_pushinteger(L, Color_Opposite[colornum-1][0]); // push color
|
lua_pushinteger(L, skincolors[colornum].invcolor); // push color
|
||||||
lua_pushinteger(L, Color_Opposite[colornum-1][1]); // push sign shade index, 0-15
|
lua_pushinteger(L, skincolors[colornum].invshade); // push sign shade index, 0-15
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -449,10 +449,8 @@ static int mobj_set(lua_State *L)
|
||||||
return UNIMPLEMENTED;
|
return UNIMPLEMENTED;
|
||||||
case mobj_angle:
|
case mobj_angle:
|
||||||
mo->angle = luaL_checkangle(L, 3);
|
mo->angle = luaL_checkangle(L, 3);
|
||||||
if (mo->player == &players[consoleplayer])
|
if (mo->player)
|
||||||
localangle = mo->angle;
|
P_SetPlayerAngle(mo->player, mo->angle);
|
||||||
else if (mo->player == &players[secondarydisplayplayer])
|
|
||||||
localangle2 = mo->angle;
|
|
||||||
break;
|
break;
|
||||||
case mobj_rollangle:
|
case mobj_rollangle:
|
||||||
mo->rollangle = luaL_checkangle(L, 3);
|
mo->rollangle = luaL_checkangle(L, 3);
|
||||||
|
@ -574,9 +572,9 @@ static int mobj_set(lua_State *L)
|
||||||
}
|
}
|
||||||
case mobj_color:
|
case mobj_color:
|
||||||
{
|
{
|
||||||
UINT8 newcolor = (UINT8)luaL_checkinteger(L,3);
|
UINT16 newcolor = (UINT16)luaL_checkinteger(L,3);
|
||||||
if (newcolor >= MAXTRANSLATIONS)
|
if (newcolor >= numskincolors)
|
||||||
return luaL_error(L, "mobj.color %d out of range (0 - %d).", newcolor, MAXTRANSLATIONS-1);
|
return luaL_error(L, "mobj.color %d out of range (0 - %d).", newcolor, numskincolors-1);
|
||||||
mo->color = newcolor;
|
mo->color = newcolor;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -829,6 +827,15 @@ static int mapthing_set(lua_State *L)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mapthing_num(lua_State *L)
|
||||||
|
{
|
||||||
|
mapthing_t *mt = *((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING));
|
||||||
|
if (!mt)
|
||||||
|
return luaL_error(L, "accessed mapthing_t doesn't exist anymore.");
|
||||||
|
lua_pushinteger(L, mt-mapthings);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int lib_iterateMapthings(lua_State *L)
|
static int lib_iterateMapthings(lua_State *L)
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
@ -893,6 +900,9 @@ int LUA_MobjLib(lua_State *L)
|
||||||
|
|
||||||
lua_pushcfunction(L, mapthing_set);
|
lua_pushcfunction(L, mapthing_set);
|
||||||
lua_setfield(L, -2, "__newindex");
|
lua_setfield(L, -2, "__newindex");
|
||||||
|
|
||||||
|
lua_pushcfunction(L, mapthing_num);
|
||||||
|
lua_setfield(L, -2, "__len");
|
||||||
lua_pop(L,1);
|
lua_pop(L,1);
|
||||||
|
|
||||||
lua_newuserdata(L, 0);
|
lua_newuserdata(L, 0);
|
||||||
|
|
|
@ -461,9 +461,9 @@ static int player_set(lua_State *L)
|
||||||
plr->flashpal = (UINT16)luaL_checkinteger(L, 3);
|
plr->flashpal = (UINT16)luaL_checkinteger(L, 3);
|
||||||
else if (fastcmp(field,"skincolor"))
|
else if (fastcmp(field,"skincolor"))
|
||||||
{
|
{
|
||||||
UINT8 newcolor = (UINT8)luaL_checkinteger(L,3);
|
UINT16 newcolor = (UINT16)luaL_checkinteger(L,3);
|
||||||
if (newcolor >= MAXSKINCOLORS)
|
if (newcolor >= numskincolors)
|
||||||
return luaL_error(L, "player.skincolor %d out of range (0 - %d).", newcolor, MAXSKINCOLORS-1);
|
return luaL_error(L, "player.skincolor %d out of range (0 - %d).", newcolor, numskincolors-1);
|
||||||
plr->skincolor = newcolor;
|
plr->skincolor = newcolor;
|
||||||
}
|
}
|
||||||
else if (fastcmp(field,"score"))
|
else if (fastcmp(field,"score"))
|
||||||
|
|
163
src/lua_script.c
163
src/lua_script.c
|
@ -78,6 +78,58 @@ FUNCNORETURN static int LUA_Panic(lua_State *L)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define LEVELS1 12 // size of the first part of the stack
|
||||||
|
#define LEVELS2 10 // size of the second part of the stack
|
||||||
|
|
||||||
|
// Error handler used with pcall() when loading scripts or calling hooks
|
||||||
|
// Takes a string with the original error message,
|
||||||
|
// appends the traceback to it, and return the result
|
||||||
|
int LUA_GetErrorMessage(lua_State *L)
|
||||||
|
{
|
||||||
|
int level = 1;
|
||||||
|
int firstpart = 1; // still before eventual `...'
|
||||||
|
lua_Debug ar;
|
||||||
|
|
||||||
|
lua_pushliteral(L, "\nstack traceback:");
|
||||||
|
while (lua_getstack(L, level++, &ar))
|
||||||
|
{
|
||||||
|
if (level > LEVELS1 && firstpart)
|
||||||
|
{
|
||||||
|
// no more than `LEVELS2' more levels?
|
||||||
|
if (!lua_getstack(L, level + LEVELS2, &ar))
|
||||||
|
level--; // keep going
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lua_pushliteral(L, "\n ..."); // too many levels
|
||||||
|
while (lua_getstack(L, level + LEVELS2, &ar)) // find last levels
|
||||||
|
level++;
|
||||||
|
}
|
||||||
|
firstpart = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
lua_pushliteral(L, "\n ");
|
||||||
|
lua_getinfo(L, "Snl", &ar);
|
||||||
|
lua_pushfstring(L, "%s:", ar.short_src);
|
||||||
|
if (ar.currentline > 0)
|
||||||
|
lua_pushfstring(L, "%d:", ar.currentline);
|
||||||
|
if (*ar.namewhat != '\0') // is there a name?
|
||||||
|
lua_pushfstring(L, " in function " LUA_QS, ar.name);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*ar.what == 'm') // main?
|
||||||
|
lua_pushfstring(L, " in main chunk");
|
||||||
|
else if (*ar.what == 'C' || *ar.what == 't')
|
||||||
|
lua_pushliteral(L, " ?"); // C function or tail call
|
||||||
|
else
|
||||||
|
lua_pushfstring(L, " in function <%s:%d>",
|
||||||
|
ar.short_src, ar.linedefined);
|
||||||
|
}
|
||||||
|
lua_concat(L, lua_gettop(L));
|
||||||
|
}
|
||||||
|
lua_concat(L, lua_gettop(L));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Moved here from lib_getenum.
|
// Moved here from lib_getenum.
|
||||||
int LUA_PushGlobals(lua_State *L, const char *word)
|
int LUA_PushGlobals(lua_State *L, const char *word)
|
||||||
{
|
{
|
||||||
|
@ -115,7 +167,10 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
||||||
lua_pushboolean(L, splitscreen);
|
lua_pushboolean(L, splitscreen);
|
||||||
return 1;
|
return 1;
|
||||||
} else if (fastcmp(word,"gamecomplete")) {
|
} else if (fastcmp(word,"gamecomplete")) {
|
||||||
lua_pushboolean(L, gamecomplete);
|
lua_pushboolean(L, (gamecomplete != 0));
|
||||||
|
return 1;
|
||||||
|
} else if (fastcmp(word,"marathonmode")) {
|
||||||
|
lua_pushinteger(L, marathonmode);
|
||||||
return 1;
|
return 1;
|
||||||
} else if (fastcmp(word,"devparm")) {
|
} else if (fastcmp(word,"devparm")) {
|
||||||
lua_pushboolean(L, devparm);
|
lua_pushboolean(L, devparm);
|
||||||
|
@ -145,6 +200,9 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
||||||
} else if (fastcmp(word,"spstage_start")) {
|
} else if (fastcmp(word,"spstage_start")) {
|
||||||
lua_pushinteger(L, spstage_start);
|
lua_pushinteger(L, spstage_start);
|
||||||
return 1;
|
return 1;
|
||||||
|
} else if (fastcmp(word,"spmarathon_start")) {
|
||||||
|
lua_pushinteger(L, spmarathon_start);
|
||||||
|
return 1;
|
||||||
} else if (fastcmp(word,"sstage_start")) {
|
} else if (fastcmp(word,"sstage_start")) {
|
||||||
lua_pushinteger(L, sstage_start);
|
lua_pushinteger(L, sstage_start);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -395,11 +453,13 @@ void LUA_ClearExtVars(void)
|
||||||
// Use this variable to prevent certain functions from running
|
// Use this variable to prevent certain functions from running
|
||||||
// if they were not called on lump load
|
// if they were not called on lump load
|
||||||
// (i.e. they were called in hooks or coroutines etc)
|
// (i.e. they were called in hooks or coroutines etc)
|
||||||
boolean lua_lumploading = false;
|
INT32 lua_lumploading = 0;
|
||||||
|
|
||||||
// Load a script from a MYFILE
|
// Load a script from a MYFILE
|
||||||
static inline void LUA_LoadFile(MYFILE *f, char *name)
|
static inline void LUA_LoadFile(MYFILE *f, char *name, boolean noresults)
|
||||||
{
|
{
|
||||||
|
int errorhandlerindex;
|
||||||
|
|
||||||
if (!name)
|
if (!name)
|
||||||
name = wadfiles[f->wad]->filename;
|
name = wadfiles[f->wad]->filename;
|
||||||
CONS_Printf("Loading Lua script from %s\n", name);
|
CONS_Printf("Loading Lua script from %s\n", name);
|
||||||
|
@ -408,19 +468,22 @@ static inline void LUA_LoadFile(MYFILE *f, char *name)
|
||||||
lua_pushinteger(gL, f->wad);
|
lua_pushinteger(gL, f->wad);
|
||||||
lua_setfield(gL, LUA_REGISTRYINDEX, "WAD");
|
lua_setfield(gL, LUA_REGISTRYINDEX, "WAD");
|
||||||
|
|
||||||
lua_lumploading = true; // turn on loading flag
|
lua_lumploading++; // turn on loading flag
|
||||||
|
|
||||||
if (luaL_loadbuffer(gL, f->data, f->size, va("@%s",name)) || lua_pcall(gL, 0, 0, 0)) {
|
lua_pushcfunction(gL, LUA_GetErrorMessage);
|
||||||
|
errorhandlerindex = lua_gettop(gL);
|
||||||
|
if (luaL_loadbuffer(gL, f->data, f->size, va("@%s",name)) || lua_pcall(gL, 0, noresults ? 0 : LUA_MULTRET, lua_gettop(gL) - 1)) {
|
||||||
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
|
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
|
||||||
lua_pop(gL,1);
|
lua_pop(gL,1);
|
||||||
}
|
}
|
||||||
lua_gc(gL, LUA_GCCOLLECT, 0);
|
lua_gc(gL, LUA_GCCOLLECT, 0);
|
||||||
|
lua_remove(gL, errorhandlerindex);
|
||||||
|
|
||||||
lua_lumploading = false; // turn off again
|
lua_lumploading--; // turn off again
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load a script from a lump
|
// Load a script from a lump
|
||||||
void LUA_LoadLump(UINT16 wad, UINT16 lump)
|
void LUA_LoadLump(UINT16 wad, UINT16 lump, boolean noresults)
|
||||||
{
|
{
|
||||||
MYFILE f;
|
MYFILE f;
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -447,7 +510,7 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump)
|
||||||
name[len] = '\0';
|
name[len] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
LUA_LoadFile(&f, name); // actually load file!
|
LUA_LoadFile(&f, name, noresults); // actually load file!
|
||||||
|
|
||||||
free(name);
|
free(name);
|
||||||
Z_Free(f.data);
|
Z_Free(f.data);
|
||||||
|
@ -730,9 +793,13 @@ void LUA_InvalidatePlayer(player_t *player)
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
ARCH_NULL=0,
|
ARCH_NULL=0,
|
||||||
ARCH_BOOLEAN,
|
ARCH_TRUE,
|
||||||
ARCH_SIGNED,
|
ARCH_FALSE,
|
||||||
ARCH_STRING,
|
ARCH_INT8,
|
||||||
|
ARCH_INT16,
|
||||||
|
ARCH_INT32,
|
||||||
|
ARCH_SMALLSTRING,
|
||||||
|
ARCH_LARGESTRING,
|
||||||
ARCH_TABLE,
|
ARCH_TABLE,
|
||||||
|
|
||||||
ARCH_MOBJINFO,
|
ARCH_MOBJINFO,
|
||||||
|
@ -752,6 +819,7 @@ enum
|
||||||
ARCH_FFLOOR,
|
ARCH_FFLOOR,
|
||||||
ARCH_SLOPE,
|
ARCH_SLOPE,
|
||||||
ARCH_MAPHEADER,
|
ARCH_MAPHEADER,
|
||||||
|
ARCH_SKINCOLOR,
|
||||||
|
|
||||||
ARCH_TEND=0xFF,
|
ARCH_TEND=0xFF,
|
||||||
};
|
};
|
||||||
|
@ -777,6 +845,7 @@ static const struct {
|
||||||
{META_FFLOOR, ARCH_FFLOOR},
|
{META_FFLOOR, ARCH_FFLOOR},
|
||||||
{META_SLOPE, ARCH_SLOPE},
|
{META_SLOPE, ARCH_SLOPE},
|
||||||
{META_MAPHEADER, ARCH_MAPHEADER},
|
{META_MAPHEADER, ARCH_MAPHEADER},
|
||||||
|
{META_SKINCOLOR, ARCH_SKINCOLOR},
|
||||||
{NULL, ARCH_NULL}
|
{NULL, ARCH_NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -817,22 +886,33 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
||||||
WRITEUINT8(save_p, ARCH_NULL);
|
WRITEUINT8(save_p, ARCH_NULL);
|
||||||
return 2;
|
return 2;
|
||||||
case LUA_TBOOLEAN:
|
case LUA_TBOOLEAN:
|
||||||
WRITEUINT8(save_p, ARCH_BOOLEAN);
|
WRITEUINT8(save_p, lua_toboolean(gL, myindex) ? ARCH_TRUE : ARCH_FALSE);
|
||||||
WRITEUINT8(save_p, lua_toboolean(gL, myindex));
|
|
||||||
break;
|
break;
|
||||||
case LUA_TNUMBER:
|
case LUA_TNUMBER:
|
||||||
{
|
{
|
||||||
lua_Integer number = lua_tointeger(gL, myindex);
|
lua_Integer number = lua_tointeger(gL, myindex);
|
||||||
WRITEUINT8(save_p, ARCH_SIGNED);
|
if (number >= INT8_MIN && number <= INT8_MAX)
|
||||||
|
{
|
||||||
|
WRITEUINT8(save_p, ARCH_INT8);
|
||||||
|
WRITESINT8(save_p, number);
|
||||||
|
}
|
||||||
|
else if (number >= INT16_MIN && number <= INT16_MAX)
|
||||||
|
{
|
||||||
|
WRITEUINT8(save_p, ARCH_INT16);
|
||||||
|
WRITEINT16(save_p, number);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WRITEUINT8(save_p, ARCH_INT32);
|
||||||
WRITEFIXED(save_p, number);
|
WRITEFIXED(save_p, number);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LUA_TSTRING:
|
case LUA_TSTRING:
|
||||||
{
|
{
|
||||||
UINT16 len = (UINT16)lua_objlen(gL, myindex); // get length of string, including embedded zeros
|
UINT32 len = (UINT32)lua_objlen(gL, myindex); // get length of string, including embedded zeros
|
||||||
const char *s = lua_tostring(gL, myindex);
|
const char *s = lua_tostring(gL, myindex);
|
||||||
UINT16 i = 0;
|
UINT32 i = 0;
|
||||||
WRITEUINT8(save_p, ARCH_STRING);
|
|
||||||
// if you're wondering why we're writing a string to save_p this way,
|
// if you're wondering why we're writing a string to save_p this way,
|
||||||
// it turns out that Lua can have embedded zeros ('\0') in the strings,
|
// it turns out that Lua can have embedded zeros ('\0') in the strings,
|
||||||
// so we can't use WRITESTRING as that cuts off when it finds a '\0'.
|
// so we can't use WRITESTRING as that cuts off when it finds a '\0'.
|
||||||
|
@ -840,7 +920,16 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
||||||
// fixing the awful crashes previously encountered for reading strings longer than 1024
|
// fixing the awful crashes previously encountered for reading strings longer than 1024
|
||||||
// (yes I know that's kind of a stupid thing to care about, but it'd be evil to trim or ignore them?)
|
// (yes I know that's kind of a stupid thing to care about, but it'd be evil to trim or ignore them?)
|
||||||
// -- Monster Iestyn 05/08/18
|
// -- Monster Iestyn 05/08/18
|
||||||
WRITEUINT16(save_p, len); // save size of string
|
if (len < 255)
|
||||||
|
{
|
||||||
|
WRITEUINT8(save_p, ARCH_SMALLSTRING);
|
||||||
|
WRITEUINT8(save_p, len); // save size of string
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WRITEUINT8(save_p, ARCH_LARGESTRING);
|
||||||
|
WRITEUINT32(save_p, len); // save size of string
|
||||||
|
}
|
||||||
while (i < len)
|
while (i < len)
|
||||||
WRITECHAR(save_p, s[i++]); // write chars individually, including the embedded zeros
|
WRITECHAR(save_p, s[i++]); // write chars individually, including the embedded zeros
|
||||||
break;
|
break;
|
||||||
|
@ -1044,6 +1133,14 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ARCH_SKINCOLOR:
|
||||||
|
{
|
||||||
|
skincolor_t *info = *((skincolor_t **)lua_touserdata(gL, myindex));
|
||||||
|
WRITEUINT8(save_p, ARCH_SKINCOLOR);
|
||||||
|
WRITEUINT16(save_p, info - skincolors);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
WRITEUINT8(save_p, ARCH_NULL);
|
WRITEUINT8(save_p, ARCH_NULL);
|
||||||
return 2;
|
return 2;
|
||||||
|
@ -1170,21 +1267,36 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
|
||||||
case ARCH_NULL:
|
case ARCH_NULL:
|
||||||
lua_pushnil(gL);
|
lua_pushnil(gL);
|
||||||
break;
|
break;
|
||||||
case ARCH_BOOLEAN:
|
case ARCH_TRUE:
|
||||||
lua_pushboolean(gL, READUINT8(save_p));
|
lua_pushboolean(gL, true);
|
||||||
break;
|
break;
|
||||||
case ARCH_SIGNED:
|
case ARCH_FALSE:
|
||||||
|
lua_pushboolean(gL, false);
|
||||||
|
break;
|
||||||
|
case ARCH_INT8:
|
||||||
|
lua_pushinteger(gL, READSINT8(save_p));
|
||||||
|
break;
|
||||||
|
case ARCH_INT16:
|
||||||
|
lua_pushinteger(gL, READINT16(save_p));
|
||||||
|
break;
|
||||||
|
case ARCH_INT32:
|
||||||
lua_pushinteger(gL, READFIXED(save_p));
|
lua_pushinteger(gL, READFIXED(save_p));
|
||||||
break;
|
break;
|
||||||
case ARCH_STRING:
|
case ARCH_SMALLSTRING:
|
||||||
|
case ARCH_LARGESTRING:
|
||||||
{
|
{
|
||||||
UINT16 len = READUINT16(save_p); // length of string, including embedded zeros
|
UINT32 len;
|
||||||
char *value;
|
char *value;
|
||||||
UINT16 i = 0;
|
UINT32 i = 0;
|
||||||
|
|
||||||
// See my comments in the ArchiveValue function;
|
// See my comments in the ArchiveValue function;
|
||||||
// it's much the same for reading strings as writing them!
|
// it's much the same for reading strings as writing them!
|
||||||
// (i.e. we can't use READSTRING either)
|
// (i.e. we can't use READSTRING either)
|
||||||
// -- Monster Iestyn 05/08/18
|
// -- Monster Iestyn 05/08/18
|
||||||
|
if (type == ARCH_SMALLSTRING)
|
||||||
|
len = READUINT8(save_p); // length of string, including embedded zeros
|
||||||
|
else
|
||||||
|
len = READUINT32(save_p); // length of string, including embedded zeros
|
||||||
value = malloc(len); // make temp buffer of size len
|
value = malloc(len); // make temp buffer of size len
|
||||||
// now read the actual string
|
// now read the actual string
|
||||||
while (i < len)
|
while (i < len)
|
||||||
|
@ -1260,6 +1372,9 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
|
||||||
case ARCH_MAPHEADER:
|
case ARCH_MAPHEADER:
|
||||||
LUA_PushUserdata(gL, mapheaderinfo[READUINT16(save_p)], META_MAPHEADER);
|
LUA_PushUserdata(gL, mapheaderinfo[READUINT16(save_p)], META_MAPHEADER);
|
||||||
break;
|
break;
|
||||||
|
case ARCH_SKINCOLOR:
|
||||||
|
LUA_PushUserdata(gL, &skincolors[READUINT16(save_p)], META_SKINCOLOR);
|
||||||
|
break;
|
||||||
case ARCH_TEND:
|
case ARCH_TEND:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,9 +37,10 @@
|
||||||
void LUA_ClearExtVars(void);
|
void LUA_ClearExtVars(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern boolean lua_lumploading; // is LUA_LoadLump being called?
|
extern INT32 lua_lumploading; // is LUA_LoadLump being called?
|
||||||
|
|
||||||
void LUA_LoadLump(UINT16 wad, UINT16 lump);
|
int LUA_GetErrorMessage(lua_State *L);
|
||||||
|
void LUA_LoadLump(UINT16 wad, UINT16 lump, boolean noresults);
|
||||||
#ifdef LUA_ALLOW_BYTECODE
|
#ifdef LUA_ALLOW_BYTECODE
|
||||||
void LUA_DumpFile(const char *filename);
|
void LUA_DumpFile(const char *filename);
|
||||||
#endif
|
#endif
|
||||||
|
@ -99,5 +100,8 @@ void COM_Lua_f(void);
|
||||||
// uncomment if you want seg_t/node_t in Lua
|
// uncomment if you want seg_t/node_t in Lua
|
||||||
// #define HAVE_LUA_SEGS
|
// #define HAVE_LUA_SEGS
|
||||||
|
|
||||||
#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\
|
#define ISINLEVEL \
|
||||||
|
(gamestate == GS_LEVEL || titlemapinaction)
|
||||||
|
|
||||||
|
#define INLEVEL if (! ISINLEVEL)\
|
||||||
return luaL_error(L, "This can only be used in a level!");
|
return luaL_error(L, "This can only be used in a level!");
|
||||||
|
|
|
@ -490,30 +490,29 @@ const UINT8 gifframe_gchead[4] = {0x21,0xF9,0x04,0x04}; // GCE, bytes, packed by
|
||||||
static UINT8 *gifframe_data = NULL;
|
static UINT8 *gifframe_data = NULL;
|
||||||
static size_t gifframe_size = 8192;
|
static size_t gifframe_size = 8192;
|
||||||
|
|
||||||
|
//
|
||||||
|
// GIF_rgbconvert
|
||||||
|
// converts an RGB frame to a frame with a palette.
|
||||||
|
//
|
||||||
#ifdef HWRENDER
|
#ifdef HWRENDER
|
||||||
static void hwrconvert(void)
|
static void GIF_rgbconvert(UINT8 *linear, UINT8 *scr)
|
||||||
{
|
{
|
||||||
UINT8 *linear = HWR_GetScreenshot();
|
|
||||||
UINT8 *dest = screens[2];
|
|
||||||
UINT8 r, g, b;
|
UINT8 r, g, b;
|
||||||
INT32 x, y;
|
size_t src = 0, dest = 0;
|
||||||
size_t i = 0;
|
size_t size = (vid.width * vid.height * 3);
|
||||||
|
|
||||||
InitColorLUT(gif_framepalette);
|
InitColorLUT(gif_framepalette);
|
||||||
|
|
||||||
for (y = 0; y < vid.height; y++)
|
while (src < size)
|
||||||
{
|
{
|
||||||
for (x = 0; x < vid.width; x++, i += 3)
|
r = (UINT8)linear[src];
|
||||||
{
|
g = (UINT8)linear[src + 1];
|
||||||
r = (UINT8)linear[i];
|
b = (UINT8)linear[src + 2];
|
||||||
g = (UINT8)linear[i + 1];
|
scr[dest] = colorlookup[r >> SHIFTCOLORBITS][g >> SHIFTCOLORBITS][b >> SHIFTCOLORBITS];
|
||||||
b = (UINT8)linear[i + 2];
|
src += (3 * scrbuf_downscaleamt);
|
||||||
dest[(y * vid.width) + x] = colorlookup[r >> SHIFTCOLORBITS][g >> SHIFTCOLORBITS][b >> SHIFTCOLORBITS];
|
dest += scrbuf_downscaleamt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(linear);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -556,7 +555,11 @@ static void GIF_framewrite(void)
|
||||||
I_ReadScreen(movie_screen);
|
I_ReadScreen(movie_screen);
|
||||||
#ifdef HWRENDER
|
#ifdef HWRENDER
|
||||||
else if (rendermode == render_opengl)
|
else if (rendermode == render_opengl)
|
||||||
hwrconvert();
|
{
|
||||||
|
UINT8 *linear = HWR_GetScreenshot();
|
||||||
|
GIF_rgbconvert(linear, movie_screen);
|
||||||
|
free(linear);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -565,18 +568,20 @@ static void GIF_framewrite(void)
|
||||||
blitw = vid.width;
|
blitw = vid.width;
|
||||||
blith = vid.height;
|
blith = vid.height;
|
||||||
|
|
||||||
if (gif_frames == 0)
|
|
||||||
{
|
|
||||||
if (rendermode == render_soft)
|
|
||||||
I_ReadScreen(movie_screen);
|
|
||||||
#ifdef HWRENDER
|
#ifdef HWRENDER
|
||||||
else if (rendermode == render_opengl)
|
// Copy the current OpenGL frame into the base screen
|
||||||
|
if (rendermode == render_opengl)
|
||||||
{
|
{
|
||||||
hwrconvert();
|
UINT8 *linear = HWR_GetScreenshot();
|
||||||
VID_BlitLinearScreen(screens[2], screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
|
GIF_rgbconvert(linear, screens[0]);
|
||||||
|
free(linear);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
// Copy the first frame into the movie screen
|
||||||
|
// OpenGL already does the same above.
|
||||||
|
if (gif_frames == 0 && rendermode == render_soft)
|
||||||
|
I_ReadScreen(movie_screen);
|
||||||
|
|
||||||
movie_screen = screens[0];
|
movie_screen = screens[0];
|
||||||
}
|
}
|
||||||
|
|
|
@ -555,7 +555,8 @@ void Command_Teleport_f(void)
|
||||||
p->mo->flags2 &= ~MF2_OBJECTFLIP;
|
p->mo->flags2 &= ~MF2_OBJECTFLIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
localangle = p->mo->angle = p->drawangle = FixedAngle(mt->angle<<FRACBITS);
|
p->mo->angle = p->drawangle = FixedAngle(mt->angle<<FRACBITS);
|
||||||
|
P_SetPlayerAngle(p, p->mo->angle);
|
||||||
}
|
}
|
||||||
else // scan the thinkers to find starposts...
|
else // scan the thinkers to find starposts...
|
||||||
{
|
{
|
||||||
|
@ -619,7 +620,8 @@ void Command_Teleport_f(void)
|
||||||
p->mo->flags2 &= ~MF2_OBJECTFLIP;
|
p->mo->flags2 &= ~MF2_OBJECTFLIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
localangle = p->mo->angle = p->drawangle = mo2->angle;
|
p->mo->angle = p->drawangle = mo2->angle;
|
||||||
|
P_SetPlayerAngle(p, p->mo->angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
CONS_Printf(M_GetText("Teleporting to checkpoint %d, %d...\n"), starpostnum, starpostpath);
|
CONS_Printf(M_GetText("Teleporting to checkpoint %d, %d...\n"), starpostnum, starpostpath);
|
||||||
|
@ -673,7 +675,10 @@ void Command_Teleport_f(void)
|
||||||
|
|
||||||
i = COM_CheckParm("-ang");
|
i = COM_CheckParm("-ang");
|
||||||
if (i)
|
if (i)
|
||||||
localangle = p->drawangle = p->mo->angle = FixedAngle(atoi(COM_Argv(i + 1))<<FRACBITS);
|
{
|
||||||
|
p->drawangle = p->mo->angle = FixedAngle(atoi(COM_Argv(i + 1))<<FRACBITS);
|
||||||
|
P_SetPlayerAngle(p, p->mo->angle);
|
||||||
|
}
|
||||||
|
|
||||||
i = COM_CheckParm("-aim");
|
i = COM_CheckParm("-aim");
|
||||||
if (i)
|
if (i)
|
||||||
|
@ -978,7 +983,7 @@ static mobjflag2_t op_oldflags2 = 0;
|
||||||
static UINT32 op_oldeflags = 0;
|
static UINT32 op_oldeflags = 0;
|
||||||
static fixed_t op_oldmomx = 0, op_oldmomy = 0, op_oldmomz = 0, op_oldheight = 0;
|
static fixed_t op_oldmomx = 0, op_oldmomy = 0, op_oldmomz = 0, op_oldheight = 0;
|
||||||
static statenum_t op_oldstate = 0;
|
static statenum_t op_oldstate = 0;
|
||||||
static UINT8 op_oldcolor = 0;
|
static UINT16 op_oldcolor = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Static calculation / common output help
|
// Static calculation / common output help
|
||||||
|
@ -1032,8 +1037,8 @@ static boolean OP_HeightOkay(player_t *player, UINT8 ceiling)
|
||||||
if (ceiling)
|
if (ceiling)
|
||||||
{
|
{
|
||||||
// Truncate position to match where mapthing would be when spawned
|
// Truncate position to match where mapthing would be when spawned
|
||||||
// (this applies to every further P_GetZAt call as well)
|
// (this applies to every further P_GetSlopeZAt call as well)
|
||||||
fixed_t cheight = sec->c_slope ? P_GetZAt(sec->c_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->ceilingheight;
|
fixed_t cheight = P_GetSectorCeilingZAt(sec, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000);
|
||||||
|
|
||||||
if (((cheight - player->mo->z - player->mo->height)>>FRACBITS) >= (1 << (16-ZSHIFT)))
|
if (((cheight - player->mo->z - player->mo->height)>>FRACBITS) >= (1 << (16-ZSHIFT)))
|
||||||
{
|
{
|
||||||
|
@ -1044,7 +1049,7 @@ static boolean OP_HeightOkay(player_t *player, UINT8 ceiling)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->floorheight;
|
fixed_t fheight = P_GetSectorFloorZAt(sec, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000);
|
||||||
if (((player->mo->z - fheight)>>FRACBITS) >= (1 << (16-ZSHIFT)))
|
if (((player->mo->z - fheight)>>FRACBITS) >= (1 << (16-ZSHIFT)))
|
||||||
{
|
{
|
||||||
CONS_Printf(M_GetText("Sorry, you're too %s to place this object (max: %d %s).\n"), M_GetText("high"),
|
CONS_Printf(M_GetText("Sorry, you're too %s to place this object (max: %d %s).\n"), M_GetText("high"),
|
||||||
|
@ -1091,12 +1096,12 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c
|
||||||
mt->y = (INT16)(player->mo->y>>FRACBITS);
|
mt->y = (INT16)(player->mo->y>>FRACBITS);
|
||||||
if (ceiling)
|
if (ceiling)
|
||||||
{
|
{
|
||||||
fixed_t cheight = sec->c_slope ? P_GetZAt(sec->c_slope, mt->x << FRACBITS, mt->y << FRACBITS) : sec->ceilingheight;
|
fixed_t cheight = P_GetSectorCeilingZAt(sec, mt->x << FRACBITS, mt->y << FRACBITS);
|
||||||
mt->z = (UINT16)((cheight - player->mo->z - player->mo->height)>>FRACBITS);
|
mt->z = (UINT16)((cheight - player->mo->z - player->mo->height)>>FRACBITS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, mt->x << FRACBITS, mt->y << FRACBITS) : sec->floorheight;
|
fixed_t fheight = P_GetSectorFloorZAt(sec, mt->x << FRACBITS, mt->y << FRACBITS);
|
||||||
mt->z = (UINT16)((player->mo->z - fheight)>>FRACBITS);
|
mt->z = (UINT16)((player->mo->z - fheight)>>FRACBITS);
|
||||||
}
|
}
|
||||||
mt->angle = (INT16)(FixedInt(AngleFixed(player->mo->angle)));
|
mt->angle = (INT16)(FixedInt(AngleFixed(player->mo->angle)));
|
||||||
|
@ -1342,12 +1347,12 @@ void OP_ObjectplaceMovement(player_t *player)
|
||||||
|
|
||||||
if (!!(mobjinfo[op_currentthing].flags & MF_SPAWNCEILING) ^ !!(cv_opflags.value & MTF_OBJECTFLIP))
|
if (!!(mobjinfo[op_currentthing].flags & MF_SPAWNCEILING) ^ !!(cv_opflags.value & MTF_OBJECTFLIP))
|
||||||
{
|
{
|
||||||
fixed_t cheight = sec->c_slope ? P_GetZAt(sec->c_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->ceilingheight;
|
fixed_t cheight = P_GetSectorCeilingZAt(sec, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000);
|
||||||
op_displayflags = (UINT16)((cheight - player->mo->z - mobjinfo[op_currentthing].height)>>FRACBITS);
|
op_displayflags = (UINT16)((cheight - player->mo->z - mobjinfo[op_currentthing].height)>>FRACBITS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->floorheight;
|
fixed_t fheight = P_GetSectorFloorZAt(sec, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000);
|
||||||
op_displayflags = (UINT16)((player->mo->z - fheight)>>FRACBITS);
|
op_displayflags = (UINT16)((player->mo->z - fheight)>>FRACBITS);
|
||||||
}
|
}
|
||||||
op_displayflags <<= ZSHIFT;
|
op_displayflags <<= ZSHIFT;
|
||||||
|
|
|
@ -523,9 +523,9 @@ emblem_t *M_GetLevelEmblems(INT32 mapnum)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
skincolors_t M_GetEmblemColor(emblem_t *em)
|
skincolornum_t M_GetEmblemColor(emblem_t *em)
|
||||||
{
|
{
|
||||||
if (!em || em->color >= MAXSKINCOLORS)
|
if (!em || em->color >= numskincolors)
|
||||||
return SKINCOLOR_NONE;
|
return SKINCOLOR_NONE;
|
||||||
return em->color;
|
return em->color;
|
||||||
}
|
}
|
||||||
|
@ -549,9 +549,9 @@ const char *M_GetEmblemPatch(emblem_t *em, boolean big)
|
||||||
return pnamebuf;
|
return pnamebuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
skincolors_t M_GetExtraEmblemColor(extraemblem_t *em)
|
skincolornum_t M_GetExtraEmblemColor(extraemblem_t *em)
|
||||||
{
|
{
|
||||||
if (!em || em->color >= MAXSKINCOLORS)
|
if (!em || em->color >= numskincolors)
|
||||||
return SKINCOLOR_NONE;
|
return SKINCOLOR_NONE;
|
||||||
return em->color;
|
return em->color;
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,7 @@ typedef struct
|
||||||
INT16 tag; ///< Tag of emblem mapthing
|
INT16 tag; ///< Tag of emblem mapthing
|
||||||
INT16 level; ///< Level on which this emblem can be found.
|
INT16 level; ///< Level on which this emblem can be found.
|
||||||
UINT8 sprite; ///< emblem sprite to use, 0 - 25
|
UINT8 sprite; ///< emblem sprite to use, 0 - 25
|
||||||
UINT8 color; ///< skincolor to use
|
UINT16 color; ///< skincolor to use
|
||||||
INT32 var; ///< If needed, specifies information on the target amount to achieve (or target skin)
|
INT32 var; ///< If needed, specifies information on the target amount to achieve (or target skin)
|
||||||
char hint[110]; ///< Hint for emblem hints menu
|
char hint[110]; ///< Hint for emblem hints menu
|
||||||
UINT8 collected; ///< Do you have this emblem?
|
UINT8 collected; ///< Do you have this emblem?
|
||||||
|
@ -102,7 +102,7 @@ typedef struct
|
||||||
UINT8 conditionset; ///< Condition set that awards this emblem.
|
UINT8 conditionset; ///< Condition set that awards this emblem.
|
||||||
UINT8 showconditionset; ///< Condition set that shows this emblem.
|
UINT8 showconditionset; ///< Condition set that shows this emblem.
|
||||||
UINT8 sprite; ///< emblem sprite to use, 0 - 25
|
UINT8 sprite; ///< emblem sprite to use, 0 - 25
|
||||||
UINT8 color; ///< skincolor to use
|
UINT16 color; ///< skincolor to use
|
||||||
UINT8 collected; ///< Do you have this emblem?
|
UINT8 collected; ///< Do you have this emblem?
|
||||||
} extraemblem_t;
|
} extraemblem_t;
|
||||||
|
|
||||||
|
@ -172,9 +172,9 @@ INT32 M_CountEmblems(void);
|
||||||
|
|
||||||
// Emblem shit
|
// Emblem shit
|
||||||
emblem_t *M_GetLevelEmblems(INT32 mapnum);
|
emblem_t *M_GetLevelEmblems(INT32 mapnum);
|
||||||
skincolors_t M_GetEmblemColor(emblem_t *em);
|
skincolornum_t M_GetEmblemColor(emblem_t *em);
|
||||||
const char *M_GetEmblemPatch(emblem_t *em, boolean big);
|
const char *M_GetEmblemPatch(emblem_t *em, boolean big);
|
||||||
skincolors_t M_GetExtraEmblemColor(extraemblem_t *em);
|
skincolornum_t M_GetExtraEmblemColor(extraemblem_t *em);
|
||||||
const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big);
|
const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big);
|
||||||
|
|
||||||
// If you're looking to compare stats for unlocks or what not, use these
|
// If you're looking to compare stats for unlocks or what not, use these
|
||||||
|
|
|
@ -204,18 +204,6 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedDiv(fixed_t a, fixed_t b)
|
||||||
return FixedDiv2(a, b);
|
return FixedDiv2(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \brief The FixedRem function
|
|
||||||
|
|
||||||
\param x fixed_t number
|
|
||||||
\param y fixed_t number
|
|
||||||
|
|
||||||
\return remainder of dividing x by y
|
|
||||||
*/
|
|
||||||
FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedRem(fixed_t x, fixed_t y)
|
|
||||||
{
|
|
||||||
return x % y;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \brief The FixedSqrt function
|
/** \brief The FixedSqrt function
|
||||||
|
|
||||||
\param x fixed_t number
|
\param x fixed_t number
|
||||||
|
|
1098
src/m_menu.c
1098
src/m_menu.c
File diff suppressed because it is too large
Load Diff
34
src/m_menu.h
34
src/m_menu.h
|
@ -31,6 +31,9 @@
|
||||||
#define MENUBITS 6
|
#define MENUBITS 6
|
||||||
|
|
||||||
// Menu IDs sectioned by numeric places to signify hierarchy
|
// Menu IDs sectioned by numeric places to signify hierarchy
|
||||||
|
/**
|
||||||
|
* IF YOU MODIFY THIS, MODIFY MENUTYPES_LIST[] IN dehacked.c TO MATCH.
|
||||||
|
*/
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
MN_NONE,
|
MN_NONE,
|
||||||
|
@ -58,6 +61,8 @@ typedef enum
|
||||||
MN_SP_NIGHTS_REPLAY,
|
MN_SP_NIGHTS_REPLAY,
|
||||||
MN_SP_NIGHTS_GHOST,
|
MN_SP_NIGHTS_GHOST,
|
||||||
|
|
||||||
|
MN_SP_MARATHON,
|
||||||
|
|
||||||
// Multiplayer
|
// Multiplayer
|
||||||
MN_MP_MAIN,
|
MN_MP_MAIN,
|
||||||
MN_MP_SPLITSCREEN, // SplitServer
|
MN_MP_SPLITSCREEN, // SplitServer
|
||||||
|
@ -89,8 +94,6 @@ typedef enum
|
||||||
MN_OP_COLOR,
|
MN_OP_COLOR,
|
||||||
MN_OP_OPENGL,
|
MN_OP_OPENGL,
|
||||||
MN_OP_OPENGL_LIGHTING,
|
MN_OP_OPENGL_LIGHTING,
|
||||||
MN_OP_OPENGL_FOG,
|
|
||||||
MN_OP_OPENGL_COLOR,
|
|
||||||
|
|
||||||
MN_OP_SOUND,
|
MN_OP_SOUND,
|
||||||
|
|
||||||
|
@ -129,6 +132,9 @@ typedef enum
|
||||||
MN_SPECIAL,
|
MN_SPECIAL,
|
||||||
NUMMENUTYPES,
|
NUMMENUTYPES,
|
||||||
} menutype_t; // up to 63; MN_SPECIAL = 53
|
} menutype_t; // up to 63; MN_SPECIAL = 53
|
||||||
|
#define MTREE2(a,b) (a | (b<<MENUBITS))
|
||||||
|
#define MTREE3(a,b,c) MTREE2(a, MTREE2(b,c))
|
||||||
|
#define MTREE4(a,b,c,d) MTREE2(a, MTREE3(b,c,d))
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -349,11 +355,11 @@ typedef struct
|
||||||
// new character select
|
// new character select
|
||||||
char displayname[SKINNAMESIZE+1];
|
char displayname[SKINNAMESIZE+1];
|
||||||
SINT8 skinnum[2];
|
SINT8 skinnum[2];
|
||||||
UINT8 oppositecolor;
|
UINT16 oppositecolor;
|
||||||
char nametag[8];
|
char nametag[8];
|
||||||
patch_t *namepic;
|
patch_t *namepic;
|
||||||
UINT8 tagtextcolor;
|
UINT16 tagtextcolor;
|
||||||
UINT8 tagoutlinecolor;
|
UINT16 tagoutlinecolor;
|
||||||
} description_t;
|
} description_t;
|
||||||
|
|
||||||
// level select platter
|
// level select platter
|
||||||
|
@ -413,6 +419,7 @@ extern INT16 char_on, startchar;
|
||||||
|
|
||||||
#define MAXSAVEGAMES 31
|
#define MAXSAVEGAMES 31
|
||||||
#define NOSAVESLOT 0 //slot where Play Without Saving appears
|
#define NOSAVESLOT 0 //slot where Play Without Saving appears
|
||||||
|
#define MARATHONSLOT 420 // just has to be nonzero, but let's use one that'll show up as an obvious error if something goes wrong while not using our existing saves
|
||||||
|
|
||||||
#define BwehHehHe() S_StartSound(NULL, sfx_bewar1+M_RandomKey(4)) // Bweh heh he
|
#define BwehHehHe() S_StartSound(NULL, sfx_bewar1+M_RandomKey(4)) // Bweh heh he
|
||||||
|
|
||||||
|
@ -437,6 +444,23 @@ void Addons_option_Onchange(void);
|
||||||
// Moviemode menu updating
|
// Moviemode menu updating
|
||||||
void Moviemode_option_Onchange(void);
|
void Moviemode_option_Onchange(void);
|
||||||
|
|
||||||
|
// Player Setup menu colors linked list
|
||||||
|
typedef struct menucolor_s {
|
||||||
|
struct menucolor_s *next;
|
||||||
|
struct menucolor_s *prev;
|
||||||
|
UINT16 color;
|
||||||
|
} menucolor_t;
|
||||||
|
|
||||||
|
extern menucolor_t *menucolorhead, *menucolortail;
|
||||||
|
|
||||||
|
void M_AddMenuColor(UINT16 color);
|
||||||
|
void M_MoveColorBefore(UINT16 color, UINT16 targ);
|
||||||
|
void M_MoveColorAfter(UINT16 color, UINT16 targ);
|
||||||
|
UINT16 M_GetColorBefore(UINT16 color);
|
||||||
|
UINT16 M_GetColorAfter(UINT16 color);
|
||||||
|
void M_InitPlayerSetupColors(void);
|
||||||
|
void M_FreePlayerSetupColors(void);
|
||||||
|
|
||||||
// These defines make it a little easier to make menus
|
// These defines make it a little easier to make menus
|
||||||
#define DEFAULTMENUSTYLE(id, header, source, prev, x, y)\
|
#define DEFAULTMENUSTYLE(id, header, source, prev, x, y)\
|
||||||
{\
|
{\
|
||||||
|
|
38
src/m_misc.c
38
src/m_misc.c
|
@ -297,6 +297,44 @@ size_t FIL_ReadFileTag(char const *name, UINT8 **buffer, INT32 tag)
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Makes a copy of a text file with all newlines converted into LF newlines.
|
||||||
|
*
|
||||||
|
* \param textfilename The name of the source file
|
||||||
|
* \param binfilename The name of the destination file
|
||||||
|
*/
|
||||||
|
boolean FIL_ConvertTextFileToBinary(const char *textfilename, const char *binfilename)
|
||||||
|
{
|
||||||
|
FILE *textfile;
|
||||||
|
FILE *binfile;
|
||||||
|
UINT8 buffer[1024];
|
||||||
|
size_t count;
|
||||||
|
boolean success;
|
||||||
|
|
||||||
|
textfile = fopen(textfilename, "r");
|
||||||
|
if (!textfile)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
binfile = fopen(binfilename, "wb");
|
||||||
|
if (!binfile)
|
||||||
|
{
|
||||||
|
fclose(textfile);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
count = fread(buffer, 1, sizeof(buffer), textfile);
|
||||||
|
fwrite(buffer, 1, count, binfile);
|
||||||
|
} while (count);
|
||||||
|
|
||||||
|
success = !(ferror(textfile) || ferror(binfile));
|
||||||
|
|
||||||
|
fclose(textfile);
|
||||||
|
fclose(binfile);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
/** Check if the filename exists
|
/** Check if the filename exists
|
||||||
*
|
*
|
||||||
* \param name Filename to check.
|
* \param name Filename to check.
|
||||||
|
|
|
@ -48,6 +48,8 @@ boolean FIL_WriteFile(char const *name, const void *source, size_t length);
|
||||||
size_t FIL_ReadFileTag(char const *name, UINT8 **buffer, INT32 tag);
|
size_t FIL_ReadFileTag(char const *name, UINT8 **buffer, INT32 tag);
|
||||||
#define FIL_ReadFile(n, b) FIL_ReadFileTag(n, b, PU_STATIC)
|
#define FIL_ReadFile(n, b) FIL_ReadFileTag(n, b, PU_STATIC)
|
||||||
|
|
||||||
|
boolean FIL_ConvertTextFileToBinary(const char *textfilename, const char *binfilename);
|
||||||
|
|
||||||
boolean FIL_FileExists(const char *name);
|
boolean FIL_FileExists(const char *name);
|
||||||
boolean FIL_WriteFileOK(char const *name);
|
boolean FIL_WriteFileOK(char const *name);
|
||||||
boolean FIL_ReadFileOK(char const *name);
|
boolean FIL_ReadFileOK(char const *name);
|
||||||
|
|
|
@ -68,7 +68,7 @@ extern consvar_t cv_masterserver, cv_servername;
|
||||||
// < 0 to not connect (usually -1) (offline mode)
|
// < 0 to not connect (usually -1) (offline mode)
|
||||||
// == 0 to show all rooms, not a valid hosting room
|
// == 0 to show all rooms, not a valid hosting room
|
||||||
// anything else is whatever room the MS assigns to that number (online mode)
|
// anything else is whatever room the MS assigns to that number (online mode)
|
||||||
INT16 ms_RoomId;
|
extern INT16 ms_RoomId;
|
||||||
|
|
||||||
const char *GetMasterServerPort(void);
|
const char *GetMasterServerPort(void);
|
||||||
const char *GetMasterServerIP(void);
|
const char *GetMasterServerIP(void);
|
||||||
|
|
194
src/p_enemy.c
194
src/p_enemy.c
|
@ -312,6 +312,7 @@ void A_RolloutRock(mobj_t *actor);
|
||||||
void A_DragonbomberSpawn(mobj_t *actor);
|
void A_DragonbomberSpawn(mobj_t *actor);
|
||||||
void A_DragonWing(mobj_t *actor);
|
void A_DragonWing(mobj_t *actor);
|
||||||
void A_DragonSegment(mobj_t *actor);
|
void A_DragonSegment(mobj_t *actor);
|
||||||
|
void A_ChangeHeight(mobj_t *actor);
|
||||||
|
|
||||||
//for p_enemy.c
|
//for p_enemy.c
|
||||||
|
|
||||||
|
@ -2990,6 +2991,19 @@ void A_Boss1Laser(mobj_t *actor)
|
||||||
angle_t angle;
|
angle_t angle;
|
||||||
mobj_t *point;
|
mobj_t *point;
|
||||||
tic_t dur;
|
tic_t dur;
|
||||||
|
static const UINT8 LASERCOLORS[] =
|
||||||
|
{
|
||||||
|
SKINCOLOR_SUPERRED3,
|
||||||
|
SKINCOLOR_SUPERRED4,
|
||||||
|
SKINCOLOR_SUPERRED5,
|
||||||
|
SKINCOLOR_FLAME,
|
||||||
|
SKINCOLOR_RED,
|
||||||
|
SKINCOLOR_RED,
|
||||||
|
SKINCOLOR_FLAME,
|
||||||
|
SKINCOLOR_SUPERRED5,
|
||||||
|
SKINCOLOR_SUPERRED4,
|
||||||
|
SKINCOLOR_SUPERRED3,
|
||||||
|
};
|
||||||
|
|
||||||
if (LUA_CallAction("A_Boss1Laser", actor))
|
if (LUA_CallAction("A_Boss1Laser", actor))
|
||||||
return;
|
return;
|
||||||
|
@ -3064,7 +3078,7 @@ void A_Boss1Laser(mobj_t *actor)
|
||||||
point = P_SpawnMobj(x, y, z, locvar1);
|
point = P_SpawnMobj(x, y, z, locvar1);
|
||||||
P_SetTarget(&point->target, actor);
|
P_SetTarget(&point->target, actor);
|
||||||
point->angle = actor->angle;
|
point->angle = actor->angle;
|
||||||
speed = point->radius*2;
|
speed = point->radius;
|
||||||
point->momz = FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT), speed);
|
point->momz = FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT), speed);
|
||||||
point->momx = FixedMul(FINESINE(angle>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(point->angle>>ANGLETOFINESHIFT), speed));
|
point->momx = FixedMul(FINESINE(angle>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(point->angle>>ANGLETOFINESHIFT), speed));
|
||||||
point->momy = FixedMul(FINESINE(angle>>ANGLETOFINESHIFT), FixedMul(FINESINE(point->angle>>ANGLETOFINESHIFT), speed));
|
point->momy = FixedMul(FINESINE(angle>>ANGLETOFINESHIFT), FixedMul(FINESINE(point->angle>>ANGLETOFINESHIFT), speed));
|
||||||
|
@ -3073,23 +3087,69 @@ void A_Boss1Laser(mobj_t *actor)
|
||||||
{
|
{
|
||||||
mobj_t *mo = P_SpawnMobj(point->x, point->y, point->z, point->type);
|
mobj_t *mo = P_SpawnMobj(point->x, point->y, point->z, point->type);
|
||||||
mo->angle = point->angle;
|
mo->angle = point->angle;
|
||||||
|
mo->color = LASERCOLORS[((UINT8)(i + 3*dur) >> 2) % sizeof(LASERCOLORS)]; // codeing
|
||||||
P_UnsetThingPosition(mo);
|
P_UnsetThingPosition(mo);
|
||||||
mo->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY;
|
mo->flags = MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY;
|
||||||
P_SetThingPosition(mo);
|
P_SetThingPosition(mo);
|
||||||
|
|
||||||
|
if (dur & 1 && mo->info->missilestate)
|
||||||
|
{
|
||||||
|
P_SetMobjState(mo, mo->info->missilestate);
|
||||||
|
if (mo->info->meleestate)
|
||||||
|
{
|
||||||
|
mobj_t *mo2 = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_PARTICLE);
|
||||||
|
mo2->flags2 |= MF2_LINKDRAW;
|
||||||
|
P_SetTarget(&mo2->tracer, actor);
|
||||||
|
P_SetMobjState(mo2, mo->info->meleestate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dur == 1)
|
||||||
|
P_SpawnGhostMobj(mo);
|
||||||
|
|
||||||
x = point->x, y = point->y, z = point->z;
|
x = point->x, y = point->y, z = point->z;
|
||||||
if (P_RailThinker(point))
|
if (P_RailThinker(point))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
x += point->momx;
|
||||||
|
y += point->momy;
|
||||||
floorz = P_FloorzAtPos(x, y, z, mobjinfo[MT_EGGMOBILE_FIRE].height);
|
floorz = P_FloorzAtPos(x, y, z, mobjinfo[MT_EGGMOBILE_FIRE].height);
|
||||||
if (z - floorz < mobjinfo[MT_EGGMOBILE_FIRE].height>>1)
|
if (z - floorz < mobjinfo[MT_EGGMOBILE_FIRE].height>>1 && dur & 1)
|
||||||
{
|
{
|
||||||
point = P_SpawnMobj(x, y, floorz+1, MT_EGGMOBILE_FIRE);
|
point = P_SpawnMobj(x, y, floorz, MT_EGGMOBILE_FIRE);
|
||||||
|
point->angle = actor->angle;
|
||||||
|
point->destscale = actor->scale;
|
||||||
|
P_SetScale(point, point->destscale);
|
||||||
P_SetTarget(&point->target, actor);
|
P_SetTarget(&point->target, actor);
|
||||||
point->destscale = 3*FRACUNIT;
|
P_MobjCheckWater(point);
|
||||||
point->scalespeed = FRACUNIT>>2;
|
if (point->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))
|
||||||
point->fuse = TICRATE;
|
{
|
||||||
|
for (i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
UINT8 size = 3;
|
||||||
|
mobj_t *steam = P_SpawnMobj(x, y, point->watertop - size*mobjinfo[MT_DUST].height, MT_DUST);
|
||||||
|
P_SetScale(steam, size*actor->scale);
|
||||||
|
P_SetObjectMomZ(steam, FRACUNIT + 2*P_RandomFixed(), true);
|
||||||
|
P_InstaThrust(steam, FixedAngle(P_RandomKey(360)*FRACUNIT), 2*P_RandomFixed());
|
||||||
|
if (point->info->painsound)
|
||||||
|
S_StartSound(steam, point->info->painsound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fixed_t distx = P_ReturnThrustX(point, point->angle, point->radius);
|
||||||
|
fixed_t disty = P_ReturnThrustY(point, point->angle, point->radius);
|
||||||
|
if (P_TryMove(point, point->x + distx, point->y + disty, false) // prevents the sprite from clipping into the wall or dangling off ledges
|
||||||
|
&& P_TryMove(point, point->x - 2*distx, point->y - 2*disty, false)
|
||||||
|
&& P_TryMove(point, point->x + distx, point->y + disty, false))
|
||||||
|
{
|
||||||
|
if (point->info->seesound)
|
||||||
|
S_StartSound(point, point->info->seesound);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
P_RemoveMobj(point);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dur > 1)
|
if (dur > 1)
|
||||||
|
@ -5046,13 +5106,15 @@ void A_SignPlayer(mobj_t *actor)
|
||||||
INT32 locvar2 = var2;
|
INT32 locvar2 = var2;
|
||||||
skin_t *skin = NULL;
|
skin_t *skin = NULL;
|
||||||
mobj_t *ov;
|
mobj_t *ov;
|
||||||
UINT8 facecolor, signcolor = (UINT8)locvar2;
|
UINT16 facecolor, signcolor = 0;
|
||||||
UINT32 signframe = states[actor->info->raisestate].frame;
|
UINT32 signframe = states[actor->info->raisestate].frame;
|
||||||
|
|
||||||
|
facecolor = signcolor = (UINT16)locvar2;
|
||||||
|
|
||||||
if (LUA_CallAction("A_SignPlayer", actor))
|
if (LUA_CallAction("A_SignPlayer", actor))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (actor->tracer == NULL || locvar1 < -3 || locvar1 >= numskins || signcolor >= MAXTRANSLATIONS)
|
if (actor->tracer == NULL || locvar1 < -3 || locvar1 >= numskins || signcolor >= numskincolors)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// if no face overlay, spawn one
|
// if no face overlay, spawn one
|
||||||
|
@ -5080,12 +5142,10 @@ void A_SignPlayer(mobj_t *actor)
|
||||||
;
|
;
|
||||||
else if (!skin->sprites[SPR2_SIGN].numframes)
|
else if (!skin->sprites[SPR2_SIGN].numframes)
|
||||||
signcolor = facecolor;
|
signcolor = facecolor;
|
||||||
else if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor?
|
else if ((facecolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor?
|
||||||
signcolor = skin->prefoppositecolor;
|
signcolor = skin->prefoppositecolor;
|
||||||
else if (actor->target->player->skincolor) // Set the sign to be an appropriate background color for this player's skincolor.
|
else if (facecolor) // Set the sign to be an appropriate background color for this player's skincolor.
|
||||||
signcolor = Color_Opposite[actor->target->player->skincolor - 1][0];
|
signcolor = skincolors[facecolor].invcolor;
|
||||||
else
|
|
||||||
signcolor = SKINCOLOR_NONE;
|
|
||||||
}
|
}
|
||||||
else if (locvar1 != -3) // set to a defined skin
|
else if (locvar1 != -3) // set to a defined skin
|
||||||
{
|
{
|
||||||
|
@ -5121,7 +5181,7 @@ void A_SignPlayer(mobj_t *actor)
|
||||||
else if (skin->prefoppositecolor)
|
else if (skin->prefoppositecolor)
|
||||||
signcolor = skin->prefoppositecolor;
|
signcolor = skin->prefoppositecolor;
|
||||||
else if (facecolor)
|
else if (facecolor)
|
||||||
signcolor = Color_Opposite[facecolor - 1][0];
|
signcolor = skincolors[facecolor].invcolor;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skin)
|
if (skin)
|
||||||
|
@ -5149,22 +5209,12 @@ void A_SignPlayer(mobj_t *actor)
|
||||||
P_SetMobjState(ov, actor->info->meleestate); // S_EGGMANSIGN
|
P_SetMobjState(ov, actor->info->meleestate); // S_EGGMANSIGN
|
||||||
if (!signcolor)
|
if (!signcolor)
|
||||||
signcolor = SKINCOLOR_CARBON;
|
signcolor = SKINCOLOR_CARBON;
|
||||||
|
facecolor = signcolor;
|
||||||
}
|
}
|
||||||
|
|
||||||
actor->tracer->color = signcolor;
|
actor->tracer->color = signcolor;
|
||||||
/*
|
if (signcolor && signcolor < numskincolors)
|
||||||
If you're here from the comment above Color_Opposite,
|
signframe += (15 - skincolors[facecolor].invshade);
|
||||||
the following line is the one which is dependent on the
|
|
||||||
array being symmetrical. It gets the opposite of the
|
|
||||||
opposite of your desired colour just so it can get the
|
|
||||||
brightness frame for the End Sign. It's not a great
|
|
||||||
design choice, but it's constant time array access and
|
|
||||||
the idea that the colours should be OPPOSITES is kind
|
|
||||||
of in the name. If you have a better idea, feel free
|
|
||||||
to let me know. ~toast 2016/07/20
|
|
||||||
*/
|
|
||||||
if (signcolor && signcolor < MAXSKINCOLORS)
|
|
||||||
signframe += (15 - Color_Opposite[Color_Opposite[signcolor - 1][0] - 1][1]);
|
|
||||||
actor->tracer->frame = signframe;
|
actor->tracer->frame = signframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8744,10 +8794,10 @@ void A_ChangeColorRelative(mobj_t *actor)
|
||||||
{
|
{
|
||||||
// Have you ever seen anything so hideous?
|
// Have you ever seen anything so hideous?
|
||||||
if (actor->target)
|
if (actor->target)
|
||||||
actor->color = (UINT8)(actor->color + actor->target->color);
|
actor->color = (UINT16)(actor->color + actor->target->color);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
actor->color = (UINT8)(actor->color + locvar2);
|
actor->color = (UINT16)(actor->color + locvar2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function: A_ChangeColorAbsolute
|
// Function: A_ChangeColorAbsolute
|
||||||
|
@ -8771,7 +8821,7 @@ void A_ChangeColorAbsolute(mobj_t *actor)
|
||||||
actor->color = actor->target->color;
|
actor->color = actor->target->color;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
actor->color = (UINT8)locvar2;
|
actor->color = (UINT16)locvar2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function: A_Dye
|
// Function: A_Dye
|
||||||
|
@ -8788,11 +8838,9 @@ void A_Dye(mobj_t *actor)
|
||||||
|
|
||||||
mobj_t *target = ((locvar1 && actor->target) ? actor->target : actor);
|
mobj_t *target = ((locvar1 && actor->target) ? actor->target : actor);
|
||||||
UINT8 color = (UINT8)locvar2;
|
UINT8 color = (UINT8)locvar2;
|
||||||
#ifdef HAVE_BLUA
|
|
||||||
if (LUA_CallAction("A_Dye", actor))
|
if (LUA_CallAction("A_Dye", actor))
|
||||||
return;
|
return;
|
||||||
#endif
|
if (color >= numskincolors)
|
||||||
if (color >= MAXTRANSLATIONS)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!color)
|
if (!color)
|
||||||
|
@ -9649,6 +9697,9 @@ void A_SplitShot(mobj_t *actor)
|
||||||
if (LUA_CallAction("A_SplitShot", actor))
|
if (LUA_CallAction("A_SplitShot", actor))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!actor->target)
|
||||||
|
return;
|
||||||
|
|
||||||
A_FaceTarget(actor);
|
A_FaceTarget(actor);
|
||||||
{
|
{
|
||||||
const angle_t an = (actor->angle + ANGLE_90) >> ANGLETOFINESHIFT;
|
const angle_t an = (actor->angle + ANGLE_90) >> ANGLETOFINESHIFT;
|
||||||
|
@ -12642,8 +12693,8 @@ void A_Boss5FindWaypoint(mobj_t *actor)
|
||||||
else // locvar1 == 0
|
else // locvar1 == 0
|
||||||
{
|
{
|
||||||
fixed_t hackoffset = P_MobjFlip(actor)*56*FRACUNIT;
|
fixed_t hackoffset = P_MobjFlip(actor)*56*FRACUNIT;
|
||||||
INT32 numwaypoints = 0;
|
INT32 numfangwaypoints = 0;
|
||||||
mobj_t **waypoints;
|
mobj_t **fangwaypoints;
|
||||||
INT32 key;
|
INT32 key;
|
||||||
|
|
||||||
actor->z += hackoffset;
|
actor->z += hackoffset;
|
||||||
|
@ -12668,7 +12719,7 @@ void A_Boss5FindWaypoint(mobj_t *actor)
|
||||||
continue;
|
continue;
|
||||||
if (!P_CheckSight(actor, mapthings[i].mobj))
|
if (!P_CheckSight(actor, mapthings[i].mobj))
|
||||||
continue;
|
continue;
|
||||||
numwaypoints++;
|
numfangwaypoints++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// players also count as waypoints apparently
|
// players also count as waypoints apparently
|
||||||
|
@ -12690,11 +12741,11 @@ void A_Boss5FindWaypoint(mobj_t *actor)
|
||||||
continue;
|
continue;
|
||||||
if (!P_CheckSight(actor, players[i].mo))
|
if (!P_CheckSight(actor, players[i].mo))
|
||||||
continue;
|
continue;
|
||||||
numwaypoints++;
|
numfangwaypoints++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!numwaypoints)
|
if (!numfangwaypoints)
|
||||||
{
|
{
|
||||||
// restore z position
|
// restore z position
|
||||||
actor->z -= hackoffset;
|
actor->z -= hackoffset;
|
||||||
|
@ -12702,8 +12753,8 @@ void A_Boss5FindWaypoint(mobj_t *actor)
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate the table and reset count to zero
|
// allocate the table and reset count to zero
|
||||||
waypoints = Z_Calloc(sizeof(*waypoints)*numwaypoints, PU_STATIC, NULL);
|
fangwaypoints = Z_Calloc(sizeof(*waypoints)*numfangwaypoints, PU_STATIC, NULL);
|
||||||
numwaypoints = 0;
|
numfangwaypoints = 0;
|
||||||
|
|
||||||
// now find them again and add them to the table!
|
// now find them again and add them to the table!
|
||||||
for (i = 0; i < nummapthings; i++)
|
for (i = 0; i < nummapthings; i++)
|
||||||
|
@ -12728,7 +12779,7 @@ void A_Boss5FindWaypoint(mobj_t *actor)
|
||||||
}
|
}
|
||||||
if (!P_CheckSight(actor, mapthings[i].mobj))
|
if (!P_CheckSight(actor, mapthings[i].mobj))
|
||||||
continue;
|
continue;
|
||||||
waypoints[numwaypoints++] = mapthings[i].mobj;
|
fangwaypoints[numfangwaypoints++] = mapthings[i].mobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actor->extravalue2 > 1)
|
if (actor->extravalue2 > 1)
|
||||||
|
@ -12749,25 +12800,25 @@ void A_Boss5FindWaypoint(mobj_t *actor)
|
||||||
continue;
|
continue;
|
||||||
if (!P_CheckSight(actor, players[i].mo))
|
if (!P_CheckSight(actor, players[i].mo))
|
||||||
continue;
|
continue;
|
||||||
waypoints[numwaypoints++] = players[i].mo;
|
fangwaypoints[numfangwaypoints++] = players[i].mo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore z position
|
// restore z position
|
||||||
actor->z -= hackoffset;
|
actor->z -= hackoffset;
|
||||||
|
|
||||||
if (!numwaypoints)
|
if (!numfangwaypoints)
|
||||||
{
|
{
|
||||||
Z_Free(waypoints); // free table
|
Z_Free(fangwaypoints); // free table
|
||||||
goto nowaypoints; // ???
|
goto nowaypoints; // ???
|
||||||
}
|
}
|
||||||
|
|
||||||
key = P_RandomKey(numwaypoints);
|
key = P_RandomKey(numfangwaypoints);
|
||||||
|
|
||||||
P_SetTarget(&actor->tracer, waypoints[key]);
|
P_SetTarget(&actor->tracer, fangwaypoints[key]);
|
||||||
if (actor->tracer->type == MT_FANGWAYPOINT)
|
if (actor->tracer->type == MT_FANGWAYPOINT)
|
||||||
actor->tracer->reactiontime = numwaypoints/4; // Monster Iestyn: is this how it should be? I count center waypoints as waypoints unlike the original Lua script
|
actor->tracer->reactiontime = numfangwaypoints/4; // Monster Iestyn: is this how it should be? I count center waypoints as waypoints unlike the original Lua script
|
||||||
Z_Free(waypoints); // free table
|
Z_Free(fangwaypoints); // free table
|
||||||
}
|
}
|
||||||
|
|
||||||
// now face the tracer you just set!
|
// now face the tracer you just set!
|
||||||
|
@ -13311,8 +13362,9 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing)
|
||||||
P_ResetPlayer(player);
|
P_ResetPlayer(player);
|
||||||
A_PlayActiveSound(dustdevil);
|
A_PlayActiveSound(dustdevil);
|
||||||
}
|
}
|
||||||
|
player->powers[pw_carry] = CR_DUSTDEVIL;
|
||||||
player->powers[pw_nocontrol] = 2;
|
player->powers[pw_nocontrol] = 2;
|
||||||
player->drawangle += ANG20;
|
P_SetTarget(&thing->tracer, dustdevil);
|
||||||
P_SetPlayerMobjState(thing, S_PLAY_PAIN);
|
P_SetPlayerMobjState(thing, S_PLAY_PAIN);
|
||||||
|
|
||||||
if (dist > dragamount)
|
if (dist > dragamount)
|
||||||
|
@ -13332,7 +13384,9 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing)
|
||||||
P_ResetPlayer(player);
|
P_ResetPlayer(player);
|
||||||
thing->z = dustdevil->z + dustdevil->height;
|
thing->z = dustdevil->z + dustdevil->height;
|
||||||
thrust = 20 * FRACUNIT;
|
thrust = 20 * FRACUNIT;
|
||||||
|
player->powers[pw_carry] = CR_NONE;
|
||||||
player->powers[pw_nocontrol] = 0;
|
player->powers[pw_nocontrol] = 0;
|
||||||
|
P_SetTarget(&thing->tracer, NULL);
|
||||||
S_StartSound(thing, sfx_wdjump);
|
S_StartSound(thing, sfx_wdjump);
|
||||||
P_SetPlayerMobjState(thing, S_PLAY_FALL);
|
P_SetPlayerMobjState(thing, S_PLAY_FALL);
|
||||||
}
|
}
|
||||||
|
@ -14409,3 +14463,43 @@ void A_DragonSegment(mobj_t *actor)
|
||||||
actor->angle = hangle;
|
actor->angle = hangle;
|
||||||
P_TeleportMove(actor, target->x + xdist, target->y + ydist, target->z + zdist);
|
P_TeleportMove(actor, target->x + xdist, target->y + ydist, target->z + zdist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function: A_ChangeHeight
|
||||||
|
//
|
||||||
|
// Description: Changes the actor's height by var1
|
||||||
|
//
|
||||||
|
// var1 = height
|
||||||
|
// var2 =
|
||||||
|
// &1: height is absolute
|
||||||
|
// &2: scale with actor's scale
|
||||||
|
//
|
||||||
|
void A_ChangeHeight(mobj_t *actor)
|
||||||
|
{
|
||||||
|
INT32 locvar1 = var1;
|
||||||
|
INT32 locvar2 = var2;
|
||||||
|
fixed_t height = locvar1;
|
||||||
|
boolean reverse;
|
||||||
|
|
||||||
|
if (LUA_CallAction("A_ChangeHeight", actor))
|
||||||
|
return;
|
||||||
|
|
||||||
|
reverse = (actor->eflags & MFE_VERTICALFLIP) || (actor->flags2 & MF2_OBJECTFLIP);
|
||||||
|
|
||||||
|
if (locvar2 & 2)
|
||||||
|
height = FixedMul(height, actor->scale);
|
||||||
|
|
||||||
|
P_UnsetThingPosition(actor);
|
||||||
|
if (locvar2 & 1)
|
||||||
|
{
|
||||||
|
if (reverse)
|
||||||
|
actor->z += actor->height - locvar1;
|
||||||
|
actor->height = locvar1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (reverse)
|
||||||
|
actor->z -= locvar1;
|
||||||
|
actor->height += locvar1;
|
||||||
|
}
|
||||||
|
P_SetThingPosition(actor);
|
||||||
|
}
|
||||||
|
|
|
@ -696,10 +696,20 @@ void T_BounceCheese(bouncecheese_t *bouncer)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bouncer->speed >= 0) // move floor first to fix height desync and any bizarre bugs following that
|
||||||
|
{
|
||||||
|
T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->floorheight - 70*FRACUNIT,
|
||||||
|
false, false, -1); // move floor
|
||||||
|
T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->ceilingheight -
|
||||||
|
70*FRACUNIT, false, true, -1); // move ceiling
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->ceilingheight -
|
T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->ceilingheight -
|
||||||
70*FRACUNIT, false, true, -1); // move ceiling
|
70*FRACUNIT, false, true, -1); // move ceiling
|
||||||
T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->floorheight - 70*FRACUNIT,
|
T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->floorheight - 70*FRACUNIT,
|
||||||
false, false, -1); // move floor
|
false, false, -1); // move floor
|
||||||
|
}
|
||||||
|
|
||||||
bouncer->sector->floorspeed = -bouncer->speed/2;
|
bouncer->sector->floorspeed = -bouncer->speed/2;
|
||||||
bouncer->sector->ceilspeed = 42;
|
bouncer->sector->ceilspeed = 42;
|
||||||
|
@ -2231,9 +2241,9 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
|
||||||
{
|
{
|
||||||
mobj_t *spawned = NULL;
|
mobj_t *spawned = NULL;
|
||||||
if (*rover->t_slope)
|
if (*rover->t_slope)
|
||||||
topz = P_GetZAt(*rover->t_slope, a, b) - (spacing>>1);
|
topz = P_GetSlopeZAt(*rover->t_slope, a, b) - (spacing>>1);
|
||||||
if (*rover->b_slope)
|
if (*rover->b_slope)
|
||||||
bottomz = P_GetZAt(*rover->b_slope, a, b);
|
bottomz = P_GetSlopeZAt(*rover->b_slope, a, b);
|
||||||
|
|
||||||
for (c = topz; c > bottomz; c -= spacing)
|
for (c = topz; c > bottomz; c -= spacing)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1143,10 +1143,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
||||||
|
|
||||||
toucher->angle = special->angle;
|
toucher->angle = special->angle;
|
||||||
|
|
||||||
if (player == &players[consoleplayer])
|
P_SetPlayerAngle(player, toucher->angle);
|
||||||
localangle = toucher->angle;
|
|
||||||
else if (player == &players[secondarydisplayplayer])
|
|
||||||
localangle2 = toucher->angle;
|
|
||||||
|
|
||||||
P_ResetPlayer(player);
|
P_ResetPlayer(player);
|
||||||
|
|
||||||
|
@ -1564,10 +1561,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
||||||
|
|
||||||
#if 0 // camera redirection - deemed unnecessary
|
#if 0 // camera redirection - deemed unnecessary
|
||||||
toucher->angle = special->angle;
|
toucher->angle = special->angle;
|
||||||
if (player == &players[consoleplayer])
|
P_SetPlayerAngle(player, toucher->angle);
|
||||||
localangle = toucher->angle;
|
|
||||||
else if (player == &players[secondarydisplayplayer])
|
|
||||||
localangle2 = toucher->angle;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
S_StartSound(toucher, special->info->attacksound); // home run
|
S_StartSound(toucher, special->info->attacksound); // home run
|
||||||
|
|
|
@ -138,6 +138,10 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor);
|
||||||
void P_ResetPlayer(player_t *player);
|
void P_ResetPlayer(player_t *player);
|
||||||
boolean P_PlayerCanDamage(player_t *player, mobj_t *thing);
|
boolean P_PlayerCanDamage(player_t *player, mobj_t *thing);
|
||||||
boolean P_IsLocalPlayer(player_t *player);
|
boolean P_IsLocalPlayer(player_t *player);
|
||||||
|
void P_SetPlayerAngle(player_t *player, angle_t angle);
|
||||||
|
angle_t P_GetLocalAngle(player_t *player);
|
||||||
|
void P_SetLocalAngle(player_t *player, angle_t angle);
|
||||||
|
void P_ForceLocalAngle(player_t *player, angle_t angle);
|
||||||
|
|
||||||
boolean P_IsObjectInGoop(mobj_t *mo);
|
boolean P_IsObjectInGoop(mobj_t *mo);
|
||||||
boolean P_IsObjectOnGround(mobj_t *mo);
|
boolean P_IsObjectOnGround(mobj_t *mo);
|
||||||
|
|
215
src/p_map.c
215
src/p_map.c
|
@ -372,12 +372,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
||||||
object->angle = object->player->drawangle = spring->angle;
|
object->angle = object->player->drawangle = spring->angle;
|
||||||
|
|
||||||
if (!demoplayback || P_ControlStyle(object->player) == CS_LMAOGALOG)
|
if (!demoplayback || P_ControlStyle(object->player) == CS_LMAOGALOG)
|
||||||
{
|
P_SetPlayerAngle(object->player, spring->angle);
|
||||||
if (object->player == &players[consoleplayer])
|
|
||||||
localangle = spring->angle;
|
|
||||||
else if (object->player == &players[secondarydisplayplayer])
|
|
||||||
localangle2 = spring->angle;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object->player->pflags & PF_GLIDING)
|
if (object->player->pflags & PF_GLIDING)
|
||||||
|
@ -1310,12 +1305,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
||||||
thing->angle = tmthing->angle;
|
thing->angle = tmthing->angle;
|
||||||
|
|
||||||
if (!demoplayback || P_ControlStyle(thing->player) == CS_LMAOGALOG)
|
if (!demoplayback || P_ControlStyle(thing->player) == CS_LMAOGALOG)
|
||||||
{
|
P_SetPlayerAngle(thing->player, thing->angle);
|
||||||
if (thing->player == &players[consoleplayer])
|
|
||||||
localangle = thing->angle;
|
|
||||||
else if (thing->player == &players[secondarydisplayplayer])
|
|
||||||
localangle2 = thing->angle;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3202,102 +3192,83 @@ isblocking:
|
||||||
static boolean P_IsClimbingValid(player_t *player, angle_t angle)
|
static boolean P_IsClimbingValid(player_t *player, angle_t angle)
|
||||||
{
|
{
|
||||||
fixed_t platx, platy;
|
fixed_t platx, platy;
|
||||||
subsector_t *glidesector;
|
sector_t *glidesector;
|
||||||
fixed_t floorz, ceilingz;
|
fixed_t floorz, ceilingz;
|
||||||
|
mobj_t *mo = player->mo;
|
||||||
|
ffloor_t *rover;
|
||||||
|
|
||||||
platx = P_ReturnThrustX(player->mo, angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale));
|
platx = P_ReturnThrustX(mo, angle, mo->radius + FixedMul(8*FRACUNIT, mo->scale));
|
||||||
platy = P_ReturnThrustY(player->mo, angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale));
|
platy = P_ReturnThrustY(mo, angle, mo->radius + FixedMul(8*FRACUNIT, mo->scale));
|
||||||
|
|
||||||
glidesector = R_PointInSubsector(player->mo->x + platx, player->mo->y + platy);
|
glidesector = R_PointInSubsector(mo->x + platx, mo->y + platy)->sector;
|
||||||
|
|
||||||
floorz = glidesector->sector->f_slope ? P_GetZAt(glidesector->sector->f_slope, player->mo->x, player->mo->y) : glidesector->sector->floorheight;
|
floorz = P_GetSectorFloorZAt (glidesector, mo->x, mo->y);
|
||||||
ceilingz = glidesector->sector->c_slope ? P_GetZAt(glidesector->sector->c_slope, player->mo->x, player->mo->y) : glidesector->sector->ceilingheight;
|
ceilingz = P_GetSectorCeilingZAt(glidesector, mo->x, mo->y);
|
||||||
|
|
||||||
if (glidesector->sector != player->mo->subsector->sector)
|
if (glidesector != mo->subsector->sector)
|
||||||
{
|
{
|
||||||
boolean floorclimb = false;
|
boolean floorclimb = false;
|
||||||
fixed_t topheight, bottomheight;
|
fixed_t topheight, bottomheight;
|
||||||
|
|
||||||
if (glidesector->sector->ffloors)
|
for (rover = glidesector->ffloors; rover; rover = rover->next)
|
||||||
{
|
|
||||||
ffloor_t *rover;
|
|
||||||
for (rover = glidesector->sector->ffloors; rover; rover = rover->next)
|
|
||||||
{
|
{
|
||||||
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER))
|
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
topheight = *rover->topheight;
|
topheight = P_GetFFloorTopZAt (rover, mo->x, mo->y);
|
||||||
bottomheight = *rover->bottomheight;
|
bottomheight = P_GetFFloorBottomZAt(rover, mo->x, mo->y);
|
||||||
|
|
||||||
if (*rover->t_slope)
|
|
||||||
topheight = P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y);
|
|
||||||
if (*rover->b_slope)
|
|
||||||
bottomheight = P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y);
|
|
||||||
|
|
||||||
floorclimb = true;
|
floorclimb = true;
|
||||||
|
|
||||||
if (player->mo->eflags & MFE_VERTICALFLIP)
|
if (mo->eflags & MFE_VERTICALFLIP)
|
||||||
{
|
|
||||||
if ((topheight < player->mo->z + player->mo->height) && ((player->mo->z + player->mo->height + player->mo->momz) < topheight))
|
|
||||||
{
|
{
|
||||||
|
if ((topheight < mo->z + mo->height) && ((mo->z + mo->height + mo->momz) < topheight))
|
||||||
floorclimb = true;
|
floorclimb = true;
|
||||||
}
|
if (topheight < mo->z) // Waaaay below the ledge.
|
||||||
if (topheight < player->mo->z) // Waaaay below the ledge.
|
|
||||||
{
|
|
||||||
floorclimb = false;
|
floorclimb = false;
|
||||||
}
|
if (bottomheight > mo->z + mo->height - FixedMul(16*FRACUNIT,mo->scale))
|
||||||
if (bottomheight > player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale))
|
|
||||||
{
|
|
||||||
floorclimb = false;
|
floorclimb = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((bottomheight > player->mo->z) && ((player->mo->z - player->mo->momz) > bottomheight))
|
if ((bottomheight > mo->z) && ((mo->z - mo->momz) > bottomheight))
|
||||||
{
|
|
||||||
floorclimb = true;
|
floorclimb = true;
|
||||||
}
|
if (bottomheight > mo->z + mo->height) // Waaaay below the ledge.
|
||||||
if (bottomheight > player->mo->z + player->mo->height) // Waaaay below the ledge.
|
|
||||||
{
|
|
||||||
floorclimb = false;
|
floorclimb = false;
|
||||||
}
|
if (topheight < mo->z + FixedMul(16*FRACUNIT,mo->scale))
|
||||||
if (topheight < player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale))
|
|
||||||
{
|
|
||||||
floorclimb = false;
|
floorclimb = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (floorclimb)
|
if (floorclimb)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (player->mo->eflags & MFE_VERTICALFLIP)
|
if (mo->eflags & MFE_VERTICALFLIP)
|
||||||
{
|
{
|
||||||
if ((floorz <= player->mo->z + player->mo->height)
|
if ((floorz <= mo->z + mo->height)
|
||||||
&& ((player->mo->z + player->mo->height - player->mo->momz) <= floorz))
|
&& ((mo->z + mo->height - mo->momz) <= floorz))
|
||||||
floorclimb = true;
|
floorclimb = true;
|
||||||
|
|
||||||
if ((floorz > player->mo->z)
|
if ((floorz > mo->z)
|
||||||
&& glidesector->sector->floorpic == skyflatnum)
|
&& glidesector->floorpic == skyflatnum)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ((player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale) > ceilingz)
|
if ((mo->z + mo->height - FixedMul(16*FRACUNIT,mo->scale) > ceilingz)
|
||||||
|| (player->mo->z + player->mo->height <= floorz))
|
|| (mo->z + mo->height <= floorz))
|
||||||
floorclimb = true;
|
floorclimb = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((ceilingz >= player->mo->z)
|
if ((ceilingz >= mo->z)
|
||||||
&& ((player->mo->z - player->mo->momz) >= ceilingz))
|
&& ((mo->z - mo->momz) >= ceilingz))
|
||||||
floorclimb = true;
|
floorclimb = true;
|
||||||
|
|
||||||
if ((ceilingz < player->mo->z+player->mo->height)
|
if ((ceilingz < mo->z+mo->height)
|
||||||
&& glidesector->sector->ceilingpic == skyflatnum)
|
&& glidesector->ceilingpic == skyflatnum)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ((player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale) < floorz)
|
if ((mo->z + FixedMul(16*FRACUNIT,mo->scale) < floorz)
|
||||||
|| (player->mo->z >= ceilingz))
|
|| (mo->z >= ceilingz))
|
||||||
floorclimb = true;
|
floorclimb = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3310,73 +3281,43 @@ static boolean P_IsClimbingValid(player_t *player, angle_t angle)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
static boolean PTR_LineIsBlocking(line_t *li)
|
||||||
// PTR_SlideTraverse
|
|
||||||
//
|
|
||||||
static boolean PTR_SlideTraverse(intercept_t *in)
|
|
||||||
{
|
{
|
||||||
line_t *li;
|
|
||||||
|
|
||||||
I_Assert(in->isaline);
|
|
||||||
|
|
||||||
li = in->d.line;
|
|
||||||
|
|
||||||
// one-sided linedefs are always solid to sliding movement.
|
// one-sided linedefs are always solid to sliding movement.
|
||||||
// one-sided linedef
|
|
||||||
if (!li->backsector)
|
if (!li->backsector)
|
||||||
{
|
return !P_PointOnLineSide(slidemo->x, slidemo->y, li);
|
||||||
if (P_PointOnLineSide(slidemo->x, slidemo->y, li))
|
|
||||||
return true; // don't hit the back side
|
|
||||||
goto isblocking;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(slidemo->flags & MF_MISSILE))
|
if (!(slidemo->flags & MF_MISSILE))
|
||||||
{
|
{
|
||||||
if (li->flags & ML_IMPASSIBLE)
|
if (li->flags & ML_IMPASSIBLE)
|
||||||
goto isblocking;
|
return true;
|
||||||
|
|
||||||
if ((slidemo->flags & (MF_ENEMY|MF_BOSS)) && li->flags & ML_BLOCKMONSTERS)
|
if ((slidemo->flags & (MF_ENEMY|MF_BOSS)) && li->flags & ML_BLOCKMONSTERS)
|
||||||
goto isblocking;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set openrange, opentop, openbottom
|
// set openrange, opentop, openbottom
|
||||||
P_LineOpening(li, slidemo);
|
P_LineOpening(li, slidemo);
|
||||||
|
|
||||||
if (openrange < slidemo->height)
|
if (openrange < slidemo->height)
|
||||||
goto isblocking; // doesn't fit
|
return true; // doesn't fit
|
||||||
|
|
||||||
if (opentop - slidemo->z < slidemo->height)
|
if (opentop - slidemo->z < slidemo->height)
|
||||||
goto isblocking; // mobj is too high
|
return true; // mobj is too high
|
||||||
|
|
||||||
if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, slidemo->scale))
|
if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, slidemo->scale))
|
||||||
goto isblocking; // too big a step up
|
return true; // too big a step up
|
||||||
|
|
||||||
// this line doesn't block movement
|
return false;
|
||||||
return true;
|
|
||||||
|
|
||||||
// the line does block movement,
|
|
||||||
// see if it is closer than best so far
|
|
||||||
isblocking:
|
|
||||||
if (li->polyobj && slidemo->player)
|
|
||||||
{
|
|
||||||
if ((li->polyobj->lines[0]->backsector->flags & SF_TRIGGERSPECIAL_TOUCH) && !(li->polyobj->flags & POF_NOSPECIALS))
|
|
||||||
P_ProcessSpecialSector(slidemo->player, slidemo->subsector->sector, li->polyobj->lines[0]->backsector);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slidemo->player && (slidemo->player->pflags & PF_GLIDING || slidemo->player->climbing)
|
static void PTR_GlideClimbTraverse(line_t *li)
|
||||||
&& slidemo->player->charability == CA_GLIDEANDCLIMB)
|
|
||||||
{
|
{
|
||||||
line_t *checkline = li;
|
line_t *checkline = li;
|
||||||
sector_t *checksector;
|
|
||||||
ffloor_t *rover;
|
ffloor_t *rover;
|
||||||
fixed_t topheight, bottomheight;
|
fixed_t topheight, bottomheight;
|
||||||
boolean fofline = false;
|
boolean fofline = false;
|
||||||
INT32 side = P_PointOnLineSide(slidemo->x, slidemo->y, li);
|
sector_t *checksector = (li->backsector && !P_PointOnLineSide(slidemo->x, slidemo->y, li)) ? li->backsector : li->frontsector;
|
||||||
|
|
||||||
if (!side && li->backsector)
|
|
||||||
checksector = li->backsector;
|
|
||||||
else
|
|
||||||
checksector = li->frontsector;
|
|
||||||
|
|
||||||
if (checksector->ffloors)
|
if (checksector->ffloors)
|
||||||
{
|
{
|
||||||
|
@ -3385,13 +3326,8 @@ isblocking:
|
||||||
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP))
|
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
topheight = *rover->topheight;
|
topheight = P_GetFFloorTopZAt (rover, slidemo->x, slidemo->y);
|
||||||
bottomheight = *rover->bottomheight;
|
bottomheight = P_GetFFloorBottomZAt(rover, slidemo->x, slidemo->y);
|
||||||
|
|
||||||
if (*rover->t_slope)
|
|
||||||
topheight = P_GetZAt(*rover->t_slope, slidemo->x, slidemo->y);
|
|
||||||
if (*rover->b_slope)
|
|
||||||
bottomheight = P_GetZAt(*rover->b_slope, slidemo->x, slidemo->y);
|
|
||||||
|
|
||||||
if (topheight < slidemo->z)
|
if (topheight < slidemo->z)
|
||||||
continue;
|
continue;
|
||||||
|
@ -3433,12 +3369,7 @@ isblocking:
|
||||||
{
|
{
|
||||||
slidemo->angle = climbangle;
|
slidemo->angle = climbangle;
|
||||||
/*if (!demoplayback || P_ControlStyle(slidemo->player) == CS_LMAOGALOG)
|
/*if (!demoplayback || P_ControlStyle(slidemo->player) == CS_LMAOGALOG)
|
||||||
{
|
P_SetPlayerAngle(slidemo->player, slidemo->angle);*/
|
||||||
if (slidemo->player == &players[consoleplayer])
|
|
||||||
localangle = slidemo->angle;
|
|
||||||
else if (slidemo->player == &players[secondarydisplayplayer])
|
|
||||||
localangle2 = slidemo->angle;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (!slidemo->player->climbing)
|
if (!slidemo->player->climbing)
|
||||||
{
|
{
|
||||||
|
@ -3467,6 +3398,29 @@ isblocking:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean PTR_SlideTraverse(intercept_t *in)
|
||||||
|
{
|
||||||
|
line_t *li;
|
||||||
|
|
||||||
|
I_Assert(in->isaline);
|
||||||
|
|
||||||
|
li = in->d.line;
|
||||||
|
|
||||||
|
if (!PTR_LineIsBlocking(li))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// the line blocks movement,
|
||||||
|
// see if it is closer than best so far
|
||||||
|
if (li->polyobj && slidemo->player)
|
||||||
|
{
|
||||||
|
if ((li->polyobj->lines[0]->backsector->flags & SF_TRIGGERSPECIAL_TOUCH) && !(li->polyobj->flags & POF_NOSPECIALS))
|
||||||
|
P_ProcessSpecialSector(slidemo->player, slidemo->subsector->sector, li->polyobj->lines[0]->backsector);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slidemo->player && slidemo->player->charability == CA_GLIDEANDCLIMB
|
||||||
|
&& (slidemo->player->pflags & PF_GLIDING || slidemo->player->climbing))
|
||||||
|
PTR_GlideClimbTraverse(li);
|
||||||
|
|
||||||
if (in->frac < bestslidefrac && (!slidemo->player || !slidemo->player->climbing))
|
if (in->frac < bestslidefrac && (!slidemo->player || !slidemo->player->climbing))
|
||||||
{
|
{
|
||||||
secondslidefrac = bestslidefrac;
|
secondslidefrac = bestslidefrac;
|
||||||
|
@ -3596,9 +3550,7 @@ static void P_CheckLavaWall(mobj_t *mo, sector_t *sec)
|
||||||
if (rover->master->flags & ML_BLOCKMONSTERS)
|
if (rover->master->flags & ML_BLOCKMONSTERS)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
topheight = *rover->t_slope ?
|
topheight = P_GetFFloorTopZAt(rover, mo->x, mo->y);
|
||||||
P_GetZAt(*rover->t_slope, mo->x, mo->y) :
|
|
||||||
*rover->topheight;
|
|
||||||
|
|
||||||
if (mo->eflags & MFE_VERTICALFLIP)
|
if (mo->eflags & MFE_VERTICALFLIP)
|
||||||
{
|
{
|
||||||
|
@ -3611,9 +3563,7 @@ static void P_CheckLavaWall(mobj_t *mo, sector_t *sec)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bottomheight = *rover->b_slope ?
|
bottomheight = P_GetFFloorBottomZAt(rover, mo->x, mo->y);
|
||||||
P_GetZAt(*rover->b_slope, mo->x, mo->y) :
|
|
||||||
*rover->bottomheight;
|
|
||||||
|
|
||||||
if (mo->eflags & MFE_VERTICALFLIP)
|
if (mo->eflags & MFE_VERTICALFLIP)
|
||||||
{
|
{
|
||||||
|
@ -4199,11 +4149,8 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
|
||||||
|
|
||||||
topheight = *rover->topheight;
|
topheight = *rover->topheight;
|
||||||
bottomheight = *rover->bottomheight;
|
bottomheight = *rover->bottomheight;
|
||||||
|
//topheight = P_GetFFloorTopZAt (rover, thing->x, thing->y);
|
||||||
/*if (rover->t_slope)
|
//bottomheight = P_GetFFloorBottomZAt(rover, thing->x, thing->y);
|
||||||
topheight = P_GetZAt(rover->t_slope, thing->x, thing->y);
|
|
||||||
if (rover->b_slope)
|
|
||||||
bottomheight = P_GetZAt(rover->b_slope, thing->x, thing->y);*/
|
|
||||||
|
|
||||||
delta1 = thing->z - (bottomheight + topheight)/2;
|
delta1 = thing->z - (bottomheight + topheight)/2;
|
||||||
delta2 = thingtop - (bottomheight + topheight)/2;
|
delta2 = thingtop - (bottomheight + topheight)/2;
|
||||||
|
@ -4980,10 +4927,7 @@ void P_MapEnd(void)
|
||||||
fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
|
fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
|
||||||
{
|
{
|
||||||
sector_t *sec = R_PointInSubsector(x, y)->sector;
|
sector_t *sec = R_PointInSubsector(x, y)->sector;
|
||||||
fixed_t floorz = sec->floorheight;
|
fixed_t floorz = P_GetSectorFloorZAt(sec, x, y);
|
||||||
|
|
||||||
if (sec->f_slope)
|
|
||||||
floorz = P_GetZAt(sec->f_slope, x, y);
|
|
||||||
|
|
||||||
// Intercept the stupid 'fall through 3dfloors' bug Tails 03-17-2002
|
// Intercept the stupid 'fall through 3dfloors' bug Tails 03-17-2002
|
||||||
if (sec->ffloors)
|
if (sec->ffloors)
|
||||||
|
@ -5000,13 +4944,8 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
|
||||||
if ((!(rover->flags & FF_SOLID || rover->flags & FF_QUICKSAND) || (rover->flags & FF_SWIMMABLE)))
|
if ((!(rover->flags & FF_SOLID || rover->flags & FF_QUICKSAND) || (rover->flags & FF_SWIMMABLE)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
topheight = *rover->topheight;
|
topheight = P_GetFFloorTopZAt (rover, x, y);
|
||||||
bottomheight = *rover->bottomheight;
|
bottomheight = P_GetFFloorBottomZAt(rover, x, y);
|
||||||
|
|
||||||
if (*rover->t_slope)
|
|
||||||
topheight = P_GetZAt(*rover->t_slope, x, y);
|
|
||||||
if (*rover->b_slope)
|
|
||||||
bottomheight = P_GetZAt(*rover->b_slope, x, y);
|
|
||||||
|
|
||||||
if (rover->flags & FF_QUICKSAND)
|
if (rover->flags & FF_QUICKSAND)
|
||||||
{
|
{
|
||||||
|
|
|
@ -303,22 +303,16 @@ void P_CameraLineOpening(line_t *linedef)
|
||||||
// If you can see through it, why not move the camera through it too?
|
// If you can see through it, why not move the camera through it too?
|
||||||
if (front->camsec >= 0)
|
if (front->camsec >= 0)
|
||||||
{
|
{
|
||||||
frontfloor = sectors[front->camsec].floorheight;
|
// SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
|
||||||
frontceiling = sectors[front->camsec].ceilingheight;
|
frontfloor = P_GetSectorFloorZAt (§ors[front->camsec], camera.x, camera.y);
|
||||||
if (sectors[front->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
|
frontceiling = P_GetSectorCeilingZAt(§ors[front->camsec], camera.x, camera.y);
|
||||||
frontfloor = P_GetZAt(sectors[front->camsec].f_slope, camera.x, camera.y);
|
|
||||||
if (sectors[front->camsec].c_slope)
|
|
||||||
frontceiling = P_GetZAt(sectors[front->camsec].c_slope, camera.x, camera.y);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (front->heightsec >= 0)
|
else if (front->heightsec >= 0)
|
||||||
{
|
{
|
||||||
frontfloor = sectors[front->heightsec].floorheight;
|
// SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
|
||||||
frontceiling = sectors[front->heightsec].ceilingheight;
|
frontfloor = P_GetSectorFloorZAt (§ors[front->heightsec], camera.x, camera.y);
|
||||||
if (sectors[front->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
|
frontceiling = P_GetSectorCeilingZAt(§ors[front->heightsec], camera.x, camera.y);
|
||||||
frontfloor = P_GetZAt(sectors[front->heightsec].f_slope, camera.x, camera.y);
|
|
||||||
if (sectors[front->heightsec].c_slope)
|
|
||||||
frontceiling = P_GetZAt(sectors[front->heightsec].c_slope, camera.x, camera.y);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -327,21 +321,15 @@ void P_CameraLineOpening(line_t *linedef)
|
||||||
}
|
}
|
||||||
if (back->camsec >= 0)
|
if (back->camsec >= 0)
|
||||||
{
|
{
|
||||||
backfloor = sectors[back->camsec].floorheight;
|
// SRB2CBTODO: ESLOPE (sectors[back->heightsec].f_slope)
|
||||||
backceiling = sectors[back->camsec].ceilingheight;
|
backfloor = P_GetSectorFloorZAt (§ors[back->camsec], camera.x, camera.y);
|
||||||
if (sectors[back->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
|
backceiling = P_GetSectorCeilingZAt(§ors[back->camsec], camera.x, camera.y);
|
||||||
frontfloor = P_GetZAt(sectors[back->camsec].f_slope, camera.x, camera.y);
|
|
||||||
if (sectors[back->camsec].c_slope)
|
|
||||||
frontceiling = P_GetZAt(sectors[back->camsec].c_slope, camera.x, camera.y);
|
|
||||||
}
|
}
|
||||||
else if (back->heightsec >= 0)
|
else if (back->heightsec >= 0)
|
||||||
{
|
{
|
||||||
backfloor = sectors[back->heightsec].floorheight;
|
// SRB2CBTODO: ESLOPE (sectors[back->heightsec].f_slope)
|
||||||
backceiling = sectors[back->heightsec].ceilingheight;
|
backfloor = P_GetSectorFloorZAt (§ors[back->heightsec], camera.x, camera.y);
|
||||||
if (sectors[back->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
|
backceiling = P_GetSectorCeilingZAt(§ors[back->heightsec], camera.x, camera.y);
|
||||||
frontfloor = P_GetZAt(sectors[back->heightsec].f_slope, camera.x, camera.y);
|
|
||||||
if (sectors[back->heightsec].c_slope)
|
|
||||||
frontceiling = P_GetZAt(sectors[back->heightsec].c_slope, camera.x, camera.y);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
576
src/p_mobj.c
576
src/p_mobj.c
|
@ -436,7 +436,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
|
||||||
|
|
||||||
mobj->sprite2 = spr2;
|
mobj->sprite2 = spr2;
|
||||||
mobj->frame = frame|(st->frame&~FF_FRAMEMASK);
|
mobj->frame = frame|(st->frame&~FF_FRAMEMASK);
|
||||||
if (mobj->color >= MAXSKINCOLORS && mobj->color < MAXTRANSLATIONS) // Super colours? Super bright!
|
if (mobj->color >= FIRSTSUPERCOLOR && mobj->color < numskincolors) // Super colours? Super bright!
|
||||||
mobj->frame |= FF_FULLBRIGHT;
|
mobj->frame |= FF_FULLBRIGHT;
|
||||||
}
|
}
|
||||||
// Regular sprites
|
// Regular sprites
|
||||||
|
@ -926,13 +926,8 @@ boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover)
|
||||||
|| ((rover->flags & FF_BLOCKOTHERS) && !mobj->player)))
|
|| ((rover->flags & FF_BLOCKOTHERS) && !mobj->player)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
topheight = *rover->topheight;
|
topheight = P_GetFFloorTopZAt (rover, mobj->x, mobj->y);
|
||||||
bottomheight = *rover->bottomheight;
|
bottomheight = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y);
|
||||||
|
|
||||||
if (*rover->t_slope)
|
|
||||||
topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y);
|
|
||||||
if (*rover->b_slope)
|
|
||||||
bottomheight = P_GetZAt(*rover->b_slope, mobj->x, mobj->y);
|
|
||||||
|
|
||||||
if (mobj->z > topheight)
|
if (mobj->z > topheight)
|
||||||
return false;
|
return false;
|
||||||
|
@ -963,12 +958,12 @@ static fixed_t HighestOnLine(fixed_t radius, fixed_t x, fixed_t y, line_t *line,
|
||||||
/*CONS_Printf("BEFORE: v1 = %f %f %f\n",
|
/*CONS_Printf("BEFORE: v1 = %f %f %f\n",
|
||||||
FIXED_TO_FLOAT(v1.x),
|
FIXED_TO_FLOAT(v1.x),
|
||||||
FIXED_TO_FLOAT(v1.y),
|
FIXED_TO_FLOAT(v1.y),
|
||||||
FIXED_TO_FLOAT(P_GetZAt(slope, v1.x, v1.y))
|
FIXED_TO_FLOAT(P_GetSlopeZAt(slope, v1.x, v1.y))
|
||||||
);
|
);
|
||||||
CONS_Printf(" v2 = %f %f %f\n",
|
CONS_Printf(" v2 = %f %f %f\n",
|
||||||
FIXED_TO_FLOAT(v2.x),
|
FIXED_TO_FLOAT(v2.x),
|
||||||
FIXED_TO_FLOAT(v2.y),
|
FIXED_TO_FLOAT(v2.y),
|
||||||
FIXED_TO_FLOAT(P_GetZAt(slope, v2.x, v2.y))
|
FIXED_TO_FLOAT(P_GetSlopeZAt(slope, v2.x, v2.y))
|
||||||
);*/
|
);*/
|
||||||
|
|
||||||
if (abs(v1.x-x) > radius) {
|
if (abs(v1.x-x) > radius) {
|
||||||
|
@ -1026,24 +1021,24 @@ static fixed_t HighestOnLine(fixed_t radius, fixed_t x, fixed_t y, line_t *line,
|
||||||
/*CONS_Printf("AFTER: v1 = %f %f %f\n",
|
/*CONS_Printf("AFTER: v1 = %f %f %f\n",
|
||||||
FIXED_TO_FLOAT(v1.x),
|
FIXED_TO_FLOAT(v1.x),
|
||||||
FIXED_TO_FLOAT(v1.y),
|
FIXED_TO_FLOAT(v1.y),
|
||||||
FIXED_TO_FLOAT(P_GetZAt(slope, v1.x, v1.y))
|
FIXED_TO_FLOAT(P_GetSlopeZAt(slope, v1.x, v1.y))
|
||||||
);
|
);
|
||||||
CONS_Printf(" v2 = %f %f %f\n",
|
CONS_Printf(" v2 = %f %f %f\n",
|
||||||
FIXED_TO_FLOAT(v2.x),
|
FIXED_TO_FLOAT(v2.x),
|
||||||
FIXED_TO_FLOAT(v2.y),
|
FIXED_TO_FLOAT(v2.y),
|
||||||
FIXED_TO_FLOAT(P_GetZAt(slope, v2.x, v2.y))
|
FIXED_TO_FLOAT(P_GetSlopeZAt(slope, v2.x, v2.y))
|
||||||
);*/
|
);*/
|
||||||
|
|
||||||
// Return the higher of the two points
|
// Return the higher of the two points
|
||||||
if (actuallylowest)
|
if (actuallylowest)
|
||||||
return min(
|
return min(
|
||||||
P_GetZAt(slope, v1.x, v1.y),
|
P_GetSlopeZAt(slope, v1.x, v1.y),
|
||||||
P_GetZAt(slope, v2.x, v2.y)
|
P_GetSlopeZAt(slope, v2.x, v2.y)
|
||||||
);
|
);
|
||||||
else
|
else
|
||||||
return max(
|
return max(
|
||||||
P_GetZAt(slope, v1.x, v1.y),
|
P_GetSlopeZAt(slope, v1.x, v1.y),
|
||||||
P_GetZAt(slope, v2.x, v2.y)
|
P_GetSlopeZAt(slope, v2.x, v2.y)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1077,7 +1072,7 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t
|
||||||
|
|
||||||
// If the highest point is in the sector, then we have it easy! Just get the Z at that point
|
// If the highest point is in the sector, then we have it easy! Just get the Z at that point
|
||||||
if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector))
|
if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector))
|
||||||
return P_GetZAt(slope, testx, testy);
|
return P_GetSlopeZAt(slope, testx, testy);
|
||||||
|
|
||||||
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
|
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
|
||||||
if (perfect) {
|
if (perfect) {
|
||||||
|
@ -1117,7 +1112,7 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t
|
||||||
// If we're just testing for base sector location (no collision line), just go for the center's spot...
|
// If we're just testing for base sector location (no collision line), just go for the center's spot...
|
||||||
// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
|
// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
|
||||||
if (line == NULL)
|
if (line == NULL)
|
||||||
return P_GetZAt(slope, x, y);
|
return P_GetSlopeZAt(slope, x, y);
|
||||||
|
|
||||||
return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
|
return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
|
||||||
} else // Well, that makes it easy. Just get the floor height
|
} else // Well, that makes it easy. Just get the floor height
|
||||||
|
@ -1154,7 +1149,7 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed
|
||||||
|
|
||||||
// If the highest point is in the sector, then we have it easy! Just get the Z at that point
|
// If the highest point is in the sector, then we have it easy! Just get the Z at that point
|
||||||
if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector))
|
if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector))
|
||||||
return P_GetZAt(slope, testx, testy);
|
return P_GetSlopeZAt(slope, testx, testy);
|
||||||
|
|
||||||
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
|
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
|
||||||
if (perfect) {
|
if (perfect) {
|
||||||
|
@ -1194,7 +1189,7 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed
|
||||||
// If we're just testing for base sector location (no collision line), just go for the center's spot...
|
// If we're just testing for base sector location (no collision line), just go for the center's spot...
|
||||||
// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
|
// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
|
||||||
if (line == NULL)
|
if (line == NULL)
|
||||||
return P_GetZAt(slope, x, y);
|
return P_GetSlopeZAt(slope, x, y);
|
||||||
|
|
||||||
return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
|
return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
|
||||||
} else // Well, that makes it easy. Just get the ceiling height
|
} else // Well, that makes it easy. Just get the ceiling height
|
||||||
|
@ -1232,7 +1227,7 @@ fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fix
|
||||||
|
|
||||||
// If the highest point is in the sector, then we have it easy! Just get the Z at that point
|
// If the highest point is in the sector, then we have it easy! Just get the Z at that point
|
||||||
if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector))
|
if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector))
|
||||||
return P_GetZAt(slope, testx, testy);
|
return P_GetSlopeZAt(slope, testx, testy);
|
||||||
|
|
||||||
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
|
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
|
||||||
if (perfect) {
|
if (perfect) {
|
||||||
|
@ -1272,7 +1267,7 @@ fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fix
|
||||||
// If we're just testing for base sector location (no collision line), just go for the center's spot...
|
// If we're just testing for base sector location (no collision line), just go for the center's spot...
|
||||||
// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
|
// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
|
||||||
if (line == NULL)
|
if (line == NULL)
|
||||||
return P_GetZAt(slope, x, y);
|
return P_GetSlopeZAt(slope, x, y);
|
||||||
|
|
||||||
return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
|
return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
|
||||||
} else // Well, that makes it easy. Just get the floor height
|
} else // Well, that makes it easy. Just get the floor height
|
||||||
|
@ -1309,7 +1304,7 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f
|
||||||
|
|
||||||
// If the highest point is in the sector, then we have it easy! Just get the Z at that point
|
// If the highest point is in the sector, then we have it easy! Just get the Z at that point
|
||||||
if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector))
|
if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector))
|
||||||
return P_GetZAt(slope, testx, testy);
|
return P_GetSlopeZAt(slope, testx, testy);
|
||||||
|
|
||||||
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
|
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
|
||||||
if (perfect) {
|
if (perfect) {
|
||||||
|
@ -1349,7 +1344,7 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f
|
||||||
// If we're just testing for base sector location (no collision line), just go for the center's spot...
|
// If we're just testing for base sector location (no collision line), just go for the center's spot...
|
||||||
// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
|
// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
|
||||||
if (line == NULL)
|
if (line == NULL)
|
||||||
return P_GetZAt(slope, x, y);
|
return P_GetSlopeZAt(slope, x, y);
|
||||||
|
|
||||||
return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
|
return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
|
||||||
} else // Well, that makes it easy. Just get the ceiling height
|
} else // Well, that makes it easy. Just get the ceiling height
|
||||||
|
@ -1673,28 +1668,34 @@ static void P_PushableCheckBustables(mobj_t *mo)
|
||||||
P_SetThingPosition(mo);
|
P_SetThingPosition(mo);
|
||||||
|
|
||||||
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
|
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
|
||||||
{
|
|
||||||
if (!node->m_sector)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (node->m_sector->ffloors)
|
|
||||||
{
|
{
|
||||||
ffloor_t *rover;
|
ffloor_t *rover;
|
||||||
fixed_t topheight, bottomheight;
|
fixed_t topheight, bottomheight;
|
||||||
|
|
||||||
|
if (!node->m_sector)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!node->m_sector->ffloors)
|
||||||
|
continue;
|
||||||
|
|
||||||
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
|
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
|
||||||
{
|
{
|
||||||
if (!(rover->flags & FF_EXISTS)) continue;
|
if (!(rover->flags & FF_EXISTS))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!(rover->flags & FF_BUSTUP)) continue;
|
if (!(rover->flags & FF_BUSTUP))
|
||||||
|
continue;
|
||||||
|
|
||||||
// Needs ML_EFFECT4 flag for pushables to break it
|
// Needs ML_EFFECT4 flag for pushables to break it
|
||||||
if (!(rover->master->flags & ML_EFFECT4)) continue;
|
if (!(rover->master->flags & ML_EFFECT4))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (rover->master->frontsector->crumblestate != CRUMBLE_NONE)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (rover->master->frontsector->crumblestate == CRUMBLE_NONE)
|
|
||||||
{
|
|
||||||
topheight = P_GetFOFTopZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
|
topheight = P_GetFOFTopZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
|
||||||
bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
|
bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
|
||||||
|
|
||||||
// Height checks
|
// Height checks
|
||||||
if (rover->flags & FF_SHATTERBOTTOM)
|
if (rover->flags & FF_SHATTERBOTTOM)
|
||||||
{
|
{
|
||||||
|
@ -1738,8 +1739,6 @@ static void P_PushableCheckBustables(mobj_t *mo)
|
||||||
goto bustupdone;
|
goto bustupdone;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
bustupdone:
|
bustupdone:
|
||||||
P_UnsetThingPosition(mo);
|
P_UnsetThingPosition(mo);
|
||||||
mo->x = oldx;
|
mo->x = oldx;
|
||||||
|
@ -1772,7 +1771,7 @@ void P_XYMovement(mobj_t *mo)
|
||||||
fixed_t oldx, oldy; // reducing bobbing/momentum on ice when up against walls
|
fixed_t oldx, oldy; // reducing bobbing/momentum on ice when up against walls
|
||||||
boolean moved;
|
boolean moved;
|
||||||
pslope_t *oldslope = NULL;
|
pslope_t *oldslope = NULL;
|
||||||
vector3_t slopemom;
|
vector3_t slopemom = {0,0,0};
|
||||||
fixed_t predictedz = 0;
|
fixed_t predictedz = 0;
|
||||||
|
|
||||||
I_Assert(mo != NULL);
|
I_Assert(mo != NULL);
|
||||||
|
@ -2798,6 +2797,94 @@ static boolean P_ZMovement(mobj_t *mo)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for "Mario" blocks to hit and bounce them
|
||||||
|
static void P_CheckMarioBlocks(mobj_t *mo)
|
||||||
|
{
|
||||||
|
msecnode_t *node;
|
||||||
|
|
||||||
|
if (netgame && mo->player->spectator)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
|
||||||
|
{
|
||||||
|
ffloor_t *rover;
|
||||||
|
|
||||||
|
if (!node->m_sector->ffloors)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
|
||||||
|
{
|
||||||
|
if (!(rover->flags & FF_EXISTS))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(rover->flags & FF_MARIO))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (mo->eflags & MFE_VERTICALFLIP)
|
||||||
|
continue; // if you were flipped, your head isn't actually hitting your ceilingz is it?
|
||||||
|
|
||||||
|
if (*rover->bottomheight != mo->ceilingz)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (rover->flags & FF_SHATTERBOTTOM) // Brick block!
|
||||||
|
EV_CrumbleChain(node->m_sector, rover);
|
||||||
|
else // Question block!
|
||||||
|
EV_MarioBlock(rover, node->m_sector, mo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we're on a polyobject that triggers a linedef executor.
|
||||||
|
static boolean P_PlayerPolyObjectZMovement(mobj_t *mo)
|
||||||
|
{
|
||||||
|
msecnode_t *node;
|
||||||
|
boolean stopmovecut = false;
|
||||||
|
|
||||||
|
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
|
||||||
|
{
|
||||||
|
sector_t *sec = node->m_sector;
|
||||||
|
subsector_t *newsubsec;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < numsubsectors; i++)
|
||||||
|
{
|
||||||
|
polyobj_t *po;
|
||||||
|
sector_t *polysec;
|
||||||
|
newsubsec = &subsectors[i];
|
||||||
|
|
||||||
|
if (newsubsec->sector != sec)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (po = newsubsec->polyList; po; po = (polyobj_t *)(po->link.next))
|
||||||
|
{
|
||||||
|
if (!(po->flags & POF_SOLID))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!P_MobjInsidePolyobj(po, mo))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
polysec = po->lines[0]->backsector;
|
||||||
|
|
||||||
|
// Moving polyobjects should act like conveyors if the player lands on one. (I.E. none of the momentum cut thing below) -Red
|
||||||
|
if ((mo->z == polysec->ceilingheight || mo->z + mo->height == polysec->floorheight) && po->thinker)
|
||||||
|
stopmovecut = true;
|
||||||
|
|
||||||
|
if (!(po->flags & POF_LDEXEC))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (mo->z != polysec->ceilingheight)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// We're landing on a PO, so check for a linedef executor.
|
||||||
|
// Trigger tags are 32000 + the PO's ID number.
|
||||||
|
P_LinedefExecute((INT16)(32000 + po->id), mo, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stopmovecut;
|
||||||
|
}
|
||||||
|
|
||||||
static void P_PlayerZMovement(mobj_t *mo)
|
static void P_PlayerZMovement(mobj_t *mo)
|
||||||
{
|
{
|
||||||
boolean onground;
|
boolean onground;
|
||||||
|
@ -2894,66 +2981,10 @@ static void P_PlayerZMovement(mobj_t *mo)
|
||||||
|
|
||||||
mo->eflags |= MFE_JUSTHITFLOOR; // Spin Attack
|
mo->eflags |= MFE_JUSTHITFLOOR; // Spin Attack
|
||||||
|
|
||||||
|
clipmomz = P_PlayerHitFloor(mo->player, true);
|
||||||
|
|
||||||
|
if (!P_PlayerPolyObjectZMovement(mo))
|
||||||
{
|
{
|
||||||
// Check if we're on a polyobject
|
|
||||||
// that triggers a linedef executor.
|
|
||||||
msecnode_t *node;
|
|
||||||
boolean stopmovecut = false;
|
|
||||||
|
|
||||||
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
|
|
||||||
{
|
|
||||||
sector_t *sec = node->m_sector;
|
|
||||||
subsector_t *newsubsec;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < numsubsectors; i++)
|
|
||||||
{
|
|
||||||
newsubsec = &subsectors[i];
|
|
||||||
|
|
||||||
if (newsubsec->sector != sec)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (newsubsec->polyList)
|
|
||||||
{
|
|
||||||
polyobj_t *po = newsubsec->polyList;
|
|
||||||
sector_t *polysec;
|
|
||||||
|
|
||||||
while(po)
|
|
||||||
{
|
|
||||||
if (!P_MobjInsidePolyobj(po, mo) || !(po->flags & POF_SOLID))
|
|
||||||
{
|
|
||||||
po = (polyobj_t *)(po->link.next);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We're inside it! Yess...
|
|
||||||
polysec = po->lines[0]->backsector;
|
|
||||||
|
|
||||||
// Moving polyobjects should act like conveyors if the player lands on one. (I.E. none of the momentum cut thing below) -Red
|
|
||||||
if ((mo->z == polysec->ceilingheight || mo->z+mo->height == polysec->floorheight) && po->thinker)
|
|
||||||
stopmovecut = true;
|
|
||||||
|
|
||||||
if (!(po->flags & POF_LDEXEC))
|
|
||||||
{
|
|
||||||
po = (polyobj_t *)(po->link.next);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mo->z == polysec->ceilingheight)
|
|
||||||
{
|
|
||||||
// We're landing on a PO, so check for
|
|
||||||
// a linedef executor.
|
|
||||||
// Trigger tags are 32000 + the PO's ID number.
|
|
||||||
P_LinedefExecute((INT16)(32000 + po->id), mo, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
po = (polyobj_t *)(po->link.next);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!stopmovecut)
|
|
||||||
// Cut momentum in half when you hit the ground and
|
// Cut momentum in half when you hit the ground and
|
||||||
// aren't pressing any controls.
|
// aren't pressing any controls.
|
||||||
if (!(mo->player->cmd.forwardmove || mo->player->cmd.sidemove) && !mo->player->cmomx && !mo->player->cmomy && !(mo->player->pflags & PF_SPINNING))
|
if (!(mo->player->cmd.forwardmove || mo->player->cmd.sidemove) && !mo->player->cmomx && !mo->player->cmomy && !(mo->player->pflags & PF_SPINNING))
|
||||||
|
@ -2963,8 +2994,6 @@ static void P_PlayerZMovement(mobj_t *mo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clipmomz = P_PlayerHitFloor(mo->player, true);
|
|
||||||
|
|
||||||
if (!(mo->player->pflags & PF_SPINNING) && mo->player->powers[pw_carry] != CR_NIGHTSMODE)
|
if (!(mo->player->pflags & PF_SPINNING) && mo->player->powers[pw_carry] != CR_NIGHTSMODE)
|
||||||
mo->player->pflags &= ~PF_STARTDASH;
|
mo->player->pflags &= ~PF_STARTDASH;
|
||||||
|
|
||||||
|
@ -3019,39 +3048,10 @@ nightsdone:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for "Mario" blocks to hit and bounce them
|
|
||||||
if (P_MobjFlip(mo)*mo->momz > 0)
|
if (P_MobjFlip(mo)*mo->momz > 0)
|
||||||
{
|
{
|
||||||
msecnode_t *node;
|
if (CheckForMarioBlocks)
|
||||||
|
P_CheckMarioBlocks(mo);
|
||||||
if (CheckForMarioBlocks && !(netgame && mo->player->spectator)) // Only let the player punch
|
|
||||||
{
|
|
||||||
// Search the touching sectors, from side-to-side...
|
|
||||||
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
|
|
||||||
{
|
|
||||||
ffloor_t *rover;
|
|
||||||
if (!node->m_sector->ffloors)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
|
|
||||||
{
|
|
||||||
if (!(rover->flags & FF_EXISTS))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Come on, it's time to go...
|
|
||||||
if (rover->flags & FF_MARIO
|
|
||||||
&& !(mo->eflags & MFE_VERTICALFLIP) // if you were flipped, your head isn't actually hitting your ceilingz is it?
|
|
||||||
&& *rover->bottomheight == mo->ceilingz) // The player's head hit the bottom!
|
|
||||||
{
|
|
||||||
// DO THE MARIO!
|
|
||||||
if (rover->flags & FF_SHATTERBOTTOM) // Brick block!
|
|
||||||
EV_CrumbleChain(node->m_sector, rover);
|
|
||||||
else // Question block!
|
|
||||||
EV_MarioBlock(rover, node->m_sector, mo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // Ugly ugly billions of braces! Argh!
|
|
||||||
}
|
|
||||||
|
|
||||||
// hit the ceiling
|
// hit the ceiling
|
||||||
if (mariomode)
|
if (mariomode)
|
||||||
|
@ -3210,9 +3210,7 @@ static boolean P_SceneryZMovement(mobj_t *mo)
|
||||||
//
|
//
|
||||||
boolean P_CanRunOnWater(player_t *player, ffloor_t *rover)
|
boolean P_CanRunOnWater(player_t *player, ffloor_t *rover)
|
||||||
{
|
{
|
||||||
fixed_t topheight = *rover->t_slope ?
|
fixed_t topheight = P_GetFFloorTopZAt(rover, player->mo->x, player->mo->y);
|
||||||
P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) :
|
|
||||||
*rover->topheight;
|
|
||||||
|
|
||||||
if (!player->powers[pw_carry] && !player->homing
|
if (!player->powers[pw_carry] && !player->homing
|
||||||
&& ((player->powers[pw_super] || player->charflags & SF_RUNONWATER || player->dashmode >= DASHMODE_THRESHOLD) && player->mo->ceilingz-topheight >= player->mo->height)
|
&& ((player->powers[pw_super] || player->charflags & SF_RUNONWATER || player->dashmode >= DASHMODE_THRESHOLD) && player->mo->ceilingz-topheight >= player->mo->height)
|
||||||
|
@ -3255,14 +3253,8 @@ void P_MobjCheckWater(mobj_t *mobj)
|
||||||
|| ((rover->flags & FF_BLOCKOTHERS) && !mobj->player)))
|
|| ((rover->flags & FF_BLOCKOTHERS) && !mobj->player)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
topheight = *rover->topheight;
|
topheight = P_GetFFloorTopZAt (rover, mobj->x, mobj->y);
|
||||||
bottomheight = *rover->bottomheight;
|
bottomheight = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y);
|
||||||
|
|
||||||
if (*rover->t_slope)
|
|
||||||
topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y);
|
|
||||||
|
|
||||||
if (*rover->b_slope)
|
|
||||||
bottomheight = P_GetZAt(*rover->b_slope, mobj->x, mobj->y);
|
|
||||||
|
|
||||||
if (mobj->eflags & MFE_VERTICALFLIP)
|
if (mobj->eflags & MFE_VERTICALFLIP)
|
||||||
{
|
{
|
||||||
|
@ -3509,14 +3501,8 @@ static void P_SceneryCheckWater(mobj_t *mobj)
|
||||||
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->flags & FF_BLOCKOTHERS)
|
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->flags & FF_BLOCKOTHERS)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
topheight = *rover->topheight;
|
topheight = P_GetFFloorTopZAt (rover, mobj->x, mobj->y);
|
||||||
bottomheight = *rover->bottomheight;
|
bottomheight = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y);
|
||||||
|
|
||||||
if (*rover->t_slope)
|
|
||||||
topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y);
|
|
||||||
|
|
||||||
if (*rover->b_slope)
|
|
||||||
bottomheight = P_GetZAt(*rover->b_slope, mobj->x, mobj->y);
|
|
||||||
|
|
||||||
if (topheight <= mobj->z
|
if (topheight <= mobj->z
|
||||||
|| bottomheight > (mobj->z + (mobj->height>>1)))
|
|| bottomheight > (mobj->z + (mobj->height>>1)))
|
||||||
|
@ -3561,13 +3547,9 @@ static boolean P_CameraCheckHeat(camera_t *thiscam)
|
||||||
if (!(rover->flags & FF_EXISTS))
|
if (!(rover->flags & FF_EXISTS))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (halfheight >= (*rover->t_slope ?
|
if (halfheight >= P_GetFFloorTopZAt(rover, thiscam->x, thiscam->y))
|
||||||
P_GetZAt(*rover->t_slope, thiscam->x, thiscam->y) :
|
|
||||||
*rover->topheight))
|
|
||||||
continue;
|
continue;
|
||||||
if (halfheight <= (*rover->b_slope ?
|
if (halfheight <= P_GetFFloorBottomZAt(rover, thiscam->x, thiscam->y))
|
||||||
P_GetZAt(*rover->b_slope, thiscam->x, thiscam->y) :
|
|
||||||
*rover->bottomheight))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1)
|
if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1)
|
||||||
|
@ -3595,13 +3577,9 @@ static boolean P_CameraCheckWater(camera_t *thiscam)
|
||||||
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->flags & FF_BLOCKOTHERS)
|
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->flags & FF_BLOCKOTHERS)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (halfheight >= (*rover->t_slope ?
|
if (halfheight >= P_GetFFloorTopZAt(rover, thiscam->x, thiscam->y))
|
||||||
P_GetZAt(*rover->t_slope, thiscam->x, thiscam->y) :
|
|
||||||
*rover->topheight))
|
|
||||||
continue;
|
continue;
|
||||||
if (halfheight <= (
|
if (halfheight <= P_GetFFloorBottomZAt(rover, thiscam->x, thiscam->y))
|
||||||
*rover->b_slope ? P_GetZAt(*rover->b_slope, thiscam->x, thiscam->y) :
|
|
||||||
*rover->bottomheight))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -3777,13 +3755,114 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
static void P_CheckCrumblingPlatforms(mobj_t *mobj)
|
||||||
// P_PlayerMobjThinker
|
|
||||||
//
|
|
||||||
static void P_PlayerMobjThinker(mobj_t *mobj)
|
|
||||||
{
|
{
|
||||||
msecnode_t *node;
|
msecnode_t *node;
|
||||||
|
|
||||||
|
if (netgame && mobj->player->spectator)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
|
||||||
|
{
|
||||||
|
ffloor_t *rover;
|
||||||
|
|
||||||
|
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
|
||||||
|
{
|
||||||
|
if (!(rover->flags & FF_EXISTS))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(rover->flags & FF_CRUMBLE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (mobj->eflags & MFE_VERTICALFLIP)
|
||||||
|
{
|
||||||
|
if (P_GetSpecialBottomZ(mobj, sectors + rover->secnum, node->m_sector) != mobj->z + mobj->height)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (P_GetSpecialTopZ(mobj, sectors + rover->secnum, node->m_sector) != mobj->z)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), mobj->player, rover->alpha, !(rover->flags & FF_NORETURN));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean P_MobjTouchesSectorWithWater(mobj_t *mobj)
|
||||||
|
{
|
||||||
|
msecnode_t *node;
|
||||||
|
|
||||||
|
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
|
||||||
|
{
|
||||||
|
ffloor_t *rover;
|
||||||
|
|
||||||
|
if (!node->m_sector->ffloors)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
|
||||||
|
{
|
||||||
|
if (!(rover->flags & FF_EXISTS))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(rover->flags & FF_SWIMMABLE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for floating water platforms and bounce them
|
||||||
|
static void P_CheckFloatbobPlatforms(mobj_t *mobj)
|
||||||
|
{
|
||||||
|
msecnode_t *node;
|
||||||
|
|
||||||
|
// Can't land on anything if you're not moving downwards
|
||||||
|
if (P_MobjFlip(mobj)*mobj->momz >= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!P_MobjTouchesSectorWithWater(mobj))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
|
||||||
|
{
|
||||||
|
ffloor_t *rover;
|
||||||
|
|
||||||
|
if (!node->m_sector->ffloors)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
|
||||||
|
{
|
||||||
|
if (!(rover->flags & FF_EXISTS))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(rover->flags & FF_FLOATBOB))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
if (mobj->eflags & MFE_VERTICALFLIP)
|
||||||
|
{
|
||||||
|
if (abs(*rover->bottomheight - (mobj->z + mobj->height)) > abs(mobj->momz))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (abs(*rover->topheight - mobj->z) > abs(mobj->momz))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initiate a 'bouncy' elevator function which slowly diminishes.
|
||||||
|
EV_BounceSector(rover->master->frontsector, -mobj->momz, rover->master);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void P_PlayerMobjThinker(mobj_t *mobj)
|
||||||
|
{
|
||||||
I_Assert(mobj != NULL);
|
I_Assert(mobj != NULL);
|
||||||
I_Assert(mobj->player != NULL);
|
I_Assert(mobj->player != NULL);
|
||||||
I_Assert(!P_MobjWasRemoved(mobj));
|
I_Assert(!P_MobjWasRemoved(mobj));
|
||||||
|
@ -3836,77 +3915,10 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
|
||||||
else
|
else
|
||||||
P_TryMove(mobj, mobj->x, mobj->y, true);
|
P_TryMove(mobj, mobj->x, mobj->y, true);
|
||||||
|
|
||||||
if (!(netgame && mobj->player->spectator))
|
P_CheckCrumblingPlatforms(mobj);
|
||||||
{
|
|
||||||
// Crumbling platforms
|
|
||||||
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
|
|
||||||
{
|
|
||||||
fixed_t topheight, bottomheight;
|
|
||||||
ffloor_t *rover;
|
|
||||||
|
|
||||||
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
|
if (CheckForFloatBob)
|
||||||
{
|
P_CheckFloatbobPlatforms(mobj);
|
||||||
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_CRUMBLE))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
topheight = P_GetSpecialTopZ(mobj, sectors + rover->secnum, node->m_sector);
|
|
||||||
bottomheight = P_GetSpecialBottomZ(mobj, sectors + rover->secnum, node->m_sector);
|
|
||||||
|
|
||||||
if ((topheight == mobj->z && !(mobj->eflags & MFE_VERTICALFLIP))
|
|
||||||
|| (bottomheight == mobj->z + mobj->height && mobj->eflags & MFE_VERTICALFLIP)) // You nut.
|
|
||||||
EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), mobj->player, rover->alpha, !(rover->flags & FF_NORETURN));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for floating water platforms and bounce them
|
|
||||||
if (CheckForFloatBob && P_MobjFlip(mobj)*mobj->momz < 0)
|
|
||||||
{
|
|
||||||
boolean thereiswater = false;
|
|
||||||
|
|
||||||
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
|
|
||||||
{
|
|
||||||
if (node->m_sector->ffloors)
|
|
||||||
{
|
|
||||||
ffloor_t *rover;
|
|
||||||
// Get water boundaries first
|
|
||||||
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
|
|
||||||
{
|
|
||||||
if (!(rover->flags & FF_EXISTS))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (rover->flags & FF_SWIMMABLE) // Is there water?
|
|
||||||
{
|
|
||||||
thereiswater = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (thereiswater)
|
|
||||||
{
|
|
||||||
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
|
|
||||||
{
|
|
||||||
if (node->m_sector->ffloors)
|
|
||||||
{
|
|
||||||
ffloor_t *rover;
|
|
||||||
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
|
|
||||||
{
|
|
||||||
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_FLOATBOB))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((!(mobj->eflags & MFE_VERTICALFLIP) && abs(*rover->topheight-mobj->z) <= abs(mobj->momz)) // The player is landing on the cheese!
|
|
||||||
|| (mobj->eflags & MFE_VERTICALFLIP && abs(*rover->bottomheight-(mobj->z+mobj->height)) <= abs(mobj->momz)))
|
|
||||||
{
|
|
||||||
// Initiate a 'bouncy' elevator function
|
|
||||||
// which slowly diminishes.
|
|
||||||
EV_BounceSector(rover->master->frontsector, -mobj->momz, rover->master);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // Ugly ugly billions of braces! Argh!
|
|
||||||
}
|
|
||||||
|
|
||||||
// always do the gravity bit now, that's simpler
|
// always do the gravity bit now, that's simpler
|
||||||
// BUT CheckPosition only if wasn't done before.
|
// BUT CheckPosition only if wasn't done before.
|
||||||
|
@ -3949,9 +3961,7 @@ static void CalculatePrecipFloor(precipmobj_t *mobj)
|
||||||
mobjsecsubsec = mobj->subsector->sector;
|
mobjsecsubsec = mobj->subsector->sector;
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
mobj->floorz = mobjsecsubsec->f_slope ?
|
mobj->floorz = P_GetSectorFloorZAt(mobjsecsubsec, mobj->x, mobj->y);
|
||||||
P_GetZAt(mobjsecsubsec->f_slope, mobj->x, mobj->y) :
|
|
||||||
mobjsecsubsec->floorheight;
|
|
||||||
if (mobjsecsubsec->ffloors)
|
if (mobjsecsubsec->ffloors)
|
||||||
{
|
{
|
||||||
ffloor_t *rover;
|
ffloor_t *rover;
|
||||||
|
@ -3966,11 +3976,7 @@ static void CalculatePrecipFloor(precipmobj_t *mobj)
|
||||||
if (!(rover->flags & FF_BLOCKOTHERS) && !(rover->flags & FF_SWIMMABLE))
|
if (!(rover->flags & FF_BLOCKOTHERS) && !(rover->flags & FF_SWIMMABLE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (*rover->t_slope)
|
topheight = P_GetFFloorTopZAt(rover, mobj->x, mobj->y);
|
||||||
topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y);
|
|
||||||
else
|
|
||||||
topheight = *rover->topheight;
|
|
||||||
|
|
||||||
if (topheight > mobj->floorz)
|
if (topheight > mobj->floorz)
|
||||||
mobj->floorz = topheight;
|
mobj->floorz = topheight;
|
||||||
}
|
}
|
||||||
|
@ -7056,8 +7062,7 @@ static void P_MobjScaleThink(mobj_t *mobj)
|
||||||
fixed_t oldheight = mobj->height;
|
fixed_t oldheight = mobj->height;
|
||||||
UINT8 correctionType = 0; // Don't correct Z position, just gain height
|
UINT8 correctionType = 0; // Don't correct Z position, just gain height
|
||||||
|
|
||||||
if ((mobj->flags & MF_NOCLIPHEIGHT || (mobj->z > mobj->floorz && mobj->z + mobj->height < mobj->ceilingz))
|
if (mobj->flags & MF_NOCLIPHEIGHT || (mobj->z > mobj->floorz && mobj->z + mobj->height < mobj->ceilingz))
|
||||||
&& mobj->type != MT_EGGMOBILE_FIRE)
|
|
||||||
correctionType = 1; // Correct Z position by centering
|
correctionType = 1; // Correct Z position by centering
|
||||||
else if (mobj->eflags & MFE_VERTICALFLIP)
|
else if (mobj->eflags & MFE_VERTICALFLIP)
|
||||||
correctionType = 2; // Correct Z position by moving down
|
correctionType = 2; // Correct Z position by moving down
|
||||||
|
@ -7078,10 +7083,6 @@ static void P_MobjScaleThink(mobj_t *mobj)
|
||||||
/// \todo Lua hook for "reached destscale"?
|
/// \todo Lua hook for "reached destscale"?
|
||||||
switch (mobj->type)
|
switch (mobj->type)
|
||||||
{
|
{
|
||||||
case MT_EGGMOBILE_FIRE:
|
|
||||||
mobj->destscale = FRACUNIT;
|
|
||||||
mobj->scalespeed = FRACUNIT>>4;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -8257,6 +8258,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj)
|
||||||
// See Linedef Exec 457 (Track mobj angle to point)
|
// See Linedef Exec 457 (Track mobj angle to point)
|
||||||
static void P_TracerAngleThink(mobj_t *mobj)
|
static void P_TracerAngleThink(mobj_t *mobj)
|
||||||
{
|
{
|
||||||
|
angle_t looking;
|
||||||
angle_t ang;
|
angle_t ang;
|
||||||
|
|
||||||
if (!mobj->tracer)
|
if (!mobj->tracer)
|
||||||
|
@ -8271,7 +8273,12 @@ static void P_TracerAngleThink(mobj_t *mobj)
|
||||||
// mobj->cvval - Allowable failure delay
|
// mobj->cvval - Allowable failure delay
|
||||||
// mobj->cvmem - Failure timer
|
// mobj->cvmem - Failure timer
|
||||||
|
|
||||||
ang = mobj->angle - R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y);
|
if (mobj->player)
|
||||||
|
looking = ( mobj->player->cmd.angleturn << 16 );/* fixes CS_LMAOGALOG */
|
||||||
|
else
|
||||||
|
looking = mobj->angle;
|
||||||
|
|
||||||
|
ang = looking - R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y);
|
||||||
|
|
||||||
// \todo account for distance between mobj and tracer
|
// \todo account for distance between mobj and tracer
|
||||||
// Because closer mobjs can be facing beyond the angle tolerance
|
// Because closer mobjs can be facing beyond the angle tolerance
|
||||||
|
@ -9461,7 +9468,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
||||||
case MT_BOSSFLYPOINT:
|
case MT_BOSSFLYPOINT:
|
||||||
return false;
|
return false;
|
||||||
case MT_NIGHTSCORE:
|
case MT_NIGHTSCORE:
|
||||||
mobj->color = (UINT8)(leveltime % SKINCOLOR_WHITE);
|
mobj->color = (UINT16)(leveltime % SKINCOLOR_WHITE);
|
||||||
break;
|
break;
|
||||||
case MT_JETFUME1:
|
case MT_JETFUME1:
|
||||||
if (!P_JetFume1Think(mobj))
|
if (!P_JetFume1Think(mobj))
|
||||||
|
@ -10496,12 +10503,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
||||||
// Make sure scale matches destscale immediately when spawned
|
// Make sure scale matches destscale immediately when spawned
|
||||||
P_SetScale(mobj, mobj->destscale);
|
P_SetScale(mobj, mobj->destscale);
|
||||||
|
|
||||||
mobj->floorz = mobj->subsector->sector->f_slope ?
|
mobj->floorz = P_GetSectorFloorZAt (mobj->subsector->sector, x, y);
|
||||||
P_GetZAt(mobj->subsector->sector->f_slope, x, y) :
|
mobj->ceilingz = P_GetSectorCeilingZAt(mobj->subsector->sector, x, y);
|
||||||
mobj->subsector->sector->floorheight;
|
|
||||||
mobj->ceilingz = mobj->subsector->sector->c_slope ?
|
|
||||||
P_GetZAt(mobj->subsector->sector->c_slope, x, y) :
|
|
||||||
mobj->subsector->sector->ceilingheight;
|
|
||||||
|
|
||||||
mobj->floorrover = NULL;
|
mobj->floorrover = NULL;
|
||||||
mobj->ceilingrover = NULL;
|
mobj->ceilingrover = NULL;
|
||||||
|
@ -10672,7 +10675,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
||||||
break;
|
break;
|
||||||
case MT_EGGROBO1:
|
case MT_EGGROBO1:
|
||||||
mobj->movecount = P_RandomKey(13);
|
mobj->movecount = P_RandomKey(13);
|
||||||
mobj->color = SKINCOLOR_RUBY + P_RandomKey(MAXSKINCOLORS - SKINCOLOR_RUBY);
|
mobj->color = SKINCOLOR_RUBY + P_RandomKey(numskincolors - SKINCOLOR_RUBY);
|
||||||
break;
|
break;
|
||||||
case MT_HIVEELEMENTAL:
|
case MT_HIVEELEMENTAL:
|
||||||
mobj->extravalue1 = 5;
|
mobj->extravalue1 = 5;
|
||||||
|
@ -10854,12 +10857,8 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
|
||||||
// set subsector and/or block links
|
// set subsector and/or block links
|
||||||
P_SetPrecipitationThingPosition(mobj);
|
P_SetPrecipitationThingPosition(mobj);
|
||||||
|
|
||||||
mobj->floorz = starting_floorz = mobj->subsector->sector->f_slope ?
|
mobj->floorz = starting_floorz = P_GetSectorFloorZAt (mobj->subsector->sector, x, y);
|
||||||
P_GetZAt(mobj->subsector->sector->f_slope, x, y) :
|
mobj->ceilingz = P_GetSectorCeilingZAt(mobj->subsector->sector, x, y);
|
||||||
mobj->subsector->sector->floorheight;
|
|
||||||
mobj->ceilingz = mobj->subsector->sector->c_slope ?
|
|
||||||
P_GetZAt(mobj->subsector->sector->c_slope, x, y) :
|
|
||||||
mobj->subsector->sector->ceilingheight;
|
|
||||||
|
|
||||||
mobj->floorrover = NULL;
|
mobj->floorrover = NULL;
|
||||||
mobj->ceilingrover = NULL;
|
mobj->ceilingrover = NULL;
|
||||||
|
@ -11390,6 +11389,14 @@ void P_SpawnPlayer(INT32 playernum)
|
||||||
p->realtime = leveltime;
|
p->realtime = leveltime;
|
||||||
p->followitem = skins[p->skin].followitem;
|
p->followitem = skins[p->skin].followitem;
|
||||||
|
|
||||||
|
// Make sure player's stats are reset if they were in dashmode!
|
||||||
|
if (p->dashmode)
|
||||||
|
{
|
||||||
|
p->dashmode = 0;
|
||||||
|
p->normalspeed = skins[p->skin].normalspeed;
|
||||||
|
p->jumpfactor = skins[p->skin].jumpfactor;
|
||||||
|
}
|
||||||
|
|
||||||
//awayview stuff
|
//awayview stuff
|
||||||
p->awayviewmobj = NULL;
|
p->awayviewmobj = NULL;
|
||||||
p->awayviewtics = 0;
|
p->awayviewtics = 0;
|
||||||
|
@ -11428,10 +11435,7 @@ void P_AfterPlayerSpawn(INT32 playernum)
|
||||||
player_t *p = &players[playernum];
|
player_t *p = &players[playernum];
|
||||||
mobj_t *mobj = p->mo;
|
mobj_t *mobj = p->mo;
|
||||||
|
|
||||||
if (playernum == consoleplayer)
|
P_SetPlayerAngle(p, mobj->angle);
|
||||||
localangle = mobj->angle;
|
|
||||||
else if (playernum == secondarydisplayplayer)
|
|
||||||
localangle2 = mobj->angle;
|
|
||||||
|
|
||||||
p->viewheight = 41*p->height/48;
|
p->viewheight = 41*p->height/48;
|
||||||
|
|
||||||
|
@ -11448,7 +11452,6 @@ void P_AfterPlayerSpawn(INT32 playernum)
|
||||||
HU_Start();
|
HU_Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
SV_SpawnPlayer(playernum, mobj->x, mobj->y, mobj->angle);
|
|
||||||
p->drawangle = mobj->angle;
|
p->drawangle = mobj->angle;
|
||||||
|
|
||||||
if (camera.chase)
|
if (camera.chase)
|
||||||
|
@ -11494,12 +11497,8 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
|
||||||
// set Z height
|
// set Z height
|
||||||
sector = R_PointInSubsector(x, y)->sector;
|
sector = R_PointInSubsector(x, y)->sector;
|
||||||
|
|
||||||
floor = sector->f_slope ?
|
floor = P_GetSectorFloorZAt (sector, x, y);
|
||||||
P_GetZAt(sector->f_slope, x, y) :
|
ceiling = P_GetSectorCeilingZAt(sector, x, y);
|
||||||
sector->floorheight;
|
|
||||||
ceiling = sector->c_slope ?
|
|
||||||
P_GetZAt(sector->c_slope, x, y) :
|
|
||||||
sector->ceilingheight;
|
|
||||||
ceilingspawn = ceiling - mobjinfo[MT_PLAYER].height;
|
ceilingspawn = ceiling - mobjinfo[MT_PLAYER].height;
|
||||||
|
|
||||||
if (mthing)
|
if (mthing)
|
||||||
|
@ -11569,12 +11568,8 @@ void P_MovePlayerToStarpost(INT32 playernum)
|
||||||
P_SetThingPosition(mobj);
|
P_SetThingPosition(mobj);
|
||||||
sector = R_PointInSubsector(mobj->x, mobj->y)->sector;
|
sector = R_PointInSubsector(mobj->x, mobj->y)->sector;
|
||||||
|
|
||||||
floor = sector->f_slope ?
|
floor = P_GetSectorFloorZAt (sector, mobj->x, mobj->y);
|
||||||
P_GetZAt(sector->f_slope, mobj->x, mobj->y) :
|
ceiling = P_GetSectorCeilingZAt(sector, mobj->x, mobj->y);
|
||||||
sector->floorheight;
|
|
||||||
ceiling = sector->c_slope ?
|
|
||||||
P_GetZAt(sector->c_slope, mobj->x, mobj->y) :
|
|
||||||
sector->ceilingheight;
|
|
||||||
|
|
||||||
z = p->starpostz << FRACBITS;
|
z = p->starpostz << FRACBITS;
|
||||||
|
|
||||||
|
@ -11623,11 +11618,9 @@ fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const f
|
||||||
|
|
||||||
// Establish height.
|
// Establish height.
|
||||||
if (flip)
|
if (flip)
|
||||||
return (ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) : ss->sector->ceilingheight)
|
return P_GetSectorCeilingZAt(ss->sector, x, y) - offset - mobjinfo[mobjtype].height;
|
||||||
- offset - mobjinfo[mobjtype].height;
|
|
||||||
else
|
else
|
||||||
return (ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) : ss->sector->floorheight)
|
return P_GetSectorFloorZAt(ss->sector, x, y) + offset;
|
||||||
+ offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y)
|
fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y)
|
||||||
|
@ -11966,7 +11959,7 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj)
|
||||||
{
|
{
|
||||||
INT32 j;
|
INT32 j;
|
||||||
emblem_t* emblem = M_GetLevelEmblems(gamemap);
|
emblem_t* emblem = M_GetLevelEmblems(gamemap);
|
||||||
skincolors_t emcolor;
|
skincolornum_t emcolor;
|
||||||
|
|
||||||
while (emblem)
|
while (emblem)
|
||||||
{
|
{
|
||||||
|
@ -11989,7 +11982,7 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj)
|
||||||
|
|
||||||
mobj->health = j + 1;
|
mobj->health = j + 1;
|
||||||
emcolor = M_GetEmblemColor(&emblemlocations[j]); // workaround for compiler complaint about bad function casting
|
emcolor = M_GetEmblemColor(&emblemlocations[j]); // workaround for compiler complaint about bad function casting
|
||||||
mobj->color = (UINT8)emcolor;
|
mobj->color = (UINT16)emcolor;
|
||||||
|
|
||||||
if (emblemlocations[j].collected
|
if (emblemlocations[j].collected
|
||||||
|| (emblemlocations[j].type == ET_SKIN && emblemlocations[j].var != players[0].skin))
|
|| (emblemlocations[j].type == ET_SKIN && emblemlocations[j].var != players[0].skin))
|
||||||
|
@ -12628,7 +12621,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
|
||||||
break;
|
break;
|
||||||
case MT_BALLOON:
|
case MT_BALLOON:
|
||||||
if (mthing->angle > 0)
|
if (mthing->angle > 0)
|
||||||
mobj->color = ((mthing->angle - 1) % (MAXSKINCOLORS - 1)) + 1;
|
mobj->color = ((mthing->angle - 1) % (numskincolors - 1)) + 1;
|
||||||
break;
|
break;
|
||||||
#define makesoftwarecorona(mo, h) \
|
#define makesoftwarecorona(mo, h) \
|
||||||
corona = P_SpawnMobjFromMobj(mo, 0, 0, h<<FRACBITS, MT_PARTICLE);\
|
corona = P_SpawnMobjFromMobj(mo, 0, 0, h<<FRACBITS, MT_PARTICLE);\
|
||||||
|
@ -12728,9 +12721,14 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
|
||||||
mobj->threshold = min(mthing->extrainfo, 7);
|
mobj->threshold = min(mthing->extrainfo, 7);
|
||||||
break;
|
break;
|
||||||
case MT_TUBEWAYPOINT:
|
case MT_TUBEWAYPOINT:
|
||||||
mobj->health = mthing->angle & 255;
|
{
|
||||||
mobj->threshold = mthing->angle >> 8;
|
UINT8 sequence = mthing->angle >> 8;
|
||||||
|
UINT8 id = mthing->angle & 255;
|
||||||
|
mobj->health = id;
|
||||||
|
mobj->threshold = sequence;
|
||||||
|
P_AddWaypoint(sequence, id, mobj);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case MT_IDEYAANCHOR:
|
case MT_IDEYAANCHOR:
|
||||||
mobj->health = mthing->extrainfo;
|
mobj->health = mthing->extrainfo;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -312,7 +312,7 @@ typedef struct mobj_s
|
||||||
void *skin; // overrides 'sprite' when non-NULL (for player bodies to 'remember' the skin)
|
void *skin; // overrides 'sprite' when non-NULL (for player bodies to 'remember' the skin)
|
||||||
// Player and mobj sprites in multiplayer modes are modified
|
// Player and mobj sprites in multiplayer modes are modified
|
||||||
// using an internal color lookup table for re-indexing.
|
// using an internal color lookup table for re-indexing.
|
||||||
UINT8 color; // This replaces MF_TRANSLATION. Use 0 for default (no translation).
|
UINT16 color; // This replaces MF_TRANSLATION. Use 0 for default (no translation).
|
||||||
|
|
||||||
// Interaction info, by BLOCKMAP.
|
// Interaction info, by BLOCKMAP.
|
||||||
// Links in blocks (if needed).
|
// Links in blocks (if needed).
|
||||||
|
|
427
src/p_polyobj.c
427
src/p_polyobj.c
|
@ -240,6 +240,9 @@ static void Polyobj_GetInfo(polyobj_t *po)
|
||||||
/*if (lines[i].flags & ML_EFFECT5)
|
/*if (lines[i].flags & ML_EFFECT5)
|
||||||
po->flags &= ~POF_CLIPPLANES;*/
|
po->flags &= ~POF_CLIPPLANES;*/
|
||||||
|
|
||||||
|
if (lines[i].flags & ML_EFFECT6)
|
||||||
|
po->flags |= POF_SPLAT;
|
||||||
|
|
||||||
if (lines[i].flags & ML_NOCLIMB) // Has a linedef executor
|
if (lines[i].flags & ML_NOCLIMB) // Has a linedef executor
|
||||||
po->flags |= POF_LDEXEC;
|
po->flags |= POF_LDEXEC;
|
||||||
}
|
}
|
||||||
|
@ -1039,7 +1042,7 @@ static boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean check
|
||||||
// The formula for this can be found here:
|
// The formula for this can be found here:
|
||||||
// http://www.inversereality.org/tutorials/graphics%20programming/2dtransformations.html
|
// http://www.inversereality.org/tutorials/graphics%20programming/2dtransformations.html
|
||||||
// It is, of course, just a vector-matrix multiplication.
|
// It is, of course, just a vector-matrix multiplication.
|
||||||
static inline void Polyobj_rotatePoint(vertex_t *v, const vertex_t *c, angle_t ang)
|
static inline void Polyobj_rotatePoint(vertex_t *v, const vector2_t *c, angle_t ang)
|
||||||
{
|
{
|
||||||
vertex_t tmp = *v;
|
vertex_t tmp = *v;
|
||||||
|
|
||||||
|
@ -1092,7 +1095,7 @@ static void Polyobj_rotateLine(line_t *ld)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Causes objects resting on top of the rotating polyobject to 'ride' with its movement.
|
// Causes objects resting on top of the rotating polyobject to 'ride' with its movement.
|
||||||
static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta, UINT8 turnthings)
|
static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta, UINT8 turnthings)
|
||||||
{
|
{
|
||||||
static INT32 pomovecount = 10000;
|
static INT32 pomovecount = 10000;
|
||||||
INT32 x, y;
|
INT32 x, y;
|
||||||
|
@ -1156,10 +1159,7 @@ static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta,
|
||||||
|
|
||||||
if (turnthings == 2 || (turnthings == 1 && !mo->player)) {
|
if (turnthings == 2 || (turnthings == 1 && !mo->player)) {
|
||||||
mo->angle += delta;
|
mo->angle += delta;
|
||||||
if (mo->player == &players[consoleplayer])
|
P_SetPlayerAngle(mo->player, (angle_t)(mo->player->angleturn << 16) + delta);
|
||||||
localangle += delta;
|
|
||||||
else if (mo->player == &players[secondarydisplayplayer])
|
|
||||||
localangle2 += delta;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1172,7 +1172,7 @@ static boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, bo
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
angle_t angle;
|
angle_t angle;
|
||||||
vertex_t origin;
|
vector2_t origin;
|
||||||
INT32 hitflags = 0;
|
INT32 hitflags = 0;
|
||||||
|
|
||||||
// don't move bad polyobjects
|
// don't move bad polyobjects
|
||||||
|
@ -1569,17 +1569,39 @@ void T_PolyObjMove(polymove_t *th)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void T_MovePolyObj(polyobj_t *po, fixed_t distx, fixed_t disty, fixed_t distz)
|
||||||
|
{
|
||||||
|
polyobj_t *child;
|
||||||
|
INT32 start;
|
||||||
|
|
||||||
|
Polyobj_moveXY(po, distx, disty, true);
|
||||||
|
// TODO: use T_MovePlane
|
||||||
|
po->lines[0]->backsector->floorheight += distz;
|
||||||
|
po->lines[0]->backsector->ceilingheight += distz;
|
||||||
|
// Sal: Remember to check your sectors!
|
||||||
|
// Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap
|
||||||
|
// updating objects in the front one too just added teleporting to ground bugs
|
||||||
|
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage));
|
||||||
|
// Apply action to mirroring polyobjects as well
|
||||||
|
start = 0;
|
||||||
|
while ((child = Polyobj_GetChild(po, &start)))
|
||||||
|
{
|
||||||
|
if (child->isBad)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Polyobj_moveXY(child, distx, disty, true);
|
||||||
|
// TODO: use T_MovePlane
|
||||||
|
child->lines[0]->backsector->floorheight += distz;
|
||||||
|
child->lines[0]->backsector->ceilingheight += distz;
|
||||||
|
P_CheckSector(child->lines[0]->backsector, (boolean)(child->damage));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void T_PolyObjWaypoint(polywaypoint_t *th)
|
void T_PolyObjWaypoint(polywaypoint_t *th)
|
||||||
{
|
{
|
||||||
mobj_t *mo2;
|
|
||||||
mobj_t *target = NULL;
|
mobj_t *target = NULL;
|
||||||
mobj_t *waypoint = NULL;
|
|
||||||
thinker_t *wp;
|
|
||||||
fixed_t adjustx, adjusty, adjustz;
|
|
||||||
fixed_t momx, momy, momz, dist;
|
|
||||||
INT32 start;
|
|
||||||
polyobj_t *po = Polyobj_GetForNum(th->polyObjNum);
|
polyobj_t *po = Polyobj_GetForNum(th->polyObjNum);
|
||||||
polyobj_t *oldpo = po;
|
fixed_t speed = th->speed;
|
||||||
|
|
||||||
if (!po)
|
if (!po)
|
||||||
#ifdef RANGECHECK
|
#ifdef RANGECHECK
|
||||||
|
@ -1593,31 +1615,10 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check for displacement due to override and reattach when possible
|
// check for displacement due to override and reattach when possible
|
||||||
if (po->thinker == NULL)
|
if (!po->thinker)
|
||||||
po->thinker = &th->thinker;
|
po->thinker = &th->thinker;
|
||||||
|
|
||||||
/*
|
target = waypoints[th->sequence][th->pointnum];
|
||||||
// Find out target first.
|
|
||||||
// We redo this each tic to make savegame compatibility easier.
|
|
||||||
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
|
||||||
{
|
|
||||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mo2 = (mobj_t *)wp;
|
|
||||||
|
|
||||||
if (mo2->type != MT_TUBEWAYPOINT)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (mo2->threshold == th->sequence && mo2->health == th->pointnum)
|
|
||||||
{
|
|
||||||
target = mo2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
target = th->target;
|
|
||||||
|
|
||||||
if (!target)
|
if (!target)
|
||||||
{
|
{
|
||||||
|
@ -1625,172 +1626,67 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compensate for position offset
|
// Move along the waypoint sequence until speed for the current tic is exhausted
|
||||||
adjustx = po->centerPt.x + th->diffx;
|
while (speed > 0)
|
||||||
adjusty = po->centerPt.y + th->diffy;
|
{
|
||||||
adjustz = po->lines[0]->backsector->floorheight + (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2 + th->diffz;
|
mobj_t *waypoint = NULL;
|
||||||
|
fixed_t pox, poy, poz;
|
||||||
|
fixed_t distx, disty, distz, dist;
|
||||||
|
|
||||||
dist = P_AproxDistance(P_AproxDistance(target->x - adjustx, target->y - adjusty), target->z - adjustz);
|
// Current position of polyobject
|
||||||
|
pox = po->centerPt.x;
|
||||||
|
poy = po->centerPt.y;
|
||||||
|
poz = (po->lines[0]->backsector->floorheight + po->lines[0]->backsector->ceilingheight)/2;
|
||||||
|
|
||||||
|
// Calculate the distance between the polyobject and the waypoint
|
||||||
|
distx = target->x - pox;
|
||||||
|
disty = target->y - poy;
|
||||||
|
distz = target->z - poz;
|
||||||
|
dist = P_AproxDistance(P_AproxDistance(distx, disty), distz);
|
||||||
|
|
||||||
if (dist < 1)
|
if (dist < 1)
|
||||||
dist = 1;
|
dist = 1;
|
||||||
|
|
||||||
momx = FixedMul(FixedDiv(target->x - adjustx, dist), (th->speed));
|
// Will the polyobject overshoot its target?
|
||||||
momy = FixedMul(FixedDiv(target->y - adjusty, dist), (th->speed));
|
if (speed < dist)
|
||||||
momz = FixedMul(FixedDiv(target->z - adjustz, dist), (th->speed));
|
|
||||||
|
|
||||||
// Calculate the distance between the polyobject and the waypoint
|
|
||||||
// 'dist' already equals this.
|
|
||||||
|
|
||||||
// Will the polyobject be FURTHER away if the momx/momy/momz is added to
|
|
||||||
// its current coordinates, or closer? (shift down to fracunits to avoid approximation errors)
|
|
||||||
if (dist>>FRACBITS <= P_AproxDistance(P_AproxDistance(target->x - adjustx - momx, target->y - adjusty - momy), target->z - adjustz - momz)>>FRACBITS)
|
|
||||||
{
|
{
|
||||||
// If further away, set XYZ of polyobject to waypoint location
|
// No. Move towards waypoint
|
||||||
fixed_t amtx, amty, amtz;
|
fixed_t momx, momy, momz;
|
||||||
fixed_t diffz;
|
|
||||||
amtx = (target->x - th->diffx) - po->centerPt.x;
|
|
||||||
amty = (target->y - th->diffy) - po->centerPt.y;
|
|
||||||
Polyobj_moveXY(po, amtx, amty, true);
|
|
||||||
// TODO: use T_MovePlane
|
|
||||||
amtz = (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2;
|
|
||||||
diffz = po->lines[0]->backsector->floorheight - (target->z - amtz);
|
|
||||||
po->lines[0]->backsector->floorheight = target->z - amtz;
|
|
||||||
po->lines[0]->backsector->ceilingheight = target->z + amtz;
|
|
||||||
// Sal: Remember to check your sectors!
|
|
||||||
// Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap
|
|
||||||
// updating objects in the front one too just added teleporting to ground bugs
|
|
||||||
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage));
|
|
||||||
// Apply action to mirroring polyobjects as well
|
|
||||||
start = 0;
|
|
||||||
while ((po = Polyobj_GetChild(oldpo, &start)))
|
|
||||||
{
|
|
||||||
if (po->isBad)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Polyobj_moveXY(po, amtx, amty, true);
|
momx = FixedMul(FixedDiv(target->x - pox, dist), speed);
|
||||||
// TODO: use T_MovePlane
|
momy = FixedMul(FixedDiv(target->y - poy, dist), speed);
|
||||||
po->lines[0]->backsector->floorheight += diffz; // move up/down by same amount as the parent did
|
momz = FixedMul(FixedDiv(target->z - poz, dist), speed);
|
||||||
po->lines[0]->backsector->ceilingheight += diffz;
|
T_MovePolyObj(po, momx, momy, momz);
|
||||||
// Sal: Remember to check your sectors!
|
return;
|
||||||
// Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap
|
|
||||||
// updating objects in the front one too just added teleporting to ground bugs
|
|
||||||
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage));
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
po = oldpo;
|
{
|
||||||
|
// Yes. Teleport to waypoint and look for the next one
|
||||||
|
T_MovePolyObj(po, distx, disty, distz);
|
||||||
|
|
||||||
if (!th->stophere)
|
if (!th->stophere)
|
||||||
{
|
{
|
||||||
CONS_Debug(DBG_POLYOBJ, "Looking for next waypoint...\n");
|
CONS_Debug(DBG_POLYOBJ, "Looking for next waypoint...\n");
|
||||||
|
waypoint = (th->direction == -1) ? P_GetPreviousWaypoint(target, false) : P_GetNextWaypoint(target, false);
|
||||||
|
|
||||||
// Find next waypoint
|
if (!waypoint && th->returnbehavior == PWR_WRAP) // If specified, wrap waypoints
|
||||||
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
|
||||||
{
|
|
||||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mo2 = (mobj_t *)wp;
|
|
||||||
|
|
||||||
if (mo2->type != MT_TUBEWAYPOINT)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (mo2->threshold != th->sequence)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (th->direction == -1)
|
|
||||||
{
|
|
||||||
if (mo2->health == target->health - 1)
|
|
||||||
{
|
|
||||||
waypoint = mo2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (mo2->health == target->health + 1)
|
|
||||||
{
|
|
||||||
waypoint = mo2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!waypoint && th->wrap) // If specified, wrap waypoints
|
|
||||||
{
|
{
|
||||||
if (!th->continuous)
|
if (!th->continuous)
|
||||||
{
|
{
|
||||||
th->wrap = 0;
|
th->returnbehavior = PWR_STOP;
|
||||||
th->stophere = true;
|
th->stophere = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
waypoint = (th->direction == -1) ? P_GetLastWaypoint(th->sequence) : P_GetFirstWaypoint(th->sequence);
|
||||||
{
|
|
||||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mo2 = (mobj_t *)wp;
|
|
||||||
|
|
||||||
if (mo2->type != MT_TUBEWAYPOINT)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (mo2->threshold != th->sequence)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (th->direction == -1)
|
|
||||||
{
|
|
||||||
if (waypoint == NULL)
|
|
||||||
waypoint = mo2;
|
|
||||||
else if (mo2->health > waypoint->health)
|
|
||||||
waypoint = mo2;
|
|
||||||
}
|
}
|
||||||
else
|
else if (!waypoint && th->returnbehavior == PWR_COMEBACK) // Come back to the start
|
||||||
{
|
|
||||||
if (mo2->health == 0)
|
|
||||||
{
|
|
||||||
waypoint = mo2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!waypoint && th->comeback) // Come back to the start
|
|
||||||
{
|
{
|
||||||
th->direction = -th->direction;
|
th->direction = -th->direction;
|
||||||
|
|
||||||
if (!th->continuous)
|
if (!th->continuous)
|
||||||
th->comeback = false;
|
th->returnbehavior = PWR_STOP;
|
||||||
|
|
||||||
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
waypoint = (th->direction == -1) ? P_GetPreviousWaypoint(target, false) : P_GetNextWaypoint(target, false);
|
||||||
{
|
|
||||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mo2 = (mobj_t *)wp;
|
|
||||||
|
|
||||||
if (mo2->type != MT_TUBEWAYPOINT)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (mo2->threshold != th->sequence)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (th->direction == -1)
|
|
||||||
{
|
|
||||||
if (mo2->health == target->health - 1)
|
|
||||||
{
|
|
||||||
waypoint = mo2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (mo2->health == target->health + 1)
|
|
||||||
{
|
|
||||||
waypoint = mo2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1800,24 +1696,12 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
||||||
|
|
||||||
target = waypoint;
|
target = waypoint;
|
||||||
th->pointnum = target->health;
|
th->pointnum = target->health;
|
||||||
// Set the mobj as your target! -- Monster Iestyn 27/12/19
|
|
||||||
P_SetTarget(&th->target, target);
|
|
||||||
|
|
||||||
// calculate MOMX/MOMY/MOMZ for next waypoint
|
// Calculate remaining speed
|
||||||
// change slope
|
speed -= dist;
|
||||||
dist = P_AproxDistance(P_AproxDistance(target->x - adjustx, target->y - adjusty), target->z - adjustz);
|
|
||||||
|
|
||||||
if (dist < 1)
|
|
||||||
dist = 1;
|
|
||||||
|
|
||||||
momx = FixedMul(FixedDiv(target->x - adjustx, dist), (th->speed));
|
|
||||||
momy = FixedMul(FixedDiv(target->y - adjusty, dist), (th->speed));
|
|
||||||
momz = FixedMul(FixedDiv(target->z - adjustz, dist), (th->speed));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
momx = momy = momz = 0;
|
|
||||||
|
|
||||||
if (!th->stophere)
|
if (!th->stophere)
|
||||||
CONS_Debug(DBG_POLYOBJ, "Next waypoint not found!\n");
|
CONS_Debug(DBG_POLYOBJ, "Next waypoint not found!\n");
|
||||||
|
|
||||||
|
@ -1828,36 +1712,6 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// momx/momy/momz already equals the right speed
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move the polyobject
|
|
||||||
Polyobj_moveXY(po, momx, momy, true);
|
|
||||||
// TODO: use T_MovePlane
|
|
||||||
po->lines[0]->backsector->floorheight += momz;
|
|
||||||
po->lines[0]->backsector->ceilingheight += momz;
|
|
||||||
// Sal: Remember to check your sectors!
|
|
||||||
// Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap
|
|
||||||
// updating objects in the front one too just added teleporting to ground bugs
|
|
||||||
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage));
|
|
||||||
|
|
||||||
// Apply action to mirroring polyobjects as well
|
|
||||||
start = 0;
|
|
||||||
while ((po = Polyobj_GetChild(oldpo, &start)))
|
|
||||||
{
|
|
||||||
if (po->isBad)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Polyobj_moveXY(po, momx, momy, true);
|
|
||||||
// TODO: use T_MovePlane
|
|
||||||
po->lines[0]->backsector->floorheight += momz;
|
|
||||||
po->lines[0]->backsector->ceilingheight += momz;
|
|
||||||
// Sal: Remember to check your sectors!
|
|
||||||
// Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap
|
|
||||||
// updating objects in the front one too just added teleporting to ground bugs
|
|
||||||
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2276,11 +2130,7 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
||||||
{
|
{
|
||||||
polyobj_t *po;
|
polyobj_t *po;
|
||||||
polywaypoint_t *th;
|
polywaypoint_t *th;
|
||||||
mobj_t *mo2;
|
|
||||||
mobj_t *first = NULL;
|
mobj_t *first = NULL;
|
||||||
mobj_t *last = NULL;
|
|
||||||
mobj_t *target = NULL;
|
|
||||||
thinker_t *wp;
|
|
||||||
|
|
||||||
if (!(po = Polyobj_GetForNum(pwdata->polyObjNum)))
|
if (!(po = Polyobj_GetForNum(pwdata->polyObjNum)))
|
||||||
{
|
{
|
||||||
|
@ -2304,56 +2154,16 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
||||||
// set fields
|
// set fields
|
||||||
th->polyObjNum = pwdata->polyObjNum;
|
th->polyObjNum = pwdata->polyObjNum;
|
||||||
th->speed = pwdata->speed;
|
th->speed = pwdata->speed;
|
||||||
th->sequence = pwdata->sequence; // Used to specify sequence #
|
th->sequence = pwdata->sequence;
|
||||||
if (pwdata->reverse)
|
th->direction = (pwdata->flags & PWF_REVERSE) ? -1 : 1;
|
||||||
th->direction = -1;
|
|
||||||
else
|
|
||||||
th->direction = 1;
|
|
||||||
|
|
||||||
th->comeback = pwdata->comeback;
|
th->returnbehavior = pwdata->returnbehavior;
|
||||||
th->continuous = pwdata->continuous;
|
if (pwdata->flags & PWF_LOOP)
|
||||||
th->wrap = pwdata->wrap;
|
th->continuous = true;
|
||||||
th->stophere = false;
|
th->stophere = false;
|
||||||
|
|
||||||
// Find the first waypoint we need to use
|
// Find the first waypoint we need to use
|
||||||
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
first = (th->direction == -1) ? P_GetLastWaypoint(th->sequence) : P_GetFirstWaypoint(th->sequence);
|
||||||
{
|
|
||||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mo2 = (mobj_t *)wp;
|
|
||||||
|
|
||||||
if (mo2->type != MT_TUBEWAYPOINT)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (mo2->threshold != th->sequence)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (th->direction == -1) // highest waypoint #
|
|
||||||
{
|
|
||||||
if (mo2->health == 0)
|
|
||||||
last = mo2;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (first == NULL)
|
|
||||||
first = mo2;
|
|
||||||
else if (mo2->health > first->health)
|
|
||||||
first = mo2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // waypoint 0
|
|
||||||
{
|
|
||||||
if (mo2->health == 0)
|
|
||||||
first = mo2;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (last == NULL)
|
|
||||||
last = mo2;
|
|
||||||
else if (mo2->health > last->health)
|
|
||||||
last = mo2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!first)
|
if (!first)
|
||||||
{
|
{
|
||||||
|
@ -2363,77 +2173,16 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hotfix to not crash on single-waypoint sequences -Red
|
// Sanity check: If all waypoints are in the same location,
|
||||||
if (!last)
|
// don't allow the movement to be continuous so we don't get stuck in an infinite loop.
|
||||||
last = first;
|
if (th->continuous && P_IsDegeneratedWaypointSequence(th->sequence))
|
||||||
|
|
||||||
// Set diffx, diffy, diffz
|
|
||||||
// Put these at 0 for now...might not be needed after all.
|
|
||||||
th->diffx = 0;//first->x - po->centerPt.x;
|
|
||||||
th->diffy = 0;//first->y - po->centerPt.y;
|
|
||||||
th->diffz = 0;//first->z - (po->lines[0]->backsector->floorheight + (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2);
|
|
||||||
|
|
||||||
if (last->x == po->centerPt.x
|
|
||||||
&& last->y == po->centerPt.y
|
|
||||||
&& last->z == (po->lines[0]->backsector->floorheight + (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2))
|
|
||||||
{
|
{
|
||||||
// Already at the destination point...
|
CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: All waypoints are in the same location!\n");
|
||||||
if (!th->wrap)
|
th->continuous = false;
|
||||||
{
|
|
||||||
po->thinker = NULL;
|
|
||||||
P_RemoveThinker(&th->thinker);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the actual target movement waypoint
|
th->pointnum = first->health;
|
||||||
target = first;
|
|
||||||
/*for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
|
||||||
{
|
|
||||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mo2 = (mobj_t *)wp;
|
|
||||||
|
|
||||||
if (mo2->type != MT_TUBEWAYPOINT)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (mo2->threshold != th->sequence)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (th->direction == -1) // highest waypoint #
|
|
||||||
{
|
|
||||||
if (mo2->health == first->health - 1)
|
|
||||||
{
|
|
||||||
target = mo2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // waypoint 0
|
|
||||||
{
|
|
||||||
if (mo2->health == first->health + 1)
|
|
||||||
{
|
|
||||||
target = mo2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (!target)
|
|
||||||
{
|
|
||||||
CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: Missing target waypoint!\n");
|
|
||||||
po->thinker = NULL;
|
|
||||||
P_RemoveThinker(&th->thinker);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set pointnum
|
|
||||||
th->pointnum = target->health;
|
|
||||||
th->target = NULL; // set to NULL first so the below doesn't go wrong
|
|
||||||
// Set the mobj as your target! -- Monster Iestyn 27/12/19
|
|
||||||
P_SetTarget(&th->target, target);
|
|
||||||
|
|
||||||
// We don't deal with the mirror crap here, we'll
|
|
||||||
// handle that in the T_Thinker function.
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ typedef enum
|
||||||
POF_SOLID = 0x3, ///< Clips things.
|
POF_SOLID = 0x3, ///< Clips things.
|
||||||
POF_TESTHEIGHT = 0x4, ///< Test line collision with heights
|
POF_TESTHEIGHT = 0x4, ///< Test line collision with heights
|
||||||
POF_RENDERSIDES = 0x8, ///< Renders the sides.
|
POF_RENDERSIDES = 0x8, ///< Renders the sides.
|
||||||
POF_RENDERTOP = 0x10, ///< Renders the top..
|
POF_RENDERTOP = 0x10, ///< Renders the top.
|
||||||
POF_RENDERBOTTOM = 0x20, ///< Renders the bottom.
|
POF_RENDERBOTTOM = 0x20, ///< Renders the bottom.
|
||||||
POF_RENDERPLANES = 0x30, ///< Renders top and bottom.
|
POF_RENDERPLANES = 0x30, ///< Renders top and bottom.
|
||||||
POF_RENDERALL = 0x38, ///< Renders everything.
|
POF_RENDERALL = 0x38, ///< Renders everything.
|
||||||
|
@ -49,6 +49,7 @@ typedef enum
|
||||||
POF_LDEXEC = 0x400, ///< This PO triggers a linedef executor.
|
POF_LDEXEC = 0x400, ///< This PO triggers a linedef executor.
|
||||||
POF_ONESIDE = 0x800, ///< Only use the first side of the linedef.
|
POF_ONESIDE = 0x800, ///< Only use the first side of the linedef.
|
||||||
POF_NOSPECIALS = 0x1000, ///< Don't apply sector specials.
|
POF_NOSPECIALS = 0x1000, ///< Don't apply sector specials.
|
||||||
|
POF_SPLAT = 0x2000, ///< Use splat flat renderer (treat cyan pixels as invisible).
|
||||||
} polyobjflags_e;
|
} polyobjflags_e;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -140,6 +141,14 @@ typedef struct polymove_s
|
||||||
UINT32 angle; // angle along which to move
|
UINT32 angle; // angle along which to move
|
||||||
} polymove_t;
|
} polymove_t;
|
||||||
|
|
||||||
|
// PolyObject waypoint movement return behavior
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
PWR_STOP, // Stop after reaching last waypoint
|
||||||
|
PWR_WRAP, // Wrap back to first waypoint
|
||||||
|
PWR_COMEBACK, // Repeat sequence in reverse
|
||||||
|
} polywaypointreturn_e;
|
||||||
|
|
||||||
typedef struct polywaypoint_s
|
typedef struct polywaypoint_s
|
||||||
{
|
{
|
||||||
thinker_t thinker; // must be first
|
thinker_t thinker; // must be first
|
||||||
|
@ -149,17 +158,9 @@ typedef struct polywaypoint_s
|
||||||
INT32 sequence; // waypoint sequence #
|
INT32 sequence; // waypoint sequence #
|
||||||
INT32 pointnum; // waypoint #
|
INT32 pointnum; // waypoint #
|
||||||
INT32 direction; // 1 for normal, -1 for backwards
|
INT32 direction; // 1 for normal, -1 for backwards
|
||||||
UINT8 comeback; // reverses and comes back when the end is reached
|
UINT8 returnbehavior; // behavior after reaching the last waypoint
|
||||||
UINT8 wrap; // Wrap around waypoints
|
UINT8 continuous; // continuously move - used with PWR_WRAP or PWR_COMEBACK
|
||||||
UINT8 continuous; // continuously move - used with COMEBACK or WRAP
|
|
||||||
UINT8 stophere; // Will stop after it reaches the next waypoint
|
UINT8 stophere; // Will stop after it reaches the next waypoint
|
||||||
|
|
||||||
// Difference between location of PO and location of waypoint (offset)
|
|
||||||
fixed_t diffx;
|
|
||||||
fixed_t diffy;
|
|
||||||
fixed_t diffz;
|
|
||||||
|
|
||||||
mobj_t *target; // next waypoint mobj
|
|
||||||
} polywaypoint_t;
|
} polywaypoint_t;
|
||||||
|
|
||||||
typedef struct polyslidedoor_s
|
typedef struct polyslidedoor_s
|
||||||
|
@ -254,15 +255,19 @@ typedef struct polymovedata_s
|
||||||
UINT8 overRide; // if true, will override any action on the object
|
UINT8 overRide; // if true, will override any action on the object
|
||||||
} polymovedata_t;
|
} polymovedata_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
PWF_REVERSE = 1, // Move through waypoints in reverse order
|
||||||
|
PWF_LOOP = 1<<1, // Loop movement (used with PWR_WRAP or PWR_COMEBACK)
|
||||||
|
} polywaypointflags_e;
|
||||||
|
|
||||||
typedef struct polywaypointdata_s
|
typedef struct polywaypointdata_s
|
||||||
{
|
{
|
||||||
INT32 polyObjNum; // numeric id of polyobject to affect
|
INT32 polyObjNum; // numeric id of polyobject to affect
|
||||||
INT32 sequence; // waypoint sequence #
|
INT32 sequence; // waypoint sequence #
|
||||||
fixed_t speed; // linear speed
|
fixed_t speed; // linear speed
|
||||||
UINT8 reverse; // if true, will go in reverse waypoint order
|
UINT8 returnbehavior; // behavior after reaching the last waypoint
|
||||||
UINT8 comeback; // reverses and comes back when the end is reached
|
UINT8 flags; // PWF_ flags
|
||||||
UINT8 wrap; // Wrap around waypoints
|
|
||||||
UINT8 continuous; // continuously move - used with COMEBACK or WRAP
|
|
||||||
} polywaypointdata_t;
|
} polywaypointdata_t;
|
||||||
|
|
||||||
// polyobject door types
|
// polyobject door types
|
||||||
|
|
|
@ -103,6 +103,8 @@ static void P_NetArchivePlayers(void)
|
||||||
|
|
||||||
// no longer send ticcmds, player name, skin, or color
|
// no longer send ticcmds, player name, skin, or color
|
||||||
|
|
||||||
|
WRITEINT16(save_p, players[i].angleturn);
|
||||||
|
WRITEINT16(save_p, players[i].oldrelangleturn);
|
||||||
WRITEANGLE(save_p, players[i].aiming);
|
WRITEANGLE(save_p, players[i].aiming);
|
||||||
WRITEANGLE(save_p, players[i].drawangle);
|
WRITEANGLE(save_p, players[i].drawangle);
|
||||||
WRITEANGLE(save_p, players[i].viewrollangle);
|
WRITEANGLE(save_p, players[i].viewrollangle);
|
||||||
|
@ -311,6 +313,8 @@ static void P_NetUnArchivePlayers(void)
|
||||||
// sending player names, skin and color should not be necessary at all!
|
// sending player names, skin and color should not be necessary at all!
|
||||||
// (that data is handled in the server config now)
|
// (that data is handled in the server config now)
|
||||||
|
|
||||||
|
players[i].angleturn = READINT16(save_p);
|
||||||
|
players[i].oldrelangleturn = READINT16(save_p);
|
||||||
players[i].aiming = READANGLE(save_p);
|
players[i].aiming = READANGLE(save_p);
|
||||||
players[i].drawangle = READANGLE(save_p);
|
players[i].drawangle = READANGLE(save_p);
|
||||||
players[i].viewrollangle = READANGLE(save_p);
|
players[i].viewrollangle = READANGLE(save_p);
|
||||||
|
@ -717,6 +721,34 @@ static void P_NetUnArchiveColormaps(void)
|
||||||
net_colormaps = NULL;
|
net_colormaps = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void P_NetArchiveWaypoints(void)
|
||||||
|
{
|
||||||
|
INT32 i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < NUMWAYPOINTSEQUENCES; i++)
|
||||||
|
{
|
||||||
|
WRITEUINT16(save_p, numwaypoints[i]);
|
||||||
|
for (j = 0; j < numwaypoints[i]; j++)
|
||||||
|
WRITEUINT32(save_p, waypoints[i][j] ? waypoints[i][j]->mobjnum : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void P_NetUnArchiveWaypoints(void)
|
||||||
|
{
|
||||||
|
INT32 i, j;
|
||||||
|
UINT32 mobjnum;
|
||||||
|
|
||||||
|
for (i = 0; i < NUMWAYPOINTSEQUENCES; i++)
|
||||||
|
{
|
||||||
|
numwaypoints[i] = READUINT16(save_p);
|
||||||
|
for (j = 0; j < numwaypoints[i]; j++)
|
||||||
|
{
|
||||||
|
mobjnum = READUINT32(save_p);
|
||||||
|
waypoints[i][j] = (mobjnum == 0) ? NULL : P_FindNewPosition(mobjnum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// World Archiving
|
/// World Archiving
|
||||||
///
|
///
|
||||||
|
@ -1593,7 +1625,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
|
||||||
if (diff2 & MD2_SKIN)
|
if (diff2 & MD2_SKIN)
|
||||||
WRITEUINT8(save_p, (UINT8)((skin_t *)mobj->skin - skins));
|
WRITEUINT8(save_p, (UINT8)((skin_t *)mobj->skin - skins));
|
||||||
if (diff2 & MD2_COLOR)
|
if (diff2 & MD2_COLOR)
|
||||||
WRITEUINT8(save_p, mobj->color);
|
WRITEUINT16(save_p, mobj->color);
|
||||||
if (diff2 & MD2_EXTVAL1)
|
if (diff2 & MD2_EXTVAL1)
|
||||||
WRITEINT32(save_p, mobj->extravalue1);
|
WRITEINT32(save_p, mobj->extravalue1);
|
||||||
if (diff2 & MD2_EXTVAL2)
|
if (diff2 & MD2_EXTVAL2)
|
||||||
|
@ -1888,8 +1920,7 @@ static void SaveLaserThinker(const thinker_t *th, const UINT8 type)
|
||||||
{
|
{
|
||||||
const laserthink_t *ht = (const void *)th;
|
const laserthink_t *ht = (const void *)th;
|
||||||
WRITEUINT8(save_p, type);
|
WRITEUINT8(save_p, type);
|
||||||
WRITEUINT32(save_p, SaveSector(ht->sector));
|
WRITEINT16(save_p, ht->tag);
|
||||||
WRITEUINT32(save_p, SaveSector(ht->sec));
|
|
||||||
WRITEUINT32(save_p, SaveLine(ht->sourceline));
|
WRITEUINT32(save_p, SaveLine(ht->sourceline));
|
||||||
WRITEUINT8(save_p, ht->nobosses);
|
WRITEUINT8(save_p, ht->nobosses);
|
||||||
}
|
}
|
||||||
|
@ -1996,6 +2027,7 @@ static inline void SavePolyrotatetThinker(const thinker_t *th, const UINT8 type)
|
||||||
WRITEINT32(save_p, ht->polyObjNum);
|
WRITEINT32(save_p, ht->polyObjNum);
|
||||||
WRITEINT32(save_p, ht->speed);
|
WRITEINT32(save_p, ht->speed);
|
||||||
WRITEINT32(save_p, ht->distance);
|
WRITEINT32(save_p, ht->distance);
|
||||||
|
WRITEUINT8(save_p, ht->turnobjs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SavePolymoveThinker(const thinker_t *th, const UINT8 type)
|
static void SavePolymoveThinker(const thinker_t *th, const UINT8 type)
|
||||||
|
@ -2019,14 +2051,9 @@ static void SavePolywaypointThinker(const thinker_t *th, UINT8 type)
|
||||||
WRITEINT32(save_p, ht->sequence);
|
WRITEINT32(save_p, ht->sequence);
|
||||||
WRITEINT32(save_p, ht->pointnum);
|
WRITEINT32(save_p, ht->pointnum);
|
||||||
WRITEINT32(save_p, ht->direction);
|
WRITEINT32(save_p, ht->direction);
|
||||||
WRITEUINT8(save_p, ht->comeback);
|
WRITEUINT8(save_p, ht->returnbehavior);
|
||||||
WRITEUINT8(save_p, ht->wrap);
|
|
||||||
WRITEUINT8(save_p, ht->continuous);
|
WRITEUINT8(save_p, ht->continuous);
|
||||||
WRITEUINT8(save_p, ht->stophere);
|
WRITEUINT8(save_p, ht->stophere);
|
||||||
WRITEFIXED(save_p, ht->diffx);
|
|
||||||
WRITEFIXED(save_p, ht->diffy);
|
|
||||||
WRITEFIXED(save_p, ht->diffz);
|
|
||||||
WRITEUINT32(save_p, SaveMobjnum(ht->target));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SavePolyslidedoorThinker(const thinker_t *th, const UINT8 type)
|
static void SavePolyslidedoorThinker(const thinker_t *th, const UINT8 type)
|
||||||
|
@ -2553,11 +2580,6 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
|
||||||
i = READUINT8(save_p);
|
i = READUINT8(save_p);
|
||||||
mobj->player = &players[i];
|
mobj->player = &players[i];
|
||||||
mobj->player->mo = mobj;
|
mobj->player->mo = mobj;
|
||||||
// added for angle prediction
|
|
||||||
if (consoleplayer == i)
|
|
||||||
localangle = mobj->angle;
|
|
||||||
if (secondarydisplayplayer == i)
|
|
||||||
localangle2 = mobj->angle;
|
|
||||||
}
|
}
|
||||||
if (diff & MD_MOVEDIR)
|
if (diff & MD_MOVEDIR)
|
||||||
mobj->movedir = READANGLE(save_p);
|
mobj->movedir = READANGLE(save_p);
|
||||||
|
@ -2606,7 +2628,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
|
||||||
if (diff2 & MD2_SKIN)
|
if (diff2 & MD2_SKIN)
|
||||||
mobj->skin = &skins[READUINT8(save_p)];
|
mobj->skin = &skins[READUINT8(save_p)];
|
||||||
if (diff2 & MD2_COLOR)
|
if (diff2 & MD2_COLOR)
|
||||||
mobj->color = READUINT8(save_p);
|
mobj->color = READUINT16(save_p);
|
||||||
if (diff2 & MD2_EXTVAL1)
|
if (diff2 & MD2_EXTVAL1)
|
||||||
mobj->extravalue1 = READINT32(save_p);
|
mobj->extravalue1 = READINT32(save_p);
|
||||||
if (diff2 & MD2_EXTVAL2)
|
if (diff2 & MD2_EXTVAL2)
|
||||||
|
@ -2995,16 +3017,10 @@ static thinker_t* LoadPusherThinker(actionf_p1 thinker)
|
||||||
static inline thinker_t* LoadLaserThinker(actionf_p1 thinker)
|
static inline thinker_t* LoadLaserThinker(actionf_p1 thinker)
|
||||||
{
|
{
|
||||||
laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
|
||||||
ffloor_t *rover = NULL;
|
|
||||||
ht->thinker.function.acp1 = thinker;
|
ht->thinker.function.acp1 = thinker;
|
||||||
ht->sector = LoadSector(READUINT32(save_p));
|
ht->tag = READINT16(save_p);
|
||||||
ht->sec = LoadSector(READUINT32(save_p));
|
|
||||||
ht->sourceline = LoadLine(READUINT32(save_p));
|
ht->sourceline = LoadLine(READUINT32(save_p));
|
||||||
ht->nobosses = READUINT8(save_p);
|
ht->nobosses = READUINT8(save_p);
|
||||||
for (rover = ht->sector->ffloors; rover; rover = rover->next)
|
|
||||||
if (rover->secnum == (size_t)(ht->sec - sectors)
|
|
||||||
&& rover->master == ht->sourceline)
|
|
||||||
ht->ffloor = rover;
|
|
||||||
return &ht->thinker;
|
return &ht->thinker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3139,6 +3155,7 @@ static inline thinker_t* LoadPolyrotatetThinker(actionf_p1 thinker)
|
||||||
ht->polyObjNum = READINT32(save_p);
|
ht->polyObjNum = READINT32(save_p);
|
||||||
ht->speed = READINT32(save_p);
|
ht->speed = READINT32(save_p);
|
||||||
ht->distance = READINT32(save_p);
|
ht->distance = READINT32(save_p);
|
||||||
|
ht->turnobjs = READUINT8(save_p);
|
||||||
return &ht->thinker;
|
return &ht->thinker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3164,14 +3181,9 @@ static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker)
|
||||||
ht->sequence = READINT32(save_p);
|
ht->sequence = READINT32(save_p);
|
||||||
ht->pointnum = READINT32(save_p);
|
ht->pointnum = READINT32(save_p);
|
||||||
ht->direction = READINT32(save_p);
|
ht->direction = READINT32(save_p);
|
||||||
ht->comeback = READUINT8(save_p);
|
ht->returnbehavior = READUINT8(save_p);
|
||||||
ht->wrap = READUINT8(save_p);
|
|
||||||
ht->continuous = READUINT8(save_p);
|
ht->continuous = READUINT8(save_p);
|
||||||
ht->stophere = READUINT8(save_p);
|
ht->stophere = READUINT8(save_p);
|
||||||
ht->diffx = READFIXED(save_p);
|
|
||||||
ht->diffy = READFIXED(save_p);
|
|
||||||
ht->diffz = READFIXED(save_p);
|
|
||||||
ht->target = LoadMobj(READUINT32(save_p));
|
|
||||||
return &ht->thinker;
|
return &ht->thinker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3418,7 +3430,6 @@ static void P_NetUnArchiveThinkers(void)
|
||||||
|
|
||||||
case tc_polywaypoint:
|
case tc_polywaypoint:
|
||||||
th = LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint);
|
th = LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint);
|
||||||
restoreNum = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tc_polyslidedoor:
|
case tc_polyslidedoor:
|
||||||
|
@ -3478,7 +3489,6 @@ static void P_NetUnArchiveThinkers(void)
|
||||||
if (restoreNum)
|
if (restoreNum)
|
||||||
{
|
{
|
||||||
executor_t *delay = NULL;
|
executor_t *delay = NULL;
|
||||||
polywaypoint_t *polywp = NULL;
|
|
||||||
UINT32 mobjnum;
|
UINT32 mobjnum;
|
||||||
for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; currentthinker = currentthinker->next)
|
for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; currentthinker = currentthinker->next)
|
||||||
{
|
{
|
||||||
|
@ -3489,15 +3499,6 @@ static void P_NetUnArchiveThinkers(void)
|
||||||
continue;
|
continue;
|
||||||
delay->caller = P_FindNewPosition(mobjnum);
|
delay->caller = P_FindNewPosition(mobjnum);
|
||||||
}
|
}
|
||||||
for (currentthinker = thlist[THINK_POLYOBJ].next; currentthinker != &thlist[THINK_POLYOBJ]; currentthinker = currentthinker->next)
|
|
||||||
{
|
|
||||||
if (currentthinker->function.acp1 != (actionf_p1)T_PolyObjWaypoint)
|
|
||||||
continue;
|
|
||||||
polywp = (void *)currentthinker;
|
|
||||||
if (!(mobjnum = (UINT32)(size_t)polywp->target))
|
|
||||||
continue;
|
|
||||||
polywp->target = P_FindNewPosition(mobjnum);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3807,10 +3808,10 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
|
||||||
if (mapoverride != 0)
|
if (mapoverride != 0)
|
||||||
{
|
{
|
||||||
gamemap = mapoverride;
|
gamemap = mapoverride;
|
||||||
gamecomplete = true;
|
gamecomplete = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
gamecomplete = false;
|
gamecomplete = 0;
|
||||||
|
|
||||||
// gamemap changed; we assume that its map header is always valid,
|
// gamemap changed; we assume that its map header is always valid,
|
||||||
// so make it so
|
// so make it so
|
||||||
|
@ -4070,6 +4071,7 @@ void P_SaveNetGame(void)
|
||||||
P_NetArchiveThinkers();
|
P_NetArchiveThinkers();
|
||||||
P_NetArchiveSpecials();
|
P_NetArchiveSpecials();
|
||||||
P_NetArchiveColormaps();
|
P_NetArchiveColormaps();
|
||||||
|
P_NetArchiveWaypoints();
|
||||||
}
|
}
|
||||||
LUA_Archive();
|
LUA_Archive();
|
||||||
|
|
||||||
|
@ -4108,6 +4110,7 @@ boolean P_LoadNetGame(void)
|
||||||
P_NetUnArchiveThinkers();
|
P_NetUnArchiveThinkers();
|
||||||
P_NetUnArchiveSpecials();
|
P_NetUnArchiveSpecials();
|
||||||
P_NetUnArchiveColormaps();
|
P_NetUnArchiveColormaps();
|
||||||
|
P_NetUnArchiveWaypoints();
|
||||||
P_RelinkPointers();
|
P_RelinkPointers();
|
||||||
P_FinishMobjs();
|
P_FinishMobjs();
|
||||||
}
|
}
|
||||||
|
|
132
src/p_setup.c
132
src/p_setup.c
|
@ -144,6 +144,133 @@ mapthing_t *playerstarts[MAXPLAYERS];
|
||||||
mapthing_t *bluectfstarts[MAXPLAYERS];
|
mapthing_t *bluectfstarts[MAXPLAYERS];
|
||||||
mapthing_t *redctfstarts[MAXPLAYERS];
|
mapthing_t *redctfstarts[MAXPLAYERS];
|
||||||
|
|
||||||
|
// Maintain waypoints
|
||||||
|
mobj_t *waypoints[NUMWAYPOINTSEQUENCES][WAYPOINTSEQUENCESIZE];
|
||||||
|
UINT16 numwaypoints[NUMWAYPOINTSEQUENCES];
|
||||||
|
|
||||||
|
void P_AddWaypoint(UINT8 sequence, UINT8 id, mobj_t *waypoint)
|
||||||
|
{
|
||||||
|
waypoints[sequence][id] = waypoint;
|
||||||
|
if (id >= numwaypoints[sequence])
|
||||||
|
numwaypoints[sequence] = id + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void P_ResetWaypoints(void)
|
||||||
|
{
|
||||||
|
UINT16 sequence, id;
|
||||||
|
for (sequence = 0; sequence < NUMWAYPOINTSEQUENCES; sequence++)
|
||||||
|
{
|
||||||
|
for (id = 0; id < numwaypoints[sequence]; id++)
|
||||||
|
waypoints[sequence][id] = NULL;
|
||||||
|
|
||||||
|
numwaypoints[sequence] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mobj_t *P_GetFirstWaypoint(UINT8 sequence)
|
||||||
|
{
|
||||||
|
return waypoints[sequence][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
mobj_t *P_GetLastWaypoint(UINT8 sequence)
|
||||||
|
{
|
||||||
|
return waypoints[sequence][numwaypoints[sequence] - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
mobj_t *P_GetPreviousWaypoint(mobj_t *current, boolean wrap)
|
||||||
|
{
|
||||||
|
UINT8 sequence = current->threshold;
|
||||||
|
UINT8 id = current->health;
|
||||||
|
|
||||||
|
if (id == 0)
|
||||||
|
{
|
||||||
|
if (!wrap)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
id = numwaypoints[sequence] - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
id--;
|
||||||
|
|
||||||
|
return waypoints[sequence][id];
|
||||||
|
}
|
||||||
|
|
||||||
|
mobj_t *P_GetNextWaypoint(mobj_t *current, boolean wrap)
|
||||||
|
{
|
||||||
|
UINT8 sequence = current->threshold;
|
||||||
|
UINT8 id = current->health;
|
||||||
|
|
||||||
|
if (id == numwaypoints[sequence] - 1)
|
||||||
|
{
|
||||||
|
if (!wrap)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
id = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
id++;
|
||||||
|
|
||||||
|
return waypoints[sequence][id];
|
||||||
|
}
|
||||||
|
|
||||||
|
mobj_t *P_GetClosestWaypoint(UINT8 sequence, mobj_t *mo)
|
||||||
|
{
|
||||||
|
UINT8 wp;
|
||||||
|
mobj_t *mo2, *result = NULL;
|
||||||
|
fixed_t bestdist = 0;
|
||||||
|
fixed_t curdist;
|
||||||
|
|
||||||
|
for (wp = 0; wp < numwaypoints[sequence]; wp++)
|
||||||
|
{
|
||||||
|
mo2 = waypoints[sequence][wp];
|
||||||
|
|
||||||
|
if (!mo2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
curdist = P_AproxDistance(P_AproxDistance(mo->x - mo2->x, mo->y - mo2->y), mo->z - mo2->z);
|
||||||
|
|
||||||
|
if (result && curdist > bestdist)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
result = mo2;
|
||||||
|
bestdist = curdist;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if all waypoints are in the same location
|
||||||
|
boolean P_IsDegeneratedWaypointSequence(UINT8 sequence)
|
||||||
|
{
|
||||||
|
mobj_t *first, *waypoint;
|
||||||
|
UINT8 wp;
|
||||||
|
|
||||||
|
if (numwaypoints[sequence] <= 1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
first = waypoints[sequence][0];
|
||||||
|
|
||||||
|
for (wp = 1; wp < numwaypoints[sequence]; wp++)
|
||||||
|
{
|
||||||
|
waypoint = waypoints[sequence][wp];
|
||||||
|
|
||||||
|
if (!waypoint)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (waypoint->x != first->x)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (waypoint->y != first->y)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (waypoint->z != first->z)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Logs an error about a map being corrupt, then terminate.
|
/** Logs an error about a map being corrupt, then terminate.
|
||||||
* This allows reporting highly technical errors for usefulness, without
|
* This allows reporting highly technical errors for usefulness, without
|
||||||
* confusing a novice map designer who simply needs to run ZenNode.
|
* confusing a novice map designer who simply needs to run ZenNode.
|
||||||
|
@ -217,6 +344,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
|
||||||
mapheaderinfo[num]->actnum = 0;
|
mapheaderinfo[num]->actnum = 0;
|
||||||
mapheaderinfo[num]->typeoflevel = 0;
|
mapheaderinfo[num]->typeoflevel = 0;
|
||||||
mapheaderinfo[num]->nextlevel = (INT16)(i + 1);
|
mapheaderinfo[num]->nextlevel = (INT16)(i + 1);
|
||||||
|
mapheaderinfo[num]->marathonnext = 0;
|
||||||
mapheaderinfo[num]->startrings = 0;
|
mapheaderinfo[num]->startrings = 0;
|
||||||
mapheaderinfo[num]->sstimer = 90;
|
mapheaderinfo[num]->sstimer = 90;
|
||||||
mapheaderinfo[num]->ssspheres = 1;
|
mapheaderinfo[num]->ssspheres = 1;
|
||||||
|
@ -3181,7 +3309,7 @@ static boolean CanSaveLevel(INT32 mapnum)
|
||||||
// Any levels that have the savegame flag can save normally.
|
// Any levels that have the savegame flag can save normally.
|
||||||
// If the game is complete for this save slot, then any level can save!
|
// If the game is complete for this save slot, then any level can save!
|
||||||
// On the other side of the spectrum, if lastmaploaded is 0, then the save file has only just been created and needs to save ASAP!
|
// On the other side of the spectrum, if lastmaploaded is 0, then the save file has only just been created and needs to save ASAP!
|
||||||
return (mapheaderinfo[mapnum-1]->levelflags & LF_SAVEGAME || gamecomplete || !lastmaploaded);
|
return (mapheaderinfo[mapnum-1]->levelflags & LF_SAVEGAME || (gamecomplete != 0) || marathonmode || !lastmaploaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void P_RunSpecialStageWipe(void)
|
static void P_RunSpecialStageWipe(void)
|
||||||
|
@ -3545,6 +3673,8 @@ boolean P_LoadLevel(boolean fromnetsave)
|
||||||
|
|
||||||
P_ResetSpawnpoints();
|
P_ResetSpawnpoints();
|
||||||
|
|
||||||
|
P_ResetWaypoints();
|
||||||
|
|
||||||
P_MapStart();
|
P_MapStart();
|
||||||
|
|
||||||
if (!P_LoadMapFromFile())
|
if (!P_LoadMapFromFile())
|
||||||
|
|
|
@ -259,10 +259,10 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
|
||||||
fracx = los->strace.x + FixedMul(los->strace.dx, frac);
|
fracx = los->strace.x + FixedMul(los->strace.dx, frac);
|
||||||
fracy = los->strace.y + FixedMul(los->strace.dy, frac);
|
fracy = los->strace.y + FixedMul(los->strace.dy, frac);
|
||||||
// calculate sector heights
|
// calculate sector heights
|
||||||
frontf = (front->f_slope) ? P_GetZAt(front->f_slope, fracx, fracy) : front->floorheight;
|
frontf = P_GetSectorFloorZAt (front, fracx, fracy);
|
||||||
frontc = (front->c_slope) ? P_GetZAt(front->c_slope, fracx, fracy) : front->ceilingheight;
|
frontc = P_GetSectorCeilingZAt(front, fracx, fracy);
|
||||||
backf = (back->f_slope) ? P_GetZAt(back->f_slope, fracx, fracy) : back->floorheight;
|
backf = P_GetSectorFloorZAt (back , fracx, fracy);
|
||||||
backc = (back->c_slope) ? P_GetZAt(back->c_slope, fracx, fracy) : back->ceilingheight;
|
backc = P_GetSectorCeilingZAt(back , fracx, fracy);
|
||||||
// crosses a two sided line
|
// crosses a two sided line
|
||||||
// no wall to block sight with?
|
// no wall to block sight with?
|
||||||
if (frontf == backf && frontc == backc
|
if (frontf == backf && frontc == backc
|
||||||
|
@ -312,8 +312,8 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
topz = (*rover->t_slope) ? P_GetZAt(*rover->t_slope, fracx, fracy) : *rover->topheight;
|
topz = P_GetFFloorTopZAt (rover, fracx, fracy);
|
||||||
bottomz = (*rover->b_slope) ? P_GetZAt(*rover->b_slope, fracx, fracy) : *rover->bottomheight;
|
bottomz = P_GetFFloorBottomZAt(rover, fracx, fracy);
|
||||||
topslope = FixedDiv( topz - los->sightzstart, frac);
|
topslope = FixedDiv( topz - los->sightzstart, frac);
|
||||||
bottomslope = FixedDiv(bottomz - los->sightzstart, frac);
|
bottomslope = FixedDiv(bottomz - los->sightzstart, frac);
|
||||||
if (topslope >= los->topslope && bottomslope <= los->bottomslope)
|
if (topslope >= los->topslope && bottomslope <= los->bottomslope)
|
||||||
|
@ -328,8 +328,8 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
topz = (*rover->t_slope) ? P_GetZAt(*rover->t_slope, fracx, fracy) : *rover->topheight;
|
topz = P_GetFFloorTopZAt (rover, fracx, fracy);
|
||||||
bottomz = (*rover->b_slope) ? P_GetZAt(*rover->b_slope, fracx, fracy) : *rover->bottomheight;
|
bottomz = P_GetFFloorBottomZAt(rover, fracx, fracy);
|
||||||
topslope = FixedDiv( topz - los->sightzstart, frac);
|
topslope = FixedDiv( topz - los->sightzstart, frac);
|
||||||
bottomslope = FixedDiv(bottomz - los->sightzstart, frac);
|
bottomslope = FixedDiv(bottomz - los->sightzstart, frac);
|
||||||
if (topslope >= los->topslope && bottomslope <= los->bottomslope)
|
if (topslope >= los->topslope && bottomslope <= los->bottomslope)
|
||||||
|
@ -457,21 +457,10 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*rover->t_slope)
|
topz1 = P_GetFFloorTopZAt (rover, t1->x, t1->y);
|
||||||
{
|
topz2 = P_GetFFloorTopZAt (rover, t2->x, t2->y);
|
||||||
topz1 = P_GetZAt(*rover->t_slope, t1->x, t1->y);
|
bottomz1 = P_GetFFloorBottomZAt(rover, t1->x, t1->y);
|
||||||
topz2 = P_GetZAt(*rover->t_slope, t2->x, t2->y);
|
bottomz2 = P_GetFFloorBottomZAt(rover, t2->x, t2->y);
|
||||||
}
|
|
||||||
else
|
|
||||||
topz1 = topz2 = *rover->topheight;
|
|
||||||
|
|
||||||
if (*rover->b_slope)
|
|
||||||
{
|
|
||||||
bottomz1 = P_GetZAt(*rover->b_slope, t1->x, t1->y);
|
|
||||||
bottomz2 = P_GetZAt(*rover->b_slope, t2->x, t2->y);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
bottomz1 = bottomz2 = *rover->bottomheight;
|
|
||||||
|
|
||||||
// Check for blocking floors here.
|
// Check for blocking floors here.
|
||||||
if ((los.sightzstart < bottomz1 && t2->z >= topz2)
|
if ((los.sightzstart < bottomz1 && t2->z >= topz2)
|
||||||
|
|
|
@ -655,12 +655,8 @@ void P_SpawnSlopes(const boolean fromsave) {
|
||||||
// Various utilities related to slopes
|
// Various utilities related to slopes
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
|
||||||
// P_GetZAt
|
|
||||||
//
|
|
||||||
// Returns the height of the sloped plane at (x, y) as a fixed_t
|
// Returns the height of the sloped plane at (x, y) as a fixed_t
|
||||||
//
|
fixed_t P_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y)
|
||||||
fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y)
|
|
||||||
{
|
{
|
||||||
fixed_t dist = FixedMul(x - slope->o.x, slope->d.x) +
|
fixed_t dist = FixedMul(x - slope->o.x, slope->d.x) +
|
||||||
FixedMul(y - slope->o.y, slope->d.y);
|
FixedMul(y - slope->o.y, slope->d.y);
|
||||||
|
@ -668,6 +664,42 @@ fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y)
|
||||||
return slope->o.z + FixedMul(dist, slope->zdelta);
|
return slope->o.z + FixedMul(dist, slope->zdelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Like P_GetSlopeZAt but falls back to z if slope is NULL
|
||||||
|
fixed_t P_GetZAt(const pslope_t *slope, fixed_t x, fixed_t y, fixed_t z)
|
||||||
|
{
|
||||||
|
return slope ? P_GetSlopeZAt(slope, x, y) : z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the height of the sector floor at (x, y)
|
||||||
|
fixed_t P_GetSectorFloorZAt(const sector_t *sector, fixed_t x, fixed_t y)
|
||||||
|
{
|
||||||
|
return sector->f_slope ? P_GetSlopeZAt(sector->f_slope, x, y) : sector->floorheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the height of the sector ceiling at (x, y)
|
||||||
|
fixed_t P_GetSectorCeilingZAt(const sector_t *sector, fixed_t x, fixed_t y)
|
||||||
|
{
|
||||||
|
return sector->c_slope ? P_GetSlopeZAt(sector->c_slope, x, y) : sector->ceilingheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the height of the FOF top at (x, y)
|
||||||
|
fixed_t P_GetFFloorTopZAt(const ffloor_t *ffloor, fixed_t x, fixed_t y)
|
||||||
|
{
|
||||||
|
return *ffloor->t_slope ? P_GetSlopeZAt(*ffloor->t_slope, x, y) : *ffloor->topheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the height of the FOF bottom at (x, y)
|
||||||
|
fixed_t P_GetFFloorBottomZAt(const ffloor_t *ffloor, fixed_t x, fixed_t y)
|
||||||
|
{
|
||||||
|
return *ffloor->b_slope ? P_GetSlopeZAt(*ffloor->b_slope, x, y) : *ffloor->bottomheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the height of the light list at (x, y)
|
||||||
|
fixed_t P_GetLightZAt(const lightlist_t *light, fixed_t x, fixed_t y)
|
||||||
|
{
|
||||||
|
return light->slope ? P_GetSlopeZAt(light->slope, x, y) : light->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// P_QuantizeMomentumToSlope
|
// P_QuantizeMomentumToSlope
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue