forked from Ports/perfect_dark
port: net: sync some projectiles, doors, parts of bgun, etc
This commit is contained in:
1 parent
41d9cb4578
commit
aae0f70dd3
28 files changed
+1763
-186
No files matched your search
@@ -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
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
|
||||
@@ -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
File diff suppressed because it is too large.
Load diff
+58
-4
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in new issue
Block a user