port: net: sync some projectiles, doors, parts of bgun, etc

This commit is contained in:
fgsfds committed 2023-12-23 22:09:37 +01:00
1 parent 41d9cb4578
commit aae0f70dd3
28 files changed
+1763 -186

No files matched your search

+7
View File
@@ -32,6 +32,7 @@ enum virtkey {
VK_LEFTBRACKET = 47,
VK_RIGHTBRACKET = 48,
VK_SEMICOLON = 51,
VK_GRAVE = 53,
VK_COMMA = 54,
VK_PERIOD = 55,
VK_DELETE = 76,
@@ -214,6 +215,12 @@ void inputSetDefaultKeyBinds(s32 cidx, s32 n64mode);
void inputClearLastKey(void);
s32 inputGetLastKey(void);
void inputStartTextInput(void);
void inputStopTextInput(void);
void inputClearLastTextChar(void);
char inputGetLastTextChar(void);
// get/set Input.MouseDefaultLocked
s32 inputGetMouseDefaultLocked(void);
void inputSetMouseDefaultLocked(s32 defaultLocked);
+21 -10
View File
@@ -14,6 +14,9 @@
#define NET_DEFAULT_PORT 27100
#define NET_NULL_CLIENT 0xFF
#define NET_NULL_PROP 0
#define NETCHAN_DEFAULT 0
#define NETCHAN_COUNT 1
@@ -24,6 +27,7 @@
#define DISCONNECT_BANNED 4
#define DISCONNECT_TIMEOUT 5
#define DISCONNECT_FULL 6
#define DISCONNECT_LATE 7
#define CLSTATE_DISCONNECTED 0
#define CLSTATE_CONNECTING 1
@@ -34,13 +38,16 @@
#define UCMD_FIRE (1 << 0)
#define UCMD_ACTIVATE (1 << 1)
#define UCMD_RELOAD (1 << 2)
#define UCMD_FIREMODE (1 << 3)
#define UCMD_AIMMODE (1 << 4)
#define UCMD_DUCK (1 << 5)
#define UCMD_SQUAT (1 << 6)
#define UCMD_ZOOMIN (1 << 7)
#define UCMD_SELECT (1 << 8)
#define UCMD_CHAT (1 << 19)
#define UCMD_AIMMODE (1 << 3)
#define UCMD_DUCK (1 << 4)
#define UCMD_SQUAT (1 << 5)
#define UCMD_ZOOMIN (1 << 6)
#define UCMD_SELECT (1 << 7)
#define UCMD_EYESSHUT (1 << 8)
#define UCMD_SECONDARY (1 << 9)
#define UCMD_RESPAWN (1 << 27)
#define UCMD_CHAT (1 << 28)
#define UCMD_IMPORTANT_MASK (UCMD_FIRE | UCMD_ACTIVATE | UCMD_RELOAD | UCMD_AIMMODE | UCMD_SELECT)
#define UCMD_FL_FORCEPOS (1 << 29)
#define UCMD_FL_FORCEANGLE (1 << 30)
#define UCMD_FL_FORCEGROUND (1 << 31)
@@ -52,10 +59,10 @@ struct netplayermove {
f32 leanofs; // analog lean value (-1 .. 1; equal to player->swaytarget / 75.f)
f32 crouchofs; // analog crouch value (-90 for SQUAT, 0 for STAND; player->crouchofs)
f32 movespeed[2]; // move inputs, [0] is forward, [1] is sideways; used mostly for animation
f32 lookspeed[2]; // look inputs, [0] is theta, [1] is verta
f32 angles[2]; // view angles, [0] is theta, [1] is verta
f32 crosspos[2]; // crosshair position in aiming mode
s8 weaponnum; // switch to this weapon if UCMD_SELECT is set
struct coord pos; // player position at g_NetTick == tick
s16 rooms[2]; // cam_room, floorroom
};
struct netclient {
@@ -93,7 +100,8 @@ extern s32 g_NetMode;
extern u32 g_NetTick;
extern u32 g_NetInterpTicks;
extern u32 g_NetExterpTicks;
extern u32 g_NetNextSyncId;
extern s32 g_NetMaxClients;
extern s32 g_NetNumClients;
@@ -115,9 +123,12 @@ s32 netStartClient(const char *addr);
u32 netSend(struct netclient *dstcl, struct netbuf *buf, const s32 reliable);
void netChat(const char *text);
void netServerStageStart(void);
void netServerStageEnd(void);
void netPlayersAllocate(void);
void netSyncIdsAllocate(void);
#endif // _IN_NET_H
+3
View File
@@ -26,6 +26,8 @@ s64 netbufReadS64(struct netbuf *buf);
f32 netbufReadF32(struct netbuf *buf);
char *netbufReadStr(struct netbuf *buf);
u32 netbufReadCoord(struct netbuf *buf, struct coord *out);
u32 netbufReadMtxf(struct netbuf *buf, Mtxf *out);
u32 netbufReadSkip(struct netbuf *buf, u32 count);
void netbufStartWrite(struct netbuf *buf);
s32 netbufWriteLeft(const struct netbuf *buf);
@@ -41,6 +43,7 @@ u32 netbufWriteS64(struct netbuf *buf, const s64 v);
u32 netbufWriteF32(struct netbuf *buf, const f32 v);
u32 netbufWriteStr(struct netbuf *buf, const char *v);
u32 netbufWriteCoord(struct netbuf *buf, const struct coord *v);
u32 netbufWriteMtxf(struct netbuf *buf, const Mtxf *in);
void netbufReset(struct netbuf *buf);
+44 -12
View File
@@ -5,32 +5,64 @@
#include "net/net.h"
#include "net/netbuf.h"
#define SVC_BAD 0 // trash
#define SVC_NOP 1 // does nothing
#define SVC_AUTH 2 // auth response, sent in response to CLC_AUTH
#define SVC_CHAT 3 // chat message
#define SVC_STAGE_START 4 // start level
#define SVC_STAGE_END 5 // end level
#define SVC_PLAYER_MOVE 6 // player movement
#define SVC_BAD 0x00 // trash
#define SVC_NOP 0x01 // does nothing
#define SVC_AUTH 0x02 // auth response, sent in response to CLC_AUTH
#define SVC_CHAT 0x03 // chat message
#define SVC_STAGE_START 0x10 // start level
#define SVC_STAGE_END 0x11 // end level
#define SVC_PLAYER_MOVE 0x20 // player movement and inputs
#define SVC_PLAYER_GUNS 0x21 // player gun state
#define SVC_PLAYER_STATS 0x22 // player stats (health etc)
#define SVC_PROP_MOVE 0x30 // prop movement
#define SVC_PROP_SPAWN 0x31 // new prop spawned
#define SVC_PROP_DAMAGE 0x32 // prop was damaged
#define SVC_PROP_PICKUP 0x33 // prop was picked up
#define SVC_PROP_USE 0x34 // door/lift/etc was used
#define SVC_PROP_DOOR 0x35 // door state changed
#define SVC_CHR_DAMAGE 0x42 // chr was damaged
#define SVC_CHR_DISARM 0x43 // chr's weapons were dropped
#define CLC_BAD 0 // trash
#define CLC_NOP 1 // does nothing
#define CLC_AUTH 2 // auth request, sent immediately after connecting
#define CLC_CHAT 3 // chat message
#define CLC_MOVE 4 // player input
#define CLC_BAD 0x00 // trash
#define CLC_NOP 0x01 // does nothing
#define CLC_AUTH 0x02 // auth request, sent immediately after connecting
#define CLC_CHAT 0x03 // chat message
#define CLC_MOVE 0x04 // player input
u32 netmsgClcAuthWrite(struct netbuf *dst);
u32 netmsgClcAuthRead(struct netbuf *src, struct netclient *srccl);
u32 netmsgClcChatWrite(struct netbuf *dst, const char *str);
u32 netmsgClcChatRead(struct netbuf *src, struct netclient *srccl);
u32 netmsgClcMoveWrite(struct netbuf *dst);
u32 netmsgClcMoveRead(struct netbuf *src, struct netclient *srccl);
u32 netmsgSvcAuthWrite(struct netbuf *dst, struct netclient *authcl);
u32 netmsgSvcAuthRead(struct netbuf *src, struct netclient *srccl);
u32 netmsgSvcChatWrite(struct netbuf *dst, const char *str);
u32 netmsgSvcChatRead(struct netbuf *src, struct netclient *srccl);
u32 netmsgSvcStageStartWrite(struct netbuf *dst);
u32 netmsgSvcStageStartRead(struct netbuf *src, struct netclient *srccl);
u32 netmsgSvcStageEndWrite(struct netbuf *dst);
u32 netmsgSvcStageEndRead(struct netbuf *src, struct netclient *srccl);
u32 netmsgSvcPlayerMoveWrite(struct netbuf *dst, struct netclient *movecl);
u32 netmsgSvcPlayerMoveRead(struct netbuf *src, struct netclient *srccl);
u32 netmsgSvcPlayerStatsWrite(struct netbuf *dst, struct netclient *actcl);
u32 netmsgSvcPlayerStatsRead(struct netbuf *src, struct netclient *srccl);
u32 netmsgSvcPropSpawnWrite(struct netbuf *dst, struct prop *prop);
u32 netmsgSvcPropSpawnRead(struct netbuf *src, struct netclient *srccl);
u32 netmsgSvcPropMoveWrite(struct netbuf *dst, struct prop *prop, struct coord *initrot);
u32 netmsgSvcPropMoveRead(struct netbuf *src, struct netclient *srccl);
u32 netmsgSvcPropDamageWrite(struct netbuf *dst, struct prop *prop, f32 damage, struct coord *pos, s32 weaponnum, s32 playernum);
u32 netmsgSvcPropDamageRead(struct netbuf *src, struct netclient *srccl);
u32 netmsgSvcPropPickupWrite(struct netbuf *dst, struct netclient *actcl, struct prop *prop, const s32 tickop);
u32 netmsgSvcPropPickupRead(struct netbuf *src, struct netclient *srccl);
u32 netmsgSvcPropUseWrite(struct netbuf *dst, struct prop *prop, struct netclient *usercl, const s32 tickop);
u32 netmsgSvcPropUseRead(struct netbuf *src, struct netclient *srccl);
u32 netmsgSvcPropDoorWrite(struct netbuf *dst, struct prop *prop, struct netclient *usercl);
u32 netmsgSvcPropDoorRead(struct netbuf *src, struct netclient *srccl);
u32 netmsgSvcChrDamageWrite(struct netbuf *dst, struct chrdata *chr, f32 damage, struct coord *vector, struct gset *gset, struct prop *aprop, s32 hitpart, bool damageshield, struct prop *prop2, s32 side, s16 *arg11, bool explosion, struct coord *explosionpos);
u32 netmsgSvcChrDamageRead(struct netbuf *src, struct netclient *srccl);
u32 netmsgSvcChrDisarmWrite(struct netbuf *dst, struct chrdata *chr, struct prop *attacker, u8 weaponnum, f32 wpndamage, struct coord *wpnpos);
u32 netmsgSvcChrDisarmRead(struct netbuf *src, struct netclient *srccl);
#endif
+8 -4
View File
@@ -7,10 +7,13 @@ extern "C" {
#include <PR/ultratypes.h>
enum LogLevel {
LOG_NOTE,
LOG_WARNING,
LOG_ERROR,
#define LOGFLAG_SHOWMSG (1 << 7)
enum loglevel {
LOG_NOTE = 0,
LOG_CHAT = 0 | LOGFLAG_SHOWMSG,
LOG_WARNING = 1 | LOGFLAG_SHOWMSG,
LOG_ERROR = 2 | LOGFLAG_SHOWMSG,
};
void sysInitArgs(s32 argc, const char **argv);
@@ -21,6 +24,7 @@ const char *sysArgGetString(const char *arg);
s32 sysArgGetInt(const char *arg, s32 defval);
u64 sysGetMicroseconds(void);
f32 sysGetSeconds(void);
void sysFatalError(const char *fmt, ...) __attribute__((noreturn));
+14
View File
@@ -12,4 +12,18 @@ char *strParseToken(char *str, char *out, s32 *outCount);
char *strFmt(const char *fmt, ...);
char *strDuplicate(const char *str);
static inline f32 lerpf(const f32 a, const f32 b, const f32 t) {
return a + (b - a) * t;
}
static inline f32 lerpanglef(const f32 a, const f32 b, const f32 t) {
f32 d = b - a;
if (d > 180.f) {
d -= 360.f;
} else if (d < -180.f) {
d += 360.f;
}
return a + d * t;
}
#endif
+40
View File
@@ -81,6 +81,8 @@ static f32 mouseSensX = 1.5f;
static f32 mouseSensY = 1.5f;
static s32 lastKey = 0;
static char lastChar = 0;
static s32 textInput = 0;
static const char *ckNames[CK_TOTAL_COUNT] = {
"R_CBUTTONS",
@@ -512,6 +514,12 @@ static int inputEventFilter(void *data, SDL_Event *event)
}
break;
case SDL_TEXTINPUT:
if (!lastChar && event->text.text[0] && (u8)event->text.text[0] < 0x80) {
lastChar = event->text.text[0];
}
break;
default:
break;
}
@@ -719,6 +727,14 @@ s32 inputReadController(s32 idx, OSContPad *npad)
npad->button = 0;
if (textInput) {
npad->stick_x = 0;
npad->stick_y = 0;
npad->rstick_x = 0;
npad->rstick_y = 0;
return 0;
}
for (u32 i = 0; i < CONT_NUM_BUTTONS; ++i) {
if (inputBindPressed(idx, i)) {
npad->button |= 1U << i;
@@ -1247,6 +1263,30 @@ s32 inputGetLastKey(void)
return lastKey;
}
void inputStartTextInput(void)
{
lastChar = 0;
lastKey = 0;
textInput = 1;
SDL_StartTextInput();
}
void inputClearLastTextChar(void)
{
lastChar = 0;
}
char inputGetLastTextChar(void)
{
return lastChar;
}
void inputStopTextInput(void)
{
SDL_StopTextInput();
textInput = 0;
}
PD_CONSTRUCTOR static void inputConfigInit(void)
{
configRegisterInt("Input.MouseEnabled", &mouseEnabled, 0, 1);
+175 -35
View File
@@ -11,11 +11,13 @@
#include "constants.h"
#include "data.h"
#include "bss.h"
#include "game/chraction.h"
#include "game/bot.h"
#include "game/botact.h"
#include "game/hudmsg.h"
#include "game/playermgr.h"
#include "game/bondgun.h"
#include "lib/main.h"
#include "config.h"
#include "system.h"
#include "console.h"
#include "utils.h"
s32 g_NetMode = NETMODE_NONE;
@@ -23,9 +25,10 @@ s32 g_NetMode = NETMODE_NONE;
u32 g_NetTick = 0;
u32 g_NetInterpTicks = 6;
u32 g_NetExterpTicks = 6;
s32 g_NetSimPacketLoss = 20;
s32 g_NetSimPacketLoss = 0;
u32 g_NetNextSyncId = 1;
s32 g_NetMaxClients = NET_MAX_CLIENTS;
s32 g_NetNumClients = 0;
@@ -35,7 +38,7 @@ struct netclient *g_NetLocalClient = &g_NetClients[NET_MAX_CLIENTS];
static u8 g_NetMsgBuf[NET_BUFSIZE];
struct netbuf g_NetMsg = { .data = g_NetMsgBuf, .size = sizeof(g_NetMsgBuf) };
static u8 g_NetMsgRelBuf[NET_BUFSIZE];
static u8 g_NetMsgRelBuf[NET_BUFSIZE * 4]; // reliable buffer can be reliably fragmented
struct netbuf g_NetMsgRel = { .data = g_NetMsgRelBuf, .size = sizeof(g_NetMsgRelBuf) };
static s32 g_NetInit = false;
@@ -132,6 +135,10 @@ const char *netFormatClientAddr(const struct netclient *cl)
static inline void netClientReset(struct netclient *cl)
{
if (cl->state >= CLSTATE_GAME && cl->player) {
cl->player->client = NULL;
cl->player->isremote = false;
}
memset(cl, 0, sizeof(*cl));
cl->out.data = cl->out_data;
cl->out.size = sizeof(cl->out_data);
@@ -159,13 +166,11 @@ static inline void netClientRecordMove(struct netclient *cl, const struct player
move->leanofs = pl->swaytarget / 75.f;
move->movespeed[0] = pl->speedforwards;
move->movespeed[1] = pl->speedsideways;
move->lookspeed[0] = pl->speedtheta;
move->lookspeed[1] = pl->speedverta;
move->angles[0] = pl->vv_theta;
move->angles[1] = pl->vv_verta;
move->pos = (pl->prop) ? pl->prop->pos : pl->cam_pos;
move->rooms[0] = pl->cam_room;
move->rooms[1] = pl->floorroom;
move->crosspos[0] = pl->crosspos[0];
move->crosspos[1] = pl->crosspos[1];
move->ucmd = pl->ucmd;
if (pl->crouchpos == CROUCHPOS_DUCK) {
@@ -174,19 +179,53 @@ static inline void netClientRecordMove(struct netclient *cl, const struct player
move->ucmd |= UCMD_SQUAT;
}
if (pl->bondactivateorreload & JO_ACTION_ACTIVATE) {
move->ucmd |= UCMD_ACTIVATE;
if (pl->gunctrl.switchtoweaponnum >= 0) {
move->ucmd |= UCMD_SELECT;
move->weaponnum = pl->gunctrl.switchtoweaponnum;
} else {
move->weaponnum = -1;
}
if (pl->bondactivateorreload & JO_ACTION_RELOAD) {
move->ucmd |= UCMD_RELOAD;
const s32 oldnum = g_Vars.currentplayernum;
setCurrentPlayerNum(cl->playernum);
if (bgunIsUsingSecondaryFunction()) {
move->ucmd |= UCMD_SECONDARY;
}
setCurrentPlayerNum(oldnum);
if (cl != g_NetLocalClient && !cl->forcetick && (move->ucmd & UCMD_FL_FORCEMASK)) {
cl->forcetick = move->tick;
sysLogPrintf(LOG_NOTE, "NET: forcing client %u to move at tick %u", cl->id, cl->forcetick);
}
}
static inline s32 netClientNeedReliableMove(const struct netclient *cl)
{
const struct netplayermove *move = &cl->outmove[0];
const struct netplayermove *moveprev = &cl->outmove[1];
return !moveprev->tick || (g_NetMode == NETMODE_SERVER && cl->forcetick) ||
(moveprev->ucmd & UCMD_IMPORTANT_MASK) != (move->ucmd & UCMD_IMPORTANT_MASK);
}
static inline void netFlushSendBuffers(void)
{
if (g_NetMsgRel.wp) {
if (g_NetMsgRel.error) {
sysLogPrintf(LOG_WARNING, "NET: reliable out buffer overflow");
}
netSend(NULL, &g_NetMsgRel, true);
}
if (g_NetMsg.wp) {
if (g_NetMsg.error) {
sysLogPrintf(LOG_WARNING, "NET: unreliable out buffer overflow");
}
netSend(NULL, &g_NetMsg, false);
}
}
void netInit(void)
{
if (enet_initialize() < 0) {
@@ -219,10 +258,16 @@ s32 netStartServer(u16 port, s32 maxclients)
g_NetLocalClient->settings.bodynum = g_PlayerConfigsArray[0].base.mpbodynum;
g_NetLocalClient->settings.headnum = g_PlayerConfigsArray[0].base.mpheadnum;
memcpy(g_NetLocalClient->settings.name, g_PlayerConfigsArray[0].base.name, sizeof(g_NetLocalClient->settings.name));
// the \n will be readded in the playerconfig
char *newline = strrchr(g_NetLocalClient->settings.name, '\n');
if (newline) {
*newline = '\0';
}
g_NetMode = NETMODE_SERVER;
g_NetTick = 0;
g_NetNextSyncId = 1;
sysLogPrintf(LOG_NOTE, "NET: created server on port %u", port);
@@ -235,6 +280,11 @@ void netServerStageStart(void)
return;
}
if (g_StageNum == STAGE_TITLE || g_StageNum == STAGE_CITRAINING) {
g_NetLocalClient->state = CLSTATE_LOBBY;
return;
}
g_NetLocalClient->state = CLSTATE_GAME;
netbufStartWrite(&g_NetMsgRel);
@@ -249,6 +299,7 @@ void netServerStageEnd(void)
}
g_NetLocalClient->state = CLSTATE_LOBBY;
netbufStartWrite(&g_NetMsgRel);
netmsgSvcStageEndWrite(&g_NetMsgRel);
netSend(NULL, &g_NetMsgRel, true);
@@ -292,10 +343,16 @@ s32 netStartClient(const char *addr)
g_NetLocalClient->settings.bodynum = g_PlayerConfigsArray[0].base.mpbodynum;
g_NetLocalClient->settings.headnum = g_PlayerConfigsArray[0].base.mpheadnum;
memcpy(g_NetLocalClient->settings.name, g_PlayerConfigsArray[0].base.name, sizeof(g_NetLocalClient->settings.name));
// the \n will be readded in the playerconfig
char *newline = strrchr(g_NetLocalClient->settings.name, '\n');
if (newline) {
*newline = '\0';
}
g_NetMode = NETMODE_CLIENT;
g_NetTick = 0;
g_NetNextSyncId = 1;
sysLogPrintf(LOG_NOTE, "NET: waiting for response from %s...", addr);
@@ -308,6 +365,8 @@ s32 netDisconnect(void)
return -1;
}
const bool wasingame = (g_NetLocalClient->state >= CLSTATE_GAME);
for (s32 i = 0; i < NET_MAX_CLIENTS + 1; ++i) {
if (g_NetClients[i].peer) {
enet_peer_disconnect_now(g_NetClients[i].peer, DISCONNECT_SHUTDOWN);
@@ -330,6 +389,11 @@ s32 netDisconnect(void)
sysLogPrintf(LOG_NOTE, "NET: disconnected");
if (wasingame) {
mainEndStage();
g_MpSetup.chrslots = 1;
}
return 0;
}
@@ -339,12 +403,20 @@ static void netServerEvConnect(ENetPeer *peer, const u32 data)
sysLogPrintf(LOG_NOTE, "NET: connection attempt from %s", addrstr);
++g_NetNumClients;
if (data != NET_PROTOCOL_VER) {
sysLogPrintf(LOG_NOTE, "NET: %s rejected: protocol mismatch", addrstr);
enet_peer_disconnect(peer, DISCONNECT_VERSION);
return;
}
if (g_NetLocalClient && g_NetLocalClient->state > CLSTATE_LOBBY) {
sysLogPrintf(LOG_NOTE, "NET: %s rejected: late joins not allowed", addrstr);
enet_peer_disconnect(peer, DISCONNECT_LATE);
return;
}
struct netclient *cl = NULL;
// id 0 is the local client
@@ -365,8 +437,6 @@ static void netServerEvConnect(ENetPeer *peer, const u32 data)
cl->state = CLSTATE_AUTH; // skip CLSTATE_CONNECTING, since we already know it connected
cl->peer = peer;
enet_peer_set_data(peer, cl);
++g_NetNumClients;
}
static void netServerEvDisconnect(struct netclient *cl)
@@ -377,6 +447,8 @@ static void netServerEvDisconnect(struct netclient *cl)
enet_peer_reset(cl->peer);
}
sysLogPrintf(LOG_CHAT, "NET: %s (client %u) disconnected", cl->settings.name, cl->id);
netClientReset(cl);
--g_NetNumClients;
@@ -392,7 +464,7 @@ static void netServerEvReceive(struct netclient *cl)
switch (msgid) {
case CLC_NOP: rc = 0; break;
case CLC_AUTH: rc = netmsgClcAuthRead(&cl->in, cl); break;
case CLC_CHAT: rc = 0; break;
case CLC_CHAT: rc = netmsgClcChatRead(&cl->in, cl); break;
case CLC_MOVE: rc = netmsgClcMoveRead(&cl->in, cl); break;
default:
rc = 1;
@@ -421,6 +493,8 @@ static void netClientEvDisconnect(const u32 reason)
{
sysLogPrintf(LOG_NOTE, "NET: kicked from server, reason: %u", reason);
netDisconnect();
sysLogPrintf(LOG_CHAT, "NET: disconnected from server");
}
static void netClientEvReceive(struct netclient *cl)
@@ -433,10 +507,19 @@ static void netClientEvReceive(struct netclient *cl)
switch (msgid) {
case SVC_NOP: rc = 0; break;
case SVC_AUTH: rc = netmsgSvcAuthRead(&cl->in, cl); break;
case SVC_CHAT: rc = 0; break;
case SVC_CHAT: rc = netmsgSvcChatRead(&cl->in, cl); break;
case SVC_STAGE_START: rc = netmsgSvcStageStartRead(&cl->in, cl); break;
case SVC_STAGE_END: rc = netmsgSvcStageEndRead(&cl->in, cl); break;
case SVC_PLAYER_MOVE: rc = netmsgSvcPlayerMoveRead(&cl->in, cl); break;
case SVC_PLAYER_STATS: rc = netmsgSvcPlayerStatsRead(&cl->in, cl); break;
case SVC_PROP_MOVE: rc = netmsgSvcPropMoveRead(&cl->in, cl); break;
case SVC_PROP_SPAWN: rc = netmsgSvcPropSpawnRead(&cl->in, cl); break;
case SVC_PROP_DAMAGE: rc = netmsgSvcPropDamageRead(&cl->in, cl); break;
case SVC_PROP_PICKUP: rc = netmsgSvcPropPickupRead(&cl->in, cl); break;
case SVC_PROP_USE: rc = netmsgSvcPropUseRead(&cl->in, cl); break;
case SVC_PROP_DOOR: rc = netmsgSvcPropDoorRead(&cl->in, cl); break;
case SVC_CHR_DAMAGE: rc = netmsgSvcChrDamageRead(&cl->in, cl); break;
case SVC_CHR_DISARM: rc = netmsgSvcChrDisarmRead(&cl->in, cl); break;
default:
rc = 1;
break;
@@ -522,34 +605,28 @@ void netEndFrame(void)
return;
}
// send whatever messages have accumulated so far
netFlushSendBuffers();
if (g_NetLocalClient->state == CLSTATE_GAME && g_NetLocalClient->player && g_NetLocalClient->player->prop) {
if (g_NetMode == NETMODE_CLIENT) {
netClientRecordMove(g_NetLocalClient, g_NetLocalClient->player);
netmsgClcMoveWrite(&g_NetMsg);
if (g_NetTick > 100) {
netClientRecordMove(g_NetLocalClient, g_NetLocalClient->player);
netmsgClcMoveWrite(netClientNeedReliableMove(g_NetLocalClient) ? &g_NetMsgRel : &g_NetMsg);
}
} else {
for (s32 i = 0; i < g_NetMaxClients; ++i) {
struct netclient *cl = &g_NetClients[i];
if (cl->state >= CLSTATE_GAME && cl->player) {
netClientRecordMove(cl, cl->player);
netmsgSvcPlayerMoveWrite(cl->forcetick ? &g_NetMsgRel : &g_NetMsg, cl);
netmsgSvcPlayerMoveWrite(netClientNeedReliableMove(g_NetLocalClient) ? &g_NetMsgRel : &g_NetMsg, cl);
}
}
}
}
if (g_NetMsgRel.wp) {
if (g_NetMsgRel.error) {
sysLogPrintf(LOG_WARNING, "NET: reliable out buffer overflow");
}
netSend(NULL, &g_NetMsgRel, true);
}
if (g_NetMsg.wp) {
if (g_NetMsg.error) {
sysLogPrintf(LOG_WARNING, "NET: unreliable out buffer overflow");
}
netSend(NULL, &g_NetMsg, false);
}
// send position updates
netFlushSendBuffers();
enet_host_flush(g_NetHost);
}
@@ -610,7 +687,7 @@ void netPlayersAllocate(void)
cfg->controlmode = CONTROLMODE_NA;
cfg->base.mpbodynum = cl->settings.bodynum;
cfg->base.mpheadnum = cl->settings.headnum;
memcpy(cfg->base.name, cl->settings.name, MAX_PLAYERNAME);
snprintf(cfg->base.name, sizeof(cfg->base.name), "%s\n", cl->settings.name);
}
cl->player = g_Vars.players[cl->playernum];
@@ -620,3 +697,66 @@ void netPlayersAllocate(void)
cl->player->isremote = (cl != g_NetLocalClient);
}
}
void netSyncIdsAllocate(void)
{
// allocate sync ids sequentially for all active or paused props
g_NetNextSyncId = 1;
// don't allocate anything else if we're in lobby
if (g_StageNum == STAGE_TITLE || g_StageNum == STAGE_CITRAINING) {
return;
}
// iterate active props first
struct prop *prop = g_Vars.activeprops;
while (prop && prop != g_Vars.pausedprops) {
prop->syncid = prop - g_Vars.props + 1;
if (prop->syncid > g_NetNextSyncId) {
g_NetNextSyncId = prop->syncid;
}
prop = prop->next;
}
// then the paused props
prop = g_Vars.pausedprops;
while (prop) {
prop->syncid = prop - g_Vars.props + 1;
if (prop->syncid > g_NetNextSyncId) {
g_NetNextSyncId = prop->syncid;
}
prop = prop->next;
}
// HACK: when we're a client, we'll need to swap our player and server player's props
// because of what we do in netPlayersAllocate
if (g_NetMode == NETMODE_CLIENT) {
const u16 sid = g_Vars.players[g_NetLocalClient->id]->prop->syncid;
g_Vars.players[g_NetLocalClient->id]->prop->syncid = g_Vars.players[0]->prop->syncid;
g_Vars.players[0]->prop->syncid = sid;
}
sysLogPrintf(LOG_NOTE, "NET: last initial syncid: %u", g_NetNextSyncId);
}
void netChat(const char *text)
{
char tmp[1024];
if (!g_NetMode || !g_NetLocalClient || g_NetLocalClient->state < CLSTATE_LOBBY) {
return;
}
snprintf(tmp, sizeof(tmp), "%s: %s", g_NetLocalClient->settings.name, text);
char *nl = strchr(tmp, '\n');
if (nl) {
*nl = ' ';
}
if (g_NetMode == NETMODE_SERVER) {
sysLogPrintf(LOG_CHAT, tmp);
netmsgSvcChatWrite(&g_NetMsgRel, tmp);
} else {
netmsgClcChatWrite(&g_NetMsgRel, tmp);
}
}
+35
View File
@@ -132,6 +132,28 @@ u32 netbufReadCoord(struct netbuf *buf, struct coord *out)
return 0;
}
u32 netbufReadMtxf(struct netbuf *buf, Mtxf *out)
{
if (netbufCanRead(buf, sizeof(*out))) {
for (s32 i = 0; i < 4; ++i) {
for (s32 j = 0; j < 4; ++j) {
out->m[i][j] = netbufReadF32(buf);
}
}
return sizeof(*out);
}
return 0;
}
u32 netbufReadSkip(struct netbuf *buf, u32 count)
{
if (netbufCanRead(buf, count)) {
buf->rp += count;
return count;
}
return 0;
}
/* write */
void netbufStartWrite(struct netbuf *buf)
@@ -264,6 +286,19 @@ u32 netbufWriteCoord(struct netbuf *buf, const struct coord *v)
return 0;
}
u32 netbufWriteMtxf(struct netbuf *buf, const Mtxf *in)
{
if (netbufCanWrite(buf, sizeof(*in))) {
for (s32 i = 0; i < 4; ++i) {
for (s32 j = 0; j < 4; ++j) {
netbufWriteF32(buf, in->m[i][j]);
}
}
return sizeof(*in);
}
return 0;
}
void netbufReset(struct netbuf *buf)
{
memset(buf, 0, sizeof(*buf));
+2
View File
@@ -15,6 +15,7 @@
#include "net/net.h"
extern MenuItemHandlerResult menuhandlerMainMenuCombatSimulator(s32 operation, struct menuitem *item, union handlerdata *data);
extern MenuItemHandlerResult menuhandlerMpAdvancedSetup(s32 operation, struct menuitem *item, union handlerdata *data);
static s32 g_NetMenuMaxPlayers = NET_MAX_CLIENTS;
static s32 g_NetMenuPort = NET_DEFAULT_PORT;
@@ -44,6 +45,7 @@ static MenuItemHandlerResult menuhandlerHostStart(s32 operation, struct menuitem
if (operation == MENUOP_SET) {
if (netStartServer(g_NetMenuPort, g_NetMenuMaxPlayers) == 0) {
menuhandlerMainMenuCombatSimulator(MENUOP_SET, NULL, NULL);
menuhandlerMpAdvancedSetup(MENUOP_SET, NULL, NULL);
}
}
+966 -22
View File
File diff suppressed because it is too large. Load diff
+58 -4
View File
@@ -56,6 +56,9 @@
#ifndef PLATFORM_N64
#include "game/stagetable.h"
#include "video.h"
#include "net/net.h"
#include "net/netmsg.h"
#include "system.h"
#endif
#define GUNLOADSTATE_FLUX 0
@@ -4472,7 +4475,7 @@ struct defaultobj *bgunCreateThrownProjectile2(struct chrdata *chr, struct gset
* 2 = fumbling grenade from right hand (due to nbomb)
* 3 = fumbling grenade from left hand (actually not possible)
*/
void bgunCreateThrownProjectile(s32 handnum, struct gset *gset)
struct defaultobj *bgunCreateThrownProjectile(s32 handnum, struct gset *gset)
{
struct coord velocity = {0, 0, 0};
Mtxf sp1f4;
@@ -4502,6 +4505,13 @@ void bgunCreateThrownProjectile(s32 handnum, struct gset *gset)
struct trainingdata *data;
u32 stack;
#ifndef PLATFORM_N64
// don't do anything if we're not the authority
if (g_NetMode == NETMODE_CLIENT) {
return NULL;
}
#endif
if (handnum >= 2) {
droppinggrenade = true;
handnum -= 2;
@@ -4667,7 +4677,16 @@ void bgunCreateThrownProjectile(s32 handnum, struct gset *gset)
weapon->base.hidden |= OBJHFLAG_THROWNKNIFE;
}
}
#ifndef PLATFORM_N64
if (obj && g_NetMode == NETMODE_SERVER) {
netmsgSvcPropSpawnWrite(&g_NetMsgRel, obj->prop);
netmsgSvcPropMoveWrite(&g_NetMsgRel, obj->prop, NULL);
}
#endif
}
return obj;
}
void bgunUpdateHeldRocket(s32 handnum)
@@ -4771,6 +4790,12 @@ void bgunCreateFiredProjectile(s32 handnum)
f32 spd4[4];
f32 spc4[4];
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_CLIENT) {
return;
}
#endif
hand = g_Vars.currentplayer->hands + handnum;
playerprop = g_Vars.currentplayer->prop;
@@ -4983,6 +5008,13 @@ void bgunCreateFiredProjectile(s32 handnum)
weapon->base.prop = NULL;
weapon->base.model = NULL;
}
#ifndef PLATFORM_N64
if (!failed && g_NetMode == NETMODE_SERVER) {
netmsgSvcPropSpawnWrite(&g_NetMsgRel, weapon->base.prop);
netmsgSvcPropMoveWrite(&g_NetMsgRel, weapon->base.prop, NULL);
}
#endif
#else
// NTSC beta doesn't have any of the failure checks
Mtxf sp78;
@@ -6313,6 +6345,13 @@ void bgunDisarm(struct prop *attackerprop)
s32 modelnum;
s32 i;
bool drop;
struct defaultobj *obj;
#ifndef PLATFORM_N64
// don't do anything if we're not the authority
if (g_NetMode == NETMODE_CLIENT) {
return;
}
#endif
if (!weaponHasFlag(weaponnum, WEAPONFLAG_UNDROPPABLE) && weaponnum <= WEAPON_RCP45) {
#if VERSION >= VERSION_NTSC_1_0
@@ -6330,6 +6369,12 @@ void bgunDisarm(struct prop *attackerprop)
return;
}
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_SERVER) {
netmsgSvcChrDisarmWrite(&g_NetMsgRel, player->prop->chr, attackerprop, weaponnum, 0.f, NULL);
}
#endif
chr = player->prop->chr;
drop = true;
@@ -6358,7 +6403,7 @@ void bgunDisarm(struct prop *attackerprop)
&& player->hands[i].stateminor == HANDSTATEMINOR_ATTACK_THROW_0) {
#endif
drop = false;
bgunCreateThrownProjectile(i + 2, &player->hands[i].gset);
obj = bgunCreateThrownProjectile(i + 2, &player->hands[i].gset);
}
}
}
@@ -6382,6 +6427,13 @@ void bgunDisarm(struct prop *attackerprop)
}
objDrop(prop2, true);
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_SERVER) {
netmsgSvcPropSpawnWrite(&g_NetMsgRel, prop2);
netmsgSvcPropMoveWrite(&g_NetMsgRel, prop2, NULL);
}
#endif
}
}
@@ -11734,7 +11786,7 @@ void bgunSetTriggerOn(s32 handnum, bool on)
s32 bgunConsiderToggleGunFunction(s32 usedowntime, bool trigpressed, bool fromactivemenu, bool fromdedicatedbutton)
{
#ifndef PLATFORM_N64
const bool extcontrols = PLAYER_EXTCFG().extcontrols;
const bool extcontrols = PLAYER_EXTCFG().extcontrols || g_Vars.currentplayer->isremote;
#endif
switch (bgunGetWeaponNum(HAND_RIGHT)) {
case WEAPON_SNIPERRIFLE:
@@ -11795,6 +11847,8 @@ s32 bgunConsiderToggleGunFunction(s32 usedowntime, bool trigpressed, bool fromac
g_Vars.currentplayer->hands[HAND_RIGHT].activatesecondary = true;
}
sysLogPrintf(LOG_NOTE, "switchan %d -> %d", bgunIsUsingSecondaryFunction(), fromdedicatedbutton);
return USETIMER_STOP;
case WEAPON_MAULER:
case WEAPON_CMP150:
@@ -11841,7 +11895,7 @@ void bgun0f0a8c50(void)
case WEAPON_LAPTOPGUN:
case WEAPON_DRAGON:
case WEAPON_REMOTEMINE:
if (PLAYER_EXTCFG().extcontrols) {
if (PLAYER_EXTCFG().extcontrols || g_Vars.currentplayer->isremote) {
return;
}
break;
+92 -36
View File
@@ -43,7 +43,9 @@
#include "input.h"
#include "video.h"
#include "system.h"
#include "utils.h"
#include "net/net.h"
#include "net/netmsg.h"
static void bgunProcessQuickDetonate(struct movedata *data, u32 c1buttons, u32 c1buttonsthisframe, u32 buttons1, u32 buttons2) {
if ((((c1buttons & (buttons1)) && (c1buttonsthisframe & (buttons2)))
@@ -107,10 +109,23 @@ static void bgunProcessInputAltButton(struct movedata *data, s8 contpad, s32 i)
}
}
static inline void bmoveProcessRemoteInput(void)
static inline void bmoveProcessRemoteInput(const bool allowc1buttons)
{
struct player *pl = g_Vars.currentplayer;
struct netplayermove *inmove = &pl->client->inmove[0];
struct netplayermove *inmoveprev = &pl->client->inmove[1];
s32 moveticks = inmove->tick - inmoveprev->tick;
if (moveticks > g_NetInterpTicks) {
moveticks = g_NetInterpTicks;
}
if (!inmove->tick) {
// no input
inmove->pos = inmoveprev->pos = pl->prop->pos;
inmove->angles[0] = inmoveprev->angles[0] = pl->vv_theta;
inmove->angles[1] = inmoveprev->angles[1] = pl->vv_verta;
inmove->ucmd = 0;
}
if (inmove->ucmd & UCMD_DUCK) {
pl->crouchpos = CROUCHPOS_DUCK;
@@ -122,19 +137,47 @@ static inline void bmoveProcessRemoteInput(void)
pl->bondactivateorreload = 0;
pl->eyesshut = (inmove->ucmd & UCMD_EYESSHUT) != 0;
pl->speedtheta = 0.f; // TODO: figure out if anglespeed is even required
pl->speedverta = 0.f;
pl->crouchoffset = inmove->crouchofs;
pl->oldcrosspos[0] = pl->crosspos[0];
pl->oldcrosspos[1] = pl->crosspos[1];
pl->crosspos[0] = inmove->crosspos[0];
pl->crosspos[1] = inmove->crosspos[1];
if (inmove->ucmd & UCMD_SELECT) {
bgunEquipWeapon(inmove->weaponnum);
}
const bool fireguns = (inmove->ucmd & UCMD_FIRE) &&
!g_Vars.currentplayer->waitforzrelease && allowc1buttons;
if ((inmove->ucmd & UCMD_SECONDARY) && !bgunIsUsingSecondaryFunction()) {
bgunConsiderToggleGunFunction(0, false, false, true);
} else if (!(inmove->ucmd & UCMD_SECONDARY) && bgunIsUsingSecondaryFunction()) {
// do not switch back to primary if in the process of throwing laptop
if (!(bgunGetWeaponNum(HAND_RIGHT) == WEAPON_LAPTOPGUN && pl->hands[HAND_RIGHT].state == HANDSTATE_ATTACK)) {
bgunConsiderToggleGunFunction(0, false, false, true);
}
}
bgunTickGameplay(fireguns);
if (fireguns && g_NetMode == NETMODE_SERVER) {
netmsgSvcPlayerStatsWrite(&g_NetMsgRel, pl->client);
}
if (inmove->ucmd & UCMD_RELOAD) {
pl->bondactivateorreload |= JO_ACTION_RELOAD;
}
if (g_NetMode == NETMODE_SERVER) {
if (inmove->ucmd & UCMD_ACTIVATE) {
pl->bondactivateorreload |= JO_ACTION_ACTIVATE;
}
if (inmove->ucmd & UCMD_RELOAD) {
pl->bondactivateorreload |= JO_ACTION_RELOAD;
}
if (pl->bondactivateorreload) {
bmoveHandleActivate();
}
bgunTickGameplay((inmove->ucmd & UCMD_FIRE) != 0);
if (g_Vars.bondvisible && (bgunIsFiring(HAND_RIGHT) || bgunIsFiring(HAND_LEFT))) {
f32 noiseradius = 0.f;
@@ -150,16 +193,18 @@ static inline void bmoveProcessRemoteInput(void)
bgunSetSightVisible(GUNSIGHTREASON_NOTAIMING, (inmove->ucmd & UCMD_AIMMODE) != 0);
pl->speedgo = inmove->movespeed[0];
pl->speedforwards = inmove->movespeed[0];
pl->speedstrafe = inmove->movespeed[1];
pl->speedsideways = inmove->movespeed[1];
pl->speedtheta = inmove->lookspeed[0];
pl->speedverta = inmove->lookspeed[1];
pl->vv_theta = inmove->angles[0];
pl->vv_verta = inmove->angles[1];
const bool forcepos = !inmoveprev->tick || !moveticks || (inmove->ucmd & UCMD_FL_FORCEANGLE);
pl->crouchoffset = inmove->crouchofs;
// lerp towards the current speeds and angles
const f32 dt = (forcepos ? 1.f : (1.f / (f32)moveticks));
f32 t = (forcepos ? 1.f : ((f32)pl->client->lerpticks / (f32)moveticks));
if (t > 1.f) {
t = 1.f;
}
pl->speedgo = pl->speedforwards = lerpf(inmoveprev->movespeed[0], inmove->movespeed[0], t);
pl->speedstrafe = pl->speedsideways = lerpf(inmoveprev->movespeed[1], inmove->movespeed[1], t);
pl->vv_theta = lerpanglef(pl->vv_theta, inmove->angles[0], dt);
pl->vv_verta = lerpanglef(pl->vv_verta, inmove->angles[1], dt);
if (pl->bondmovemode == MOVEMODE_GRAB) {
bgrabUpdateSpeedTheta();
@@ -177,22 +222,6 @@ static inline void bmoveProcessRemoteInput(void)
} else {
pl->speedmaxtime60 = 0;
}
if (pl->speedforwards > 1) {
pl->speedforwards = 1;
}
if (pl->speedforwards < -1) {
pl->speedforwards = -1;
}
if (pl->speedsideways > 1) {
pl->speedsideways = 1;
}
if (pl->speedsideways < -1) {
pl->speedsideways = -1;
}
pl->speedforwards *= 1.08f;
pl->speedforwards *= pl->speedboost;
}
#endif // PLATFORM_N64
@@ -403,10 +432,37 @@ void bmoveApplyMoveData(struct movedata *data)
} else if (g_Vars.currentplayer->bondmovemode == MOVEMODE_WALK) {
bwalkApplyMoveData(data);
}
#ifndef PLATFORM_N64
// record some inputs if this is a local player
if (g_NetMode && !g_Vars.currentplayer->isremote) {
g_Vars.currentplayer->ucmd = 0;
if (g_Vars.currentplayer->isdead) {
if (g_NetMode == NETMODE_CLIENT) {
if (joyGetButtons(optionsGetContpadNum1(g_Vars.currentplayerstats->mpindex), 0xb000)) {
g_Vars.currentplayer->ucmd |= UCMD_RESPAWN;
}
}
} else {
if (data->triggeron) {
g_Vars.currentplayer->ucmd |= UCMD_FIRE;
}
if (data->aiming) {
g_Vars.currentplayer->ucmd |= UCMD_AIMMODE;
}
if (g_Vars.currentplayer->bondactivateorreload & JO_ACTION_ACTIVATE) {
g_Vars.currentplayer->ucmd |= UCMD_ACTIVATE;
}
if (g_Vars.currentplayer->bondactivateorreload & JO_ACTION_RELOAD) {
g_Vars.currentplayer->ucmd |= UCMD_RELOAD;
}
if (data->eyesshut) {
g_Vars.currentplayer->ucmd |= UCMD_EYESSHUT;
}
if (data->weaponbackoffset || data->weaponforwardoffset) {
g_Vars.currentplayer->ucmd |= UCMD_SELECT;
}
}
}
#endif
}
@@ -813,7 +869,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
bool allowmcross = false;
if (g_Vars.currentplayer->isremote) {
bmoveProcessRemoteInput();
bmoveProcessRemoteInput(allowc1buttons);
return;
}
#endif
+41 -39
View File
@@ -29,25 +29,26 @@
#ifndef PLATFORM_N64
#include "net/net.h"
#include "system.h"
#include "utils.h"
static inline void lerpcoord(struct coord *c, const struct coord *a, const struct coord *b, const f32 t) {
c->x = lerpf(a->x, b->x, t);
c->y = lerpf(a->y, b->y, t);
c->z = lerpf(a->z, b->z, t);
}
static void bwalkUpdateRemote(void)
{
struct player *pl = g_Vars.currentplayer;
const struct netplayermove *inmove = &pl->client->inmove[0];
const struct netplayermove *inmoveprev = &pl->client->inmove[1];
struct coord delta, target;
f32 spc8, spc4;
struct coord delta;
u16 cdtype = CDTYPE_ALL;
s32 moveticks = inmove->tick - inmoveprev->tick;
if (moveticks > g_NetInterpTicks) {
moveticks = g_NetInterpTicks;
}
const bool forcepos = !inmoveprev->tick || !moveticks ||
(inmove->ucmd & UCMD_FL_FORCEPOS) ||
(fabsf(pl->prop->pos.x - inmove->pos.x) > 256.f) ||
(fabsf(pl->prop->pos.y - inmove->pos.y) > 256.f) ||
(fabsf(pl->prop->pos.z - inmove->pos.z) > 256.f);
pl->client->inmovetick = inmove->tick;
pl->bondshotspeed.x = 0.f;
@@ -55,38 +56,39 @@ static void bwalkUpdateRemote(void)
pl->bondshotspeed.z = 0.f;
pl->bondbreathing = 0.f;
if (forcepos) {
// no interpolation, set position and lock the lad in place
delta.x = 0.f;
delta.y = 0.f;
delta.z = 0.f;
pl->prop->pos = inmove->pos;
pl->client->lerpticks = g_NetInterpTicks + g_NetExterpTicks;
} else if (pl->client->lerpticks <= moveticks) {
// lerp towards the new position
const f32 t = (f32)pl->client->lerpticks / (f32)moveticks;
target.x = inmoveprev->pos.x + (inmove->pos.x - inmoveprev->pos.x) * t;
target.y = inmoveprev->pos.y + (inmove->pos.y - inmoveprev->pos.y) * t;
target.z = inmoveprev->pos.z + (inmove->pos.z - inmoveprev->pos.z) * t;
delta.x = target.x - pl->prop->pos.x;
delta.y = target.y - pl->prop->pos.y;
delta.z = target.z - pl->prop->pos.z;
pl->client->lerpticks += g_Vars.lvupdate60;
} else if (pl->client->lerpticks <= moveticks + g_NetExterpTicks) {
// try extrapolating based on inputs for a while
pl->client->lerpticks += g_Vars.lvupdate60;
bwalk0f0c69b8();
return;
} else {
// we're too far gone, lock position
delta.x = 0.f;
delta.y = 0.f;
delta.z = 0.f;
pl->prop->pos = inmove->pos;
}
const bool forcepos = !inmoveprev->tick ||
(inmove->ucmd & UCMD_FL_FORCEPOS) ||
(fabsf(pl->prop->pos.x - inmove->pos.x) > 512.f) ||
(fabsf(pl->prop->pos.y - inmove->pos.y) > 512.f) ||
(fabsf(pl->prop->pos.z - inmove->pos.z) > 512.f);
bwalkUpdateCrouchOffset();
bwalk0f0c63bc(&delta, g_Vars.currentplayer->swaytarget == 0.0f, CDTYPE_ALL);
delta.x = 0.f;
delta.y = 0.f;
delta.z = 0.f;
// extrapolate
bwalk0f0c69b8();
if (forcepos) {
// no interpolation, set position and lock the lad in place
pl->prop->pos = inmove->pos;
pl->client->lerpticks = g_NetInterpTicks + 1;
cdtype = CDTYPE_PLAYERS; // don't get stuck in the local client
} else if (!moveticks) {
// duplicate move, reposition to correct coords
delta.x = inmove->pos.x - pl->prop->pos.x;
delta.x = inmove->pos.y - pl->prop->pos.y;
delta.x = inmove->pos.z - pl->prop->pos.z;
bwalk0f0c63bc(&delta, pl->swaytarget == 0.0f, cdtype);
} else if (pl->client->lerpticks <= moveticks) {
// lerp towards the correct position
const f32 dt = (f32)1.f / (f32)moveticks;
delta.x = g_Vars.lvupdate60freal * (inmove->pos.x - pl->prop->pos.x) * dt;
delta.y = g_Vars.lvupdate60freal * (inmove->pos.y - pl->prop->pos.y) * dt;
delta.z = g_Vars.lvupdate60freal * (inmove->pos.z - pl->prop->pos.z) * dt;
bwalk0f0c63bc(&delta, pl->swaytarget == 0.0f, cdtype);
pl->client->lerpticks += g_Vars.lvupdate60;
}
}
#endif
+13 -3
View File
@@ -49,6 +49,8 @@
#include "types.h"
#ifndef PLATFORM_N64
#include "video.h"
#include "net/net.h"
#include "net/netmsg.h"
#endif
void rng2SetSeed(u32 seed);
@@ -4691,9 +4693,17 @@ void chrHit(struct shotdata *shotdata, struct hit *hit)
|| weapon->weaponnum == WEAPON_TIMEDMINE
|| weapon->weaponnum == WEAPON_REMOTEMINE
|| weapon->weaponnum == WEAPON_PROXIMITYMINE) {
objSetDropped(hit->prop, DROPTYPE_DEFAULT);
chr->hidden |= CHRHFLAG_DROPPINGITEM;
objDamage(&weapon->base, gsetGetDamage(&shotdata->gset), &sp98, shotdata->gset.weaponnum, g_Vars.currentplayernum);
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_SERVER) {
netmsgSvcChrDisarmWrite(&g_NetMsgRel, chr, g_Vars.currentplayer->prop, weapon->weaponnum, gsetGetDamage(&shotdata->gset), &sp98);
}
if (g_NetMode != NETMODE_CLIENT)
#endif
{
objSetDropped(hit->prop, DROPTYPE_DEFAULT);
chr->hidden |= CHRHFLAG_DROPPINGITEM;
objDamage(&weapon->base, gsetGetDamage(&shotdata->gset), &sp98, shotdata->gset.weaponnum, g_Vars.currentplayernum);
}
return;
}
+47 -3
View File
@@ -4105,6 +4105,12 @@ bool func0f034080(struct chrdata *chr, struct modelnode *node, struct prop *prop
*/
void chrDamageByMisc(struct chrdata *chr, f32 damage, struct coord *vector, struct gset *gset, struct prop *prop)
{
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_CLIENT) {
// don't do anything if we're not the authority
return;
}
#endif
chrDamage(chr, damage, vector, gset, prop, HITPART_GENERAL,
false, // damageshield
NULL, // prop2
@@ -4118,6 +4124,12 @@ void chrDamageByMisc(struct chrdata *chr, f32 damage, struct coord *vector, stru
void chrDamageByLaser(struct chrdata *chr, f32 damage, struct coord *vector, struct gset *gset, struct prop *prop)
{
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_CLIENT) {
// don't do anything if we're not the authority
return;
}
#endif
chrDamage(chr, damage, vector, gset, prop, HITPART_GENERAL,
true, // damageshield
chr->prop, // prop2
@@ -4131,6 +4143,12 @@ void chrDamageByLaser(struct chrdata *chr, f32 damage, struct coord *vector, str
void func0f0341dc(struct chrdata *chr, f32 damage, struct coord *vector, struct gset *gset, struct prop *prop, s32 hitpart, struct prop *prop2, struct modelnode *node, struct model *model, s32 side, s16 *arg10)
{
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_CLIENT) {
// don't do anything if we're not the authority
return;
}
#endif
chrDamage(chr, damage, vector, gset, prop, hitpart,
true, // damageshield
prop2, // prop2
@@ -4152,6 +4170,13 @@ void func0f034248(struct chrdata *chr, f32 damage, struct coord *vector, struct
s32 side = 0;
s32 hitpart = HITPART_GENERAL;
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_CLIENT) {
// don't do anything if we're not the authority
return;
}
#endif
if (chrGetShield(chr) >= 0 && chr->model) {
chrCalculateShieldHit(chr, &chr->prop->pos, vector, &node, &hitpart, &model, &side);
}
@@ -4176,6 +4201,13 @@ void chrDamageByImpact(struct chrdata *chr, f32 damage, struct coord *vector, st
struct model *model = NULL;
s32 side = 0;
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_CLIENT) {
// don't do anything if we're not the authority
return;
}
#endif
if (chrGetShield(chr) >= 0 && chr->model) {
chrCalculateShieldHit(chr, &chr->prop->pos, vector, &node, &hitpart, &model, &side);
}
@@ -4193,6 +4225,12 @@ void chrDamageByImpact(struct chrdata *chr, f32 damage, struct coord *vector, st
void chrDamageByExplosion(struct chrdata *chr, f32 damage, struct coord *vector, struct prop *prop, struct coord *explosionpos)
{
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_CLIENT) {
// don't do anything if we're not the authority
return;
}
#endif
chrDamage(chr, damage, vector, NULL, prop, HITPART_GENERAL,
true, // damageshield
chr->prop, // prop2
@@ -4277,9 +4315,9 @@ void chrDamage(struct chrdata *chr, f32 damage, struct coord *vector, struct gse
s32 choketype = CHOKETYPE_NONE;
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_CLIENT) {
// don't do anything if we're not the authority
return;
if (g_NetMode == NETMODE_SERVER) {
netmsgSvcChrDamageWrite(&g_NetMsgRel, chr, damage, vector, gset, aprop, hitpart,
damageshield, prop2, side, arg11, explosion, explosionpos);
}
#endif
@@ -4853,6 +4891,12 @@ void chrDamage(struct chrdata *chr, f32 damage, struct coord *vector, struct gse
}
}
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_SERVER && g_Vars.currentplayer->client) {
netmsgSvcPlayerStatsWrite(&g_NetMsgRel, g_Vars.currentplayer->client);
}
#endif
setCurrentPlayerNum(prevplayernum);
return;
}
+4 -4
View File
@@ -2183,7 +2183,7 @@ Gfx *text0f156a24(Gfx *gdl, s32 x, s32 y, struct fontchar *char1, s32 arg4, s32
if (y + char1->baseline >= arg5) {
if (arg5 + arg7 >= y + char1->baseline + char1->height + 2) {
if (g_TextRotated90) {
gSPTextureRectangleFlip(gdl++,
gSPTextureRectangleFlipEXT(gdl++,
((y - char1->baseline) - ((char1->height + 2) * var8007fad0)) * 4,
x * 4,
(y - char1->baseline) * 4,
@@ -2194,7 +2194,7 @@ Gfx *text0f156a24(Gfx *gdl, s32 x, s32 y, struct fontchar *char1, s32 arg4, s32
1024 / var8007fad0,
-1024);
} else {
gSPTextureRectangle(gdl++,
gSPTextureRectangleEXT(gdl++,
x * 4,
(y + char1->baseline) * 4,
(x + char1->width * var8007fad0 + 2) * 4,
@@ -2207,7 +2207,7 @@ Gfx *text0f156a24(Gfx *gdl, s32 x, s32 y, struct fontchar *char1, s32 arg4, s32
}
} else {
if (arg5 + arg7 >= y + char1->baseline) {
gSPTextureRectangle(gdl++,
gSPTextureRectangleEXT(gdl++,
x * 4,
(y + char1->baseline) * 4,
(x + char1->width * var8007fad0 + 2) * 4,
@@ -2221,7 +2221,7 @@ Gfx *text0f156a24(Gfx *gdl, s32 x, s32 y, struct fontchar *char1, s32 arg4, s32
}
} else {
if (y + char1->baseline + char1->height + 2 >= arg5) {
gSPTextureRectangle(gdl++,
gSPTextureRectangleEXT(gdl++,
x * 4,
arg5 * 4,
(x + char1->width * var8007fad0 + 2) * 4,
+23 -7
View File
@@ -323,6 +323,11 @@ void lvReset(s32 stagenum)
s32 i;
s32 j;
#ifndef PLATFORM_N64
// if we're a server, signal to clients that the level is changing
netServerStageStart();
#endif
tilesReset();
bgReset(g_Vars.stagenum);
bgBuildTables(g_Vars.stagenum);
@@ -364,11 +369,6 @@ void lvReset(s32 stagenum)
g_Vars.playerstats[i].kills[j] = 0;
}
}
#ifndef PLATFORM_N64
// if we're a server, signal to clients that the level is changing
netServerStageStart();
#endif
}
mpSetDefaultNamesIfEmpty();
@@ -469,6 +469,12 @@ void lvReset(s32 stagenum)
pheadReset();
}
#ifndef PLATFORM_N64
if (g_NetMode) {
netSyncIdsAllocate();
}
#endif
modelmgrSetLvResetting(false);
var80084018 = 1;
schedResetArtifacts();
@@ -1094,7 +1100,8 @@ Gfx *lvRender(Gfx *gdl)
#ifndef PLATFORM_N64
if (g_NetMode) {
forcesingleplayer = true;
// tick all players, we'll skip the rendering
forcesingleplayer = false;
}
#endif
@@ -1678,12 +1685,21 @@ Gfx *lvRender(Gfx *gdl)
}
if (g_Vars.currentplayer->dostartnewlife) {
playerStartNewLife();
#ifndef PLATFORM_N64
if (g_NetMode != NETMODE_CLIENT)
#endif
playerStartNewLife();
}
}
artifactsTick();
#ifndef PLATFORM_N64
if (g_NetMode && i) {
gdl = savedgdl;
}
#endif
if ((g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0)
#if VERSION >= VERSION_NTSC_1_0
&& playerHasSharedViewport()
+1 -1
View File
@@ -5384,7 +5384,7 @@ Gfx *menuRender(Gfx *gdl)
sprintf(text, "Client: ID %u", g_NetLocalClient->id);
}
x = viewleft + 2;
y = viewtop + 2;
y = viewbottom - 9;
colour = 0x5070ffff;
gdl = textRenderProjected(gdl, &x, &y, text, g_CharsHandelGothicSm, g_FontHandelGothicSm, colour, viGetWidth(), viGetHeight(), 0, 0);
} else
+18
View File
@@ -221,6 +221,12 @@ void menuTick(void)
viBlack(false);
g_MpNumJoined = 0;
#ifndef PLATFORM_N64
if (g_NetMode) {
g_Vars.mpsetupmenu = MPSETUPMENU_ADVSETUP;
g_MpSetup.chrslots = 1;
} else
#endif
if (g_Vars.usingadvsetup) {
g_Vars.mpsetupmenu = MPSETUPMENU_ADVSETUP;
} else {
@@ -236,6 +242,13 @@ void menuTick(void)
if (g_Vars.mpsetupmenu == MPSETUPMENU_ADVSETUP) {
g_MpNumJoined++;
func0f17fcb0(true);
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_CLIENT) {
// autodump client into waiting screen while host is changing settings
extern struct menudialogdef g_NetJoiningDialog;
menuPushDialog(&g_NetJoiningDialog);
}
#endif
} else if (g_MpNumJoined == 0) {
g_MpNumJoined++;
@@ -536,7 +549,12 @@ void menuTick(void)
func0f0fd548(4);
}
#ifdef PLATFORM_N64
for (i = 0; i < MAX_PLAYERS; i++) {
#else
const s32 maxplayers = g_NetMode ? 1 : MAX_PLAYERS;
for (i = 0; i < maxplayers; i++) {
#endif
if (g_MpSetup.chrslots & (1 << i)) {
if (g_Vars.coopplayernum >= 0) {
if (g_Vars.stagenum == STAGE_DEEPSEA) {
+11
View File
@@ -19,6 +19,9 @@
#include "lib/main.h"
#include "data.h"
#include "types.h"
#ifndef PLATFORM_N64
#include "net/net.h"
#endif
struct menudialogdef g_MpEndscreenChallengeCompletedMenuDialog;
struct menudialogdef g_MpEndscreenIndGameOverMenuDialog;
@@ -102,6 +105,11 @@ MenuItemHandlerResult menuhandlerMpEndGame(s32 operation, struct menuitem *item,
{
if (operation == MENUOP_SET) {
g_Vars.currentplayer->aborted = true;
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_CLIENT) {
netDisconnect();
} else
#endif
mainEndStage();
}
@@ -831,6 +839,9 @@ void mpPushEndscreenDialog(u32 arg0, u32 playernum)
&& g_PlayerConfigsArray[g_MpPlayerNum].fileguid.fileid == 0
&& g_PlayerConfigsArray[g_MpPlayerNum].fileguid.deviceserial == 0) {
g_PlayerConfigsArray[g_MpPlayerNum].options |= OPTION_ASKEDSAVEPLAYER;
#ifndef PLATFORM_N64
if (!g_NetMode)
#endif
menuPushDialog(&g_MpEndscreenSavePlayerMenuDialog);
}
}
+34 -2
View File
@@ -73,6 +73,8 @@
#ifndef PLATFORM_N64
#include "video.h"
#include "input.h"
#include "net/net.h"
#include "net/netmsg.h"
#endif
s32 g_DefaultWeapons[2];
@@ -1116,6 +1118,12 @@ void playerSpawn(void)
}
playerUpdatePerimInfo();
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_SERVER && g_Vars.currentplayer->client) {
netmsgSvcPlayerStatsWrite(&g_NetMsgRel, g_Vars.currentplayer->client);
}
#endif
}
void playerResetBond(struct playerbond *pb, struct coord *pos)
@@ -4677,6 +4685,13 @@ Gfx *playerRenderHud(Gfx *gdl)
if (g_Vars.antiplayernum >= 0 && g_Vars.currentplayer == g_Vars.anti) {
// Anti
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_SERVER && g_Vars.currentplayer->isremote) {
if (g_Vars.currentplayer->client->inmove[0].ucmd & UCMD_RESPAWN) {
g_Vars.currentplayer->dostartnewlife = true;
}
} else if (g_NetMode != NETMODE_CLIENT)
#endif
if (joyGetButtons(optionsGetContpadNum1(g_Vars.currentplayerstats->mpindex), 0xb000) && !mpIsPaused()) {
g_Vars.currentplayer->dostartnewlife = true;
}
@@ -4690,8 +4705,12 @@ Gfx *playerRenderHud(Gfx *gdl)
f32 stealhealth;
f32 shield;
canrestart = joyGetButtons(optionsGetContpadNum1(g_Vars.currentplayerstats->mpindex), 0xb000)
&& !mpIsPaused();
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_SERVER && g_Vars.currentplayer->isremote) {
canrestart = (g_Vars.currentplayer->client->inmove[0].ucmd & UCMD_RESPAWN) != 0;
} else if (g_NetMode != NETMODE_CLIENT)
#endif
canrestart = joyGetButtons(optionsGetContpadNum1(g_Vars.currentplayerstats->mpindex), 0xb000) && !mpIsPaused();
// Get ready to respawn.
// The other player's health will be halved.
@@ -4797,6 +4816,13 @@ Gfx *playerRenderHud(Gfx *gdl)
}
}
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_SERVER && g_Vars.currentplayer->isremote) {
if (!mpIsPaused() && g_NumReasonsToEndMpMatch == 0 && (g_Vars.currentplayer->client->inmove[0].ucmd & UCMD_RESPAWN)) {
canrestart = true;
}
} else if (g_NetMode != NETMODE_CLIENT)
#endif
if (joyGetButtons(optionsGetContpadNum1(g_Vars.currentplayerstats->mpindex), 0xb000)
&& !mpIsPaused()
&& g_NumReasonsToEndMpMatch == 0) {
@@ -4880,6 +4906,12 @@ void playerDie(bool force)
struct chrdata *chr = g_Vars.currentplayer->prop->chr;
s32 shooter;
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_CLIENT) {
return;
}
#endif
if (chr->lastshooter >= 0 && chr->timeshooter > 0) {
shooter = chr->lastshooter;
} else {
+1 -1
View File
@@ -64,7 +64,7 @@ void playermgrAllocatePlayers(s32 count)
}
#ifndef PLATFORM_N64
if (g_NetMode) {
if (g_NetMode && g_StageNum != STAGE_TITLE && g_StageNum != STAGE_CITRAINING) {
netPlayersAllocate();
}
#endif
+14
View File
@@ -41,6 +41,7 @@
#include "types.h"
#ifndef PLATFORM_N64
#include "net/net.h"
#include "net/netmsg.h"
#endif
s16 *g_RoomPropListChunkIndexes;
@@ -170,6 +171,10 @@ struct prop *propAllocate(void)
prop->propupdate60err = 2;
prop->opawallhits = NULL;
prop->xluwallhits = NULL;
#ifndef PLATFORM_N64
// NOTE: this will be automatically overwritten at the start of the stage for the setup props
prop->syncid = (g_NetMode == NETMODE_SERVER) ? g_NetNextSyncId++ : 0;
#endif
g_Vars.propstates[prop->propstateindex].propcount++;
g_Vars.allocstateindex++;
@@ -202,6 +207,9 @@ void propFree(struct prop *prop)
prop->prev = NULL;
prop->chr = NULL;
prop->rooms[0] = -1;
#ifndef PLATFORM_N64
prop->syncid = 0;
#endif
g_Vars.freeprops = prop;
}
@@ -1528,6 +1536,12 @@ bool currentPlayerInteract(bool eyespy)
propExecuteTickOperation(prop, op);
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_SERVER) {
netmsgSvcPropUseWrite(&g_NetMsgRel, prop, g_Vars.currentplayer->client, op);
}
#endif
return false;
}
+86 -2
View File
@@ -79,6 +79,7 @@
#include "string.h"
#ifndef PLATFORM_N64
#include "net/net.h"
#include "net/netmsg.h"
#endif
void rng2SetSeed(u32 seed);
@@ -8120,6 +8121,13 @@ void liftTick(struct prop *prop)
stop = (stop + 1) % 4;
} while (lift->pads[stop] < 0);
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_CLIENT) {
// don't start if we're not the authority
return;
}
#endif
liftGoToStop(lift, stop);
}
}
@@ -14211,6 +14219,12 @@ void objBounce(struct defaultobj *obj, struct coord *gundir2d)
projectile->speed.z += 3.3333333f * dir.z;
projectile->ownerprop = g_Vars.currentplayer->prop;
projectile->bouncecount = 1;
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_SERVER) {
netmsgSvcPropMoveWrite(&g_NetMsgRel, obj->prop, &rot);
}
#endif
}
}
@@ -14288,6 +14302,11 @@ void objApplyMomentum(struct defaultobj *obj, struct coord *speed, f32 rotation,
projectile->unk0ec = 0.07852732f;
projectile->unk0f0 = 6.6666665f;
}
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_SERVER) {
netmsgSvcPropMoveWrite(&g_NetMsgRel, obj->prop, NULL);
}
#endif
return;
}
@@ -14318,6 +14337,12 @@ void objApplyMomentum(struct defaultobj *obj, struct coord *speed, f32 rotation,
projectile->unk0ec = 0.07852732f;
projectile->unk0f0 = 1.6666666f;
}
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_SERVER) {
netmsgSvcPropMoveWrite(&g_NetMsgRel, obj->prop, NULL);
}
#endif
}
}
@@ -15358,9 +15383,14 @@ void objTakeGunfire(struct defaultobj *obj, f32 damage, struct coord *pos, s32 w
void objDamage(struct defaultobj *obj, f32 damage, struct coord *pos, s32 weaponnum, s32 playernum)
{
#ifndef PLATFORM_N64
// if we aren't the authority, don't do anything
// if we aren't the authority, don't do anything, unless called from netmsg handler
if (g_NetMode == NETMODE_CLIENT) {
return;
if (damage < 0.f) {
// HACK: negative damage means we were called from netmsg.c
damage = -damage;
} else {
return;
}
}
#endif
@@ -15951,6 +15981,10 @@ void objHit(struct shotdata *shotdata, struct hit *hit)
pushdir.y = shotdata->gundir3d.y;
pushdir.z = shotdata->gundir3d.z;
#ifndef PLATFORM_N64
// don't push anything if we're not the authority
if (g_NetMode != NETMODE_CLIENT)
#endif
func0f082e84(obj, &spa4, &pushdir, &spb0, true);
} else {
bool bounce = false;
@@ -15973,6 +16007,13 @@ void objHit(struct shotdata *shotdata, struct hit *hit)
bounce = false;
}
#ifndef PLATFORM_N64
// don't bounce anything if we're not the authority
if (g_NetMode == NETMODE_CLIENT) {
bounce = false;
}
#endif
if (bounce) {
objBounce(obj, &shotdata->gundir2d);
}
@@ -17281,6 +17322,11 @@ s32 propPickupByPlayer(struct prop *prop, bool showhudmsg)
if (sp64) {
weaponPlayPickupSound(weapon->weaponnum);
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_SERVER && g_Vars.currentplayer->client) {
netmsgSvcPropPickupWrite(&g_NetMsgRel, g_Vars.currentplayer->client, prop, sp64);
}
#endif
}
return sp64;
@@ -17291,6 +17337,11 @@ s32 propPickupByPlayer(struct prop *prop, bool showhudmsg)
if (sp64) {
weaponPlayPickupSound(weapon->weaponnum);
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_SERVER && g_Vars.currentplayer->client) {
netmsgSvcPropPickupWrite(&g_NetMsgRel, g_Vars.currentplayer->client, prop, sp64);
}
#endif
}
return sp64;
@@ -17458,6 +17509,13 @@ s32 propPickupByPlayer(struct prop *prop, bool showhudmsg)
break;
}
#ifndef PLATFORM_N64
if (result != TICKOP_NONE && g_NetMode == NETMODE_SERVER && g_Vars.currentplayer->client) {
netmsgSvcPropPickupWrite(&g_NetMsgRel, g_Vars.currentplayer->client, prop, result);
netmsgSvcPlayerStatsWrite(&g_NetMsgRel, g_Vars.currentplayer->client);
}
#endif
if (result == TICKOP_FREE && (obj->hidden & OBJHFLAG_TAGGED) == 0) {
objFree(obj, false, obj->hidden2 & OBJH2FLAG_CANREGEN);
return TICKOP_FREE;
@@ -19074,6 +19132,13 @@ void doorsCheckAutomatic(void)
s16 *propnumptr;
s16 propnums[256];
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_CLIENT) {
// don't do anything if we're not the authority
return;
}
#endif
roomGetProps(g_Vars.currentplayer->prop->rooms, propnums, 256);
propnumptr = propnums;
@@ -19850,6 +19915,11 @@ void doorSetMode(struct doorobj *door, s32 newmode)
} else {
door->mode = newmode;
}
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_SERVER) {
netmsgSvcPropDoorWrite(&g_NetMsgRel, door->base.prop, g_Vars.currentplayer->client);
}
#endif
}
/**
@@ -21215,6 +21285,13 @@ void weaponCreateForPlayerDrop(s32 weaponnum)
struct chrdata *chr;
u32 stack2;
#ifndef PLATFORM_N64
// don't do anything if we're not the authority
if (g_NetMode == NETMODE_CLIENT) {
return;
}
#endif
chr = g_Vars.currentplayer->prop->chr;
prop = weaponCreateForChr(chr, playermgrGetModelOfWeapon(weaponnum), weaponnum, OBJFLAG_WEAPON_AICANNOTUSE, NULL, NULL);
@@ -21225,6 +21302,13 @@ void weaponCreateForPlayerDrop(s32 weaponnum)
if (weaponnum == WEAPON_BRIEFCASE2) {
scenarioHandleDroppedToken(chr, prop);
}
#ifndef PLATFORM_N64
if (g_NetMode == NETMODE_SERVER) {
netmsgSvcPropSpawnWrite(&g_NetMsgRel, prop);
netmsgSvcPropMoveWrite(&g_NetMsgRel, prop, NULL);
}
#endif
}
}
+1
View File
@@ -15,6 +15,7 @@
#define bool s32
#define ubool u32
extern s32 g_StageNum;
extern u8 *g_StackLeftAddrs[NUM_THREADS];
extern u8 *g_StackRightAddrs[NUM_THREADS];
extern u8 *g_StackAllocatedPos;
+1 -1
View File
@@ -76,7 +76,7 @@ struct modeldef *bgunGetCartModeldef(void);
void bgun0f09ebcc(struct defaultobj *obj, struct coord *coord, RoomNum *rooms, Mtxf *matrix1, struct coord *velocity, Mtxf *matrix2, struct prop *prop, struct coord *pos);
void bgun0f09ed2c(struct defaultobj *obj, struct coord *coord, Mtxf *arg2, struct coord *velocity, Mtxf *arg4);
struct defaultobj *bgunCreateThrownProjectile2(struct chrdata *chr, struct gset *gset, struct coord *pos, RoomNum *rooms, Mtxf *arg4, struct coord *velocity);
void bgunCreateThrownProjectile(s32 handnum, struct gset *gset);
struct defaultobj *bgunCreateThrownProjectile(s32 handnum, struct gset *gset);
void bgunUpdateHeldRocket(s32 handnum);
void bgunCreateHeldRocket(s32 handnum, struct weaponfunc_shootprojectile *func);
void bgunFreeHeldRocket(s32 handnum);
+3
View File
@@ -324,6 +324,9 @@ struct prop {
/*0x3f*/ u8 active : 1;
/*0x40*/ struct wallhit *opawallhits; // opaque
/*0x44*/ struct wallhit *xluwallhits; // translucent
#ifndef PLATFORM_N64
/*0x48*/ u32 syncid;
#endif
};
struct packedpad {