Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 21-installer-nodd
  • 2210-pre1
  • 2210-pre2
  • 2210-rc1
  • 2210-rc2
  • 2210-rc3
  • 2211-pre1
  • 2211-pre2
  • 2211-rc1
  • 2212-pre1
  • 64-gl-log
  • COM_ImmedExecute-lua
  • DJGPP
  • accel-momentum
  • any-resolution
  • appveyor
  • blend-locking
  • blentran
  • blua-unary-not-fix
  • boost-tickrate
  • bustablemobjzfix
  • bustablesoundz
  • cleanup-opengl
  • cleanupmusic
  • cmake-valgrind
  • crawlacommander-sprites
  • cutscene-cleanup
  • dd-music-bypass
  • dd-music-fix
  • delfile2
  • deprecate-lua-dedicated-server
  • dpl-2
  • dropshadows-spawning
  • dynabsp
  • emblem-drawing
  • exchndl-xp-fix
  • few-kart-lua-changes
  • ffloorclip
  • fix-cvar-conflicts
  • fix-opengl-shear-roll
  • flipfuncpointers
  • floorsprite-and-shadow-fake-planes-fix
  • fof-lightlist-fixes
  • font-FUCK
  • font_drawer
  • frictionrefactor
  • fuck-macros-1
  • gamepad-luakeydown
  • gamepad-morefixes
  • gamepad_experiments
  • gametype-refactor
  • ghost-networking
  • gif-splitting
  • gitlab-ci
  • grr-lj
  • hitboxviewer
  • http-download
  • hwr-texture-cache-refactor
  • hwrender2
  • improve-439
  • increase-packet-tics
  • input-display
  • input-display-translucency
  • io
  • joystick-juggling-maz
  • keycodes-only
  • ksf-wadfiles
  • ld413-mp-fix
  • levelstruct
  • libpng-version-support
  • linedef-actions
  • lj-test
  • lol-states
  • loopedsounds
  • lower-unpegged-fix
  • lua-colorlib
  • lua-command-netids
  • lua-extracolormap
  • lua-local
  • lua-minmax-plus-bruh-moments
  • makefile-auto-mingw-gcc
  • makefile-tinkering
  • map-components-signedness-fixes
  • master
  • menu-edits
  • mobj-dispoffset
  • more-cleanup
  • multithread
  • musicdef-lua
  • net-test
  • netcode-refactor
  • netcode-rerefactor
  • netcode-tests
  • netxcmd-refactor
  • next
  • next-test
  • next-test-2021-7-11
  • nextmapspecialoverride
  • nexttest
  • no-airwalking
  • SRB2_release_2.1
  • SRB2_release_2.1.1
  • SRB2_release_2.1.10
  • SRB2_release_2.1.11
  • SRB2_release_2.1.12
  • SRB2_release_2.1.14
  • SRB2_release_2.1.15
  • SRB2_release_2.1.16
  • SRB2_release_2.1.16a
  • SRB2_release_2.1.17
  • SRB2_release_2.1.18
  • SRB2_release_2.1.19
  • SRB2_release_2.1.2
  • SRB2_release_2.1.20
  • SRB2_release_2.1.21
  • SRB2_release_2.1.22
  • SRB2_release_2.1.23
  • SRB2_release_2.1.24
  • SRB2_release_2.1.25
  • SRB2_release_2.1.3
  • SRB2_release_2.1.4
  • SRB2_release_2.1.5
  • SRB2_release_2.1.6
  • SRB2_release_2.1.7
  • SRB2_release_2.1.8
  • SRB2_release_2.1.9
  • SRB2_release_2.2.0
  • SRB2_release_2.2.1
  • SRB2_release_2.2.10
  • SRB2_release_2.2.11
  • SRB2_release_2.2.2
  • SRB2_release_2.2.3
  • SRB2_release_2.2.4
  • SRB2_release_2.2.5
  • SRB2_release_2.2.6
  • SRB2_release_2.2.7
  • SRB2_release_2.2.8
  • SRB2_release_2.2.9
  • td-release-v1.0.0
139 results

Target

Select target project
  • STJr/SRB2
  • Sryder/SRB2
  • wolfy852/SRB2
  • Alpha2244/SRB2
  • Inuyasha/SRB2
  • yoshibot/SRB2
  • TehRealSalt/SRB2
  • PrisimaTF/SRB2
  • Hatninja/SRB2
  • SteelT/SRB2
  • james/SRB2
  • ShaderWraith/SRB2
  • SinnamonLat/SRB2
  • mazmazz_/SRB2
  • filpAM/SRB2
  • chaoloveicemdboy/SRB2
  • Whooa21/SRB2
  • Machturne/SRB2
  • Golden/SRB2
  • Tatsuru/SRB2
  • Snu/SRB2
  • Zwip-Zwap_Zapony/SRB2
  • fickleheart/SRB2
  • alphaRexJames/SRB2
  • JJK/SRB2
  • diskpoppy/SRB2
  • Hannu_Hanhi/SRB2
  • ZipperQR/SRB2
  • kays/SRB2
  • spherallic/SRB2
  • Zippy_Zolton/SRB2
  • namiishere/SRB2
  • Ors/SRB2
  • SMS_Alfredo/SRB2
  • sonic_edge/SRB2
  • lavla/SRB2
  • ashi/SRB2
  • X.organic/SRB2
  • Fafabis/SRB2
  • Meziu/SRB2
  • v-rob/SRB2
  • tertu/SRB2
  • bitten2up/SRB2
  • flarn2006/SRB2
  • Krabs/SRB2
  • clairebun/SRB2
  • Lactozilla/SRB2
  • thehackstack/SRB2
  • Spice/SRB2
  • win8linux/SRB2
  • JohnFrostFox/SRB2
  • talktoneon726/SRB2
  • Wane/SRB2
  • Lamibe/SRB2
  • spectrumuk2/srb-2
  • nerdyminer18/srb-2
  • 256nil/SRB2
  • ARJr/SRB2
  • Alam/SRB2
  • Zenya/srb-2-marathon-demos
  • Acelite/srb-2-archivedmodifications
  • MIDIMan/SRB2
  • Lach/SRB2
  • Frostiikin/bounce-tweaks
  • Jaden/SRB2
  • Tyron/SRB2
  • Astronight/SRB2
  • Mari0shi06/SRB2
  • aiire/SRB2
  • Galactice/SRB2
  • srb2-ports/srb2-dreamcast
  • sdasdas/SRB2
  • chreas/srb-2-vr
  • StarManiaKG/the-story-of-sinically-rocketing-and-botching-the-2nd
  • LoganAir/SRB2
  • NepDisk/srb-2
  • alufolie91/SRB2
  • Felicia.iso/SRB2
  • twi/SRB2
  • BarrelsOFun/SRB2
  • Speed2411/SRB2
  • Leather_Realms/SRB2
  • Ayemar/SRB2
  • Acelite/SRB2
  • VladDoc/SRB2
  • kaldrum/model-features
  • strawberryfox417/SRB2
  • Lugent/SRB2
  • Rem/SRB2
  • Refrag/SRB2
  • Henry_3230/srb-3230
  • TehPuertoRicanSpartan2/tprs-srb2
  • Leminn/srb-2-marathon-stuff
  • chromaticpipe2/SRB2
  • MiguelGustavo15/SRB2
  • Maru/srb-2-tests
  • SilicDev/SRB2
  • UnmatchedBracket/SRB2
  • HybridDog/SRB2
  • xordspar0/SRB2
  • jsjhbewfhh/SRB2
  • Fancy2209/SRB2
  • Lorsoen/SRB2
  • shindoukin/SRB2
  • GamerOfDays/SRB2
  • Craftyawesome/SRB2
  • tenshi-tensai-tennoji/SRB2
  • Scarfdudebalder/SRB2
  • luigi-budd/srb-2-fix-interplag-lockon
  • mskluesner/SRB2
  • johnpetersa19/SRB2
  • Pheazant/SRB2
  • chromaticpipe2/srb2classic
  • romoney5/SRB2
  • PAS/SRB2Classic
  • BlueStaggo/SRB2
  • Jisk/srb-2-beef-jerky
117 results
Select Git revision
  • 1392-2-2-15-attempting-to-draw-a-hud-graphic-with-the-same-lump-name-as-a-lua-script-crashes-the
  • 21-installer-nodd
  • 2210-pre1
  • 2210-pre2
  • 2210-rc1
  • 2210-rc2
  • 2210-rc3
  • 2211-pre1
  • 2211-pre2
  • 2211-rc1
  • 2212-pre1
  • 2212-pre2
  • 2212-pre3
  • 2212-rc1
  • 2213
  • 2214-pre1
  • 2214-pre2
  • 2214-pre3
  • 2214-pre4
  • 2_2_12
  • 64-gl-log
  • COM_ImmedExecute-lua
  • DJGPP
  • accel-momentum
  • acs
  • action-args
  • alpha-fixes
  • any-resolution
  • appveyor
  • blend-locking
  • blentran
  • blua-unary-not-fix
  • boost-tickrate
  • bustablesoundz
  • cleanup-opengl
  • cleanupmusic
  • clipmidtex
  • cmake-valgrind
  • crawlacommander-sprites
  • custom-map-names
  • custom-teams
  • cutscene-cleanup
  • dd-music-bypass
  • dd-music-fix
  • delfile2
  • deprecate-lua-dedicated-server
  • dpl-2
  • dropshadows-spawning
  • dynabsp
  • emblem-drawing
  • exchndl-xp-fix
  • extra-textures
  • few-kart-lua-changes
  • ffloorclip
  • fix-167
  • fix-cvar-conflicts
  • fix-opengl-parameter-crash
  • fix-opengl-shear-roll
  • flipfuncpointers
  • fof-lightlist-fixes
  • font-FUCK
  • frictionrefactor
  • fuck-macros-1
  • gamepad-luakeydown
  • gamepad-morefixes
  • gamepad_experiments
  • gametype-refactor
  • gametype-refactor-1
  • gametype-refactor-player-spawns
  • ghost-networking
  • gif-splitting
  • grr-lj
  • hitboxviewer
  • hwr-texture-cache-refactor
  • hwrender2
  • improve-439
  • increase-maxconditionsets
  • increase-packet-tics
  • input-display
  • input-display-translucency
  • io
  • joystick-juggling-maz
  • just-in-case
  • keycodes-only
  • ksf-wadfiles
  • ld413-mp-fix
  • levelstruct
  • libpng-version-support
  • linedef-actions
  • lj-test
  • lol-states
  • loopedsounds
  • lower-unpegged-fix
  • lua-change-gametype
  • lua-command-netids
  • lua-gfx-2
  • lua-gfx-sprites
  • lua-local
  • makefile-auto-mingw-gcc
  • makefile-tinkering
  • SRB2_release_2.1
  • SRB2_release_2.1.1
  • SRB2_release_2.1.10
  • SRB2_release_2.1.11
  • SRB2_release_2.1.12
  • SRB2_release_2.1.14
  • SRB2_release_2.1.15
  • SRB2_release_2.1.16
  • SRB2_release_2.1.16a
  • SRB2_release_2.1.17
  • SRB2_release_2.1.18
  • SRB2_release_2.1.19
  • SRB2_release_2.1.2
  • SRB2_release_2.1.20
  • SRB2_release_2.1.21
  • SRB2_release_2.1.22
  • SRB2_release_2.1.23
  • SRB2_release_2.1.24
  • SRB2_release_2.1.25
  • SRB2_release_2.1.3
  • SRB2_release_2.1.4
  • SRB2_release_2.1.5
  • SRB2_release_2.1.6
  • SRB2_release_2.1.7
  • SRB2_release_2.1.8
  • SRB2_release_2.1.9
  • SRB2_release_2.2.0
  • SRB2_release_2.2.1
  • SRB2_release_2.2.10
  • SRB2_release_2.2.11
  • SRB2_release_2.2.12
  • SRB2_release_2.2.13
  • SRB2_release_2.2.15
  • SRB2_release_2.2.2
  • SRB2_release_2.2.3
  • SRB2_release_2.2.4
  • SRB2_release_2.2.5
  • SRB2_release_2.2.6
  • SRB2_release_2.2.7
  • SRB2_release_2.2.8
  • SRB2_release_2.2.9
  • td-release-v1.0.0
