Merge branch 'fgs-port' into port-enh-mpsetupfile

This commit is contained in:
Raf committed 2025-03-31 10:34:42 +08:00
commit 0316317aa3
12 files changed
+128 -99

No files matched your search

+2 -2
View File
@@ -266,7 +266,7 @@ jobs:
build-flatpak-bundle:
name: "Build flatpak bundle"
runs-on: ubuntu-latest
needs: [build-i686-linux, build-x86_64-linux]
needs: [build-x86_64-linux]
container:
image: bilelmoussaoui/flatpak-github-actions:freedesktop-23.08
options: --privileged
@@ -274,7 +274,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: pd-i686-linux
name: pd-x86_64-linux
path: dist/linux/bin/
- uses: flatpak/flatpak-github-actions/flatpak-builder@v6
+1 -1
View File
@@ -1,7 +1,7 @@
[Desktop Entry]
Name=Perfect Dark
Comment=Modern source port of Perfect Dark
Exec=pd
Exec=io.github.fgsfdsfgs.perfect_dark.sh
Icon=io.github.fgsfdsfgs.perfect_dark
Terminal=false
Type=Application
+4 -4
View File
@@ -11,14 +11,14 @@ done
# Default to pd as executable but switch to jpn/pal if the NTSC rom
# is missing but JPN/PAL are present.
# TODO: Other arch
executable="pd.i686"
executable="pd.x86_64"
if [ -f ${XDG_DATA_HOME}/roms/pd.ntsc-final.z64 ] | \
[ -f ${XDG_DATA_HOME}/roms/pd.ntsc-1.0.z64 ]; then
executable="pd.i686"
executable="pd.x86_64"
elif [ -f ${XDG_DATA_HOME}/roms/pd.jpn-final.z64 ]; then
executable="pd.jpn.i686"
executable="pd.jpn.x86_64"
elif [ -f ${XDG_DATA_HOME}/roms/pd.pal-final.z64 ]; then
executable="pd.pal.i686"
executable="pd.pal.x86_64"
fi
# If first parameter passed to this script is one of the pd executables,
+6 -56
View File
@@ -1,13 +1,11 @@
app-id: io.github.fgsfdsfgs.perfect_dark
runtime: org.freedesktop.Platform
runtime-version: &runtime-version '23.08'
runtime-version: "23.08"
sdk: org.freedesktop.Sdk
command: io.github.fgsfdsfgs.perfect_dark.sh
finish-args:
# hardware 3D and controller access
- --device=all
# X11 + XShm access
- --share=ipc
- --socket=x11
# Audio
@@ -15,59 +13,16 @@ finish-args:
# Enable network for multiplayer
- --share=network
# Parameters for 32-bit extensions
x-gl-version: &gl-version '1.4'
x-gl-versions: &gl-versions 23.08;1.4
x-gl-merge-dirs: &gl-merge-dirs vulkan/icd.d;glvnd/egl_vendor.d;egl/egl_external_platform.d;OpenCL/vendors;lib/dri;lib/d3d;lib/gbm;vulkan/explicit_layer.d;vulkan/implicit_layer.d
add-extensions:
org.freedesktop.Platform.Compat.i386:
directory: lib/i386-linux-gnu
version: '23.08'
org.freedesktop.Platform.GL32:
directory: lib/i386-linux-gnu/GL
version: *gl-version
versions: *gl-versions
subdirectories: true
no-autodownload: true
autodelete: false
add-ld-path: lib
merge-dirs: *gl-merge-dirs
download-if: active-gl-driver
enable-if: active-gl-driver
autoprune-unless: active-gl-driver
org.freedesktop.Platform.GL32.Debug:
directory: lib/debug/lib/i386-linux-gnu/GL
version: *gl-version
versions: *gl-versions
subdirectories: true
no-autodownload: true
merge-dirs: *gl-merge-dirs
enable-if: active-gl-driver
autoprune-unless: active-gl-driver
org.freedesktop.Platform.VAAPI.Intel.i386:
directory: lib/i386-linux-gnu/dri/intel-vaapi-driver
version: *runtime-version
versions: *runtime-version
autodelete: false
no-autodownload: true
add-ld-path: lib
download-if: have-intel-gpu
autoprune-unless: have-intel-gpu
modules:
- name: perfect_dark
buildsystem: simple
sources:
- type: file
path: bin/pd.i686
path: bin/pd.x86_64
- type: file
path: bin/pd.jpn.i686
path: bin/pd.jpn.x86_64
- type: file
path: bin/pd.pal.i686
path: bin/pd.pal.x86_64
- type: file
path: io.github.fgsfdsfgs.perfect_dark.sh
- type: file
@@ -78,13 +33,8 @@ modules:
path: io.github.fgsfdsfgs.perfect_dark.desktop
build-commands: []
post-install:
# create extension mountpoints
- mkdir -p /app/lib/i386-linux-gnu
- mkdir -p /app/lib/i386-linux-gnu/GL
- mkdir -p /app/lib/debug/lib/i386-linux-gnu/GL
- mkdir -p /app/lib/i386-linux-gnu/dri/intel-vaapi-driver
# port
- install -Dm 755 -t /app/bin/ pd*
# Install the binaries
- install -Dm 755 -t /app/bin/ pd.*
- install -Dm 755 ${FLATPAK_ID}.sh /app/bin/${FLATPAK_ID}.sh
- install -Dm 644 ${FLATPAK_ID}.desktop /app/share/applications/${FLATPAK_ID}.desktop
- install -Dm 644 ${FLATPAK_ID}.metainfo.xml /app/share/metainfo/${FLATPAK_ID}.metainfo.xml
+37
View File
@@ -74,6 +74,9 @@ static s32 connectedMask = 0;
static s32 numJoysticks = 0;
static s32 useHIDAPI = 1;
static s32 useRawInput = 1;
static s32 mouseEnabled = 1;
static s32 mouseX, mouseY;
static s32 mouseDX, mouseDY;
@@ -674,6 +677,38 @@ static inline void inputLoadBinds(void)
s32 inputInit(void)
{
// Set SDL hints before initializing the controller subsystem.
if (useHIDAPI) {
#if SDL_VERSION_ATLEAST(2, 0, 12)
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE, "1");
#endif
#if SDL_VERSION_ATLEAST(2, 0, 14)
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5, "1");
#endif
#if SDL_VERSION_ATLEAST(2, 0, 22)
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1");
// the two hints below enable Rumble and Motion Sensor for PS4/5 pads connected via bluetooth
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
#endif
#if SDL_VERSION_ATLEAST(2, 23, 2)
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS, "1");
#endif
#if SDL_VERSION_ATLEAST(2, 25, 1)
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS3, "1");
#endif
#if SDL_VERSION_ATLEAST(2, 26, 0)
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_WII, "1");
#endif
}
if (useRawInput) {
SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT, "1");
}
if (!SDL_WasInit(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC)) {
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC);
}
@@ -1509,6 +1544,8 @@ PD_CONSTRUCTOR static void inputConfigInit(void)
configRegisterFloat("Input.MouseSpeedY", &mouseSensY, -10.f, 10.f);
configRegisterInt("Input.FakeGamepads", &fakeControllers, 0, 4);
configRegisterInt("Input.FirstGamepadNum", &firstController, 0, 3);
configRegisterInt("Input.UseHIDAPI", &useHIDAPI, 0, 1);
configRegisterInt("Input.UseRawInput", &useRawInput, 0, 1);
char secname[] = "Input.Player1.Binds";
char keyname[256] = { 0 };
+10 -2
View File
@@ -57,18 +57,26 @@ u8 *preprocessMpConfigs(u8* data, u32 size, u32* outSize)
for (s32 j = 0; j < ARRAYCOUNT(cfg->setup.weapons); ++j) {
#if VERSION == VERSION_JPN_FINAL /* TODO: replace with runtime check */
if (cfg->setup.weapons[j] >= 0x24) {
// weapons after and including the shield need to be shifted
// weapons after and including the shield need to be shifted (for classic weapons)
cfg->setup.weapons[j] += (MPWEAPON_SHIELD - MPWEAPON_PP9I);
}
if (cfg->setup.weapons[j] >= 0x22) {
// weapons after and including the cloaking device need to be shifted (for IR Scanner and Night Vision)
cfg->setup.weapons[j] += (MPWEAPON_CLOAKINGDEVICE - MPWEAPON_NIGHTVISION);
}
if (cfg->setup.weapons[j] >= 0x19) {
// weapons after the combat knife also need to be shifted up in JPN
cfg->setup.weapons[j]++;
}
#else
// in other versions we only care about the shield and above
if (cfg->setup.weapons[j] >= 0x25) {
// weapons after and including the shield need to be shifted (for classic weapons)
cfg->setup.weapons[j] += (MPWEAPON_SHIELD - MPWEAPON_PP9I);
}
if (cfg->setup.weapons[j] >= 0x23) {
// weapons after and including the cloaking device need to be shifted (for IR Scanner and Night Vision)
cfg->setup.weapons[j] += (MPWEAPON_CLOAKINGDEVICE - MPWEAPON_NIGHTVISION);
}
#endif
}
}
+29 -2
View File
@@ -31,7 +31,7 @@ char var800a41c0[26];
char var800a41c0[24];
#endif
u8 g_IrScanlines[2][480];
u8 g_IrScanlines[4][480];
#if VERSION < VERSION_NTSC_1_0
u8 var800a8b58nb[0x1c0];
@@ -2356,6 +2356,10 @@ Gfx *bviewDrawIrLens(Gfx *gdl)
gSPSetExtraGeometryModeEXT(gdl++, G_MODULATE_EXT);
#endif
// fixes off by one error w/ two top players
if (g_Vars.currentplayernum == 0 || g_Vars.currentplayernum == 1) {
scanbottom++;
}
for (i = scantop; i < scanbottom; i++) {
#if VERSION >= VERSION_NTSC_1_0
if (i & 1) {
@@ -2392,6 +2396,10 @@ Gfx *bviewDrawIrLens(Gfx *gdl)
s32 semicirclewidth = sqrtf(sqinnerradius - (s32) (f0 * f0)) * (viewwidth / (f32) SCREEN_WIDTH_LO);
s32 semicircleright = viewcentrex + semicirclewidth;
s32 rightsidewidth = viewwidth - semicircleright;
// if playernum is 1 or 3, shift to the right by viewwidth
if (g_Vars.currentplayernum == 1 || g_Vars.currentplayernum == 3) {
rightsidewidth += viewwidth;
}
#ifdef PLATFORM_N64
// Left and right of semicircle
@@ -2405,14 +2413,22 @@ Gfx *bviewDrawIrLens(Gfx *gdl)
gdl = bviewCopyPixels(gdl, fb, i, 5, i, 1.0f, viewleft, viewwidth);
}
#else
// Left and right of semicircle
// Scanlines to the left and right of the semicircle
gDPFillRectangle(gdl++, viewleft, i, viewcentrex, i + 1);
if (PLAYERCOUNT() <= 2 && g_Vars.currentplayernum == 0 && i == viewcentrey) {
semicircleright -= 1;
}
else if (PLAYERCOUNT() > 2 && (g_Vars.currentplayernum == 1 || g_Vars.currentplayernum == 3 ) && i == viewcentrey) {
semicircleright -= 1;
}
gDPFillRectangle(gdl++, semicircleright, i, semicircleright + rightsidewidth, i + 1);
// The semicircle itself has a static colour
gDPSetPrimColorViaWord(gdl++, 0, 0, 0xee0000ff);
gDPFillRectangle(gdl++, viewcentrex, i, viewcentrex + semicirclewidth, i + 1);
} else {
// scanlines above and below the semicircle
gDPFillRectangle(gdl++, viewleft, i, viewleft + viewwidth, i + 1);
}
#endif
@@ -2781,6 +2797,10 @@ Gfx *bviewDrawIrBinoculars(Gfx *gdl)
s32 viewleft = viGetViewLeft();
s32 viewright = viewleft + viewwidth;
s32 viewbottom = viewtop + viewheight;
// fixes off by one error w/ two top players
if (g_Vars.currentplayernum == 0 || g_Vars.currentplayernum == 1) {
viewbottom++;
}
s32 leftx = viewleft + viewwidth / 3;
s32 rightx = viewleft + (viewwidth * 2) / 3;
s32 centrey = (viewtop + viewbottom) / 2;
@@ -2798,6 +2818,13 @@ Gfx *bviewDrawIrBinoculars(Gfx *gdl)
for (y = viewtop; y < viewbottom; y++) {
s32 ytocentre = centrey - y;
s32 sqytocentre = ytocentre * ytocentre;
if (PLAYERCOUNT() <= 2) {
sqytocentre += 1;
} else if (PLAYERCOUNT() > 2) {
if (g_Vars.currentplayernum == 1 || g_Vars.currentplayernum == 3) {
sqytocentre += 1;
}
}
if (sqytocentre < sqradius) {
s32 xoffset = (viewwidth / (f32) SCREEN_WIDTH_LO) * sqrtf(sqradius - sqytocentre);
+2 -2
View File
@@ -5118,7 +5118,7 @@ struct weapon invitem_nightvision = {
L_GUN_059, // name
L_GUN_000, // manufacturer
L_GUN_191, // description
WEAPONFLAG_ONEHANDED | WEAPONFLAG_AICANUSE | WEAPONFLAG_00000080 | WEAPONFLAG_DUALWIELD | WEAPONFLAG_UNDROPPABLE,
WEAPONFLAG_ONEHANDED | WEAPONFLAG_AICANUSE | WEAPONFLAG_00000080 | WEAPONFLAG_UNDROPPABLE,
};
struct weaponfunc invfunc_horizonscanner_primary = {
@@ -5344,7 +5344,7 @@ struct weapon invitem_irscanner = {
L_GUN_069, // name
L_GUN_000, // manufacturer
L_GUN_194, // description
WEAPONFLAG_ONEHANDED | WEAPONFLAG_AICANUSE | WEAPONFLAG_00000040 | WEAPONFLAG_DUALWIELD | WEAPONFLAG_UNDROPPABLE,
WEAPONFLAG_ONEHANDED | WEAPONFLAG_AICANUSE | WEAPONFLAG_00000040 | WEAPONFLAG_UNDROPPABLE,
};
struct weaponfunc invfunc_disguise_primary = {
+15 -13
View File
@@ -103,23 +103,25 @@ struct mpweapon g_MpWeapons[NUM_MPWEAPONS] = {
#ifndef PLATFORM_N64
// fix X-Ray Scanner model
/*0x22*/ { WEAPON_XRAYSCANNER, 0, 0, 0, 0, 1, MPFEATURE_WEAPON_XRAYSCANNER, MODEL_XRAYSPECS, 256 },
/*0x23*/ { WEAPON_NIGHTVISION, 0, 0, 0, 0, 1, 0, MODEL_CHRNIGHTSIGHT, 256 },
/*0x24*/ { WEAPON_IRSCANNER, 0, 0, 0, 0, 1, 0, MODEL_MISC_IRSPECS, 256 },
#else
/*0x22*/ { WEAPON_XRAYSCANNER, 0, 0, 0, 0, 1, MPFEATURE_WEAPON_XRAYSCANNER, MODEL_CHRNIGHTSIGHT, 256 },
#endif
/*0x23*/ { WEAPON_CLOAKINGDEVICE, 0, 0, 0, 0, 1, MPFEATURE_WEAPON_CLOAKINGDEVICE, MODEL_CHRCLOAKER, 256 },
/*0x24*/ { WEAPON_COMBATBOOST, 0, 0, 0, 0, 1, MPFEATURE_WEAPON_COMBATBOOST, MODEL_CHRSPEEDPILL, 256 },
/*0x25*/ { WEAPON_CLOAKINGDEVICE, 0, 0, 0, 0, 1, MPFEATURE_WEAPON_CLOAKINGDEVICE, MODEL_CHRCLOAKER, 256 },
/*0x26*/ { WEAPON_COMBATBOOST, 0, 0, 0, 0, 1, MPFEATURE_WEAPON_COMBATBOOST, MODEL_CHRSPEEDPILL, 256 },
#ifndef PLATFORM_N64
/*0x25*/ { WEAPON_PP9I, AMMOTYPE_PISTOL, 80, 0, 0, 1, 0, MODEL_CHRWPPK, 256 },
/*0x26*/ { WEAPON_CC13, AMMOTYPE_PISTOL, 80, 0, 0, 1, 0, MODEL_CHRTT33, 256 },
/*0x27*/ { WEAPON_KL01313, AMMOTYPE_SMG, 100, 0, 0, 1, 0, MODEL_CHRSKORPION, 256 },
/*0x28*/ { WEAPON_KF7SPECIAL, AMMOTYPE_RIFLE, 100, 0, 0, 1, 0, MODEL_CHRKALASH, 256 },
/*0x29*/ { WEAPON_ZZT, AMMOTYPE_SMG, 100, 0, 0, 1, 0, MODEL_CHRUZI, 256 },
/*0x2a*/ { WEAPON_DMC, AMMOTYPE_SMG, 100, 0, 0, 1, 0, MODEL_CHRMP5K, 256 },
/*0x2b*/ { WEAPON_AR53, AMMOTYPE_RIFLE, 150, 0, 0, 1, 0, MODEL_CHRM16, 256 },
/*0x2c*/ { WEAPON_RCP45, AMMOTYPE_SMG, 150, 0, 0, 1, 0, MODEL_CHRFNP90, 256 },
/*0x27*/ { WEAPON_PP9I, AMMOTYPE_PISTOL, 80, 0, 0, 1, 0, MODEL_CHRWPPK, 256 },
/*0x28*/ { WEAPON_CC13, AMMOTYPE_PISTOL, 80, 0, 0, 1, 0, MODEL_CHRTT33, 256 },
/*0x29*/ { WEAPON_KL01313, AMMOTYPE_SMG, 100, 0, 0, 1, 0, MODEL_CHRSKORPION, 256 },
/*0x2a*/ { WEAPON_KF7SPECIAL, AMMOTYPE_RIFLE, 100, 0, 0, 1, 0, MODEL_CHRKALASH, 256 },
/*0x2b*/ { WEAPON_ZZT, AMMOTYPE_SMG, 100, 0, 0, 1, 0, MODEL_CHRUZI, 256 },
/*0x2c*/ { WEAPON_DMC, AMMOTYPE_SMG, 100, 0, 0, 1, 0, MODEL_CHRMP5K, 256 },
/*0x2d*/ { WEAPON_AR53, AMMOTYPE_RIFLE, 150, 0, 0, 1, 0, MODEL_CHRM16, 256 },
/*0x2e*/ { WEAPON_RCP45, AMMOTYPE_SMG, 150, 0, 0, 1, 0, MODEL_CHRFNP90, 256 },
#endif
/*0x2d*/ { WEAPON_MPSHIELD, 0, 0, 0, 0, 1, MPFEATURE_WEAPON_SHIELD, MODEL_CHRSHIELD, 256 },
/*0x2e*/ { WEAPON_DISABLED }, // 0x25 on N64
/*0x2f*/ { WEAPON_MPSHIELD, 0, 0, 0, 0, 1, MPFEATURE_WEAPON_SHIELD, MODEL_CHRSHIELD, 256 },
/*0x30*/ { WEAPON_DISABLED }, // 0x25 on N64
};
#ifndef PLATFORM_N64
@@ -141,7 +143,7 @@ struct mpweapon g_MpWeapons[NUM_MPWEAPONS] = {
.usereloads = false, \
}
struct extplayerconfig g_PlayerExtCfg[MAX_PLAYERS] = {
struct extplayerconfig g_PlayerExtCfg[MAX_PLAYERS] = {
PLAYER_EXT_CFG_DEFAULT,
PLAYER_EXT_CFG_DEFAULT,
PLAYER_EXT_CFG_DEFAULT,
+4 -1
View File
@@ -1239,7 +1239,10 @@ MenuItemHandlerResult mpSelectRandomWeaponListHandler(s32 operation, struct menu
case 0:
// Select Dark
for (i = 0; i < ARRAYCOUNT(g_MpWeapons); i++) {
if ((i >= MPWEAPON_NONE && i <= MPWEAPON_COMBATBOOST) || i >= MPWEAPON_SHIELD) {
if ((i >= MPWEAPON_NONE && i <= MPWEAPON_XRAYSCANNER)
|| i == MPWEAPON_CLOAKINGDEVICE
|| i == MPWEAPON_COMBATBOOST
|| i >= MPWEAPON_SHIELD) {
g_MpWeaponSetRandomFilters[i] = 1;
} else {
g_MpWeaponSetRandomFilters[i] = 0;
+2 -2
View File
@@ -1616,9 +1616,9 @@ void propCalculateShadeColour(struct prop *prop, u8 *nextcol, u16 floorcol)
{
s32 shade = func0f068fc8(prop, 0);
// fix props flickering in split screen when one of the players has night vision on
// fix props flickering in split screen when one of the players has night vision or IR Goggles on
if (prop->type != PROPTYPE_PLAYER || g_Vars.currentplayer->prop != prop) {
if (USINGDEVICE(DEVICE_NIGHTVISION)) {
if (USINGDEVICE(DEVICE_NIGHTVISION) || USINGDEVICE(DEVICE_IRSCANNER)) {
if (prop->rooms[0] >= 0) {
shade = g_Rooms[prop->rooms[0]].br_settled_regional;
}
+16 -14
View File
@@ -2993,7 +2993,7 @@
#define MPWEAPON_SHIELD (VERSION == VERSION_JPN_FINAL ? 0x24 : 0x25)
#define MPWEAPON_DISABLED (VERSION == VERSION_JPN_FINAL ? 0x25 : 0x26)
#define NUM_MPWEAPONS (VERSION == VERSION_JPN_FINAL ? 0x26 : 0x27)
#else // add all classic weapons to multiplayer and allow combat knife in JPN
#else // add all classic weapons to multiplayer and allow combat knife in JPN and add IR Scanner and Night Vision
#define MPWEAPON_COMBATKNIFE 0x19
#define MPWEAPON_CROSSBOW 0x1a
#define MPWEAPON_TRANQUILIZER 0x1b
@@ -3004,19 +3004,21 @@
#define MPWEAPON_REMOTEMINE 0x20
#define MPWEAPON_LASER 0x21
#define MPWEAPON_XRAYSCANNER 0x22
#define MPWEAPON_CLOAKINGDEVICE 0x23
#define MPWEAPON_COMBATBOOST 0x24
#define MPWEAPON_PP9I 0x25
#define MPWEAPON_CC13 0x26
#define MPWEAPON_KL01313 0x27
#define MPWEAPON_KF7SPECIAL 0x28
#define MPWEAPON_ZZT 0x29
#define MPWEAPON_DMC 0x2a
#define MPWEAPON_AR53 0x2b
#define MPWEAPON_RCP45 0x2c
#define MPWEAPON_SHIELD 0x2d
#define MPWEAPON_DISABLED 0x2e
#define NUM_MPWEAPONS 0x2f
#define MPWEAPON_NIGHTVISION 0x23
#define MPWEAPON_IRSCANNER 0x24
#define MPWEAPON_CLOAKINGDEVICE 0x25
#define MPWEAPON_COMBATBOOST 0x26
#define MPWEAPON_PP9I 0x27
#define MPWEAPON_CC13 0x28
#define MPWEAPON_KL01313 0x29
#define MPWEAPON_KF7SPECIAL 0x2a
#define MPWEAPON_ZZT 0x2b
#define MPWEAPON_DMC 0x2c
#define MPWEAPON_AR53 0x2d
#define MPWEAPON_RCP45 0x2e
#define MPWEAPON_SHIELD 0x2f
#define MPWEAPON_DISABLED 0x30
#define NUM_MPWEAPONS 0x31
#endif
#define MUSICEVENTTYPE_PLAY 1