142 results
Show changes
...@@ -453,6 +453,11 @@ static void readPlayer(MYFILE *f, INT32 num) ...@@ -453,6 +453,11 @@ static void readPlayer(MYFILE *f, INT32 num)
char *word2; char *word2;
INT32 i; INT32 i;
boolean slotfound = false; boolean slotfound = false;
UINT8 mpslot;
for (mpslot = 0; mpslot < 32; mpslot++)
if (MP_PlayerMenu[mpslot].status != IT_CALL)
break;
DEH_WriteUndoline("PLAYERTEXT", description[num].notes, UNDO_ENDTEXT); DEH_WriteUndoline("PLAYERTEXT", description[num].notes, UNDO_ENDTEXT);
...@@ -508,6 +513,9 @@ static void readPlayer(MYFILE *f, INT32 num) ...@@ -508,6 +513,9 @@ static void readPlayer(MYFILE *f, INT32 num)
} }
description[num].notes[strlen(description[num].notes)-1] = '\0'; description[num].notes[strlen(description[num].notes)-1] = '\0';
description[num].notes[i] = '\0'; description[num].notes[i] = '\0';
if (MP_PlayerMenu[mpslot].status == IT_CALL)
strcpy(MP_Description[mpslot].notes, description[num].notes);
continue; continue;
} }
...@@ -584,6 +592,12 @@ static void readPlayer(MYFILE *f, INT32 num) ...@@ -584,6 +592,12 @@ static void readPlayer(MYFILE *f, INT32 num)
strlcpy(description[num].skinname, word2, sizeof description[num].skinname); strlcpy(description[num].skinname, word2, sizeof description[num].skinname);
strlwr(description[num].skinname); strlwr(description[num].skinname);
if (!strpbrk(word2,"&"))
{
MP_PlayerMenu[mpslot].status = IT_CALL;
strlcpy(MP_Description[mpslot].skinname, description[num].skinname, MAXPLAYERNAME+1);
}
} }
else else
deh_warning("readPlayer %d: unknown word '%s'", num, word); deh_warning("readPlayer %d: unknown word '%s'", num, word);
...@@ -3789,52 +3803,50 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit ...@@ -3789,52 +3803,50 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Thok // Thok
"S_THOK", "S_THOK",
// Player
"S_PLAY_STND", "S_PLAY_STND",
"S_PLAY_TAP1", "S_PLAY_WAIT",
"S_PLAY_TAP2", "S_PLAY_WALK",
"S_PLAY_RUN1", "S_PLAY_RUN",
"S_PLAY_RUN2",
"S_PLAY_RUN3",
"S_PLAY_RUN4",
"S_PLAY_RUN5",
"S_PLAY_RUN6",
"S_PLAY_RUN7",
"S_PLAY_RUN8",
"S_PLAY_SPD1",
"S_PLAY_SPD2",
"S_PLAY_SPD3",
"S_PLAY_SPD4",
"S_PLAY_ATK1",
"S_PLAY_ATK2",
"S_PLAY_ATK3",
"S_PLAY_ATK4",
"S_PLAY_SPRING",
"S_PLAY_FALL1",
"S_PLAY_FALL2",
"S_PLAY_ABL1",
"S_PLAY_ABL2",
"S_PLAY_SPC1",
"S_PLAY_SPC2",
"S_PLAY_SPC3",
"S_PLAY_SPC4",
"S_PLAY_CLIMB1",
"S_PLAY_CLIMB2",
"S_PLAY_CLIMB3",
"S_PLAY_CLIMB4",
"S_PLAY_CLIMB5",
"S_PLAY_GASP",
"S_PLAY_PAIN", "S_PLAY_PAIN",
"S_PLAY_DIE", "S_PLAY_DEAD",
"S_PLAY_TEETER1", "S_PLAY_DRWN",
"S_PLAY_TEETER2", "S_PLAY_SPIN",
"S_PLAY_CARRY", "S_PLAY_DASH",
"S_PLAY_SUPERSTAND", "S_PLAY_GASP",
"S_PLAY_SUPERWALK1", "S_PLAY_JUMP",
"S_PLAY_SUPERWALK2", "S_PLAY_SPRING",
"S_PLAY_SUPERFLY1", "S_PLAY_FALL",
"S_PLAY_SUPERFLY2", "S_PLAY_EDGE",
"S_PLAY_SUPERTEETER", "S_PLAY_RIDE",
"S_PLAY_SUPERHIT",
// CA_FLY
"S_PLAY_FLY",
"S_PLAY_FLY_TIRED",
// CA_GLIDEANDCLIMB
"S_PLAY_GLIDE",
"S_PLAY_CLING",
"S_PLAY_CLIMB",
// SF_SUPERANIMS
"S_PLAY_SUPER_STND",
"S_PLAY_SUPER_WALK",
"S_PLAY_SUPER_RUN",
"S_PLAY_SUPER_PAIN",
"S_PLAY_SUPER_STUN",
"S_PLAY_SUPER_DEAD",
"S_PLAY_SUPER_DRWN",
"S_PLAY_SUPER_SPIN",
"S_PLAY_SUPER_GASP",
"S_PLAY_SUPER_JUMP",
"S_PLAY_SUPER_SPRING",
"S_PLAY_SUPER_FALL",
"S_PLAY_SUPER_EDGE",
"S_PLAY_SUPER_RIDE",
"S_PLAY_SUPER_FLOAT",
// SF_SUPER
"S_PLAY_SUPERTRANS1", "S_PLAY_SUPERTRANS1",
"S_PLAY_SUPERTRANS2", "S_PLAY_SUPERTRANS2",
"S_PLAY_SUPERTRANS3", "S_PLAY_SUPERTRANS3",
...@@ -4585,7 +4597,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit ...@@ -4585,7 +4597,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// S_PLAY_TAP1 // S_PLAY_TAP1
"S_METALSONIC_WAIT1", "S_METALSONIC_WAIT1",
"S_METALSONIC_WAIT2", "S_METALSONIC_WAIT2",
// S_PLAY_RUN1 // S_PLAY_WALK
"S_METALSONIC_WALK1", "S_METALSONIC_WALK1",
"S_METALSONIC_WALK2", "S_METALSONIC_WALK2",
"S_METALSONIC_WALK3", "S_METALSONIC_WALK3",
...@@ -6121,10 +6133,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit ...@@ -6121,10 +6133,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SRB1_GENREX1", "S_SRB1_GENREX1",
"S_SRB1_GENREX2", "S_SRB1_GENREX2",
#ifdef SEENAMES
"S_NAMECHECK",
#endif
}; };
// RegEx to generate this from info.h: ^\tMT_([^,]+), --> \t"MT_\1", // RegEx to generate this from info.h: ^\tMT_([^,]+), --> \t"MT_\1",
...@@ -6631,9 +6639,6 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s ...@@ -6631,9 +6639,6 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_SRB1_METALSONIC", "MT_SRB1_METALSONIC",
"MT_SRB1_GOLDBOT", "MT_SRB1_GOLDBOT",
"MT_SRB1_GENREX", "MT_SRB1_GENREX",
#ifdef SEENAMES
"MT_NAMECHECK",
#endif
}; };
static const char *const MOBJFLAG_LIST[] = { static const char *const MOBJFLAG_LIST[] = {
...@@ -6682,7 +6687,6 @@ static const char *const MOBJFLAG2_LIST[] = { ...@@ -6682,7 +6687,6 @@ static const char *const MOBJFLAG2_LIST[] = {
"EXPLOSION", // Thrown ring has explosive properties "EXPLOSION", // Thrown ring has explosive properties
"SCATTER", // Thrown ring has scatter properties "SCATTER", // Thrown ring has scatter properties
"BEYONDTHEGRAVE",// Source of this missile has died and has since respawned. "BEYONDTHEGRAVE",// Source of this missile has died and has since respawned.
"PUSHED", // Mobj was already pushed this tic
"SLIDEPUSH", // MF_PUSHABLE that pushes continuously. "SLIDEPUSH", // MF_PUSHABLE that pushes continuously.
"CLASSICPUSH", // Drops straight down when object has negative Z. "CLASSICPUSH", // Drops straight down when object has negative Z.
"STANDONME", // While not pushable, stand on me anyway. "STANDONME", // While not pushable, stand on me anyway.
...@@ -6711,7 +6715,7 @@ static const char *const MOBJEFLAG_LIST[] = { ...@@ -6711,7 +6715,7 @@ static const char *const MOBJEFLAG_LIST[] = {
"JUSTSTEPPEDDOWN", // used for ramp sectors "JUSTSTEPPEDDOWN", // used for ramp sectors
"VERTICALFLIP", // Vertically flip sprite/allow upside-down physics "VERTICALFLIP", // Vertically flip sprite/allow upside-down physics
"GOOWATER", // Goo water "GOOWATER", // Goo water
"\x01", // free: 1<<7 (name un-matchable) "PUSHED", // Mobj was already pushed this tic
"SPRUNG", // Mobj was already sprung this tic "SPRUNG", // Mobj was already sprung this tic
"APPLYPMOMZ", // Platform movement "APPLYPMOMZ", // Platform movement
NULL NULL
...@@ -6823,27 +6827,31 @@ static const char *COLOR_ENUMS[] = { ...@@ -6823,27 +6827,31 @@ static const char *COLOR_ENUMS[] = {
"SILVER", // SKINCOLOR_SILVER "SILVER", // SKINCOLOR_SILVER
"GREY", // SKINCOLOR_GREY "GREY", // SKINCOLOR_GREY
"BLACK", // SKINCOLOR_BLACK "BLACK", // SKINCOLOR_BLACK
"CYAN", // SKINCOLOR_CYAN
"TEAL", // SKINCOLOR_TEAL
"STEELBLUE", // SKINCOLOR_STEELBLUE
"BLUE", // SKINCOLOR_BLUE
"PEACH", // SKINCOLOR_PEACH
"TAN", // SKINCOLOR_TAN
"PINK", // SKINCOLOR_PINK
"LAVENDER", // SKINCOLOR_LAVENDER
"PURPLE", // SKINCOLOR_PURPLE
"ORANGE", // SKINCOLOR_ORANGE
"ROSEWOOD", // SKINCOLOR_ROSEWOOD
"BEIGE", // SKINCOLOR_BEIGE "BEIGE", // SKINCOLOR_BEIGE
"PEACH", // SKINCOLOR_PEACH
"BROWN", // SKINCOLOR_BROWN "BROWN", // SKINCOLOR_BROWN
"RED", // SKINCOLOR_RED "RED", // SKINCOLOR_RED
"DARKRED", // SKINCOLOR_DARKRED "CRIMSON", // SKINCOLOR_CRIMSON
"NEONGREEN", // SKINCOLOR_NEONGREEN "ORANGE", // SKINCOLOR_ORANGE
"GREEN", // SKINCOLOR_GREEN "RUST", // SKINCOLOR_RUST
"ZIM", // SKINCOLOR_ZIM "GOLD", // SKINCOLOR_GOLD
"OLIVE", // SKINCOLOR_OLIVE
"YELLOW", // SKINCOLOR_YELLOW "YELLOW", // SKINCOLOR_YELLOW
"GOLD", // SKINCOLOR_GOLD "TAN", // SKINCOLOR_TAN
"MOSS", // SKINCOLOR_MOSS
"PERIDOT", // SKINCOLOR_PERIDOT
"GREEN", // SKINCOLOR_GREEN
"EMERALD", // SKINCOLOR_EMERALD
"AQUA", // SKINCOLOR_AQUA
"TEAL", // SKINCOLOR_TEAL
"CYAN", // SKINCOLOR_CYAN
"BLUE", // SKINCOLOR_BLUE
"AZURE", // SKINCOLOR_AZURE
"PASTEL", // SKINCOLOR_PASTEL
"PURPLE", // SKINCOLOR_PURPLE
"LAVENDER", // SKINCOLOR_LAVENDER
"MAGENTA", // SKINCOLOR_MAGENTA
"PINK", // SKINCOLOR_PINK
"ROSY", // SKINCOLOR_ROSY
// Super special awesome Super flashing colors! // Super special awesome Super flashing colors!
"SUPER1", // SKINCOLOR_SUPER1 "SUPER1", // SKINCOLOR_SUPER1
"SUPER2", // SKINCOLOR_SUPER2, "SUPER2", // SKINCOLOR_SUPER2,
...@@ -7183,11 +7191,15 @@ struct { ...@@ -7183,11 +7191,15 @@ struct {
// Player animation (panim_t) // Player animation (panim_t)
{"PA_ETC",PA_ETC}, {"PA_ETC",PA_ETC},
{"PA_IDLE",PA_IDLE}, {"PA_IDLE",PA_IDLE},
{"PA_EDGE",PA_EDGE},
{"PA_WALK",PA_WALK}, {"PA_WALK",PA_WALK},
{"PA_RUN",PA_RUN}, {"PA_RUN",PA_RUN},
{"PA_PAIN",PA_PAIN},
{"PA_ROLL",PA_ROLL}, {"PA_ROLL",PA_ROLL},
{"PA_SPRING",PA_SPRING},
{"PA_FALL",PA_FALL}, {"PA_FALL",PA_FALL},
{"PA_ABILITY",PA_ABILITY}, {"PA_ABILITY",PA_ABILITY},
{"PA_RIDE",PA_RIDE},
// Current weapon // Current weapon
{"WEP_AUTO",WEP_AUTO}, {"WEP_AUTO",WEP_AUTO},
...@@ -8049,6 +8061,27 @@ static inline int lib_getenum(lua_State *L) ...@@ -8049,6 +8061,27 @@ static inline int lib_getenum(lua_State *L)
if (mathlib) return luaL_error(L, "sprite '%s' could not be found.\n", word); if (mathlib) return luaL_error(L, "sprite '%s' could not be found.\n", word);
return 0; return 0;
} }
else if (fastncmp("SPR2_",word,4)) {
p = word+5;
for (i = 0; i < NUMPLAYERSPRITES; i++)
if (!spr2names[i][4])
{
// special 3-char cases, e.g. SPR2_RUN
// the spr2names entry will have "_" on the end, as in "RUN_"
if (spr2names[i][3] == '_' && !p[3]) {
if (fastncmp(p,spr2names[i],3)) {
lua_pushinteger(L, i);
return 1;
}
}
else if (fastncmp(p,spr2names[i],4)) {
lua_pushinteger(L, i);
return 1;
}
}
if (mathlib) return luaL_error(L, "player sprite '%s' could not be found.\n", word);
return 0;
}
else if (!mathlib && fastncmp("sfx_",word,4)) { else if (!mathlib && fastncmp("sfx_",word,4)) {
p = word+4; p = word+4;
for (i = 0; i < NUMSFX; i++) for (i = 0; i < NUMSFX; i++)
......
...@@ -139,7 +139,7 @@ ...@@ -139,7 +139,7 @@
extern FILE *logstream; extern FILE *logstream;
#endif #endif
//#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3 #define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3
#ifdef DEVELOP #ifdef DEVELOP
#define VERSION 0 // Game version #define VERSION 0 // Game version
#define SUBVERSION 0 // more precise version number #define SUBVERSION 0 // more precise version number
...@@ -148,10 +148,10 @@ extern FILE *logstream; ...@@ -148,10 +148,10 @@ extern FILE *logstream;
// most interface strings are ignored in development mode. // most interface strings are ignored in development mode.
// we use comprevision and compbranch instead. // we use comprevision and compbranch instead.
#else #else
#define VERSION 201 // Game version #define VERSION 202 // Game version
#define SUBVERSION 15 // more precise version number #define SUBVERSION 0 // more precise version number
#define VERSIONSTRING "v2.1.15" #define VERSIONSTRING "v2.2"
#define VERSIONSTRINGW L"v2.1.15" #define VERSIONSTRINGW L"v2.2"
// 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
...@@ -202,7 +202,7 @@ extern FILE *logstream; ...@@ -202,7 +202,7 @@ extern FILE *logstream;
// and should not be changed unless you have merged changes between versions of SRB2 // and should not be changed unless you have merged changes between versions of SRB2
// (such as 2.0.4 to 2.0.5, etc) into your working copy. // (such as 2.0.4 to 2.0.5, etc) into your working copy.
// Will always resemble the versionstring, 205 = 2.0.5, 210 = 2.1, etc. // Will always resemble the versionstring, 205 = 2.0.5, 210 = 2.1, etc.
#define CODEBASE 210 #define CODEBASE 220
// The Modification ID; must be obtained from Inuyasha ( http://mb.srb2.org/private.php?do=newpm&u=2604 ). // The Modification ID; must be obtained from Inuyasha ( http://mb.srb2.org/private.php?do=newpm&u=2604 ).
// DO NOT try to set this otherwise, or your modification will be unplayable through the Master Server. // DO NOT try to set this otherwise, or your modification will be unplayable through the Master Server.
...@@ -220,8 +220,8 @@ extern FILE *logstream; ...@@ -220,8 +220,8 @@ extern FILE *logstream;
// The maximum number of players, multiplayer/networking. // The maximum number of players, multiplayer/networking.
// NOTE: it needs more than this to increase the number of players... // NOTE: it needs more than this to increase the number of players...
#define MAXPLAYERS 32 #define MAXPLAYERS 64
#define MAXSKINS MAXPLAYERS #define MAXSKINS 32
#define PLAYERSMASK (MAXPLAYERS-1) #define PLAYERSMASK (MAXPLAYERS-1)
#define MAXPLAYERNAME 21 #define MAXPLAYERNAME 21
...@@ -232,27 +232,31 @@ typedef enum ...@@ -232,27 +232,31 @@ typedef enum
SKINCOLOR_SILVER, SKINCOLOR_SILVER,
SKINCOLOR_GREY, SKINCOLOR_GREY,
SKINCOLOR_BLACK, SKINCOLOR_BLACK,
SKINCOLOR_CYAN,
SKINCOLOR_TEAL,
SKINCOLOR_STEELBLUE,
SKINCOLOR_BLUE,
SKINCOLOR_PEACH,
SKINCOLOR_TAN,
SKINCOLOR_PINK,
SKINCOLOR_LAVENDER,
SKINCOLOR_PURPLE,
SKINCOLOR_ORANGE,
SKINCOLOR_ROSEWOOD,
SKINCOLOR_BEIGE, SKINCOLOR_BEIGE,
SKINCOLOR_PEACH,
SKINCOLOR_BROWN, SKINCOLOR_BROWN,
SKINCOLOR_RED, SKINCOLOR_RED,
SKINCOLOR_DARKRED, SKINCOLOR_CRIMSON,
SKINCOLOR_NEONGREEN, SKINCOLOR_ORANGE,
SKINCOLOR_GREEN, SKINCOLOR_RUST,
SKINCOLOR_ZIM,
SKINCOLOR_OLIVE,
SKINCOLOR_YELLOW,
SKINCOLOR_GOLD, SKINCOLOR_GOLD,
SKINCOLOR_YELLOW,
SKINCOLOR_TAN,
SKINCOLOR_MOSS,
SKINCOLOR_PERIDOT,
SKINCOLOR_GREEN,
SKINCOLOR_EMERALD,
SKINCOLOR_AQUA,
SKINCOLOR_TEAL,
SKINCOLOR_CYAN,
SKINCOLOR_BLUE,
SKINCOLOR_AZURE,
SKINCOLOR_PASTEL,
SKINCOLOR_PURPLE,
SKINCOLOR_LAVENDER,
SKINCOLOR_MAGENTA,
SKINCOLOR_PINK,
SKINCOLOR_ROSY,
// Careful! MAXSKINCOLORS cannot be greater than 0x20! // Careful! MAXSKINCOLORS cannot be greater than 0x20!
MAXSKINCOLORS, MAXSKINCOLORS,
...@@ -441,17 +445,9 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; ...@@ -441,17 +445,9 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Allows gravity changes in netgames, no questions asked. /// Allows gravity changes in netgames, no questions asked.
//#define NETGAME_GRAVITY //#define NETGAME_GRAVITY
/// Dumps the contents of a network save game upon consistency failure for debugging.
//#define DUMPCONSISTENCY
/// Polyobject fake flat code /// Polyobject fake flat code
#define POLYOBJECTS_PLANES #define POLYOBJECTS_PLANES
/// Improved way of dealing with ping values and a ping limit.
#define NEWPING
/// See name of player in your crosshair
#define SEENAMES
/// Who put weights on my recycler? ... Inuyasha did. /// Who put weights on my recycler? ... Inuyasha did.
/// \note XMOD port. /// \note XMOD port.
......
...@@ -480,7 +480,7 @@ extern boolean singletics; ...@@ -480,7 +480,7 @@ extern boolean singletics;
extern consvar_t cv_timetic; // display high resolution timer extern consvar_t cv_timetic; // display high resolution timer
extern consvar_t cv_forceskin; // force clients to use the server's skin extern consvar_t cv_forceskin; // force clients to use the server's skin
extern consvar_t cv_downloading; // allow clients to downloading WADs. extern consvar_t cv_downloading; // allow clients to downloading WADs.
extern ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS]; extern ticcmd_t netcmds[MAXPLAYERS];
extern INT32 adminplayer, serverplayer; extern INT32 adminplayer, serverplayer;
/// \note put these in d_clisrv outright? /// \note put these in d_clisrv outright?
......
...@@ -986,6 +986,7 @@ static const char *credits[] = { ...@@ -986,6 +986,7 @@ static const char *credits[] = {
"\"chi.miru\"", // Red's secret weapon, the REAL reason slopes exist (also helped port drawing code from ZDoom) "\"chi.miru\"", // Red's secret weapon, the REAL reason slopes exist (also helped port drawing code from ZDoom)
"Andrew \"orospakr\" Clunis", "Andrew \"orospakr\" Clunis",
"Gregor \"Oogaland\" Dick", "Gregor \"Oogaland\" Dick",
"Vivian \"toaster\" Grannell",
"Julio \"Chaos Zero 64\" Guir", "Julio \"Chaos Zero 64\" Guir",
"\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog "\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog
"Matthew \"Shuffle\" Marsalko", "Matthew \"Shuffle\" Marsalko",
...@@ -1001,6 +1002,7 @@ static const char *credits[] = { ...@@ -1001,6 +1002,7 @@ static const char *credits[] = {
"Jim \"MotorRoach\" DeMello", "Jim \"MotorRoach\" DeMello",
"Desmond \"Blade\" DesJardins", "Desmond \"Blade\" DesJardins",
"Sherman \"CoatRack\" DesJardins", "Sherman \"CoatRack\" DesJardins",
"Vivian \"toaster\" Grannell",
"Andrew \"Senku Niola\" Moran", "Andrew \"Senku Niola\" Moran",
"David \"Instant Sonic\" Spencer Jr.", "David \"Instant Sonic\" Spencer Jr.",
"\"SSNTails\"", "\"SSNTails\"",
...@@ -1035,6 +1037,7 @@ static const char *credits[] = { ...@@ -1035,6 +1037,7 @@ static const char *credits[] = {
"Sherman \"CoatRack\" DesJardins", "Sherman \"CoatRack\" DesJardins",
"Ben \"Mystic\" Geyer", "Ben \"Mystic\" Geyer",
"Nathan \"Jazz\" Giroux", "Nathan \"Jazz\" Giroux",
"Vivian \"toaster\" Grannell",
"Dan \"Blitzzo\" Hagerstrand", "Dan \"Blitzzo\" Hagerstrand",
"Kepa \"Nev3r\" Iceta", "Kepa \"Nev3r\" Iceta",
"Thomas \"Shadow Hog\" Igoe", "Thomas \"Shadow Hog\" Igoe",
...@@ -1725,10 +1728,7 @@ static void F_AdvanceToNextScene(void) ...@@ -1725,10 +1728,7 @@ static void F_AdvanceToNextScene(void)
void F_EndCutScene(void) void F_EndCutScene(void)
{ {
if (runningprecutscene) if (runningprecutscene)
{ D_MapChange(gamemap, gametype, ultimatemode, precutresetplayer, 0, true, false);
if (server)
D_MapChange(gamemap, gametype, ultimatemode, precutresetplayer, 0, true, false);
}
else else
{ {
if (cutnum == creditscutscene-1) if (cutnum == creditscutscene-1)
......
...@@ -348,7 +348,7 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu) ...@@ -348,7 +348,7 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
for (;;) for (;;)
{ {
// get fademask first so we can tell if it exists or not // get fademask first so we can tell if it exists or not
fmask = F_GetFadeMask(wipetype, wipeframe++); fmask = F_GetFadeMask(wipetype, wipeframe);
if (!fmask) if (!fmask)
break; break;
...@@ -357,6 +357,9 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu) ...@@ -357,6 +357,9 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
I_Sleep(); I_Sleep();
lastwipetic = nowtime; lastwipetic = nowtime;
if (nowtime % NEWTICRATERATIO == 0)
wipeframe++;
#ifdef HWRENDER #ifdef HWRENDER
if (rendermode == render_opengl) if (rendermode == render_opengl)
HWR_DoWipe(wipetype, wipeframe-1); // send in the wipe type and wipeframe because we need to cache the graphic HWR_DoWipe(wipetype, wipeframe-1); // send in the wipe type and wipeframe because we need to cache the graphic
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include "b_bot.h" #include "b_bot.h"
#include "m_cond.h" // condition sets #include "m_cond.h" // condition sets
#include "md5.h" // demo checksums #include "md5.h" // demo checksums
#include "d_enet.h"
gameaction_t gameaction; gameaction_t gameaction;
gamestate_t gamestate = GS_NULL; gamestate_t gamestate = GS_NULL;
...@@ -125,7 +126,7 @@ boolean useNightsSS = false; ...@@ -125,7 +126,7 @@ boolean useNightsSS = false;
UINT8 skincolor_redteam = SKINCOLOR_RED; UINT8 skincolor_redteam = SKINCOLOR_RED;
UINT8 skincolor_blueteam = SKINCOLOR_BLUE; UINT8 skincolor_blueteam = SKINCOLOR_BLUE;
UINT8 skincolor_redring = SKINCOLOR_RED; UINT8 skincolor_redring = SKINCOLOR_RED;
UINT8 skincolor_bluering = SKINCOLOR_STEELBLUE; UINT8 skincolor_bluering = SKINCOLOR_AZURE;
tic_t countdowntimer = 0; tic_t countdowntimer = 0;
boolean countdowntimeup = false; boolean countdowntimeup = false;
...@@ -439,50 +440,7 @@ consvar_t cv_fireaxis2 = {"joyaxis2_fire", "None", CV_SAVE, joyaxis_cons_t, NULL ...@@ -439,50 +440,7 @@ consvar_t cv_fireaxis2 = {"joyaxis2_fire", "None", CV_SAVE, joyaxis_cons_t, NULL
consvar_t cv_firenaxis2 = {"joyaxis2_firenormal", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_firenaxis2 = {"joyaxis2_firenormal", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif #endif
char player_names[MAXPLAYERS][MAXPLAYERNAME+1];
#if MAXPLAYERS > 32
#error "please update player_name table using the new value for MAXPLAYERS"
#endif
#ifdef SEENAMES
player_t *seenplayer; // player we're aiming at right now
#endif
char player_names[MAXPLAYERS][MAXPLAYERNAME+1] =
{
"Player 1",
"Player 2",
"Player 3",
"Player 4",
"Player 5",
"Player 6",
"Player 7",
"Player 8",
"Player 9",
"Player 10",
"Player 11",
"Player 12",
"Player 13",
"Player 14",
"Player 15",
"Player 16",
"Player 17",
"Player 18",
"Player 19",
"Player 20",
"Player 21",
"Player 22",
"Player 23",
"Player 24",
"Player 25",
"Player 26",
"Player 27",
"Player 28",
"Player 29",
"Player 30",
"Player 31",
"Player 32"
};
INT16 rw_maximums[NUM_WEAPONS] = INT16 rw_maximums[NUM_WEAPONS] =
{ {
...@@ -946,7 +904,7 @@ angle_t localangle, localangle2; ...@@ -946,7 +904,7 @@ angle_t localangle, localangle2;
static fixed_t forwardmove[2] = {25<<FRACBITS>>16, 50<<FRACBITS>>16}; 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/NEWTICRATERATIO, 1280/NEWTICRATERATIO, 320/NEWTICRATERATIO}; // + slow turn
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics) void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
{ {
...@@ -1881,7 +1839,6 @@ boolean G_Responder(event_t *ev) ...@@ -1881,7 +1839,6 @@ boolean G_Responder(event_t *ev)
void G_Ticker(boolean run) void G_Ticker(boolean run)
{ {
UINT32 i; UINT32 i;
INT32 buf;
P_MapStart(); P_MapStart();
// do player reborns if needed // do player reborns if needed
...@@ -1917,15 +1874,6 @@ void G_Ticker(boolean run) ...@@ -1917,15 +1874,6 @@ void G_Ticker(boolean run)
default: I_Error("gameaction = %d\n", gameaction); default: I_Error("gameaction = %d\n", gameaction);
} }
buf = gametic % BACKUPTICS;
// read/write demo and check turbo cheat
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1);
}
// do main actions // do main actions
switch (gamestate) switch (gamestate)
{ {
...@@ -2921,7 +2869,7 @@ void G_NextLevel(void) ...@@ -2921,7 +2869,7 @@ void G_NextLevel(void)
static void G_DoWorldDone(void) static void G_DoWorldDone(void)
{ {
if (server) //if (server)
{ {
if (gametype == GT_COOP) if (gametype == GT_COOP)
// don't reset player between maps // don't reset player between maps
...@@ -3693,6 +3641,7 @@ static ticcmd_t oldcmd; ...@@ -3693,6 +3641,7 @@ static ticcmd_t oldcmd;
#define GZT_SPRITE 0x10 // Animation frame #define GZT_SPRITE 0x10 // Animation frame
#define GZT_EXTRA 0x20 #define GZT_EXTRA 0x20
#define GZT_NIGHTS 0x40 // NiGHTS Mode stuff! #define GZT_NIGHTS 0x40 // NiGHTS Mode stuff!
#define GZT_SPR2 0x80 // Player animations
// GZT_EXTRA flags // GZT_EXTRA flags
#define EZT_THOK 0x01 // Spawned a thok object #define EZT_THOK 0x01 // Spawned a thok object
...@@ -3896,8 +3845,6 @@ void G_WriteGhostTic(mobj_t *ghost) ...@@ -3896,8 +3845,6 @@ void G_WriteGhostTic(mobj_t *ghost)
char ziptic = 0; char ziptic = 0;
UINT8 *ziptic_p; UINT8 *ziptic_p;
UINT32 i; UINT32 i;
UINT8 sprite;
UINT8 frame;
if (!demo_p) if (!demo_p)
return; return;
...@@ -3972,19 +3919,25 @@ void G_WriteGhostTic(mobj_t *ghost) ...@@ -3972,19 +3919,25 @@ void G_WriteGhostTic(mobj_t *ghost)
} }
// Store the sprite frame. // Store the sprite frame.
frame = ghost->frame & 0xFF; if ((ghost->frame & 0xFF) != oldghost.frame)
if (frame != oldghost.frame)
{ {
oldghost.frame = frame; oldghost.frame = (ghost->frame & 0xFF);
ziptic |= GZT_SPRITE; ziptic |= GZT_SPRITE;
WRITEUINT8(demo_p,oldghost.frame); WRITEUINT8(demo_p,oldghost.frame);
} }
if (ghost->sprite == SPR_PLAY
&& ghost->sprite2 != oldghost.sprite2)
{
oldghost.sprite2 = ghost->sprite2;
ziptic |= GZT_SPR2;
WRITEUINT8(demo_p,oldghost.sprite2);
}
// Check for sprite set changes // Check for sprite set changes
sprite = ghost->sprite; if (ghost->sprite != oldghost.sprite)
if (sprite != oldghost.sprite)
{ {
oldghost.sprite = sprite; oldghost.sprite = ghost->sprite;
ghostext.flags |= EZT_SPRITE; ghostext.flags |= EZT_SPRITE;
} }
...@@ -4027,7 +3980,7 @@ void G_WriteGhostTic(mobj_t *ghost) ...@@ -4027,7 +3980,7 @@ void G_WriteGhostTic(mobj_t *ghost)
ghostext.hitlist = NULL; ghostext.hitlist = NULL;
} }
if (ghostext.flags & EZT_SPRITE) if (ghostext.flags & EZT_SPRITE)
WRITEUINT8(demo_p,sprite); WRITEUINT8(demo_p,oldghost.sprite);
ghostext.flags = 0; ghostext.flags = 0;
} }
...@@ -4083,6 +4036,8 @@ void G_ConsGhostTic(void) ...@@ -4083,6 +4036,8 @@ void G_ConsGhostTic(void)
demo_p++; demo_p++;
if (ziptic & GZT_SPRITE) if (ziptic & GZT_SPRITE)
demo_p++; demo_p++;
if (ziptic & GZT_SPR2)
demo_p++;
if(ziptic & GZT_NIGHTS) { if(ziptic & GZT_NIGHTS) {
if (!testmo->player || !(testmo->player->pflags & PF_NIGHTSMODE) || !testmo->tracer) if (!testmo->player || !(testmo->player->pflags & PF_NIGHTSMODE) || !testmo->tracer)
nightsfail = true; nightsfail = true;
...@@ -4134,7 +4089,7 @@ void G_ConsGhostTic(void) ...@@ -4134,7 +4089,7 @@ void G_ConsGhostTic(void)
if (demosynced) if (demosynced)
CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n"));
demosynced = false; demosynced = false;
P_DamageMobj(mobj, players[0].mo, players[0].mo, 1); P_DamageMobj(mobj, players[0].mo, players[0].mo, 1, 0);
} }
} }
} }
...@@ -4214,6 +4169,8 @@ void G_GhostTicker(void) ...@@ -4214,6 +4169,8 @@ void G_GhostTicker(void)
g->oldmo.angle = READUINT8(g->p)<<24; g->oldmo.angle = READUINT8(g->p)<<24;
if (ziptic & GZT_SPRITE) if (ziptic & GZT_SPRITE)
g->oldmo.frame = READUINT8(g->p); g->oldmo.frame = READUINT8(g->p);
if (ziptic & GZT_SPR2)
g->oldmo.sprite2 = READUINT8(g->p);
// Update ghost // Update ghost
P_UnsetThingPosition(g->mo); P_UnsetThingPosition(g->mo);
...@@ -4223,6 +4180,7 @@ void G_GhostTicker(void) ...@@ -4223,6 +4180,7 @@ void G_GhostTicker(void)
P_SetThingPosition(g->mo); P_SetThingPosition(g->mo);
g->mo->angle = g->oldmo.angle; g->mo->angle = g->oldmo.angle;
g->mo->frame = g->oldmo.frame | tr_trans30<<FF_TRANSSHIFT; g->mo->frame = g->oldmo.frame | tr_trans30<<FF_TRANSSHIFT;
g->mo->sprite2 = g->oldmo.sprite2;
if (ziptic & GZT_EXTRA) if (ziptic & GZT_EXTRA)
{ // But wait, there's more! { // But wait, there's more!
...@@ -4395,6 +4353,8 @@ void G_ReadMetalTic(mobj_t *metal) ...@@ -4395,6 +4353,8 @@ void G_ReadMetalTic(mobj_t *metal)
oldmetal.angle = READUINT8(metal_p)<<24; oldmetal.angle = READUINT8(metal_p)<<24;
if (ziptic & GZT_SPRITE) if (ziptic & GZT_SPRITE)
metal_p++; // Currently unused. (Metal Sonic figures out what he's doing his own damn self.) metal_p++; // Currently unused. (Metal Sonic figures out what he's doing his own damn self.)
if (ziptic & GZT_SPR2)
metal_p++;
// Set movement, position, and angle // Set movement, position, and angle
// oldmetal contains where you're supposed to be. // oldmetal contains where you're supposed to be.
......
...@@ -23,9 +23,6 @@ extern char timeattackfolder[64]; ...@@ -23,9 +23,6 @@ extern char timeattackfolder[64];
extern char customversionstring[32]; extern char customversionstring[32];
#define GAMEDATASIZE (4*8192) #define GAMEDATASIZE (4*8192)
#ifdef SEENAMES
extern player_t *seenplayer;
#endif
extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1]; extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1];
extern player_t players[MAXPLAYERS]; extern player_t players[MAXPLAYERS];
...@@ -63,7 +60,7 @@ extern consvar_t cv_ghost_bestscore, cv_ghost_besttime, cv_ghost_bestrings, cv_g ...@@ -63,7 +60,7 @@ extern consvar_t cv_ghost_bestscore, cv_ghost_besttime, cv_ghost_bestrings, cv_g
// mouseaiming (looking up/down with the mouse or keyboard) // mouseaiming (looking up/down with the mouse or keyboard)
#define KB_LOOKSPEED (1<<25) #define KB_LOOKSPEED (1<<25)
#define MAXPLMOVE (50) #define MAXPLMOVE (50)
#define SLOWTURNTICS (6) #define SLOWTURNTICS (6*NEWTICRATERATIO)
// 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);
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "g_input.h" #include "g_input.h"
#include "keys.h" #include "keys.h"
#include "hu_stuff.h" // need HUFONT start & end #include "hu_stuff.h" // need HUFONT start & end
#include "d_net.h"
#include "console.h" #include "console.h"
#define MAXMOUSESENSITIVITY 100 // sensitivity steps #define MAXMOUSESENSITIVITY 100 // sensitivity steps
......
...@@ -46,8 +46,8 @@ typedef unsigned char FBOOLEAN; ...@@ -46,8 +46,8 @@ typedef unsigned char FBOOLEAN;
#define HWR_PATCHES_CHROMAKEY_COLORINDEX 0 #define HWR_PATCHES_CHROMAKEY_COLORINDEX 0
#define HWR_CHROMAKEY_EQUIVALENTCOLORINDEX 1 #define HWR_CHROMAKEY_EQUIVALENTCOLORINDEX 1
#else #else
#define HWR_PATCHES_CHROMAKEY_COLORINDEX 247 #define HWR_PATCHES_CHROMAKEY_COLORINDEX 255
#define HWR_CHROMAKEY_EQUIVALENTCOLORINDEX 220 #define HWR_CHROMAKEY_EQUIVALENTCOLORINDEX 130
#endif #endif
// the chroma key color shows on border sprites, set it to black // the chroma key color shows on border sprites, set it to black
......
...@@ -5027,7 +5027,7 @@ static void HWR_ProjectSprite(mobj_t *thing) ...@@ -5027,7 +5027,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
//Fab : 02-08-98: 'skin' override spritedef currently used for skin //Fab : 02-08-98: 'skin' override spritedef currently used for skin
if (thing->skin && thing->sprite == SPR_PLAY) if (thing->skin && thing->sprite == SPR_PLAY)
sprdef = &((skin_t *)thing->skin)->spritedef; sprdef = &((skin_t *)thing->skin)->sprites[thing->sprite2];
else else
sprdef = &sprites[thing->sprite]; sprdef = &sprites[thing->sprite];
......
...@@ -960,119 +960,109 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, ...@@ -960,119 +960,109 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
case SKINCOLOR_BLACK: case SKINCOLOR_BLACK:
blendcolor = V_GetColor(27); blendcolor = V_GetColor(27);
break; break;
case SKINCOLOR_CYAN: case SKINCOLOR_BEIGE:
blendcolor = V_GetColor(215); blendcolor = V_GetColor(247);
break; break;
case SKINCOLOR_TEAL: case SKINCOLOR_PEACH:
blendcolor = V_GetColor(221); blendcolor = V_GetColor(218);
break; break;
case SKINCOLOR_STEELBLUE: case SKINCOLOR_BROWN:
blendcolor = V_GetColor(203); blendcolor = V_GetColor(234);
break; break;
case SKINCOLOR_BLUE: case SKINCOLOR_RED:
blendcolor = V_GetColor(232); blendcolor = V_GetColor(38);
break; break;
case SKINCOLOR_PEACH: case SKINCOLOR_CRIMSON:
blendcolor = V_GetColor(71); blendcolor = V_GetColor(45);
break;
case SKINCOLOR_ORANGE:
blendcolor = V_GetColor(54);
break;
case SKINCOLOR_RUST:
blendcolor = V_GetColor(60);
break;
case SKINCOLOR_GOLD:
blendcolor = V_GetColor(67);
break;
case SKINCOLOR_YELLOW:
blendcolor = V_GetColor(73);
break; break;
case SKINCOLOR_TAN: case SKINCOLOR_TAN:
blendcolor = V_GetColor(79); blendcolor = V_GetColor(85);
break; break;
case SKINCOLOR_PINK: case SKINCOLOR_MOSS:
blendcolor = V_GetColor(147); blendcolor = V_GetColor(92);
break; break;
case SKINCOLOR_LAVENDER: case SKINCOLOR_PERIDOT:
blendcolor = V_GetColor(251); blendcolor = V_GetColor(188);
break; break;
case SKINCOLOR_PURPLE: case SKINCOLOR_GREEN:
blendcolor = V_GetColor(195); blendcolor = V_GetColor(101);
break; break;
case SKINCOLOR_ORANGE: case SKINCOLOR_EMERALD:
blendcolor = V_GetColor(87); blendcolor = V_GetColor(112);
break; break;
case SKINCOLOR_ROSEWOOD: case SKINCOLOR_AQUA:
blendcolor = V_GetColor(94); blendcolor = V_GetColor(122);
break; break;
case SKINCOLOR_BEIGE: case SKINCOLOR_TEAL:
blendcolor = V_GetColor(40); blendcolor = V_GetColor(141);
break; break;
case SKINCOLOR_BROWN: case SKINCOLOR_CYAN:
blendcolor = V_GetColor(57); blendcolor = V_GetColor(131);
break; break;
case SKINCOLOR_RED: case SKINCOLOR_BLUE:
blendcolor = V_GetColor(130); blendcolor = V_GetColor(152);
break; break;
case SKINCOLOR_DARKRED: case SKINCOLOR_AZURE:
blendcolor = V_GetColor(139); blendcolor = V_GetColor(171);
break; break;
case SKINCOLOR_NEONGREEN: case SKINCOLOR_PASTEL:
blendcolor = V_GetColor(184); blendcolor = V_GetColor(161);
break; break;
case SKINCOLOR_GREEN: case SKINCOLOR_PURPLE:
blendcolor = V_GetColor(166); blendcolor = V_GetColor(165);
break; break;
case SKINCOLOR_ZIM: case SKINCOLOR_LAVENDER:
blendcolor = V_GetColor(180); blendcolor = V_GetColor(195);
break; break;
case SKINCOLOR_OLIVE: case SKINCOLOR_MAGENTA:
blendcolor = V_GetColor(108); blendcolor = V_GetColor(183);
break; break;
case SKINCOLOR_YELLOW: case SKINCOLOR_PINK:
blendcolor = V_GetColor(104); blendcolor = V_GetColor(211);
break; break;
case SKINCOLOR_GOLD: case SKINCOLOR_ROSY:
blendcolor = V_GetColor(115); blendcolor = V_GetColor(202);
break; break;
case SKINCOLOR_SUPER1: case SKINCOLOR_SUPER1:
blendcolor = V_GetColor(97); blendcolor = V_GetColor(80);
break; break;
case SKINCOLOR_SUPER2: case SKINCOLOR_SUPER2:
blendcolor = V_GetColor(100); blendcolor = V_GetColor(83);
break; break;
case SKINCOLOR_SUPER3: case SKINCOLOR_SUPER3:
blendcolor = V_GetColor(103); blendcolor = V_GetColor(73);
break; break;
case SKINCOLOR_SUPER4: case SKINCOLOR_SUPER4:
blendcolor = V_GetColor(113); blendcolor = V_GetColor(64);
break; break;
case SKINCOLOR_SUPER5: case SKINCOLOR_SUPER5:
blendcolor = V_GetColor(116); blendcolor = V_GetColor(67);
break; break;
case SKINCOLOR_TSUPER1: case SKINCOLOR_TSUPER1:
blendcolor = V_GetColor(81);
break;
case SKINCOLOR_TSUPER2: case SKINCOLOR_TSUPER2:
blendcolor = V_GetColor(82);
break;
case SKINCOLOR_TSUPER3: case SKINCOLOR_TSUPER3:
blendcolor = V_GetColor(84);
break;
case SKINCOLOR_TSUPER4: case SKINCOLOR_TSUPER4:
blendcolor = V_GetColor(85);
break;
case SKINCOLOR_TSUPER5: case SKINCOLOR_TSUPER5:
blendcolor = V_GetColor(87);
break;
case SKINCOLOR_KSUPER1: case SKINCOLOR_KSUPER1:
blendcolor = V_GetColor(122);
break;
case SKINCOLOR_KSUPER2: case SKINCOLOR_KSUPER2:
blendcolor = V_GetColor(123);
break;
case SKINCOLOR_KSUPER3: case SKINCOLOR_KSUPER3:
blendcolor = V_GetColor(124);
break;
case SKINCOLOR_KSUPER4: case SKINCOLOR_KSUPER4:
blendcolor = V_GetColor(125);
break;
case SKINCOLOR_KSUPER5: case SKINCOLOR_KSUPER5:
blendcolor = V_GetColor(126);
break;
default: default:
blendcolor = V_GetColor(247); blendcolor = V_GetColor(255);
break; break;
} }
...@@ -1343,7 +1333,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) ...@@ -1343,7 +1333,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
else else
{ {
if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL
&& !(spr->mobj->player && (spr->mobj->state->nextstate == S_PLAY_TAP1 || spr->mobj->state->nextstate == S_PLAY_TAP2) && spr->mobj->state == &states[S_PLAY_STND])) && !(spr->mobj->player && spr->mobj->state->nextstate == S_PLAY_WAIT && spr->mobj->state == &states[S_PLAY_STND]))
{ {
const UINT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames; const UINT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames;
next = &md2->model->frames[nextframe]; next = &md2->model->frames[nextframe];
...@@ -1361,7 +1351,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) ...@@ -1361,7 +1351,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
p.z = FIXED_TO_FLOAT(spr->mobj->z); p.z = FIXED_TO_FLOAT(spr->mobj->z);
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
sprdef = &((skin_t *)spr->mobj->skin)->spritedef; sprdef = &((skin_t *)spr->mobj->skin)->sprites[spr->mobj->sprite2];
else else
sprdef = &sprites[spr->mobj->sprite]; sprdef = &sprites[spr->mobj->sprite];
......
...@@ -42,6 +42,8 @@ ...@@ -42,6 +42,8 @@
#include "p_local.h" // camera, camera2 #include "p_local.h" // camera, camera2
#include "p_tick.h" #include "p_tick.h"
#include "d_enet.h"
#ifdef HWRENDER #ifdef HWRENDER
#include "hardware/hw_main.h" #include "hardware/hw_main.h"
#endif #endif
...@@ -382,13 +384,27 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) ...@@ -382,13 +384,27 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
*/ */
static void Command_Say_f(void) static void Command_Say_f(void)
{ {
size_t numwords, ix;
char msg[256];
if (COM_Argc() < 2) if (COM_Argc() < 2)
{ {
CONS_Printf(M_GetText("say <message>: send a message\n")); CONS_Printf(M_GetText("say <message>: send a message\n"));
return; return;
} }
DoSayCommand(0, 1, 0); //DoSayCommand(0, 1, 0);
numwords = COM_Argc() - 1;
for (ix = 0; ix < numwords; ix++)
{
if (ix > 0)
strlcat(msg, " ", 256);
strlcat(msg, COM_Argv(ix + 1), 256);
}
Net_SendChat(msg);
} }
/** Send a message to a particular person. /** Send a message to a particular person.
...@@ -487,7 +503,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) ...@@ -487,7 +503,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
XBOXSTATIC UINT8 buf[2]; XBOXSTATIC UINT8 buf[2];
buf[0] = (UINT8)playernum; buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL; buf[1] = KICK_MSG_STOP_HACKING;
SendNetXCmd(XD_KICK, &buf, 2); SendNetXCmd(XD_KICK, &buf, 2);
} }
return; return;
...@@ -507,7 +523,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) ...@@ -507,7 +523,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
XBOXSTATIC char buf[2]; XBOXSTATIC char buf[2];
buf[0] = (char)playernum; buf[0] = (char)playernum;
buf[1] = KICK_MSG_CON_FAIL; buf[1] = KICK_MSG_STOP_HACKING;
SendNetXCmd(XD_KICK, &buf, 2); SendNetXCmd(XD_KICK, &buf, 2);
} }
return; return;
...@@ -718,12 +734,13 @@ static void HU_queueChatChar(char c) ...@@ -718,12 +734,13 @@ static void HU_queueChatChar(char c)
if (ci > 3) // don't send target+flags+empty message. if (ci > 3) // don't send target+flags+empty message.
{ {
if (teamtalk) Net_SendChat(&buf[2]);
/*if (teamtalk)
buf[0] = -1; // target buf[0] = -1; // target
else else
buf[0] = 0; // target buf[0] = 0; // target
buf[1] = 0; // flags buf[1] = 0; // flags
SendNetXCmd(XD_SAY, buf, 2 + strlen(&buf[2]) + 1); SendNetXCmd(XD_SAY, buf, 2 + strlen(&buf[2]) + 1);*/
} }
return; return;
} }
...@@ -1098,10 +1115,6 @@ void HU_Drawer(void) ...@@ -1098,10 +1115,6 @@ void HU_Drawer(void)
if (!automapactive && cv_crosshair2.value && !demoplayback && !camera2.chase && !players[secondarydisplayplayer].spectator) if (!automapactive && cv_crosshair2.value && !demoplayback && !camera2.chase && !players[secondarydisplayplayer].spectator)
HU_DrawCrosshair2(); HU_DrawCrosshair2();
// draw desynch text
if (hu_resynching)
V_DrawCenteredString(BASEVIDWIDTH/2, 180, V_YELLOWMAP, "Resynching...");
} }
//====================================================================== //======================================================================
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2016 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 i_net.h
/// \brief System specific network interface stuff.
#ifndef __I_NET__
#define __I_NET__
#ifdef __GNUG__
#pragma interface
#endif
#include "doomdef.h"
#include "command.h"
/// \brief program net id
#define DOOMCOM_ID (INT32)0x12345678l
/// \def MAXPACKETLENGTH
/// For use in a LAN
#define MAXPACKETLENGTH 1450
/// \def INETPACKETLENGTH
/// For use on the internet
#define INETPACKETLENGTH 1024
extern INT16 hardware_MAXPACKETLENGTH;
extern INT32 net_bandwidth; // in byte/s
#if defined(_MSC_VER)
#pragma pack(1)
#endif
typedef struct
{
/// Supposed to be DOOMCOM_ID
INT32 id;
/// SRB2 executes an INT32 to execute commands.
INT16 intnum;
/// Communication between SRB2 and the driver.
/// Is CMD_SEND or CMD_GET.
INT16 command;
/// Is dest for send, set by get (-1 = no packet).
INT16 remotenode;
/// Number of bytes in doomdata to be sent
INT16 datalength;
/// Info common to all nodes.
/// Console is always node 0.
INT16 numnodes;
/// Flag: 1 = no duplication, 2-5 = dup for slow nets.
INT16 ticdup;
/// Flag: 1 = send a backup tic in every packet.
INT16 extratics;
/// kind of game
INT16 gametype;
/// Flag: -1 = new game, 0-5 = load savegame
INT16 savegame;
/// currect map
INT16 map;
/// Info specific to this node.
INT16 consoleplayer;
/// Number of "slots": the highest player number in use plus one.
INT16 numslots;
/// The packet data to be sent.
char data[MAXPACKETLENGTH];
} ATTRPACK doomcom_t;
#if defined(_MSC_VER)
#pragma pack()
#endif
extern doomcom_t *doomcom;
/** \brief return packet in doomcom struct
*/
extern void (*I_NetGet)(void);
/** \brief ask to driver if there is data waiting
*/
extern boolean (*I_NetCanGet)(void);
/** \brief send packet within doomcom struct
*/
extern void (*I_NetSend)(void);
/** \brief ask to driver if all is ok to send data now
*/
extern boolean (*I_NetCanSend)(void);
/** \brief close a connection
\param nodenum node to be closed
\return void
*/
extern void (*I_NetFreeNodenum)(INT32 nodenum);
/** \brief open a connection with specified address
\param address address to connect to
\return number of node
*/
extern SINT8 I_NetMakeNode(const char *address);
/** \brief open a connection with specified address and port
\param address address to connect to
\param port port to connect to
\return number of node
*/
extern SINT8 (*I_NetMakeNodewPort)(const char *address, const char *port);
/** \brief open connection
*/
extern boolean (*I_NetOpenSocket)(void);
/** \brief close all connections no more allow geting any packet
*/
extern void (*I_NetCloseSocket)(void);
extern boolean (*I_Ban) (INT32 node);
extern void (*I_ClearBans)(void);
extern const char *(*I_GetNodeAddress) (INT32 node);
extern const char *(*I_GetBanAddress) (size_t ban);
extern const char *(*I_GetBanMask) (size_t ban);
extern boolean (*I_SetBanAddress) (const char *address,const char *mask);
extern boolean *bannednode;
/// \brief Called by D_SRB2Main to be defined by extern network driver
boolean I_InitNetwork(void);
#endif
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2016 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 i_tcp.c
/// \brief TCP driver, socket code.
/// This is not really OS-dependent because all OSes have the same socket API.
/// Just use ifdef for OS-dependent parts.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifdef __GNUC__
#include <unistd.h>
#endif
#ifdef __OS2__
#include <sys/types.h>
#include <sys/time.h>
#endif // __OS2__
#ifdef _PS3
#define NO_IPV6 // PSL1GHT v2 do not have IPv6 support
#endif
#ifndef NO_IPV6
#define HAVE_IPV6
#endif
#if defined (_WIN32) || defined (_WIN32_WCE)
#define USE_WINSOCK
#if defined (_WIN64) || defined (HAVE_IPV6)
#define USE_WINSOCK2
#else //_WIN64/HAVE_IPV6
#define USE_WINSOCK1
#endif
#endif //WIN32 OS
#ifdef _XBOX // XBox have on WinSock API?
#undef USE_WINSOCK
#undef USE_WINSOCK1
#undef USE_WINSOCK2
#endif
#ifdef USE_WINSOCK2
#include <ws2tcpip.h>
#endif
#include "doomdef.h"
#if defined (NOMD5) && !defined (NONET)
//#define NONET
#endif
#ifndef NONET
#ifdef USE_WINSOCK1
#include <winsock.h>
#elif !defined (SCOUW2) && !defined (SCOUW7) && !defined (__OS2__)
#ifdef HAVE_LWIP
#include <lwip/inet.h>
#elif !defined (USE_WINSOCK)
#include <arpa/inet.h>
#endif //normal BSD API
#ifdef HAVE_LWIP
#include <lwip/sockets.h>
#define ioctl lwip_ioctl
#elif !defined (USE_WINSOCK) //!HAVE_LWIP
#ifdef __APPLE_CC__
#ifndef _BSD_SOCKLEN_T_
#define _BSD_SOCKLEN_T_
#endif //_BSD_SOCKLEN_T_
#endif //__APPLE_CC__
#include <sys/socket.h>
#include <netinet/in.h>
#endif //normal BSD API
#if defined(_arch_dreamcast) && !defined(HAVE_LWIP)
#include <kos/net.h>
#elif defined(HAVE_LWIP)
#include <lwip/lwip.h>
#elif defined (_PS3)
#include <net/select.h>
#include <net/net.h>
#elif !defined(USE_WINSOCK) //!HAVE_LWIP
#include <netdb.h>
#include <sys/ioctl.h>
#endif //normal BSD API
#include <errno.h>
#include <time.h>
#ifdef _arch_dreamcast
#include "sdl/SRB2DC/dchelp.h"
#endif
#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)
#include <sys/time.h>
#endif // UNIXCOMMON
#endif // !NONET
#ifdef USE_WINSOCK
// some undefined under win32
#undef errno
//#define errno WSAGetLastError() //Alam_GBC: this is the correct way, right?
#define errno h_errno // some very strange things happen when not using h_error?!?
#ifdef EWOULDBLOCK
#undef EWOULDBLOCK
#endif
#define EWOULDBLOCK WSAEWOULDBLOCK
#ifdef EMSGSIZE
#undef EMSGSIZE
#endif
#define EMSGSIZE WSAEMSGSIZE
#ifdef ECONNREFUSED
#undef ECONNREFUSED
#endif
#define ECONNREFUSED WSAECONNREFUSED
#ifdef ETIMEDOUT
#undef ETIMEDOUT
#endif
#define ETIMEDOUT WSAETIMEDOUT
#ifndef IOC_VENDOR
#define IOC_VENDOR 0x18000000
#endif
#ifndef _WSAIOW
#define _WSAIOW(x,y) (IOC_IN|(x)|(y))
#endif
#ifndef SIO_UDP_CONNRESET
#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
#endif
#ifndef AI_ADDRCONFIG
#define AI_ADDRCONFIG 0x00000400
#endif
#ifndef STATUS_INVALID_PARAMETER
#define STATUS_INVALID_PARAMETER 0xC000000D
#endif
#endif
#ifdef __DJGPP__
#ifdef WATTCP // Alam_GBC: Wattcp may need this
#include <tcp.h>
#define strerror strerror_s
#else // wattcp
#include <lsck/lsck.h>
#endif // libsocket
#endif // djgpp
typedef union
{
struct sockaddr any;
struct sockaddr_in ip4;
#ifdef HAVE_IPV6
struct sockaddr_in6 ip6;
#endif
} mysockaddr_t;
#ifdef HAVE_MINIUPNPC
#ifdef STATIC_MINIUPNPC
#define STATICLIB
#endif
#include "miniupnpc/miniwget.h"
#include "miniupnpc/miniupnpc.h"
#include "miniupnpc/upnpcommands.h"
#undef STATICLIB
static UINT8 UPNP_support = TRUE;
#endif
#endif // !NONET
#define MAXBANS 100
#include "i_system.h"
#include "i_net.h"
#include "d_net.h"
#include "i_tcp.h"
#include "m_argv.h"
#include "doomstat.h"
// win32 or djgpp
#if defined (USE_WINSOCK) || defined (__DJGPP__)
// winsock stuff (in winsock a socket is not a file)
#define ioctl ioctlsocket
#define close closesocket
#ifdef _WIN32_WCE
#include "sdl/SRB2CE/cehelp.h"
#endif
#endif
#include "i_addrinfo.h"
#ifdef __DJGPP__
#ifdef WATTCP
#define SELECTTEST
#endif
#elif defined(HAVE_LWIP)
#define SELECTTEST
#elif !defined( _arch_dreamcast)
#define SELECTTEST
#endif
#define DEFAULTPORT "5029"
#if defined (USE_WINSOCK) && !defined (NONET)
typedef SOCKET SOCKET_TYPE;
#define BADSOCKET INVALID_SOCKET
#define ERRSOCKET (SOCKET_ERROR)
#else
#if (defined (__unix__) && !defined (MSDOS)) || defined (__APPLE__) || defined (__HAIKU__) || defined(_PS3)
typedef int SOCKET_TYPE;
#else
typedef unsigned long SOCKET_TYPE;
#endif
#define BADSOCKET (SOCKET_TYPE)(~0)
#define ERRSOCKET (-1)
#endif
#if (defined (WATTCP) && !defined (__libsocket_socklen_t)) || defined (USE_WINSOCK1)
typedef int socklen_t;
#endif
#ifndef NONET
static SOCKET_TYPE mysockets[MAXNETNODES+1] = {BADSOCKET};
static size_t mysocketses = 0;
static int myfamily[MAXNETNODES+1] = {0};
static SOCKET_TYPE nodesocket[MAXNETNODES+1] = {BADSOCKET};
static mysockaddr_t clientaddress[MAXNETNODES+1];
static mysockaddr_t broadcastaddress[MAXNETNODES+1];
static size_t broadcastaddresses = 0;
static boolean nodeconnected[MAXNETNODES+1];
static mysockaddr_t banned[MAXBANS];
static UINT8 bannedmask[MAXBANS];
#endif
static size_t numbans = 0;
static boolean SOCK_bannednode[MAXNETNODES+1]; /// \note do we really need the +1?
static boolean init_tcp_driver = false;
static char port_name[8] = DEFAULTPORT;
#ifndef NONET
#ifdef WATTCP
static void wattcp_outch(char s)
{
static char old = '\0';
char pr[2] = {s,0};
if (s == old && old == ' ') return;
else old = s;
if (s == '\r') CONS_Printf("\n");
else if (s != '\n') CONS_Printf(pr);
}
#endif
#ifdef USE_WINSOCK2
#define inet_ntop inet_ntopA
#define HAVE_NTOP
static const char* inet_ntopA(short af, const void *cp, char *buf, socklen_t len)
{
DWORD Dlen = len, AFlen = 0;
SOCKADDR_STORAGE any;
LPSOCKADDR anyp = (LPSOCKADDR)&any;
LPSOCKADDR_IN any4 = (LPSOCKADDR_IN)&any;
LPSOCKADDR_IN6 any6 = (LPSOCKADDR_IN6)&any;
if (!buf)
{
WSASetLastError(STATUS_INVALID_PARAMETER);
return NULL;
}
if (af != AF_INET && af != AF_INET6)
{
WSASetLastError(WSAEAFNOSUPPORT);
return NULL;
}
ZeroMemory(&any, sizeof(SOCKADDR_STORAGE));
any.ss_family = af;
switch (af)
{
case AF_INET:
{
CopyMemory(&any4->sin_addr, cp, sizeof(IN_ADDR));
AFlen = sizeof(SOCKADDR_IN);
break;
}
case AF_INET6:
{
CopyMemory(&any6->sin6_addr, cp, sizeof(IN6_ADDR));
AFlen = sizeof(SOCKADDR_IN6);
break;
}
}
if (WSAAddressToStringA(anyp, AFlen, NULL, buf, &Dlen) == SOCKET_ERROR)
return NULL;
return buf;
}
#elif !defined (USE_WINSOCK1)
#define HAVE_NTOP
#endif
#ifdef HAVE_MINIUPNPC // based on old XChat patch
static struct UPNPUrls urls;
static struct IGDdatas data;
static char lanaddr[64];
static void I_ShutdownUPnP(void)
{
FreeUPNPUrls(&urls);
}
static inline void I_InitUPnP(void)
{
struct UPNPDev * devlist = NULL;
int upnp_error = -2;
CONS_Printf(M_GetText("Looking for UPnP Internet Gateway Device\n"));
devlist = upnpDiscover(2000, NULL, NULL, 0, false, &upnp_error);
if (devlist)
{
struct UPNPDev *dev = devlist;
char * descXML;
int descXMLsize = 0;
while (dev)
{
if (strstr (dev->st, "InternetGatewayDevice"))
break;
dev = dev->pNext;
}
if (!dev)
dev = devlist; /* defaulting to first device */
CONS_Printf(M_GetText("Found UPnP device:\n desc: %s\n st: %s\n"),
dev->descURL, dev->st);
UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
CONS_Printf(M_GetText("Local LAN IP address: %s\n"), lanaddr);
descXML = miniwget(dev->descURL, &descXMLsize);
if (descXML)
{
parserootdesc(descXML, descXMLsize, &data);
free(descXML);
descXML = NULL;
memset(&urls, 0, sizeof(struct UPNPUrls));
memset(&data, 0, sizeof(struct IGDdatas));
GetUPNPUrls(&urls, &data, dev->descURL);
I_AddExitFunc(I_ShutdownUPnP);
}
freeUPNPDevlist(devlist);
}
else if (upnp_error == UPNPDISCOVER_SOCKET_ERROR)
{
CONS_Printf(M_GetText("No UPnP devices discovered\n"));
}
}
static inline void I_UPnP_add(const char * addr, const char *port, const char * servicetype)
{
if (addr == NULL)
addr = lanaddr;
if (!urls.controlURL || urls.controlURL[0] == '\0')
return;
UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
port, port, addr, "SRB2", servicetype, NULL, NULL);
}
static inline void I_UPnP_rem(const char *port, const char * servicetype)
{
if (!urls.controlURL || urls.controlURL[0] == '\0')
return;
UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype,
port, servicetype, NULL);
}
#endif
static const char *SOCK_AddrToStr(mysockaddr_t *sk)
{
static char s[64]; // 255.255.255.255:65535 or IPv6:65535
#ifdef HAVE_NTOP
void *addr;
if(sk->any.sa_family == AF_INET)
addr = &sk->ip4.sin_addr;
#ifdef HAVE_IPV6
else if(sk->any.sa_family == AF_INET6)
addr = &sk->ip6.sin6_addr;
#endif
else
addr = NULL;
if(addr == NULL)
sprintf(s, "No address");
else if(inet_ntop(sk->any.sa_family, addr, s, sizeof (s)) == NULL)
sprintf(s, "Unknown family type, error #%u", errno);
#ifdef HAVE_IPV6
else if(sk->any.sa_family == AF_INET6 && sk->ip6.sin6_port != 0)
strcat(s, va(":%d", ntohs(sk->ip6.sin6_port)));
#endif
else if(sk->any.sa_family == AF_INET && sk->ip4.sin_port != 0)
strcat(s, va(":%d", ntohs(sk->ip4.sin_port)));
#else
if (sk->any.sa_family == AF_INET)
{
strcpy(s, inet_ntoa(sk->ip4.sin_addr));
if (sk->ip4.sin_port != 0) strcat(s, va(":%d", ntohs(sk->ip4.sin_port)));
}
else
sprintf(s, "Unknown type");
#endif
return s;
}
#endif
static const char *SOCK_GetNodeAddress(INT32 node)
{
if (node == 0)
return "self";
#ifdef NONET
return NULL;
#else
if (!nodeconnected[node])
return NULL;
return SOCK_AddrToStr(&clientaddress[node]);
#endif
}
static const char *SOCK_GetBanAddress(size_t ban)
{
if (ban >= numbans)
return NULL;
#ifdef NONET
return NULL;
#else
return SOCK_AddrToStr(&banned[ban]);
#endif
}
static const char *SOCK_GetBanMask(size_t ban)
{
#ifdef NONET
(void)ban;
#else
static char s[16]; //255.255.255.255 netmask? no, just CDIR for only
if (ban >= numbans)
return NULL;
if (sprintf(s,"%d",bannedmask[ban]) > 0)
return s;
#endif
return NULL;
}
#ifndef NONET
static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask)
{
UINT32 bitmask = INADDR_NONE;
if (mask && mask < 32)
bitmask = htonl((UINT32)(-1) << (32 - mask));
if (b->any.sa_family == AF_INET)
return (a->ip4.sin_addr.s_addr & bitmask) == (b->ip4.sin_addr.s_addr & bitmask)
&& (b->ip4.sin_port == 0 || (a->ip4.sin_port == b->ip4.sin_port));
#ifdef HAVE_IPV6
else if (b->any.sa_family == AF_INET6)
return memcmp(&a->ip6.sin6_addr, &b->ip6.sin6_addr, sizeof(b->ip6.sin6_addr))
&& (b->ip6.sin6_port == 0 || (a->ip6.sin6_port == b->ip6.sin6_port));
#endif
else
return false;
}
static SINT8 getfreenode(void)
{
SINT8 j;
for (j = 0; j < MAXNETNODES; j++)
if (!nodeconnected[j])
{
nodeconnected[j] = true;
return j;
}
return -1;
}
// This is a hack. For some reason, nodes aren't being freed properly.
// This goes through and cleans up what nodes were supposed to be freed.
static void cleanupnodes(void)
{
SINT8 j;
if (!Playing())
return;
// Why can't I start at zero?
for (j = 1; j < MAXNETNODES; j++)
if (!nodeingame[j])
nodeconnected[j] = false;
}
#endif
#ifndef NONET
static void SOCK_Get(void)
{
size_t i, n;
int j;
ssize_t c;
mysockaddr_t fromaddress;
socklen_t fromlen;
for (n = 0; n < mysocketses; n++)
{
fromlen = (socklen_t)sizeof(fromaddress);
c = recvfrom(mysockets[n], (char *)&doomcom->data, MAXPACKETLENGTH, 0,
(void *)&fromaddress, &fromlen);
if (c != ERRSOCKET)
{
// find remote node number
for (j = 0; j <= MAXNETNODES; j++) //include LAN
{
if (SOCK_cmpaddr(&fromaddress, &clientaddress[j], 0))
{
doomcom->remotenode = (INT16)j; // good packet from a game player
doomcom->datalength = (INT16)c;
nodesocket[j] = mysockets[n];
return;
}
}
// not found
// find a free slot
cleanupnodes();
j = getfreenode();
if (j > 0)
{
M_Memcpy(&clientaddress[j], &fromaddress, fromlen);
nodesocket[j] = mysockets[n];
DEBFILE(va("New node detected: node:%d address:%s\n", j,
SOCK_GetNodeAddress(j)));
doomcom->remotenode = (INT16)j; // good packet from a game player
doomcom->datalength = (INT16)c;
// check if it's a banned dude so we can send a refusal later
for (i = 0; i < numbans; i++)
{
if (SOCK_cmpaddr(&fromaddress, &banned[i], bannedmask[i]))
{
SOCK_bannednode[j] = true;
DEBFILE("This dude has been banned\n");
break;
}
}
if (i == numbans)
SOCK_bannednode[j] = false;
return;
}
else
DEBFILE("New node detected: No more free slots\n");
}
}
doomcom->remotenode = -1; // no packet
}
#endif
// check if we can send (do not go over the buffer)
#ifndef NONET
static fd_set masterset;
#ifdef SELECTTEST
static boolean FD_CPY(fd_set *src, fd_set *dst, SOCKET_TYPE *fd, size_t len)
{
size_t i;
boolean testset = false;
FD_ZERO(dst);
for (i = 0; i < len;i++)
{
if(fd[i] != BADSOCKET && fd[i] != (SOCKET_TYPE)ERRSOCKET &&
FD_ISSET(fd[i], src) && !FD_ISSET(fd[i], dst)) // no checking for dups
{
FD_SET(fd[i], dst);
testset = true;
}
}
return testset;
}
static boolean SOCK_CanSend(void)
{
struct timeval timeval_for_select = {0, 0};
fd_set tset;
int wselect;
if(!FD_CPY(&masterset, &tset, mysockets, mysocketses))
return false;
wselect = select(255, NULL, &tset, NULL, &timeval_for_select);
if (wselect >= 1)
return true;
return false;
}
static boolean SOCK_CanGet(void)
{
struct timeval timeval_for_select = {0, 0};
fd_set tset;
int rselect;
if(!FD_CPY(&masterset, &tset, mysockets, mysocketses))
return false;
rselect = select(255, &tset, NULL, NULL, &timeval_for_select);
if (rselect >= 1)
return true;
return false;
}
#endif
#endif
#ifndef NONET
static void SOCK_Send(void)
{
ssize_t c = ERRSOCKET;
socklen_t d4 = (socklen_t)sizeof(struct sockaddr_in);
#ifdef HAVE_IPV6
socklen_t d6 = (socklen_t)sizeof(struct sockaddr_in6);
#endif
socklen_t d, da = (socklen_t)sizeof(mysockaddr_t);
size_t i, j;
if (!nodeconnected[doomcom->remotenode])
return;
if (doomcom->remotenode == BROADCASTADDR)
{
for (i = 0; i < mysocketses; i++)
{
for (j = 0; j < broadcastaddresses; j++)
{
if (myfamily[i] == broadcastaddress[j].any.sa_family)
{
if (broadcastaddress[i].any.sa_family == AF_INET)
d = d4;
#ifdef HAVE_IPV6
else if (broadcastaddress[i].any.sa_family == AF_INET6)
d = d6;
#endif
else
d = da;
c = sendto(mysockets[i], (char *)&doomcom->data, doomcom->datalength, 0,
&broadcastaddress[j].any, d);
}
}
}
return;
}
else if (nodesocket[doomcom->remotenode] == BADSOCKET)
{
for (i = 0; i < mysocketses; i++)
{
if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family)
{
if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET)
d = d4;
#ifdef HAVE_IPV6
else if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET6)
d = d6;
#endif
else
d = da;
sendto(mysockets[i], (char *)&doomcom->data, doomcom->datalength, 0,
&clientaddress[doomcom->remotenode].any, d);
}
}
return;
}
else
{
if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET)
d = d4;
#ifdef HAVE_IPV6
else if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET6)
d = d6;
#endif
else
d = da;
c = sendto(nodesocket[doomcom->remotenode], (char *)&doomcom->data, doomcom->datalength, 0,
&clientaddress[doomcom->remotenode].any, d);
}
if (c == ERRSOCKET && errno != ECONNREFUSED && errno != EWOULDBLOCK)
I_Error("SOCK_Send, error sending to node %d (%s) #%u: %s", doomcom->remotenode,
SOCK_GetNodeAddress(doomcom->remotenode), errno, strerror(errno));
}
#endif
#ifndef NONET
static void SOCK_FreeNodenum(INT32 numnode)
{
// can't disconnect from self :)
if (!numnode || numnode > MAXNETNODES)
return;
DEBFILE(va("Free node %d (%s)\n", numnode, SOCK_GetNodeAddress(numnode)));
nodeconnected[numnode] = false;
nodesocket[numnode] = BADSOCKET;
// put invalid address
memset(&clientaddress[numnode], 0, sizeof (clientaddress[numnode]));
}
#endif
//
// UDPsocket
//
#ifndef NONET
// allocate a socket
static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen)
{
SOCKET_TYPE s = socket(family, SOCK_DGRAM, IPPROTO_UDP);
int opt;
socklen_t opts;
#ifdef FIONBIO
#ifdef WATTCP
char trueval = true;
#else
unsigned long trueval = true;
#endif
#endif
mysockaddr_t straddr;
if (s == (SOCKET_TYPE)ERRSOCKET || s == BADSOCKET)
return (SOCKET_TYPE)ERRSOCKET;
#ifdef USE_WINSOCK
{ // Alam_GBC: disable the new UDP connection reset behavior for Win2k and up
#ifdef USE_WINSOCK2
DWORD dwBytesReturned = 0;
BOOL bfalse = FALSE;
WSAIoctl(s, SIO_UDP_CONNRESET, &bfalse, sizeof(bfalse),
NULL, 0, &dwBytesReturned, NULL, NULL);
#else
unsigned long falseval = false;
ioctl(s, SIO_UDP_CONNRESET, &falseval);
#endif
}
#endif
straddr.any = *addr;
I_OutputMsg("Binding to %s\n", SOCK_AddrToStr(&straddr));
if (family == AF_INET)
{
mysockaddr_t tmpaddr;
tmpaddr.any = *addr ;
if (tmpaddr.ip4.sin_addr.s_addr == htonl(INADDR_ANY))
{
opt = true;
opts = (socklen_t)sizeof(opt);
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, opts);
}
// make it broadcastable
opt = true;
opts = (socklen_t)sizeof(opt);
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&opt, opts))
{
CONS_Alert(CONS_WARNING, M_GetText("Could not get broadcast rights\n")); // I do not care anymore
}
}
#ifdef HAVE_IPV6
else if (family == AF_INET6)
{
if (memcmp(addr, &in6addr_any, sizeof(in6addr_any)) == 0) //IN6_ARE_ADDR_EQUAL
{
opt = true;
opts = (socklen_t)sizeof(opt);
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, opts);
}
#ifdef IPV6_V6ONLY
// make it IPv6 ony
opt = true;
opts = (socklen_t)sizeof(opt);
if (setsockopt(s, SOL_SOCKET, IPV6_V6ONLY, (char *)&opt, opts))
{
CONS_Alert(CONS_WARNING, M_GetText("Could not limit IPv6 bind\n")); // I do not care anymore
}
#endif
}
#endif
if (bind(s, addr, addrlen) == ERRSOCKET)
{
close(s);
I_OutputMsg("Binding failed\n");
return (SOCKET_TYPE)ERRSOCKET;
}
#ifdef FIONBIO
// make it non blocking
opt = true;
if (ioctl(s, FIONBIO, &trueval) != 0)
{
close(s);
I_OutputMsg("Seting FIOBIO on failed\n");
return (SOCKET_TYPE)ERRSOCKET;
}
#endif
opts = (socklen_t)sizeof(opt);
getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, &opts);
CONS_Printf(M_GetText("Network system buffer: %dKb\n"), opt>>10);
if (opt < 64<<10) // 64k
{
opt = 64<<10;
opts = (socklen_t)sizeof(opt);
setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, opts);
getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, &opts);
if (opt < 64<<10)
CONS_Alert(CONS_WARNING, M_GetText("Can't set buffer length to 64k, file transfer will be bad\n"));
else
CONS_Printf(M_GetText("Network system buffer set to: %dKb\n"), opt>>10);
}
return s;
}
static boolean UDP_Socket(void)
{
const char *sock_port = NULL;
size_t s;
struct my_addrinfo *ai, *runp, hints;
int gaie;
#ifdef HAVE_IPV6
const INT32 b_ipv6 = M_CheckParm("-ipv6");
#endif
for (s = 0; s < mysocketses; s++)
mysockets[s] = BADSOCKET;
for (s = 0; s < MAXNETNODES+1; s++)
nodesocket[s] = BADSOCKET;
FD_ZERO(&masterset);
s = 0;
memset(&hints, 0x00, sizeof (hints));
hints.ai_flags = AI_NUMERICHOST;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
if (M_CheckParm("-clientport"))
{
if (!M_IsNextParm())
I_Error("syntax: -clientport <portnum>");
sock_port = M_GetNextParm();
}
else
sock_port = port_name;
if (M_CheckParm("-bindaddr"))
{
while (M_IsNextParm())
{
gaie = I_getaddrinfo(M_GetNextParm(), sock_port, &hints, &ai);
if (gaie == 0)
{
runp = ai;
while (runp != NULL && s < MAXNETNODES+1)
{
mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen);
if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET)
{
FD_SET(mysockets[s], &masterset);
myfamily[s] = hints.ai_family;
s++;
}
runp = runp->ai_next;
}
I_freeaddrinfo(ai);
}
}
}
else
{
gaie = I_getaddrinfo("0.0.0.0", sock_port, &hints, &ai);
if (gaie == 0)
{
runp = ai;
while (runp != NULL && s < MAXNETNODES+1)
{
mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen);
if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET)
{
FD_SET(mysockets[s], &masterset);
myfamily[s] = hints.ai_family;
s++;
#ifdef HAVE_MINIUPNPC
if (UPNP_support)
{
I_UPnP_rem(sock_port, "UDP");
I_UPnP_add(NULL, sock_port, "UDP");
}
#endif
}
runp = runp->ai_next;
}
I_freeaddrinfo(ai);
}
}
#ifdef HAVE_IPV6
if (b_ipv6)
{
hints.ai_family = AF_INET6;
if (M_CheckParm("-bindaddr6"))
{
while (M_IsNextParm())
{
gaie = I_getaddrinfo(M_GetNextParm(), sock_port, &hints, &ai);
if (gaie == 0)
{
runp = ai;
while (runp != NULL && s < MAXNETNODES+1)
{
mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen);
if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET)
{
FD_SET(mysockets[s], &masterset);
myfamily[s] = hints.ai_family;
s++;
}
runp = runp->ai_next;
}
I_freeaddrinfo(ai);
}
}
}
else
{
gaie = I_getaddrinfo("::", sock_port, &hints, &ai);
if (gaie == 0)
{
runp = ai;
while (runp != NULL && s < MAXNETNODES+1)
{
mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen);
if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET)
{
FD_SET(mysockets[s], &masterset);
myfamily[s] = hints.ai_family;
s++;
}
runp = runp->ai_next;
}
I_freeaddrinfo(ai);
}
}
}
#endif
mysocketses = s;
if (s == 0) // no sockets?
return false;
s = 0;
// ip + udp
packetheaderlength = 20 + 8; // for stats
hints.ai_family = AF_INET;
gaie = I_getaddrinfo("127.0.0.1", "0", &hints, &ai);
if (gaie == 0)
{
runp = ai;
while (runp != NULL)
{
memcpy(&clientaddress[s], runp->ai_addr, runp->ai_addrlen);
s++;
runp = runp->ai_next;
}
I_freeaddrinfo(ai);
}
else
{
clientaddress[s].any.sa_family = AF_INET;
clientaddress[s].ip4.sin_port = htons(0);
clientaddress[s].ip4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); //GetLocalAddress(); // my own ip
s++;
}
// setup broadcast adress to BROADCASTADDR entry
gaie = I_getaddrinfo("255.255.255.255", "0", &hints, &ai);
if (gaie == 0)
{
runp = ai;
while (runp != NULL)
{
memcpy(&broadcastaddress[s], runp->ai_addr, runp->ai_addrlen);
s++;
runp = runp->ai_next;
}
I_freeaddrinfo(ai);
}
else
{
broadcastaddress[s].any.sa_family = AF_INET;
broadcastaddress[s].ip4.sin_port = htons(0);
broadcastaddress[s].ip4.sin_addr.s_addr = htonl(INADDR_BROADCAST);
s++;
}
#ifdef HAVE_IPV6
if (b_ipv6)
{
hints.ai_family = AF_INET6;
gaie = I_getaddrinfo("ff02::1", "0", &hints, &ai);
if (gaie == 0)
{
runp = ai;
while (runp != NULL)
{
memcpy(&broadcastaddress[s], runp->ai_addr, runp->ai_addrlen);
s++;
runp = runp->ai_next;
}
I_freeaddrinfo(ai);
}
}
#endif
broadcastaddresses = s;
doomcom->extratics = 1; // internet is very high ping
return true;
}
#endif
boolean I_InitTcpDriver(void)
{
boolean tcp_was_up = init_tcp_driver;
#ifndef NONET
if (!init_tcp_driver)
{
#ifdef USE_WINSOCK
#ifdef USE_WINSOCK2
const WORD VerNeed = MAKEWORD(2,2);
#else
const WORD VerNeed = MAKEWORD(1,1);
#endif
WSADATA WSAData;
const int WSAresult = WSAStartup(VerNeed, &WSAData);
if (WSAresult != 0)
{
LPCSTR WSError = NULL;
switch (WSAresult)
{
case WSASYSNOTREADY:
WSError = "The underlying network subsystem is not ready for network communication";
break;
case WSAEINPROGRESS:
WSError = "A blocking Windows Sockets 1.1 operation is in progress";
break;
case WSAEPROCLIM:
WSError = "Limit on the number of tasks supported by the Windows Sockets implementation has been reached";
break;
case WSAEFAULT:
WSError = "WSAData is not a valid pointer? What kind of setup do you have?";
break;
default:
WSError = va("Error code %u",WSAresult);
break;
}
if (WSAresult != WSAVERNOTSUPPORTED)
CONS_Debug(DBG_NETPLAY, "WinSock(TCP/IP) error: %s\n",WSError);
}
#ifdef USE_WINSOCK2
if(LOBYTE(WSAData.wVersion) != 2 ||
HIBYTE(WSAData.wVersion) != 2)
{
WSACleanup();
CONS_Debug(DBG_NETPLAY, "No WinSock(TCP/IP) 2.2 driver detected\n");
}
#else
if (LOBYTE(WSAData.wVersion) != 1 ||
HIBYTE(WSAData.wVersion) != 1)
{
WSACleanup();
CONS_Debug(DBG_NETPLAY, "No WinSock(TCP/IP) 1.1 driver detected\n");
}
#endif
CONS_Debug(DBG_NETPLAY, "WinSock description: %s\n",WSAData.szDescription);
CONS_Debug(DBG_NETPLAY, "WinSock System Status: %s\n",WSAData.szSystemStatus);
#endif
#ifdef HAVE_LWIP
lwip_kos_init();
#elif defined(_arch_dreamcast)
//return;
net_init();
#endif
#ifdef __DJGPP__
#ifdef WATTCP // Alam_GBC: survive bootp, dhcp, rarp and wattcp/pktdrv from failing to load
survive_eth = 1; // would be needed to not exit if pkt_eth_init() fails
survive_bootp = 1; // ditto for BOOTP
survive_dhcp = 1; // ditto for DHCP/RARP
survive_rarp = 1;
//_watt_do_exit = false;
//_watt_handle_cbreak = false;
//_watt_no_config = true;
_outch = wattcp_outch;
init_misc();
//#ifdef DEBUGFILE
dbug_init();
//#endif
switch (sock_init())
{
case 0:
init_tcp_driver = true;
break;
case 3:
CONS_Debug(DBG_NETPLAY, "No packet driver detected\n");
break;
case 4:
CONS_Debug(DBG_NETPLAY, "Error while talking to packet driver\n");
break;
case 5:
CONS_Debug(DBG_NETPLAY, "BOOTP failed\n");
break;
case 6:
CONS_Debug(DBG_NETPLAY, "DHCP failed\n");
break;
case 7:
CONS_Debug(DBG_NETPLAY, "RARP failed\n");
break;
case 8:
CONS_Debug(DBG_NETPLAY, "TCP/IP failed\n");
break;
case 9:
CONS_Debug(DBG_NETPLAY, "PPPoE login/discovery failed\n");
break;
default:
CONS_Debug(DBG_NETPLAY, "Unknown error with TCP/IP stack\n");
break;
}
hires_timer(0);
#else // wattcp
if (__lsck_init())
init_tcp_driver = true;
else
CONS_Debug(DBG_NETPLAY, "No TCP/IP driver detected\n");
#endif // libsocket
#endif // __DJGPP__
#ifdef _PS3
netInitialize();
#endif
#ifndef __DJGPP__
init_tcp_driver = true;
#endif
}
#endif
if (!tcp_was_up && init_tcp_driver)
{
I_AddExitFunc(I_ShutdownTcpDriver);
#ifdef HAVE_MINIUPNPC
if (M_CheckParm("-useUPnP"))
I_InitUPnP();
else
UPNP_support = false;
#endif
}
return init_tcp_driver;
}
#ifndef NONET
static void SOCK_CloseSocket(void)
{
size_t i;
for (i=0; i < MAXNETNODES+1; i++)
{
if (mysockets[i] != (SOCKET_TYPE)ERRSOCKET
&& mysockets[i] != BADSOCKET
&& FD_ISSET(mysockets[i], &masterset))
{
#if !defined (__DJGPP__) || defined (WATTCP)
FD_CLR(mysockets[i], &masterset);
close(mysockets[i]);
#endif
}
mysockets[i] = BADSOCKET;
}
}
#endif
void I_ShutdownTcpDriver(void)
{
#ifndef NONET
SOCK_CloseSocket();
CONS_Printf("I_ShutdownTcpDriver: ");
#ifdef USE_WINSOCK
WS_addrinfocleanup();
WSACleanup();
#endif
#ifdef HAVE_LWIP
lwip_kos_shutdown();
#elif defined(_arch_dreamcast)
net_shutdown();
#endif
#ifdef __DJGPP__
#ifdef WATTCP // wattcp
//_outch = NULL;
sock_exit();
#else
__lsck_uninit();
#endif // libsocket
#endif // __DJGPP__
#ifdef _PS3
netDeinitialize();
#endif
CONS_Printf("shut down\n");
init_tcp_driver = false;
#endif
}
#ifndef NONET
static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
{
SINT8 newnode = -1;
struct my_addrinfo *ai, *runp, hints;
int gaie;
if (!port || !port[0])
port = port_name;
DEBFILE(va("Creating new node: %s@%s\n", address, port));
memset (&hints, 0x00, sizeof (hints));
hints.ai_flags = 0;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
gaie = I_getaddrinfo(address, port, &hints, &ai);
if (gaie == 0)
{
cleanupnodes();
newnode = getfreenode();
}
if (newnode == -1)
{
I_freeaddrinfo(ai);
return -1;
}
else
runp = ai;
while (runp != NULL)
{
// find ip of the server
memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen);
runp = NULL;
}
I_freeaddrinfo(ai);
return newnode;
}
#endif
static boolean SOCK_OpenSocket(void)
{
#ifndef NONET
size_t i;
memset(clientaddress, 0, sizeof (clientaddress));
nodeconnected[0] = true; // always connected to self
for (i = 1; i < MAXNETNODES; i++)
nodeconnected[i] = false;
nodeconnected[BROADCASTADDR] = true;
I_NetSend = SOCK_Send;
I_NetGet = SOCK_Get;
I_NetCloseSocket = SOCK_CloseSocket;
I_NetFreeNodenum = SOCK_FreeNodenum;
I_NetMakeNodewPort = SOCK_NetMakeNodewPort;
#ifdef SELECTTEST
// seem like not work with libsocket : (
I_NetCanSend = SOCK_CanSend;
I_NetCanGet = SOCK_CanGet;
#endif
// build the socket but close it first
SOCK_CloseSocket();
return UDP_Socket();
#else
return false;
#endif
}
static boolean SOCK_Ban(INT32 node)
{
if (node > MAXNETNODES)
return false;
#ifdef NONET
return false;
#else
if (numbans == MAXBANS)
return false;
M_Memcpy(&banned[numbans], &clientaddress[node], sizeof (mysockaddr_t));
if (banned[numbans].any.sa_family == AF_INET)
{
banned[numbans].ip4.sin_port = 0;
bannedmask[numbans] = 32;
}
#ifdef HAVE_IPV6
else if (banned[numbans].any.sa_family == AF_INET6)
{
banned[numbans].ip6.sin6_port = 0;
bannedmask[numbans] = 128;
}
#endif
numbans++;
return true;
#endif
}
static boolean SOCK_SetBanAddress(const char *address, const char *mask)
{
#ifdef NONET
(void)address;
(void)mask;
return false;
#else
struct my_addrinfo *ai, *runp, hints;
int gaie;
if (numbans == MAXBANS || !address)
return false;
memset(&hints, 0x00, sizeof(hints));
hints.ai_flags = 0;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
gaie = I_getaddrinfo(address, "0", &hints, &ai);
if (gaie != 0)
return false;
runp = ai;
while(runp != NULL && numbans != MAXBANS)
{
memcpy(&banned[numbans], runp->ai_addr, runp->ai_addrlen);
if (mask)
bannedmask[numbans] = (UINT8)atoi(mask);
#ifdef HAVE_IPV6
else if (runp->ai_family == AF_INET6)
bannedmask[numbans] = 128;
#endif
else
bannedmask[numbans] = 32;
if (bannedmask[numbans] > 32 && runp->ai_family == AF_INET)
bannedmask[numbans] = 32;
#ifdef HAVE_IPV6
else if (bannedmask[numbans] > 128 && runp->ai_family == AF_INET6)
bannedmask[numbans] = 128;
#endif
numbans++;
runp = runp->ai_next;
}
I_freeaddrinfo(ai);
return true;
#endif
}
static void SOCK_ClearBans(void)
{
numbans = 0;
}
boolean I_InitTcpNetwork(void)
{
char serverhostname[255];
boolean ret = false;
// initilize the OS's TCP/IP stack
if (!I_InitTcpDriver())
return false;
if (M_CheckParm("-udpport"))
{
if (M_IsNextParm())
strcpy(port_name, M_GetNextParm());
else
strcpy(port_name, "0");
}
current_port = (UINT16)atoi(port_name);
// parse network game options,
if (M_CheckParm("-server") || dedicated)
{
server = true;
// If a number of clients (i.e. nodes) is specified, the server will wait for the clients
// to connect before starting.
// If no number is specified here, the server starts with 1 client, and others can join
// in-game.
// Since Boris has implemented join in-game, there is no actual need for specifying a
// particular number here.
// FIXME: for dedicated server, numnodes needs to be set to 0 upon start
if (dedicated)
doomcom->numnodes = 0;
/* else if (M_IsNextParm())
doomcom->numnodes = (INT16)atoi(M_GetNextParm());*/
else
doomcom->numnodes = 1;
if (doomcom->numnodes < 0)
doomcom->numnodes = 0;
if (doomcom->numnodes > MAXNETNODES)
doomcom->numnodes = MAXNETNODES;
// server
servernode = 0;
// FIXME:
// ??? and now ?
// server on a big modem ??? 4*isdn
net_bandwidth = 16000;
hardware_MAXPACKETLENGTH = INETPACKETLENGTH;
ret = true;
}
else if (M_CheckParm("-connect"))
{
if (M_IsNextParm())
strcpy(serverhostname, M_GetNextParm());
else
serverhostname[0] = 0; // assuming server in the LAN, use broadcast to detect it
// server address only in ip
if (serverhostname[0])
{
COM_BufAddText("connect \"");
COM_BufAddText(serverhostname);
COM_BufAddText("\"\n");
// probably modem
hardware_MAXPACKETLENGTH = INETPACKETLENGTH;
}
else
{
// so we're on a LAN
COM_BufAddText("connect any\n");
net_bandwidth = 800000;
hardware_MAXPACKETLENGTH = MAXPACKETLENGTH;
}
}
I_NetOpenSocket = SOCK_OpenSocket;
I_Ban = SOCK_Ban;
I_ClearBans = SOCK_ClearBans;
I_GetNodeAddress = SOCK_GetNodeAddress;
I_GetBanAddress = SOCK_GetBanAddress;
I_GetBanMask = SOCK_GetBanMask;
I_SetBanAddress = SOCK_SetBanAddress;
bannednode = SOCK_bannednode;
return ret;
}
#include "i_addrinfo.c"
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2016 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 i_tcp.h
/// \brief TCP driver, sockets.
#ifndef __I_TCP__
#define __I_TCP__
extern UINT16 current_port;
/** \brief The I_InitTcpNetwork function
\return true if going or in a netgame, else it's false
*/
boolean I_InitTcpNetwork(void);
/** \brief The I_InitTcpNetwork function
\return true if TCP/IP stack was initilized, else it's false
*/
boolean I_InitTcpDriver(void);
void I_ShutdownTcpDriver(void);
#endif
...@@ -56,6 +56,52 @@ char sprnames[NUMSPRITES + 1][5] = ...@@ -56,6 +56,52 @@ char sprnames[NUMSPRITES + 1][5] =
"SRBJ","SRBK","SRBL","SRBM","SRBN","SRBO", "SRBJ","SRBK","SRBL","SRBM","SRBN","SRBO",
}; };
char spr2names[NUMPLAYERSPRITES][5] =
{
"STND",
"WAIT",
"WALK",
"RUN_",
"PAIN",
"DEAD",
"DRWN",
"SPIN",
"DASH",
"GASP",
"JUMP",
"SPNG",
"FALL",
"EDGE",
"RIDE",
"SIGN",
"LIFE",
"FLY_",
"TIRE",
"GLID",
"CLNG",
"CLMB",
"TRNS",
"SSTD",
"SWLK",
"SRUN",
"SPAN",
"SMSL",
"SDTH",
"SDRN",
"SSPN",
"SGSP",
"SJMP",
"SSPG",
"SFAL",
"SEDG",
"SRID",
"SFLT"
};
// Doesn't work with g++, needs actionf_p1 (don't modify this comment) // Doesn't work with g++, needs actionf_p1 (don't modify this comment)
state_t states[NUMSTATES] = state_t states[NUMSTATES] =
{ {
...@@ -82,73 +128,70 @@ state_t states[NUMSTATES] = ...@@ -82,73 +128,70 @@ state_t states[NUMSTATES] =
{SPR_THOK, FF_TRANS50, 8, {NULL}, 0, 0, S_NULL}, // S_THOK {SPR_THOK, FF_TRANS50, 8, {NULL}, 0, 0, S_NULL}, // S_THOK
// Player // Player
{SPR_PLAY, 0, 105, {NULL}, 0, 0, S_PLAY_TAP1}, // S_PLAY_STND {SPR_PLAY, SPR2_STND, 105, {NULL}, 0, 0, S_PLAY_WAIT}, // S_PLAY_STND
{SPR_PLAY, 1, 16, {NULL}, 0, 0, S_PLAY_TAP2}, // S_PLAY_TAP1 {SPR_PLAY, SPR2_WAIT, 16, {NULL}, 0, 0, S_PLAY_WAIT}, // S_PLAY_WAIT
{SPR_PLAY, 2, 16, {NULL}, 0, 0, S_PLAY_TAP1}, // S_PLAY_TAP2 {SPR_PLAY, SPR2_WALK, 4, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_WALK
{SPR_PLAY, 3, 4, {NULL}, 0, 0, S_PLAY_RUN2}, // S_PLAY_RUN1 {SPR_PLAY, SPR2_RUN , 2, {NULL}, 0, 0, S_PLAY_RUN}, // S_PLAY_RUN
{SPR_PLAY, 4, 4, {NULL}, 0, 0, S_PLAY_RUN3}, // S_PLAY_RUN2 {SPR_PLAY, SPR2_PAIN, 350, {NULL}, 0, 0, S_PLAY_FALL}, // S_PLAY_PAIN
{SPR_PLAY, 5, 4, {NULL}, 0, 0, S_PLAY_RUN4}, // S_PLAY_RUN3 {SPR_PLAY, SPR2_DEAD, 4, {NULL}, 0, 0, S_PLAY_DEAD}, // S_PLAY_DEAD
{SPR_PLAY, 6, 4, {NULL}, 0, 0, S_PLAY_RUN5}, // S_PLAY_RUN4 {SPR_PLAY, SPR2_DRWN, 4, {NULL}, 0, 0, S_PLAY_DRWN}, // S_PLAY_DRWN
{SPR_PLAY, 7, 4, {NULL}, 0, 0, S_PLAY_RUN6}, // S_PLAY_RUN5 {SPR_PLAY, SPR2_SPIN, 1, {NULL}, 0, 0, S_PLAY_SPIN}, // S_PLAY_SPIN
{SPR_PLAY, 8, 4, {NULL}, 0, 0, S_PLAY_RUN7}, // S_PLAY_RUN6 {SPR_PLAY, SPR2_DASH, 2, {NULL}, 0, 0, S_PLAY_DASH}, // S_PLAY_DASH
{SPR_PLAY, 9, 4, {NULL}, 0, 0, S_PLAY_RUN8}, // S_PLAY_RUN7 {SPR_PLAY, SPR2_GASP, 14, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_GASP
{SPR_PLAY, 10, 4, {NULL}, 0, 0, S_PLAY_RUN1}, // S_PLAY_RUN8 {SPR_PLAY, SPR2_JUMP, 1, {NULL}, 0, 0, S_PLAY_JUMP}, // S_PLAY_JUMP
{SPR_PLAY, 16, 2, {NULL}, 0, 0, S_PLAY_SPD2}, // S_PLAY_SPD1 {SPR_PLAY, SPR2_SPNG, 2, {NULL}, 0, 0, S_PLAY_SPRING}, // S_PLAY_SPRING
{SPR_PLAY, 17, 2, {NULL}, 0, 0, S_PLAY_SPD3}, // S_PLAY_SPD2 {SPR_PLAY, SPR2_FALL, 2, {NULL}, 0, 0, S_PLAY_FALL}, // S_PLAY_FALL
{SPR_PLAY, 18, 2, {NULL}, 0, 0, S_PLAY_SPD4}, // S_PLAY_SPD3 {SPR_PLAY, SPR2_EDGE, 12, {NULL}, 0, 0, S_PLAY_EDGE}, // S_PLAY_EDGE
{SPR_PLAY, 19, 2, {NULL}, 0, 0, S_PLAY_SPD1}, // S_PLAY_SPD4 {SPR_PLAY, SPR2_RIDE, 4, {NULL}, 0, 0, S_PLAY_RIDE}, // S_PLAY_RIDE
{SPR_PLAY, 11, 1, {NULL}, 0, 0, S_PLAY_ATK2}, // S_PLAY_ATK1
{SPR_PLAY, 12, 1, {NULL}, 0, 0, S_PLAY_ATK3}, // S_PLAY_ATK2 // Tails abilities
{SPR_PLAY, 13, 1, {NULL}, 0, 0, S_PLAY_ATK4}, // S_PLAY_ATK3 {SPR_PLAY, SPR2_FLY , 2, {NULL}, 0, 0, S_PLAY_FLY}, // S_PLAY_FLY
{SPR_PLAY, 14, 1, {NULL}, 0, 0, S_PLAY_ATK1}, // S_PLAY_ATK4 {SPR_PLAY, SPR2_TIRE, 12, {NULL}, 0, 0, S_PLAY_FLY_TIRED}, // S_PLAY_FLY_TIRED
{SPR_PLAY, 15, -1, {NULL}, 0, 0, S_PLAY_FALL1}, // S_PLAY_SPRING
{SPR_PLAY, 31, 2, {NULL}, 0, 0, S_PLAY_FALL2}, // S_PLAY_FALL1 // Knuckles abilities
{SPR_PLAY, 32, 2, {NULL}, 0, 0, S_PLAY_FALL1}, // S_PLAY_FALL2 {SPR_PLAY, SPR2_GLID, 2, {NULL}, 0, 0, S_PLAY_GLIDE}, // S_PLAY_GLIDE
{SPR_PLAY, 20, 2, {NULL}, 0, 0, S_PLAY_ABL2}, // S_PLAY_ABL1 {SPR_PLAY, SPR2_CLNG, 6, {NULL}, 0, 0, S_PLAY_CLING}, // S_PLAY_CLING
{SPR_PLAY, 21, 2, {NULL}, 0, 0, S_PLAY_ABL1}, // S_PLAY_ABL2 {SPR_PLAY, SPR2_CLMB, 5, {NULL}, 0, 0, S_PLAY_CLIMB}, // S_PLAY_CLIMB
{SPR_PLAY, 22, 6, {NULL}, 0, 0, S_PLAY_SPC2}, // S_PLAY_SPC1
{SPR_PLAY, 23, 6, {NULL}, 0, 0, S_PLAY_SPC3}, // S_PLAY_SPC2 // Super Sonic
{SPR_PLAY, 24, 6, {NULL}, 0, 0, S_PLAY_SPC4}, // S_PLAY_SPC3 {SPR_PLAY, SPR2_SSTD, 7, {NULL}, 0, 0, S_PLAY_SUPER_STND}, // S_PLAY_SUPER_STND
{SPR_PLAY, 25, 6, {NULL}, 0, 0, S_PLAY_SPC1}, // S_PLAY_SPC4 {SPR_PLAY, SPR2_SWLK, 7, {NULL}, 0, 0, S_PLAY_SUPER_WALK}, // S_PLAY_SUPER_WALK
{SPR_PLAY, 22, -1, {NULL}, 0, 0, S_NULL}, // S_PLAY_CLIMB1 {SPR_PLAY, SPR2_SRUN, 7, {NULL}, 0, 0, S_PLAY_SUPER_RUN}, // S_PLAY_SUPER_RUN
{SPR_PLAY, 23, 5, {NULL}, 0, 0, S_PLAY_CLIMB3}, // S_PLAY_CLIMB2 {SPR_PLAY, SPR2_SPAN, -1, {NULL}, 0, 0, S_PLAY_SUPER_STND}, // S_PLAY_SUPER_PAIN
{SPR_PLAY, 24, 5, {NULL}, 0, 0, S_PLAY_CLIMB4}, // S_PLAY_CLIMB3 {SPR_PLAY, SPR2_SMSL, -1, {NULL}, 0, 0, S_PLAY_SUPER_STND}, // S_PLAY_SUPER_STUN
{SPR_PLAY, 25, 5, {NULL}, 0, 0, S_PLAY_CLIMB5}, // S_PLAY_CLIMB4 {SPR_PLAY, SPR2_SDTH, 4, {NULL}, 0, 0, S_PLAY_SUPER_DEAD}, // S_PLAY_SUPER_DEAD
{SPR_PLAY, 24, 5, {NULL}, 0, 0, S_PLAY_CLIMB2}, // S_PLAY_CLIMB5 {SPR_PLAY, SPR2_SDRN, 4, {NULL}, 0, 0, S_PLAY_SUPER_DRWN}, // S_PLAY_SUPER_DRWN
{SPR_PLAY, 26, 14, {NULL}, 0, 0, S_PLAY_RUN1}, // S_PLAY_GASP {SPR_PLAY, SPR2_SSPN, 1, {NULL}, 0, 0, S_PLAY_SUPER_SPIN}, // S_PLAY_SUPER_SPIN
{SPR_PLAY, 27, 350, {NULL}, 0, 0, S_PLAY_FALL1}, // S_PLAY_PAIN {SPR_PLAY, SPR2_SGSP, 14, {NULL}, 0, 0, S_PLAY_SUPER_WALK}, // S_PLAY_SUPER_GASP
{SPR_PLAY, 28, -1, {A_Fall}, 0, 0, S_NULL}, // S_PLAY_DIE {SPR_PLAY, SPR2_SJMP, 1, {NULL}, 0, 0, S_PLAY_SUPER_JUMP}, // S_PLAY_SUPER_JUMP
{SPR_PLAY, 29, 12, {NULL}, 0, 0, S_PLAY_TEETER2}, // S_PLAY_TEETER1 {SPR_PLAY, SPR2_SSPG, 2, {NULL}, 0, 0, S_PLAY_SUPER_SPRING}, // S_PLAY_SUPER_SPRING
{SPR_PLAY, 30, 12, {NULL}, 0, 0, S_PLAY_TEETER1}, // S_PLAY_TEETER2 {SPR_PLAY, SPR2_SFAL, 2, {NULL}, 0, 0, S_PLAY_SUPER_FALL}, // S_PLAY_SUPER_FALL
{SPR_PLAY, 33, -1, {NULL}, 0, 0, S_NULL}, // S_PLAY_CARRY {SPR_PLAY, SPR2_SEDG, 12, {NULL}, 0, 0, S_PLAY_SUPER_EDGE}, // S_PLAY_SUPER_EDGE
{SPR_PLAY, 20, -1, {NULL}, 0, 0, S_PLAY_SUPERSTAND}, // S_PLAY_SUPERSTAND {SPR_PLAY, SPR2_SRID, 4, {NULL}, 0, 0, S_PLAY_SUPER_RIDE}, // S_PLAY_SUPER_RIDE
{SPR_PLAY, 20, 7, {NULL}, 0, 0, S_PLAY_SUPERWALK2}, // S_PLAY_SUPERWALK1 {SPR_PLAY, SPR2_SFLT, 7, {NULL}, 0, 0, S_PLAY_SUPER_FLOAT}, // S_PLAY_SUPER_FLOAT
{SPR_PLAY, 21, 7, {NULL}, 0, 0, S_PLAY_SUPERWALK1}, // S_PLAY_SUPERWALK2
{SPR_PLAY, 22, 7, {NULL}, 0, 0, S_PLAY_SUPERFLY2}, // S_PLAY_SUPERFLY1 // Transforming into Super
{SPR_PLAY, 23, 7, {NULL}, 0, 0, S_PLAY_SUPERFLY1}, // S_PLAY_SUPERFLY2 {SPR_PLAY, SPR2_TRNS, 4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS2}, // S_PLAY_SUPER_TRANS
{SPR_PLAY, 24, 12, {NULL}, 0, 0, S_PLAY_SUPERTEETER}, // S_PLAY_SUPERTEETER {SPR_PLAY, SPR2_TRNS, 4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS3}, // S_PLAY_SUPER_TRANS2
{SPR_PLAY, 25, -1, {NULL}, 0, 0, S_PLAY_SUPERSTAND}, // S_PLAY_SUPERHIT {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS4}, // S_PLAY_SUPER_TRANS3
{SPR_PLAY, 36, 4, {NULL}, 0, 0, S_PLAY_SUPERTRANS2}, // S_PLAY_SUPERTRANS1 {SPR_PLAY, SPR2_TRNS, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS5}, // S_PLAY_SUPER_TRANS4
{SPR_PLAY, 37, 4, {NULL}, 0, 0, S_PLAY_SUPERTRANS3}, // S_PLAY_SUPERTRANS2 {SPR_PLAY, SPR2_TRNS, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS6}, // S_PLAY_SUPER_TRANS5
{SPR_PLAY, 32806, 4, {NULL}, 0, 0, S_PLAY_SUPERTRANS4}, // S_PLAY_SUPERTRANS3 {SPR_PLAY, SPR2_TRNS, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS7}, // S_PLAY_SUPER_TRANS6
{SPR_PLAY, 39, 3, {NULL}, 0, 0, S_PLAY_SUPERTRANS5}, // S_PLAY_SUPERTRANS4 {SPR_PLAY, SPR2_TRNS, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS8}, // S_PLAY_SUPER_TRANS7
{SPR_PLAY, 40, 3, {NULL}, 0, 0, S_PLAY_SUPERTRANS6}, // S_PLAY_SUPERTRANS5 {SPR_PLAY, SPR2_TRNS, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS9}, // S_PLAY_SUPER_TRANS8
{SPR_PLAY, 41, 3, {NULL}, 0, 0, S_PLAY_SUPERTRANS7}, // S_PLAY_SUPERTRANS6 {SPR_PLAY, SPR2_TRNS, 16, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_SUPER_TRANS9
{SPR_PLAY, 42, 3, {NULL}, 0, 0, S_PLAY_SUPERTRANS8}, // S_PLAY_SUPERTRANS7
{SPR_PLAY, 43, 3, {NULL}, 0, 0, S_PLAY_SUPERTRANS9}, // S_PLAY_SUPERTRANS8
{SPR_PLAY, 44, 16, {NULL}, 0, 0, S_PLAY_RUN1}, // S_PLAY_SUPERTRANS9
{SPR_NULL, 0, -1, {NULL}, 0, 0, S_OBJPLACE_DUMMY}, //S_OBJPLACE_DUMMY {SPR_NULL, 0, -1, {NULL}, 0, 0, S_OBJPLACE_DUMMY}, //S_OBJPLACE_DUMMY
// 1-Up Box Sprites (uses player sprite) // 1-Up Box Sprites (uses player sprite)
{SPR_PLAY, 35, 2, {NULL}, 0, 16, S_PLAY_BOX2}, // S_PLAY_BOX1 {SPR_PLAY, SPR2_LIFE, 2, {NULL}, 0, 16, S_PLAY_BOX2}, // S_PLAY_BOX1
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_PLAY_BOX1}, // S_PLAY_BOX2 {SPR_NULL, 0, 1, {NULL}, 0, 0, S_PLAY_BOX1}, // S_PLAY_BOX2
{SPR_PLAY, 35, 4, {NULL}, 0, 4, S_PLAY_ICON2}, // S_PLAY_ICON1 {SPR_PLAY, SPR2_LIFE, 4, {NULL}, 0, 4, S_PLAY_ICON2}, // S_PLAY_ICON1
{SPR_NULL, 0, 12, {NULL}, 0, 0, S_PLAY_ICON3}, // S_PLAY_ICON2 {SPR_NULL, 0, 12, {NULL}, 0, 0, S_PLAY_ICON3}, // S_PLAY_ICON2
{SPR_PLAY, 35, 18, {NULL}, 0, 4, S_NULL}, // S_PLAY_ICON3 {SPR_PLAY, SPR2_LIFE, 18, {NULL}, 0, 4, S_NULL}, // S_PLAY_ICON3
// Level end sign (uses player sprite) // Level end sign (uses player sprite)
{SPR_PLAY, 34, 1, {NULL}, 0, 24, S_PLAY_SIGN}, // S_PLAY_SIGN {SPR_PLAY, SPR2_SIGN, 1, {NULL}, 0, 24, S_PLAY_SIGN}, // S_PLAY_SIGN
// Blue Crawla // Blue Crawla
{SPR_POSS, 0, 5, {A_Look}, 0, 0, S_POSS_STND}, // S_POSS_STND {SPR_POSS, 0, 5, {A_Look}, 0, 0, S_POSS_STND}, // S_POSS_STND
...@@ -2482,9 +2525,6 @@ state_t states[NUMSTATES] = ...@@ -2482,9 +2525,6 @@ state_t states[NUMSTATES] =
{SPR_SRBO, 0, 2, {A_Look}, 0, 0, S_SRB1_GENREX1}, // S_SRB1_GENREX1 {SPR_SRBO, 0, 2, {A_Look}, 0, 0, S_SRB1_GENREX1}, // S_SRB1_GENREX1
{SPR_SRBO, 0, 2, {A_BuzzFly}, 0, 0, S_SRB1_GENREX2}, // S_SRB1_GENREX2 {SPR_SRBO, 0, 2, {A_BuzzFly}, 0, 0, S_SRB1_GENREX2}, // S_SRB1_GENREX2
#ifdef SEENAMES
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
#endif
}; };
mobjinfo_t mobjinfo[NUMMOBJTYPES] = mobjinfo_t mobjinfo[NUMMOBJTYPES] =
...@@ -2574,7 +2614,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = ...@@ -2574,7 +2614,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
-1, // doomednum -1, // doomednum
S_PLAY_STND, // spawnstate S_PLAY_STND, // spawnstate
1, // spawnhealth 1, // spawnhealth
S_PLAY_RUN1, // seestate S_PLAY_WALK, // seestate
sfx_None, // seesound sfx_None, // seesound
0, // reactiontime 0, // reactiontime
sfx_thok, // attacksound sfx_thok, // attacksound
...@@ -2582,9 +2622,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = ...@@ -2582,9 +2622,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
MT_THOK, // painchance MT_THOK, // painchance
sfx_None, // painsound sfx_None, // painsound
S_NULL, // meleestate S_NULL, // meleestate
S_PLAY_ATK1, // missilestate S_PLAY_SPIN, // missilestate
S_PLAY_DIE, // deathstate S_PLAY_DEAD, // deathstate
S_NULL, // xdeathstate S_PLAY_DRWN, // xdeathstate
sfx_None, // deathsound sfx_None, // deathsound
1, // speed 1, // speed
16*FRACUNIT, // radius 16*FRACUNIT, // radius
...@@ -2853,7 +2893,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = ...@@ -2853,7 +2893,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // painsound sfx_None, // painsound
S_NULL, // meleestate S_NULL, // meleestate
S_NULL, // missilestate S_NULL, // missilestate
S_NULL, // deathstate S_XPLD1, // deathstate
S_DETON16, // xdeathstate S_DETON16, // xdeathstate
sfx_pop, // deathsound sfx_pop, // deathsound
1*FRACUNIT, // speed 1*FRACUNIT, // speed
......
...@@ -575,6 +575,54 @@ typedef enum sprite ...@@ -575,6 +575,54 @@ typedef enum sprite
NUMSPRITES NUMSPRITES
} spritenum_t; } spritenum_t;
enum playersprite
{
SPR2_STND = 0,
SPR2_WAIT,
SPR2_WALK,
SPR2_RUN ,
SPR2_PAIN,
SPR2_DEAD,
SPR2_DRWN,
SPR2_SPIN,
SPR2_DASH,
SPR2_GASP,
SPR2_JUMP,
SPR2_SPNG, // spring
SPR2_FALL,
SPR2_EDGE,
SPR2_RIDE,
SPR2_SIGN,
SPR2_LIFE,
SPR2_FLY ,
SPR2_TIRE,
SPR2_GLID,
SPR2_CLNG,
SPR2_CLMB,
SPR2_TRNS,
SPR2_SSTD,
SPR2_SWLK,
SPR2_SRUN,
SPR2_SPAN,
SPR2_SMSL,
SPR2_SDTH,
SPR2_SDRN,
SPR2_SSPN,
SPR2_SGSP,
SPR2_SJMP,
SPR2_SSPG,
SPR2_SFAL,
SPR2_SEDG,
SPR2_SRID,
SPR2_SFLT,
NUMPLAYERSPRITES
};
typedef enum state typedef enum state
{ {
S_NULL, S_NULL,
...@@ -592,61 +640,59 @@ typedef enum state ...@@ -592,61 +640,59 @@ typedef enum state
// Thok // Thok
S_THOK, S_THOK,
// Player
S_PLAY_STND, S_PLAY_STND,
S_PLAY_TAP1, S_PLAY_WAIT,
S_PLAY_TAP2, S_PLAY_WALK,
S_PLAY_RUN1, S_PLAY_RUN,
S_PLAY_RUN2,
S_PLAY_RUN3,
S_PLAY_RUN4,
S_PLAY_RUN5,
S_PLAY_RUN6,
S_PLAY_RUN7,
S_PLAY_RUN8,
S_PLAY_SPD1,
S_PLAY_SPD2,
S_PLAY_SPD3,
S_PLAY_SPD4,
S_PLAY_ATK1,
S_PLAY_ATK2,
S_PLAY_ATK3,
S_PLAY_ATK4,
S_PLAY_SPRING,
S_PLAY_FALL1,
S_PLAY_FALL2,
S_PLAY_ABL1,
S_PLAY_ABL2,
S_PLAY_SPC1,
S_PLAY_SPC2,
S_PLAY_SPC3,
S_PLAY_SPC4,
S_PLAY_CLIMB1,
S_PLAY_CLIMB2,
S_PLAY_CLIMB3,
S_PLAY_CLIMB4,
S_PLAY_CLIMB5,
S_PLAY_GASP,
S_PLAY_PAIN, S_PLAY_PAIN,
S_PLAY_DIE, S_PLAY_DEAD,
S_PLAY_TEETER1, S_PLAY_DRWN,
S_PLAY_TEETER2, S_PLAY_SPIN,
S_PLAY_CARRY, S_PLAY_DASH,
S_PLAY_SUPERSTAND, S_PLAY_GASP,
S_PLAY_SUPERWALK1, S_PLAY_JUMP, // spin jump (todo: make jump separate from spring up for non-spin chars too?)
S_PLAY_SUPERWALK2, S_PLAY_SPRING,
S_PLAY_SUPERFLY1, S_PLAY_FALL,
S_PLAY_SUPERFLY2, S_PLAY_EDGE,
S_PLAY_SUPERTEETER, S_PLAY_RIDE,
S_PLAY_SUPERHIT,
S_PLAY_SUPERTRANS1, // CA_FLY
S_PLAY_SUPERTRANS2, S_PLAY_FLY,
S_PLAY_SUPERTRANS3, S_PLAY_FLY_TIRED,
S_PLAY_SUPERTRANS4,
S_PLAY_SUPERTRANS5, // CA_GLIDEANDCLIMB
S_PLAY_SUPERTRANS6, S_PLAY_GLIDE,
S_PLAY_SUPERTRANS7, S_PLAY_CLING,
S_PLAY_SUPERTRANS8, S_PLAY_CLIMB,
S_PLAY_SUPERTRANS9, // This has special significance in the code. If you add more frames, search for it and make the appropriate changes.
// SF_SUPERANIMS
S_PLAY_SUPER_STND,
S_PLAY_SUPER_WALK,
S_PLAY_SUPER_RUN,
S_PLAY_SUPER_PAIN,
S_PLAY_SUPER_STUN,
S_PLAY_SUPER_DEAD,
S_PLAY_SUPER_DRWN,
S_PLAY_SUPER_SPIN,
S_PLAY_SUPER_GASP,
S_PLAY_SUPER_JUMP, // see note above
S_PLAY_SUPER_SPRING,
S_PLAY_SUPER_FALL,
S_PLAY_SUPER_EDGE,
S_PLAY_SUPER_RIDE,
S_PLAY_SUPER_FLOAT,
// SF_SUPER
S_PLAY_SUPER_TRANS,
S_PLAY_SUPER_TRANS2,
S_PLAY_SUPER_TRANS3,
S_PLAY_SUPER_TRANS4,
S_PLAY_SUPER_TRANS5,
S_PLAY_SUPER_TRANS6,
S_PLAY_SUPER_TRANS7,
S_PLAY_SUPER_TRANS8,
S_PLAY_SUPER_TRANS9,
// technically the player goes here but it's an infinite tic state // technically the player goes here but it's an infinite tic state
S_OBJPLACE_DUMMY, S_OBJPLACE_DUMMY,
...@@ -1388,7 +1434,7 @@ typedef enum state ...@@ -1388,7 +1434,7 @@ typedef enum state
// S_PLAY_TAP1 // S_PLAY_TAP1
S_METALSONIC_WAIT1, S_METALSONIC_WAIT1,
S_METALSONIC_WAIT2, S_METALSONIC_WAIT2,
// S_PLAY_RUN1 // S_PLAY_WALK
S_METALSONIC_WALK1, S_METALSONIC_WALK1,
S_METALSONIC_WALK2, S_METALSONIC_WALK2,
S_METALSONIC_WALK3, S_METALSONIC_WALK3,
...@@ -2947,6 +2993,7 @@ typedef struct ...@@ -2947,6 +2993,7 @@ typedef struct
extern state_t states[NUMSTATES]; extern state_t states[NUMSTATES];
extern char sprnames[NUMSPRITES + 1][5]; extern char sprnames[NUMSPRITES + 1][5];
char spr2names[NUMPLAYERSPRITES][5];
extern state_t *astate; extern state_t *astate;
typedef enum mobj_type typedef enum mobj_type
......
...@@ -85,14 +85,6 @@ static int lib_print(lua_State *L) ...@@ -85,14 +85,6 @@ static int lib_print(lua_State *L)
return 0; return 0;
} }
static int lib_evalMath(lua_State *L)
{
const char *word = luaL_checkstring(L, 1);
LUA_Deprecated(L, "EvalMath(string)", "_G[string]");
lua_pushinteger(L, LUA_EvalMath(word));
return 1;
}
// M_RANDOM // M_RANDOM
////////////// //////////////
...@@ -1092,6 +1084,7 @@ static int lib_pDamageMobj(lua_State *L) ...@@ -1092,6 +1084,7 @@ static int lib_pDamageMobj(lua_State *L)
{ {
mobj_t *target = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)), *inflictor = NULL, *source = NULL; mobj_t *target = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)), *inflictor = NULL, *source = NULL;
INT32 damage; INT32 damage;
UINT8 damagetype;
NOHUD NOHUD
if (!target) if (!target)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
...@@ -1100,13 +1093,15 @@ static int lib_pDamageMobj(lua_State *L) ...@@ -1100,13 +1093,15 @@ static int lib_pDamageMobj(lua_State *L)
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
damage = (INT32)luaL_optinteger(L, 4, 1); damage = (INT32)luaL_optinteger(L, 4, 1);
lua_pushboolean(L, P_DamageMobj(target, inflictor, source, damage)); damagetype = (UINT8)luaL_optinteger(L, 5, 0);
lua_pushboolean(L, P_DamageMobj(target, inflictor, source, damage, damagetype));
return 1; return 1;
} }
static int lib_pKillMobj(lua_State *L) static int lib_pKillMobj(lua_State *L)
{ {
mobj_t *target = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)), *inflictor = NULL, *source = NULL; mobj_t *target = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)), *inflictor = NULL, *source = NULL;
UINT8 damagetype;
NOHUD NOHUD
if (!target) if (!target)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
...@@ -1114,7 +1109,8 @@ static int lib_pKillMobj(lua_State *L) ...@@ -1114,7 +1109,8 @@ static int lib_pKillMobj(lua_State *L)
inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_KillMobj(target, inflictor, source); damagetype = (UINT8)luaL_optinteger(L, 4, 0);
P_KillMobj(target, inflictor, source, damagetype);
return 0; return 0;
} }
...@@ -1972,7 +1968,6 @@ static int lib_gTicsToMilliseconds(lua_State *L) ...@@ -1972,7 +1968,6 @@ static int lib_gTicsToMilliseconds(lua_State *L)
static luaL_Reg lib[] = { static luaL_Reg lib[] = {
{"print", lib_print}, {"print", lib_print},
{"EvalMath", lib_evalMath},
// m_random // m_random
{"P_RandomFixed",lib_pRandomFixed}, {"P_RandomFixed",lib_pRandomFixed},
......
...@@ -79,14 +79,14 @@ deny: ...@@ -79,14 +79,14 @@ deny:
//must be hacked/buggy client //must be hacked/buggy client
lua_settop(gL, 0); // clear stack lua_settop(gL, 0); // clear stack
CONS_Alert(CONS_WARNING, M_GetText("Illegal lua command received from %s\n"), player_names[playernum]); CONS_Alert(CONS_WARNING, M_GetText("Illegal lua command received from %s\n"), player_names[playernum]);
if (server) /*if (server)
{ {
XBOXSTATIC UINT8 bufn[2]; XBOXSTATIC UINT8 bufn[2];
bufn[0] = (UINT8)playernum; bufn[0] = (UINT8)playernum;
bufn[1] = KICK_MSG_CON_FAIL; bufn[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &bufn, 2); SendNetXCmd(XD_KICK, &bufn, 2);
} }*/ ///@NET TODO
} }
// Wrapper for COM_AddCommand commands // Wrapper for COM_AddCommand commands
......
...@@ -91,6 +91,44 @@ static int lib_sprnamelen(lua_State *L) ...@@ -91,6 +91,44 @@ static int lib_sprnamelen(lua_State *L)
return 1; return 1;
} }
//
// Player Sprite Names
//
// push sprite name
static int lib_getSpr2name(lua_State *L)
{
UINT32 i;
lua_remove(L, 1); // don't care about spr2names[] dummy userdata.
if (lua_isnumber(L, 1))
{
i = lua_tonumber(L, 1);
if (i > NUMPLAYERSPRITES)
return 0;
lua_pushlstring(L, spr2names[i], 4);
return 1;
}
else if (lua_isstring(L, 1))
{
const char *name = lua_tostring(L, 1);
for (i = 0; i < NUMPLAYERSPRITES; i++)
if (fastcmp(name, spr2names[i]))
{
lua_pushinteger(L, i);
return 1;
}
}
return 0;
}
static int lib_spr2namelen(lua_State *L)
{
lua_pushinteger(L, NUMPLAYERSPRITES);
return 1;
}
//////////////// ////////////////
// STATE INFO // // STATE INFO //
//////////////// ////////////////
...@@ -923,6 +961,16 @@ int LUA_InfoLib(lua_State *L) ...@@ -923,6 +961,16 @@ int LUA_InfoLib(lua_State *L)
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
lua_setglobal(L, "sprnames"); lua_setglobal(L, "sprnames");
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getSpr2name);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lib_spr2namelen);
lua_setfield(L, -2, "__len");
lua_setmetatable(L, -2);
lua_setglobal(L, "spr2names");
lua_newuserdata(L, 0); lua_newuserdata(L, 0);
lua_createtable(L, 0, 2); lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getState); lua_pushcfunction(L, lib_getState);
......