Cleanups and some refactoring of the SuperMelee code.

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3502 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
Meep-Eep
2010-01-23 00:34:27 +00:00
parent f50c78ebda
commit 40175c65c9
29 changed files with 2091 additions and 1239 deletions
+1
View File
@@ -1,4 +1,5 @@
Changes towards version 0.7: Changes towards version 0.7:
- Clean up and some refactoring of the SuperMelee code - SvdB
- Fixed concurrent screen fades regression (bug #1079) - Alex - Fixed concurrent screen fades regression (bug #1079) - Alex
- Removed some legacy source code files related to resources - SvdB - Removed some legacy source code files related to resources - SvdB
- Put SuperMelee source files in separate subdirectory - SvdB - Put SuperMelee source files in separate subdirectory - SvdB
+16
View File
@@ -2973,6 +2973,14 @@ SOURCE=..\..\src\uqm\ships\ship.h
# PROP Default_Filter "" # PROP Default_Filter ""
# Begin Source File # Begin Source File
SOURCE=..\..\src\uqm\supermelee\buildpick.c
# End Source File
# Begin Source File
SOURCE=..\..\src\uqm\supermelee\buildpick.h
# End Source File
# Begin Source File
SOURCE=..\..\src\uqm\supermelee\loadmele.c SOURCE=..\..\src\uqm\supermelee\loadmele.c
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -2989,6 +2997,14 @@ SOURCE=..\..\src\uqm\supermelee\melee.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\src\uqm\supermelee\meleesetup.c
# End Source File
# Begin Source File
SOURCE=..\..\src\uqm\supermelee\meleesetup.h
# End Source File
# Begin Source File
SOURCE=..\..\src\uqm\supermelee\pickmele.c SOURCE=..\..\src\uqm\supermelee\pickmele.c
# End Source File # End Source File
# Begin Source File # Begin Source File
+3 -2
View File
@@ -32,6 +32,7 @@
# ifdef NETPLAY_CHECKSUM # ifdef NETPLAY_CHECKSUM
# include "netplay/checksum.h" # include "netplay/checksum.h"
# endif # endif
# include "netplay/notifyall.h"
#endif #endif
#include "supermelee/pickmele.h" #include "supermelee/pickmele.h"
#include "resinst.h" #include "resinst.h"
@@ -187,7 +188,7 @@ ProcessInput (void)
if (!(PlayerControl[cur_player] & NETWORK_CONTROL)) if (!(PlayerControl[cur_player] & NETWORK_CONTROL))
{ {
BattleInputBuffer *bib = getBattleInputBuffer(cur_player); BattleInputBuffer *bib = getBattleInputBuffer(cur_player);
sendBattleInputConnections (InputState); Netplay_NotifyAll_battleInput (InputState);
flushPacketQueues (); flushPacketQueues ();
BattleInputBuffer_push (bib, InputState); BattleInputBuffer_push (bib, InputState);
@@ -279,7 +280,7 @@ DoBattle (BATTLE_STATE *bs)
crc_processState (&state); crc_processState (&state);
checksum = (Checksum) crc_finish (&state); checksum = (Checksum) crc_finish (&state);
sendChecksumConnections ((uint32) battleFrameCount, Netplay_NotifyAll_checksum ((uint32) battleFrameCount,
(uint32) checksum); (uint32) checksum);
flushPacketQueues (); flushPacketQueues ();
addLocalChecksum (battleFrameCount, checksum); addLocalChecksum (battleFrameCount, checksum);
+2
View File
@@ -66,8 +66,10 @@ ConfirmSaveLoad (STAMP *MsgStamp)
t.CharCount = (COUNT)~0; t.CharCount = (COUNT)~0;
if (MsgStamp) if (MsgStamp)
t.pStr = GAME_STRING (SAVEGAME_STRING_BASE + 0); t.pStr = GAME_STRING (SAVEGAME_STRING_BASE + 0);
// "Saving . . ."
else else
t.pStr = GAME_STRING (SAVEGAME_STRING_BASE + 1); t.pStr = GAME_STRING (SAVEGAME_STRING_BASE + 1);
// "Loading . . ."
TextRect (&t, &r, NULL); TextRect (&t, &r, NULL);
r.corner.x -= 4; r.corner.x -= 4;
r.corner.y -= 4; r.corner.y -= 4;
+1 -1
View File
@@ -1,3 +1,3 @@
uqm_SUBDIRS="proto" uqm_SUBDIRS="proto"
uqm_CFILES="checkbuf.c checksum.c crc.c netconnection.c netinput.c netmelee.c netmisc.c netoptions.c netrcv.c netsend.c netstate.c notify.c packet.c packethandlers.c packetsenders.c packetq.c" uqm_CFILES="checkbuf.c checksum.c crc.c netconnection.c netinput.c netmelee.c netmisc.c netoptions.c netrcv.c netsend.c netstate.c notify.c notifyall.c packet.c packethandlers.c packetsenders.c packetq.c"
+44 -94
View File
@@ -61,6 +61,33 @@ removeNetConnection(int playerNr) {
numNetConnections--; numNetConnections--;
} }
size_t
getNumNetConnections(void) {
return numNetConnections;
}
// If the callback function returns 'false', the function will immediately
// return with 'false'. Otherwise it will return 'true' after calling
// the callback function for each connected player.
bool
forEachConnectedPlayer(ForEachConnectionCallback callback, void *arg) {
COUNT player;
for (player = 0; player < NUM_PLAYERS; player++)
{
NetConnection *conn = netConnections[player];
if (conn == NULL)
continue;
if (!NetConnection_isConnected(conn))
continue;
if (!(*callback)(conn, arg))
return false;
}
return true;
}
void void
closeAllConnections(void) { closeAllConnections(void) {
COUNT player; COUNT player;
@@ -87,12 +114,6 @@ closeDisconnectedConnections(void) {
} }
} }
size_t
getNumNetConnections(void) {
return numNetConnections;
}
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
@@ -120,8 +141,7 @@ NetMelee_getBattleState(NetConnection *conn) {
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
static inline static inline void
void
netInputAux(uint32 timeoutMs) { netInputAux(uint32 timeoutMs) {
NetManager_process(&timeoutMs); NetManager_process(&timeoutMs);
// This may cause more packets to be queued, hence the // This may cause more packets to be queued, hence the
@@ -249,42 +269,6 @@ allConnected(void) {
return true; return true;
} }
void
sendBattleInputConnections(BATTLE_INPUT_STATE input) {
COUNT player;
for (player = 0; player < NUM_PLAYERS; player++)
{
NetConnection *conn = netConnections[player];
if (conn == NULL)
continue;
if (!NetConnection_isConnected(conn))
continue;
Netplay_battleInput(conn, input);
}
}
#ifdef NETPLAY_CHECKSUM
void
sendChecksumConnections(uint32 frameNr, uint32 checksum) {
COUNT player;
for (player = 0; player < NUM_PLAYERS; player++)
{
NetConnection *conn = netConnections[player];
if (conn == NULL)
continue;
if (!NetConnection_isConnected(conn))
continue;
Netplay_sendChecksum(conn, frameNr, checksum);
}
}
#endif /* NETPLAY_CHECKSUM */
void void
initBattleStateDataConnections(void) { initBattleStateDataConnections(void) {
COUNT player; COUNT player;
@@ -415,28 +399,6 @@ closePlayerNetworkConnection(COUNT player) {
NetConnection_close(netConnections[player]); NetConnection_close(netConnections[player]);
} }
// If the callback function returns 'false', the function will immediately
// return with 'false'. Otherwise it will return 'true' after calling
// the callback function for each connected player.
bool
forAllConnectedPlayers(ForAllCallback callback, void *arg) {
COUNT player;
for (player = 0; player < NUM_PLAYERS; player++)
{
NetConnection *conn = netConnections[player];
if (conn == NULL)
continue;
if (!NetConnection_isConnected(conn))
continue;
if (!(*callback)(conn, arg))
return false;
}
return true;
}
bool bool
setupInputDelay(size_t localInputDelay) { setupInputDelay(size_t localInputDelay) {
COUNT player; COUNT player;
@@ -466,51 +428,39 @@ setupInputDelay(size_t localInputDelay) {
} }
static bool static bool
sendInputDelayConnection(NetConnection *conn, const size_t *delay) { setStateConnection(NetConnection *conn, void *arg) {
Netplay_sendInputDelay(conn, *delay); const NetState *state = (NetState *) arg;
return true;
}
bool
sendInputDelayConnections(size_t delay) {
return forAllConnectedPlayers(
(ForAllCallback) sendInputDelayConnection, &delay);
}
static bool
setStateConnection(NetConnection *conn, const NetState *state) {
NetConnection_setState(conn, *state); NetConnection_setState(conn, *state);
return true; return true;
} }
bool bool
setStateConnections(NetState state) { setStateConnections(NetState state) {
return forAllConnectedPlayers( return forEachConnectedPlayer(setStateConnection, &state);
(bool(*)(NetConnection *, void *)) setStateConnection, &state);
} }
static bool static bool
sendAbortConnection(NetConnection *conn, const NetplayAbortReason *reason) { sendAbortConnection(NetConnection *conn, void *arg) {
const NetplayAbortReason *reason = (NetplayAbortReason *) arg;
sendAbort(conn, *reason); sendAbort(conn, *reason);
return true; return true;
} }
bool bool
sendAbortConnections(NetplayAbortReason reason) { sendAbortConnections(NetplayAbortReason reason) {
return forAllConnectedPlayers( return forEachConnectedPlayer(sendAbortConnection, &reason);
(bool(*)(NetConnection *, void *)) sendAbortConnection, &reason);
} }
static bool static bool
resetConnection(NetConnection *conn, const NetplayResetReason *reason) { resetConnection(NetConnection *conn, void *arg) {
const NetplayResetReason *reason = (NetplayResetReason *) arg;
Netplay_localReset(conn, *reason); Netplay_localReset(conn, *reason);
return true; return true;
} }
bool bool
resetConnections(NetplayResetReason reason) { resetConnections(NetplayResetReason reason) {
return forAllConnectedPlayers( return forEachConnectedPlayer(resetConnection, &reason);
(bool(*)(NetConnection *, void *)) resetConnection, &reason);
} }
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
@@ -522,9 +472,10 @@ typedef struct {
} LocalReadyConnectionArg; } LocalReadyConnectionArg;
static bool static bool
localReadyConnection(NetConnection *conn, LocalReadyConnectionArg *arg) { localReadyConnection(NetConnection *conn, void *arg) {
Netplay_localReady(conn, arg->readyCallback, arg->readyCallbackArg, LocalReadyConnectionArg *readyArg = (LocalReadyConnectionArg *) arg;
arg->notifyRemote); Netplay_localReady(conn, readyArg->readyCallback,
readyArg->readyCallbackArg, readyArg->notifyRemote);
return true; return true;
} }
@@ -536,8 +487,7 @@ localReadyConnections(NetConnection_ReadyCallback readyCallback,
arg.readyCallbackArg = readyArg; arg.readyCallbackArg = readyArg;
arg.notifyRemote = notifyRemote; arg.notifyRemote = notifyRemote;
return forAllConnectedPlayers( return forEachConnectedPlayer(localReadyConnection, &arg);
(bool(*)(NetConnection *, void *)) localReadyConnection, &arg);
} }
@@ -636,7 +586,7 @@ typedef struct WaitReadyState WaitReadyState;
struct WaitReadyState { struct WaitReadyState {
// Common fields of INPUT_STATE_DESC, from which this structure // Common fields of INPUT_STATE_DESC, from which this structure
// "inherits". // "inherits".
BOOLEAN(*InputFunc)(void *pInputState); BOOLEAN (*InputFunc)(void *pInputState);
NetConnection *conn; NetConnection *conn;
NetConnection_ReadyCallback readyCallback; NetConnection_ReadyCallback readyCallback;
@@ -760,7 +710,7 @@ out:
return NetConnection_isConnected(conn); return NetConnection_isConnected(conn);
} }
// Wait until we have received a reset packet to all connections. If we // Wait until we have received a reset packet from all connections. If we
// ourselves have not sent a reset packet, one is sent, with reason // ourselves have not sent a reset packet, one is sent, with reason
// 'manualReset'. // 'manualReset'.
// XXX: Right now all connections are handled one by one. Handling them all // XXX: Right now all connections are handled one by one. Handling them all
+2 -6
View File
@@ -40,6 +40,8 @@ void removeNetConnection(int playerNr);
void closeAllConnections(void); void closeAllConnections(void);
void closeDisconnectedConnections(void); void closeDisconnectedConnections(void);
size_t getNumNetConnections(void); size_t getNumNetConnections(void);
typedef bool(*ForEachConnectionCallback)(NetConnection *conn, void *arg);
bool forEachConnectedPlayer(ForEachConnectionCallback callback, void *arg);
struct melee_state *NetMelee_getMeleeState(NetConnection *conn); struct melee_state *NetMelee_getMeleeState(NetConnection *conn);
struct battlestate_struct *NetMelee_getBattleState(NetConnection *conn); struct battlestate_struct *NetMelee_getBattleState(NetConnection *conn);
@@ -54,8 +56,6 @@ void connectionsLocalReady(NetConnection_ReadyCallback callback, void *arg);
bool allConnected(void); bool allConnected(void);
void sendBattleInputConnections(BATTLE_INPUT_STATE input);
void sendChecksumConnections(uint32 frameNr, uint32 checksum);
void initBattleStateDataConnections(void); void initBattleStateDataConnections(void);
void setBattleStateConnections(struct battlestate_struct *bs); void setBattleStateConnections(struct battlestate_struct *bs);
@@ -65,11 +65,7 @@ BATTLE_INPUT_STATE networkBattleInput(NetworkInputContext *context,
NetConnection *openPlayerNetworkConnection(COUNT player, void *extra); NetConnection *openPlayerNetworkConnection(COUNT player, void *extra);
void closePlayerNetworkConnection(COUNT player); void closePlayerNetworkConnection(COUNT player);
typedef bool(*ForAllCallback)(NetConnection *conn, void *arg);
bool forAllConnectedPlayers(ForAllCallback callback, void *arg);
bool setupInputDelay(size_t localInputDelay); bool setupInputDelay(size_t localInputDelay);
bool sendInputDelayConnections(size_t delay);
bool setStateConnections(NetState state); bool setStateConnections(NetState state);
bool sendAbortConnections(NetplayAbortReason reason); bool sendAbortConnections(NetplayAbortReason reason);
bool resetConnections(NetplayResetReason reason); bool resetConnections(NetplayResetReason reason);
+5 -7
View File
@@ -20,6 +20,7 @@
#include "netmisc.h" #include "netmisc.h"
#include "netmelee.h" #include "netmelee.h"
#include "notifyall.h"
#include "packetsenders.h" #include "packetsenders.h"
#include "proto/ready.h" #include "proto/ready.h"
@@ -118,8 +119,8 @@ NetMelee_enterState_inSetup(NetConnection *conn, void *arg) {
connectedFeedback(conn); connectedFeedback(conn);
entireFleetChanged(meleeState, player); Netplay_NotifyAll_setFleet(meleeState, player);
teamStringChanged(meleeState, player); Netplay_NotifyAll_setTeamName(meleeState, player);
flushPacketQueues(); flushPacketQueues();
@@ -151,13 +152,10 @@ NetMelee_reenterState_inSetup(NetConnection *conn) {
for (side = 0; side < NUM_SIDES; side++) for (side = 0; side < NUM_SIDES; side++)
{ {
entireFleetChanged(meleeState, side); Netplay_NotifyAll_setFleet(meleeState, side);
teamStringChanged(meleeState, side); Netplay_NotifyAll_setTeamName(meleeState, side);
} }
flushPacketQueues(); flushPacketQueues();
} }
} }
+13 -12
View File
@@ -37,14 +37,14 @@ netSide(NetConnection *conn, int side) {
} }
void void
Netplay_selectShip(NetConnection *conn, uint16 index) { Netplay_Notify_shipSelected(NetConnection *conn, FleetShipIndex index) {
assert(NetConnection_getState(conn) == NetState_selectShip); assert(NetConnection_getState(conn) == NetState_selectShip);
sendSelectShip(conn, index); sendSelectShip(conn, index);
} }
void void
Netplay_battleInput(NetConnection *conn, BATTLE_INPUT_STATE input) { Netplay_Notify_battleInput(NetConnection *conn, BATTLE_INPUT_STATE input) {
assert(NetConnection_getState(conn) == NetState_inBattle || assert(NetConnection_getState(conn) == NetState_inBattle ||
NetConnection_getState(conn) == NetState_endingBattle || NetConnection_getState(conn) == NetState_endingBattle ||
NetConnection_getState(conn) == NetState_endingBattle2); NetConnection_getState(conn) == NetState_endingBattle2);
@@ -53,18 +53,18 @@ Netplay_battleInput(NetConnection *conn, BATTLE_INPUT_STATE input) {
} }
void void
Netplay_teamStringChanged(NetConnection *conn, int player, Netplay_Notify_setTeamName(NetConnection *conn, int player,
const char *name, size_t len) { const char *name, size_t len) {
assert(NetConnection_getState(conn) == NetState_inSetup); assert(NetConnection_getState(conn) == NetState_inSetup);
assert(!conn->stateFlags.handshake.localOk); assert(!conn->stateFlags.handshake.localOk);
sendTeamString(conn, netSide(conn, player), name, len); sendTeamName(conn, netSide(conn, player), name, len);
} }
// On initialisation, or load. // On initialisation, or load.
void void
Netplay_entireFleetChanged(NetConnection *conn, int player, Netplay_Notify_setFleet(NetConnection *conn, int player,
const BYTE *fleet, size_t fleetSize) { const MeleeShip *fleet, size_t fleetSize) {
assert(NetConnection_getState(conn) == NetState_inSetup); assert(NetConnection_getState(conn) == NetState_inSetup);
assert(!conn->stateFlags.handshake.localOk); assert(!conn->stateFlags.handshake.localOk);
@@ -72,8 +72,8 @@ Netplay_entireFleetChanged(NetConnection *conn, int player,
} }
void void
Netplay_fleetShipChanged(NetConnection *conn, int player, Netplay_Notify_setShip(NetConnection *conn, int player,
size_t index, BYTE ship) { FleetShipIndex index, MeleeShip ship) {
assert(NetConnection_getState(conn) == NetState_inSetup); assert(NetConnection_getState(conn) == NetState_inSetup);
assert(!conn->stateFlags.handshake.localOk); assert(!conn->stateFlags.handshake.localOk);
@@ -81,7 +81,7 @@ Netplay_fleetShipChanged(NetConnection *conn, int player,
} }
void void
Netplay_seedRandom(NetConnection *conn, uint32 seed) { Netplay_Notify_seedRandom(NetConnection *conn, uint32 seed) {
assert(NetConnection_getState(conn) == NetState_preBattle); assert(NetConnection_getState(conn) == NetState_preBattle);
sendSeedRandom(conn, seed); sendSeedRandom(conn, seed);
@@ -89,14 +89,15 @@ Netplay_seedRandom(NetConnection *conn, uint32 seed) {
} }
void void
Netplay_sendInputDelay(NetConnection *conn, uint32 delay) { Netplay_Notify_inputDelay(NetConnection *conn, uint32 delay) {
assert(NetConnection_getState(conn) == NetState_preBattle); assert(NetConnection_getState(conn) == NetState_preBattle);
sendInputDelay(conn, delay); sendInputDelay(conn, delay);
} }
void void
Netplay_sendFrameCount(NetConnection *conn, BattleFrameCounter frameCount) { Netplay_Notify_frameCount(NetConnection *conn,
BattleFrameCounter frameCount) {
assert(NetConnection_getState(conn) == NetState_endingBattle); assert(NetConnection_getState(conn) == NetState_endingBattle);
sendFrameCount(conn, frameCount); sendFrameCount(conn, frameCount);
@@ -104,7 +105,7 @@ Netplay_sendFrameCount(NetConnection *conn, BattleFrameCounter frameCount) {
#ifdef NETPLAY_CHECKSUM #ifdef NETPLAY_CHECKSUM
void void
Netplay_sendChecksum(NetConnection *conn, BattleFrameCounter frameNr, Netplay_Notify_checksum(NetConnection *conn, BattleFrameCounter frameNr,
Checksum checksum) { Checksum checksum) {
assert(NetState_battleActive(NetConnection_getState(conn))); assert(NetState_battleActive(NetConnection_getState(conn)));
+16 -11
View File
@@ -27,21 +27,26 @@
#ifdef NETPLAY_CHECKSUM #ifdef NETPLAY_CHECKSUM
# include "checksum.h" # include "checksum.h"
#endif #endif
#include "../supermelee/meleeship.h"
// for MeleeShip
#include "../supermelee/meleesetup.h"
// for FleetShipIndex
void Netplay_selectShip(NetConnection *conn, uint16 index); void Netplay_Notify_shipSelected(NetConnection *conn, FleetShipIndex index);
void Netplay_battleInput(NetConnection *conn, BATTLE_INPUT_STATE input); void Netplay_Notify_battleInput(NetConnection *conn,
void Netplay_teamStringChanged(NetConnection *conn, int player, BATTLE_INPUT_STATE input);
void Netplay_Notify_setTeamName(NetConnection *conn, int player,
const char *name, size_t len); const char *name, size_t len);
void Netplay_entireFleetChanged(NetConnection *conn, int player, void Netplay_Notify_setFleet(NetConnection *conn, int player,
const BYTE *fleet, size_t fleetSize); const MeleeShip *fleet, size_t fleetSize);
void Netplay_fleetShipChanged(NetConnection *conn, int player, void Netplay_Notify_setShip(NetConnection *conn, int player,
size_t index, BYTE ship); FleetShipIndex index, MeleeShip ship);
void Netplay_seedRandom(NetConnection *conn, uint32 seed); void Netplay_Notify_seedRandom(NetConnection *conn, uint32 seed);
void Netplay_sendInputDelay(NetConnection *conn, uint32 delay); void Netplay_Notify_inputDelay(NetConnection *conn, uint32 delay);
void Netplay_sendFrameCount(NetConnection *conn, void Netplay_Notify_frameCount(NetConnection *conn,
BattleFrameCounter frameCount); BattleFrameCounter frameCount);
#ifdef NETPLAY_CHECKSUM #ifdef NETPLAY_CHECKSUM
void Netplay_sendChecksum(NetConnection *conn, void Netplay_Notify_checksum(NetConnection *conn,
BattleFrameCounter frameCount, Checksum checksum); BattleFrameCounter frameCount, Checksum checksum);
#endif #endif
+146
View File
@@ -0,0 +1,146 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "notifyall.h"
#include "netmelee.h"
#include "notify.h"
// Notify the network connections of a team name change.
void
Netplay_NotifyAll_setTeamName (MELEE_STATE *pMS, size_t playerNr)
{
const char *name;
size_t len;
size_t playerI;
name = MeleeSetup_getTeamName (pMS->meleeSetup, playerNr);
len = strlen (name);
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
{
NetConnection *conn = netConnections[playerI];
if (conn == NULL)
continue;
if (!NetConnection_isConnected (conn))
continue;
if (NetConnection_getState (conn) != NetState_inSetup)
continue;
Netplay_Notify_setTeamName (conn, playerNr, name, len);
}
}
// Notify the network connections of the configuration of a fleet.
void
Netplay_NotifyAll_setFleet (MELEE_STATE *pMS, size_t playerNr)
{
MeleeSetup *setup = pMS->meleeSetup;
const MeleeShip *ships = MeleeSetup_getFleet (setup, playerNr);
size_t playerI;
for (playerI = 0; playerI < NUM_PLAYERS; playerI++) {
NetConnection *conn = netConnections[playerI];
if (conn == NULL)
continue;
if (!NetConnection_isConnected (conn))
continue;
if (NetConnection_getState (conn) != NetState_inSetup)
continue;
Netplay_Notify_setFleet (conn, playerNr, ships, MELEE_FLEET_SIZE);
}
}
// Notify the network of a change in the configuration of a fleet.
void
Netplay_NotifyAll_setShip (MELEE_STATE *pMS, size_t playerNr, size_t index)
{
MeleeSetup *setup = pMS->meleeSetup;
MeleeShip ship = MeleeSetup_getShip (setup, playerNr, index);
size_t playerI;
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
{
NetConnection *conn = netConnections[playerI];
if (conn == NULL)
continue;
if (!NetConnection_isConnected (conn))
continue;
if (NetConnection_getState (conn) != NetState_inSetup)
continue;
Netplay_Notify_setShip (conn, playerNr, index, ship);
}
}
static bool
Netplay_NotifyAll_inputDelayCallback(NetConnection *conn, void *arg) {
const size_t *delay = (size_t *) arg;
Netplay_Notify_inputDelay(conn, *delay);
return true;
}
bool
Netplay_NotifyAll_inputDelay(size_t delay) {
return forEachConnectedPlayer(Netplay_NotifyAll_inputDelayCallback,
&delay);
}
#ifdef NETPLAY_CHECKSUM
void
Netplay_NotifyAll_checksum(BattleFrameCounter frameNr, Checksum checksum) {
COUNT player;
for (player = 0; player < NUM_PLAYERS; player++)
{
NetConnection *conn = netConnections[player];
if (conn == NULL)
continue;
if (!NetConnection_isConnected(conn))
continue;
Netplay_Notify_checksum(conn, frameNr, checksum);
}
}
#endif /* NETPLAY_CHECKSUM */
void
Netplay_NotifyAll_battleInput(BATTLE_INPUT_STATE input) {
COUNT player;
for (player = 0; player < NUM_PLAYERS; player++)
{
NetConnection *conn = netConnections[player];
if (conn == NULL)
continue;
if (!NetConnection_isConnected(conn))
continue;
Netplay_Notify_battleInput(conn, input);
}
}
+41
View File
@@ -0,0 +1,41 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef NOTIFYALL_H
#define NOTIFYALL_H
#include "../battle.h"
#include "../battlecontrols.h"
#include "../supermelee/melee.h"
#ifdef NETPLAY_CHECKSUM
# include "checksum.h"
#endif /* NETPLAY_CHECKSUM */
void Netplay_NotifyAll_setTeamName (MELEE_STATE *pMS, size_t playerNr);
void Netplay_NotifyAll_setFleet (MELEE_STATE *pMS, size_t playerNr);
void Netplay_NotifyAll_setShip (MELEE_STATE *pMS, size_t playerNr,
size_t index);
bool Netplay_NotifyAll_inputDelay(size_t delay);
#ifdef NETPLAY_CHECKSUM
void Netplay_NotifyAll_checksum(BattleFrameCounter frameNr,
Checksum checksum);
#endif /* NETPLAY_CHECKSUM */
void Netplay_NotifyAll_battleInput(BATTLE_INPUT_STATE input);
#endif /* NOTIFYALL_H */
+1 -1
View File
@@ -174,7 +174,7 @@ typedef enum {
typedef struct { typedef struct {
uint8 index; /* Position in the fleet */ uint8 index; /* Position in the fleet */
uint8 ship; /* Ship type index */ uint8 ship; /* Ship type index; actually MeleeShip */
} FleetEntry; } FleetEntry;
// Structure describing an update to a player's fleet. // Structure describing an update to a player's fleet.
// TODO: use strings as ship identifiers, instead of numbers, // TODO: use strings as ship identifiers, instead of numbers,
+29 -8
View File
@@ -39,6 +39,8 @@
// for GLOBAL // for GLOBAL
#include "../supermelee/melee.h" #include "../supermelee/melee.h"
// for various update functions. // for various update functions.
#include "../supermelee/meleeship.h"
// for MeleeShip
#include "../supermelee/pickmele.h" #include "../supermelee/pickmele.h"
// for various update functions. // for various update functions.
#include "libs/mathlib.h" #include "libs/mathlib.h"
@@ -263,16 +265,26 @@ PacketHandler_Fleet(NetConnection *conn, const Packet_Fleet *packet) {
} }
for (i = 0; i < numShips; i++) { for (i = 0; i < numShips; i++) {
int ship = packet->ships[i].ship; MeleeShip ship = (MeleeShip) packet->ships[i].ship;
int index = packet->ships[i].index; FleetShipIndex index = (FleetShipIndex) packet->ships[i].index;
bool updateResult = updateFleetShip( if (!MeleeShip_valid(ship)) {
battleStateData->meleeState, player, index, ship); log_add (log_Warning, "Invalid ship type number %d (max = %d).\n",
if (!updateResult) ship, NUM_MELEE_SHIPS - 1);
{
errno = EBADMSG; errno = EBADMSG;
return -1; return -1;
} }
if (index >= MELEE_FLEET_SIZE)
{
log_add (log_Warning, "Invalid ship position number %d "
"(max = %d).\n", index, MELEE_FLEET_SIZE - 1);
errno = EBADMSG;
return -1;
}
Melee_RemoteChange_ship (battleStateData->meleeState, conn,
player, index, ship);
} }
// Padding data may follow; it is ignored. // Padding data may follow; it is ignored.
@@ -312,8 +324,17 @@ PacketHandler_TeamName(NetConnection *conn, const Packet_TeamName *packet) {
- sizeof (Packet_TeamName) - 1; - sizeof (Packet_TeamName) - 1;
// The -1 is for not counting the terminating '\0'. // The -1 is for not counting the terminating '\0'.
updateTeamName(battleStateData->meleeState, side, {
(const char *) packet->name, nameLen); char buf[MAX_TEAM_CHARS + 1];
if (nameLen > MAX_TEAM_CHARS)
nameLen = MAX_TEAM_CHARS;
memcpy (buf, (const char *) packet->name, nameLen);
buf[nameLen] = '\0';
Melee_RemoteChange_teamName(battleStateData->meleeState, conn,
side, buf);
}
// Padding data may follow; it is ignored. // Padding data may follow; it is ignored.
return 0; return 0;
+12 -12
View File
@@ -107,7 +107,7 @@ sendHandshakeCancelAck(NetConnection *conn) {
} }
void void
sendTeamString(NetConnection *conn, NetplaySide side, const char *name, sendTeamName(NetConnection *conn, NetplaySide side, const char *name,
size_t len) { size_t len) {
Packet_TeamName *packet; Packet_TeamName *packet;
@@ -116,30 +116,30 @@ sendTeamString(NetConnection *conn, NetplaySide side, const char *name,
} }
void void
sendFleet(NetConnection *conn, NetplaySide side, const BYTE *ships, sendFleet(NetConnection *conn, NetplaySide side, const MeleeShip *ships,
size_t numShips) { size_t shipCount) {
size_t i; size_t i;
Packet_Fleet *packet; Packet_Fleet *packet;
packet = Packet_Fleet_create(side, numShips); packet = Packet_Fleet_create(side, shipCount);
for (i = 0; i < numShips; i++) { for (i = 0; i < shipCount; i++) {
packet->ships[i].index = (uint8) i; packet->ships[i].index = (uint8) i;
packet->ships[i].ship = ships[i]; packet->ships[i].ship = (uint8) ships[i];
} }
queuePacket(conn, (Packet *) packet, false); queuePacket(conn, (Packet *) packet, false);
} }
void void
sendFleetShip(NetConnection *conn, NetplaySide side, size_t shipIndex, sendFleetShip(NetConnection *conn, NetplaySide side,
BYTE ship) { FleetShipIndex shipIndex, MeleeShip ship) {
Packet_Fleet *packet; Packet_Fleet *packet;
packet = Packet_Fleet_create(side, 1); packet = Packet_Fleet_create(side, 1);
packet->ships[0].index = shipIndex; packet->ships[0].index = (uint8) shipIndex;
packet->ships[0].ship = ship; packet->ships[0].ship = (uint8) ship;
queuePacket(conn, (Packet *) packet, false); queuePacket(conn, (Packet *) packet, false);
} }
@@ -161,10 +161,10 @@ sendInputDelay(NetConnection *conn, uint32 delay) {
} }
void void
sendSelectShip(NetConnection *conn, COUNT ship) { sendSelectShip(NetConnection *conn, FleetShipIndex index) {
Packet_SelectShip *packet; Packet_SelectShip *packet;
packet = Packet_SelectShip_create(ship); packet = Packet_SelectShip_create((uint16) index);
queuePacket(conn, (Packet *) packet, false); queuePacket(conn, (Packet *) packet, false);
} }
+12 -7
View File
@@ -26,6 +26,10 @@
#include "../controls.h" #include "../controls.h"
// for BATTLE_INPUT_STATE // for BATTLE_INPUT_STATE
#include "../supermelee/meleeship.h"
// for MeleeShip
#include "../supermelee/meleesetup.h"
// for FleetShipIndex
void sendInit(NetConnection *conn); void sendInit(NetConnection *conn);
void sendPing(NetConnection *conn, uint32 id); void sendPing(NetConnection *conn, uint32 id);
@@ -37,18 +41,19 @@ void sendHandshake0(NetConnection *conn);
void sendHandshake1(NetConnection *conn); void sendHandshake1(NetConnection *conn);
void sendHandshakeCancel(NetConnection *conn); void sendHandshakeCancel(NetConnection *conn);
void sendHandshakeCancelAck(NetConnection *conn); void sendHandshakeCancelAck(NetConnection *conn);
void sendTeamString(NetConnection *conn, NetplaySide side, void sendTeamName(NetConnection *conn, NetplaySide side,
const char *name, size_t len); const char *name, size_t len);
void sendFleet(NetConnection *conn, NetplaySide side, const BYTE *ships, void sendFleet(NetConnection *conn, NetplaySide side,
size_t numShips); const MeleeShip *ships, size_t numShips);
void sendFleetShip(NetConnection *conn, NetplaySide player, void sendFleetShip(NetConnection *conn, NetplaySide player,
size_t shipIndex, BYTE ship); FleetShipIndex shipIndex, MeleeShip ship);
void sendSeedRandom(NetConnection *conn, uint32 seed); void sendSeedRandom(NetConnection *conn, uint32 seed);
void sendInputDelay(NetConnection *conn, uint32 delay); void sendInputDelay(NetConnection *conn, uint32 delay);
void sendSelectShip(NetConnection *conn, COUNT ship); void sendSelectShip(NetConnection *conn, FleetShipIndex index);
void sendBattleInput(NetConnection *conn, BATTLE_INPUT_STATE input); void sendBattleInput(NetConnection *conn, BATTLE_INPUT_STATE input);
void sendFrameCount(NetConnection *conn, uint32 frameCount); void sendFrameCount(NetConnection *conn, BattleFrameCounter frameCount);
void sendChecksum(NetConnection *conn, uint32 frameNr, uint32 checksum); void sendChecksum(NetConnection *conn, BattleFrameCounter frameNr,
Checksum checksum);
void sendAbort(NetConnection *conn, NetplayAbortReason reason); void sendAbort(NetConnection *conn, NetplayAbortReason reason);
void sendReset(NetConnection *conn, NetplayResetReason reason); void sendReset(NetConnection *conn, NetplayResetReason reason);
+1 -1
View File
@@ -1 +1 @@
uqm_CFILES="loadmele.c melee.c pickmele.c" uqm_CFILES="buildpick.c loadmele.c melee.c meleesetup.c pickmele.c"
+226
View File
@@ -0,0 +1,226 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "buildpick.h"
#include "../controls.h"
#include "../colors.h"
#include "../fmv.h"
#include "../master.h"
#include "../setup.h"
#include "../sounds.h"
#include "libs/gfxlib.h"
static FRAME BuildPickFrame;
void
BuildBuildPickFrame (void)
{
STAMP s;
RECT r;
COUNT i;
CONTEXT OldContext = SetContext (OffScreenContext);
// create team building ship selection box
s.origin.x = 0;
s.origin.y = 0;
s.frame = SetAbsFrameIndex (MeleeFrame, 27);
// 5x5 grid of ships to pick from
GetFrameRect (s.frame, &r);
BuildPickFrame = CaptureDrawable (CreateDrawable (
WANT_PIXMAP, r.extent.width, r.extent.height, 1));
SetContextFGFrame (BuildPickFrame);
SetFrameHot (s.frame, MAKE_HOT_SPOT (0, 0));
DrawStamp (&s);
for (i = 0; i < NUM_PICK_COLS * NUM_PICK_ROWS; ++i)
DrawPickIcon (i, true);
SetContext (OldContext);
}
void
DestroyBuildPickFrame (void)
{
DestroyDrawable (ReleaseDrawable (BuildPickFrame));
BuildPickFrame = 0;
}
// Draw a ship icon in the ship selection popup.
void
DrawPickIcon (MeleeShip ship, bool DrawErase)
{
STAMP s;
RECT r;
GetFrameRect (BuildPickFrame, &r);
s.origin.x = r.corner.x + 20 + (ship % NUM_PICK_COLS) * 18;
s.origin.y = r.corner.y + 5 + (ship / NUM_PICK_COLS) * 18;
s.frame = GetShipIconsFromIndex (ship);
if (DrawErase)
{ // draw icon
DrawStamp (&s);
}
else
{ // erase icon
Color OldColor;
OldColor = SetContextForeGroundColor (BLACK_COLOR);
DrawFilledStamp (&s);
SetContextForeGroundColor (OldColor);
}
}
// Pre: the called holds the GraphicsLock
void
DrawPickFrame (MELEE_STATE *pMS)
{
RECT r, r0, r1, ship_r;
STAMP s;
GetShipBox (&r0, 0, 0, 0),
GetShipBox (&r1, 1, NUM_MELEE_ROWS - 1, NUM_MELEE_COLUMNS - 1),
BoxUnion (&r0, &r1, &ship_r);
s.frame = SetAbsFrameIndex (BuildPickFrame, 0);
GetFrameRect (s.frame, &r);
r.corner.x = -(ship_r.corner.x
+ ((ship_r.extent.width - r.extent.width) >> 1));
if (pMS->side)
r.corner.y = -ship_r.corner.y;
else
r.corner.y = -(ship_r.corner.y
+ (ship_r.extent.height - r.extent.height));
SetFrameHot (s.frame, MAKE_HOT_SPOT (r.corner.x, r.corner.y));
s.origin.x = 0;
s.origin.y = 0;
DrawStamp (&s);
DrawMeleeShipStrings (pMS, pMS->currentShip);
}
void
GetBuildPickFrameRect (RECT *r)
{
GetFrameRect (BuildPickFrame, r);
}
static BOOLEAN
DoPickShip (MELEE_STATE *pMS)
{
DWORD TimeIn = GetTimeCounter ();
/* Cancel any presses of the Pause key. */
GamePaused = FALSE;
if (GLOBAL (CurrentActivity) & CHECK_ABORT)
{
pMS->buildPickConfirmed = false;
return FALSE;
}
SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT);
if (PulsedInputState.menu[KEY_MENU_SELECT] ||
PulsedInputState.menu[KEY_MENU_CANCEL])
{
// Confirm selection or cancel.
pMS->buildPickConfirmed = !PulsedInputState.menu[KEY_MENU_CANCEL];
return FALSE;
}
if (PulsedInputState.menu[KEY_MENU_SPECIAL]
&& (pMS->currentShip != MELEE_NONE))
{
// Show ship spin video.
DoShipSpin (pMS->currentShip, (MUSIC_REF) 0);
return TRUE;
}
{
MeleeShip newSelectedShip;
newSelectedShip = pMS->currentShip;
if (PulsedInputState.menu[KEY_MENU_LEFT])
{
if (newSelectedShip % NUM_PICK_COLS == 0)
newSelectedShip += NUM_PICK_COLS;
--newSelectedShip;
}
else if (PulsedInputState.menu[KEY_MENU_RIGHT])
{
++newSelectedShip;
if (newSelectedShip % NUM_PICK_COLS == 0)
newSelectedShip -= NUM_PICK_COLS;
}
if (PulsedInputState.menu[KEY_MENU_UP])
{
if (newSelectedShip >= NUM_PICK_COLS)
newSelectedShip -= NUM_PICK_COLS;
else
newSelectedShip += NUM_PICK_COLS * (NUM_PICK_ROWS - 1);
}
else if (PulsedInputState.menu[KEY_MENU_DOWN])
{
if (newSelectedShip < NUM_PICK_COLS * (NUM_PICK_ROWS - 1))
newSelectedShip += NUM_PICK_COLS;
else
newSelectedShip -= NUM_PICK_COLS * (NUM_PICK_ROWS - 1);
}
if (newSelectedShip != pMS->currentShip)
{
// A new ship has been selected.
LockMutex (GraphicsLock);
DrawPickIcon (pMS->currentShip, true);
pMS->currentShip = newSelectedShip;
DrawMeleeShipStrings (pMS, newSelectedShip);
UnlockMutex (GraphicsLock);
}
}
Melee_flashSelection (pMS);
SleepThreadUntil (TimeIn + ONE_SECOND / 30);
return TRUE;
}
// Returns true if a ship has been selected, or false if the operation has
// been cancelled or if the general abort key was pressed (in which case
// 'GLOBAL (CurrentActivity) & CHECK_ABORT' is true as usual.
// If a ship was selected, pMS->currentShip is set to the selected ship.
bool
BuildPickShip (MELEE_STATE *pMS)
{
FlushInput ();
if (pMS->currentShip == MELEE_NONE)
pMS->currentShip = 0;
LockMutex (GraphicsLock);
DrawPickFrame (pMS);
UnlockMutex (GraphicsLock);
pMS->InputFunc = DoPickShip;
DoInput (pMS, FALSE);
return pMS->buildPickConfirmed;
}
+17
View File
@@ -0,0 +1,17 @@
#ifndef BUILDPICK_H
#define BUILDPICK_H
#include <stdbool.h>
#include "melee.h"
void BuildBuildPickFrame (void);
void DestroyBuildPickFrame (void);
bool BuildPickShip (MELEE_STATE *pMS);
void GetBuildPickFrameRect (RECT *r);
void DrawPickFrame (MELEE_STATE *pMS);
void DrawPickIcon (MeleeShip ship, bool DrawErase);
#endif /* BUILDPICK_H */
+250 -283
View File
@@ -18,6 +18,7 @@
// This file handles loading of teams, but the UI and the actual loading. // This file handles loading of teams, but the UI and the actual loading.
#define MELEESETUP_INTERNAL
#include "melee.h" #include "melee.h"
#include "../controls.h" #include "../controls.h"
@@ -25,10 +26,11 @@
#include "../gamestr.h" #include "../gamestr.h"
#include "../globdata.h" #include "../globdata.h"
#include "../master.h" #include "../master.h"
#include "meleesetup.h"
#include "../save.h" #include "../save.h"
#include "../setup.h" #include "../setup.h"
#include "../sounds.h" #include "../sounds.h"
#include "../../options.h" #include "options.h"
#include "libs/log.h" #include "libs/log.h"
#include "libs/memlib.h" #include "libs/memlib.h"
@@ -48,53 +50,23 @@ static void DrawFileStrings (MELEE_STATE *pMS);
static bool FillFileView (MELEE_STATE *pMS); static bool FillFileView (MELEE_STATE *pMS);
bool
ReadTeamImage (TEAM_IMAGE *pTI, uio_Stream *load_fp)
{
int status;
FleetShipIndex i;
status = ReadResFile (pTI, sizeof (*pTI), 1, load_fp);
if (status != 1)
return false;
// Sanity check on the entries.
for (i = 0; i < MELEE_FLEET_SIZE; i++)
{
BYTE StarShip = pTI->ShipList[i];
if (StarShip == MELEE_NONE)
continue;
if (StarShip >= NUM_MELEE_SHIPS)
{
log_add (log_Warning, "Invalid ship type in loaded team (index "
"%d, ship type is %d, max valid is %d).",
i, StarShip, NUM_MELEE_SHIPS - 1);
pTI->ShipList[i] = MELEE_NONE;
}
}
return true;
}
static bool static bool
LoadTeamImage (DIRENTRY DirEntry, TEAM_IMAGE *pTI) LoadTeamImage (DIRENTRY DirEntry, MeleeTeam *team)
{ {
const BYTE *fileName; const char *fileName;
uio_Stream *load_fp; uio_Stream *stream;
bool status; bool status;
fileName = GetDirEntryAddress (DirEntry); fileName = GetDirEntryAddress (DirEntry);
load_fp = res_OpenResFile (meleeDir, (const char *) fileName, "rb");
if (load_fp == 0) stream = uio_fopen (meleeDir, fileName, "rb");
if (stream == NULL)
return false; return false;
if (LengthResFile (load_fp) != sizeof (*pTI)) if (MeleeTeam_deserialize (team, stream) == -1)
status = false; return false;
else
status = ReadTeamImage (pTI, load_fp); uio_fclose (stream);
res_CloseResFile (load_fp);
return status; return status;
} }
@@ -123,13 +95,13 @@ UnindexFleets (MELEE_STATE *pMS, COUNT index, COUNT count)
} }
static bool static bool
GetFleetByIndex (MELEE_STATE *pMS, COUNT index, TEAM_IMAGE *result) GetFleetByIndex (MELEE_STATE *pMS, COUNT index, MeleeTeam *result)
{ {
COUNT firstIndex; COUNT firstIndex;
if (index < pMS->load.preBuiltCount) if (index < pMS->load.preBuiltCount)
{ {
*result = pMS->load.preBuiltList[index]; MeleeTeam_copy (result, pMS->load.preBuiltList[index]);
return true; return true;
} }
@@ -144,7 +116,7 @@ GetFleetByIndex (MELEE_STATE *pMS, COUNT index, TEAM_IMAGE *result)
break; // Success break; // Success
{ {
const BYTE *fileName; const char *fileName;
fileName = GetDirEntryAddress (entry); fileName = GetDirEntryAddress (entry);
log_add (log_Warning, "Warning: File '%s' is not a valid " log_add (log_Warning, "Warning: File '%s' is not a valid "
"SuperMelee team.", fileName); "SuperMelee team.", fileName);
@@ -167,7 +139,7 @@ GetFleetIndexByFileName (MELEE_STATE *pMS, const char *fileName)
{ {
DIRENTRY entry = SetAbsDirEntryTableIndex (pMS->load.dirEntries, DIRENTRY entry = SetAbsDirEntryTableIndex (pMS->load.dirEntries,
pMS->load.entryIndices[index]); pMS->load.entryIndices[index]);
const BYTE *entryName = GetDirEntryAddress (entry); const char *entryName = GetDirEntryAddress (entry);
if (strcasecmp ((const char *) entryName, fileName) == 0) if (strcasecmp ((const char *) entryName, fileName) == 0)
return pMS->load.preBuiltCount + index; return pMS->load.preBuiltCount + index;
@@ -181,8 +153,8 @@ GetFleetIndexByFileName (MELEE_STATE *pMS, const char *fileName)
// fleet name and value; if not, only the fleet name and value are drawn. // fleet name and value; if not, only the fleet name and value are drawn.
// If highlite is set the text is drawn in the color used for highlighting. // If highlite is set the text is drawn in the color used for highlighting.
static void static void
DrawFileString (TEAM_IMAGE *pTI, POINT *origin, BOOLEAN drawShips, DrawFileString (const MeleeTeam *team, const POINT *origin,
BOOLEAN highlite) BOOLEAN drawShips, BOOLEAN highlite)
{ {
SetContextForeGroundColor (highlite ? SetContextForeGroundColor (highlite ?
LOAD_TEAM_NAME_TEXT_COLOR_HILITE : LOAD_TEAM_NAME_TEXT_COLOR); LOAD_TEAM_NAME_TEXT_COLOR_HILITE : LOAD_TEAM_NAME_TEXT_COLOR);
@@ -193,7 +165,7 @@ DrawFileString (TEAM_IMAGE *pTI, POINT *origin, BOOLEAN drawShips,
Text.baseline = *origin; Text.baseline = *origin;
Text.align = ALIGN_LEFT; Text.align = ALIGN_LEFT;
Text.pStr = pTI->TeamName; Text.pStr = MeleeTeam_getTeamName(team);
Text.CharCount = (COUNT)~0; Text.CharCount = (COUNT)~0;
font_DrawText (&Text); font_DrawText (&Text);
} }
@@ -203,7 +175,7 @@ DrawFileString (TEAM_IMAGE *pTI, POINT *origin, BOOLEAN drawShips,
TEXT Text; TEXT Text;
UNICODE buf[60]; UNICODE buf[60];
sprintf (buf, "%u", GetTeamValue (pTI)); sprintf (buf, "%u", MeleeTeam_getValue (team));
Text.baseline = *origin; Text.baseline = *origin;
Text.baseline.x += NUM_MELEE_COLUMNS * Text.baseline.x += NUM_MELEE_COLUMNS *
(LOAD_MELEE_BOX_WIDTH + LOAD_MELEE_BOX_SPACE) - 1; (LOAD_MELEE_BOX_WIDTH + LOAD_MELEE_BOX_SPACE) - 1;
@@ -217,15 +189,15 @@ DrawFileString (TEAM_IMAGE *pTI, POINT *origin, BOOLEAN drawShips,
if (drawShips) if (drawShips)
{ {
STAMP s; STAMP s;
FleetShipIndex index; FleetShipIndex slotI;
s.origin.x = origin->x + 1; s.origin.x = origin->x + 1;
s.origin.y = origin->y + 4; s.origin.y = origin->y + 4;
for (index = 0; index < MELEE_FLEET_SIZE; index++) for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++)
{ {
BYTE StarShip; BYTE StarShip;
StarShip = pTI->ShipList[index]; StarShip = team->ships[slotI];
if (StarShip != MELEE_NONE) if (StarShip != MELEE_NONE)
{ {
s.frame = GetShipIconsFromIndex (StarShip); s.frame = GetShipIconsFromIndex (StarShip);
@@ -247,7 +219,7 @@ FillFileView (MELEE_STATE *pMS)
for (viewI = 0; viewI < LOAD_TEAM_VIEW_SIZE; viewI++) for (viewI = 0; viewI < LOAD_TEAM_VIEW_SIZE; viewI++)
{ {
bool success = GetFleetByIndex (pMS, pMS->load.top + viewI, bool success = GetFleetByIndex (pMS, pMS->load.top + viewI,
&pMS->load.view[viewI]); pMS->load.view[viewI]);
if (!success) if (!success)
break; break;
} }
@@ -278,7 +250,7 @@ SelectFileString (MELEE_STATE *pMS, bool hilite)
origin.x = FILE_STRING_ORIGIN_X; origin.x = FILE_STRING_ORIGIN_X;
origin.y = FILE_STRING_ORIGIN_Y + viewI * ENTRY_HEIGHT; origin.y = FILE_STRING_ORIGIN_Y + viewI * ENTRY_HEIGHT;
DrawFileString (&pMS->load.view[viewI], &origin, FALSE, hilite); DrawFileString (pMS->load.view[viewI], &origin, FALSE, hilite);
UnbatchGraphics (); UnbatchGraphics ();
SetContext (OldContext); SetContext (OldContext);
@@ -303,7 +275,7 @@ DrawFileStrings (MELEE_STATE *pMS)
{ {
COUNT i; COUNT i;
for (i = pMS->load.top; i < pMS->load.bot; i++) { for (i = pMS->load.top; i < pMS->load.bot; i++) {
DrawFileString (&pMS->load.view[i - pMS->load.top], &origin, DrawFileString (pMS->load.view[i - pMS->load.top], &origin,
TRUE, FALSE); TRUE, FALSE);
origin.y += ENTRY_HEIGHT; origin.y += ENTRY_HEIGHT;
} }
@@ -379,12 +351,8 @@ DoLoadTeam (MELEE_STATE *pMS)
if (PulsedInputState.menu[KEY_MENU_SELECT]) if (PulsedInputState.menu[KEY_MENU_SELECT])
{ {
// Copy the selected fleet to the player. // Copy the selected fleet to the player.
pMS->SideState[pMS->side].TeamImage = Melee_Change_team (pMS, pMS->side,
pMS->load.view[pMS->load.cur - pMS->load.top]; pMS->load.view[pMS->load.cur - pMS->load.top]);
pMS->SideState[pMS->side].star_bucks =
GetTeamValue (&pMS->SideState[pMS->side].TeamImage);
entireFleetChanged (pMS, pMS->side);
teamStringChanged (pMS, pMS->side);
} }
pMS->InputFunc = DoMelee; pMS->InputFunc = DoMelee;
@@ -470,12 +438,6 @@ DoLoadTeam (MELEE_STATE *pMS)
return TRUE; return TRUE;
} }
int
WriteTeamImage (TEAM_IMAGE *pTI, uio_Stream *save_fp)
{
return WriteResFile (pTI, sizeof (*pTI), 1, save_fp);
}
void void
SelectTeamByFileName (MELEE_STATE *pMS, const char *fileName) SelectTeamByFileName (MELEE_STATE *pMS, const char *fileName)
{ {
@@ -509,73 +471,67 @@ DoSaveTeam (MELEE_STATE *pMS)
{ {
STAMP MsgStamp; STAMP MsgStamp;
char file[NAME_MAX]; char file[NAME_MAX];
uio_Stream *save_fp; uio_Stream *stream;
CONTEXT OldContext; CONTEXT OldContext;
bool saveOk = false;
sprintf (file, "%s.mle", pMS->SideState[pMS->side].TeamImage.TeamName); snprintf (file, sizeof file, "%s.mle",
MeleeSetup_getTeamName (pMS->meleeSetup, pMS->side));
LockMutex (GraphicsLock); LockMutex (GraphicsLock);
OldContext = SetContext (ScreenContext); OldContext = SetContext (ScreenContext);
ConfirmSaveLoad (&MsgStamp); ConfirmSaveLoad (&MsgStamp);
save_fp = res_OpenResFile (meleeDir, file, "wb"); // Show the "Saving . . ." message.
if (save_fp) UnlockMutex (GraphicsLock);
{
BOOLEAN err;
err = (BOOLEAN)(WriteTeamImage ( stream = uio_fopen (meleeDir, file, "wb");
&pMS->SideState[pMS->side].TeamImage, save_fp) == 0); if (stream != NULL)
if (res_CloseResFile (save_fp) == 0) {
err = TRUE; saveOk = (MeleeTeam_serialize (&pMS->meleeSetup->teams[pMS->side],
if (err) stream) == 0);
save_fp = 0; uio_fclose (stream);
if (!saveOk)
uio_unlink (meleeDir, file);
} }
pMS->load.top = 0; pMS->load.top = 0;
pMS->load.cur = 0; pMS->load.cur = 0;
if (save_fp == 0) // Undo the screen damage done by the "Saving . . ." message.
{ LockMutex (GraphicsLock);
DrawStamp (&MsgStamp); DrawStamp (&MsgStamp);
DestroyDrawable (ReleaseDrawable (MsgStamp.frame)); DestroyDrawable (ReleaseDrawable (MsgStamp.frame));
SetContext (OldContext); SetContext (OldContext);
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
DeleteResFile (meleeDir, file); if (!saveOk)
SaveProblem (); SaveProblem ();
}
// Update the team list; a previously existing team may have been
// deleted when save failed.
LoadTeamList (pMS); LoadTeamList (pMS);
SelectTeamByFileName (pMS, file); SelectTeamByFileName (pMS, file);
if (save_fp != 0) return (stream != 0);
{
DrawStamp (&MsgStamp);
DestroyDrawable (ReleaseDrawable (MsgStamp.frame));
SetContext (OldContext);
UnlockMutex (GraphicsLock);
}
return (save_fp != 0);
} }
static void static void
InitPreBuilt (MELEE_STATE *pMS) InitPreBuilt (MELEE_STATE *pMS)
{ {
TEAM_IMAGE *list; MeleeTeam **list;
#define PREBUILT_COUNT 15 #define PREBUILT_COUNT 15
pMS->load.preBuiltList = pMS->load.preBuiltList =
HMalloc (PREBUILT_COUNT * sizeof pMS->load.preBuiltList[0]); HMalloc (PREBUILT_COUNT * sizeof (MeleeTeam *));
pMS->load.preBuiltCount = PREBUILT_COUNT; pMS->load.preBuiltCount = PREBUILT_COUNT;
#undef PREBUILT_COUNT #undef PREBUILT_COUNT
{ {
FleetShipIndex shipI = 0; size_t fleetI;
int fleetI;
for (fleetI = 0; fleetI < pMS->load.preBuiltCount; fleetI++) for (fleetI = 0; fleetI < pMS->load.preBuiltCount; fleetI++)
for (shipI = 0; shipI < MELEE_FLEET_SIZE; shipI++) pMS->load.preBuiltList[fleetI] = MeleeTeam_new ();
pMS->load.preBuiltList[fleetI].ShipList[shipI] = MELEE_NONE;
} }
list = pMS->load.preBuiltList; list = pMS->load.preBuiltList;
@@ -583,260 +539,245 @@ InitPreBuilt (MELEE_STATE *pMS)
{ {
/* "Balanced Team 1" */ /* "Balanced Team 1" */
FleetShipIndex i = 0; FleetShipIndex i = 0;
utf8StringCopy (list->TeamName, sizeof (list->TeamName), MeleeTeam_setName (*list, GAME_STRING (MELEE_STRING_BASE + 4));
GAME_STRING (MELEE_STRING_BASE + 4)); MeleeTeam_setShip (*list, i++, MELEE_ANDROSYNTH);
list->ShipList[i++] = MELEE_ANDROSYNTH; MeleeTeam_setShip (*list, i++, MELEE_CHMMR);
list->ShipList[i++] = MELEE_CHMMR; MeleeTeam_setShip (*list, i++, MELEE_DRUUGE);
list->ShipList[i++] = MELEE_DRUUGE; MeleeTeam_setShip (*list, i++, MELEE_URQUAN);
list->ShipList[i++] = MELEE_URQUAN; MeleeTeam_setShip (*list, i++, MELEE_MELNORME);
list->ShipList[i++] = MELEE_MELNORME; MeleeTeam_setShip (*list, i++, MELEE_ORZ);
list->ShipList[i++] = MELEE_ORZ; MeleeTeam_setShip (*list, i++, MELEE_SPATHI);
list->ShipList[i++] = MELEE_SPATHI; MeleeTeam_setShip (*list, i++, MELEE_SYREEN);
list->ShipList[i++] = MELEE_SYREEN; MeleeTeam_setShip (*list, i++, MELEE_UTWIG);
list->ShipList[i++] = MELEE_UTWIG;
list++; list++;
} }
{ {
/* "Balanced Team 2" */ /* "Balanced Team 2" */
FleetShipIndex i = 0; FleetShipIndex i = 0;
utf8StringCopy (list->TeamName, sizeof (list->TeamName), MeleeTeam_setName (*list, GAME_STRING (MELEE_STRING_BASE + 5));
GAME_STRING (MELEE_STRING_BASE + 5)); MeleeTeam_setShip (*list, i++, MELEE_ARILOU);
list->ShipList[i++] = MELEE_ARILOU; MeleeTeam_setShip (*list, i++, MELEE_CHENJESU);
list->ShipList[i++] = MELEE_CHENJESU; MeleeTeam_setShip (*list, i++, MELEE_EARTHLING);
list->ShipList[i++] = MELEE_EARTHLING; MeleeTeam_setShip (*list, i++, MELEE_KOHR_AH);
list->ShipList[i++] = MELEE_KOHR_AH; MeleeTeam_setShip (*list, i++, MELEE_MYCON);
list->ShipList[i++] = MELEE_MYCON; MeleeTeam_setShip (*list, i++, MELEE_YEHAT);
list->ShipList[i++] = MELEE_YEHAT; MeleeTeam_setShip (*list, i++, MELEE_PKUNK);
list->ShipList[i++] = MELEE_PKUNK; MeleeTeam_setShip (*list, i++, MELEE_SUPOX);
list->ShipList[i++] = MELEE_SUPOX; MeleeTeam_setShip (*list, i++, MELEE_THRADDASH);
list->ShipList[i++] = MELEE_THRADDASH; MeleeTeam_setShip (*list, i++, MELEE_ZOQFOTPIK);
list->ShipList[i++] = MELEE_ZOQFOTPIK; MeleeTeam_setShip (*list, i++, MELEE_SHOFIXTI);
list->ShipList[i++] = MELEE_SHOFIXTI;
list++; list++;
} }
{ {
/* "200 points" */ /* "200 points" */
FleetShipIndex i = 0; FleetShipIndex i = 0;
utf8StringCopy (list->TeamName, sizeof (list->TeamName), MeleeTeam_setName (*list, GAME_STRING (MELEE_STRING_BASE + 6));
GAME_STRING (MELEE_STRING_BASE + 6)); MeleeTeam_setShip (*list, i++, MELEE_ANDROSYNTH);
list->ShipList[i++] = MELEE_ANDROSYNTH; MeleeTeam_setShip (*list, i++, MELEE_CHMMR);
list->ShipList[i++] = MELEE_CHMMR; MeleeTeam_setShip (*list, i++, MELEE_DRUUGE);
list->ShipList[i++] = MELEE_DRUUGE; MeleeTeam_setShip (*list, i++, MELEE_MELNORME);
list->ShipList[i++] = MELEE_MELNORME; MeleeTeam_setShip (*list, i++, MELEE_EARTHLING);
list->ShipList[i++] = MELEE_EARTHLING; MeleeTeam_setShip (*list, i++, MELEE_KOHR_AH);
list->ShipList[i++] = MELEE_KOHR_AH; MeleeTeam_setShip (*list, i++, MELEE_SUPOX);
list->ShipList[i++] = MELEE_SUPOX; MeleeTeam_setShip (*list, i++, MELEE_ORZ);
list->ShipList[i++] = MELEE_ORZ; MeleeTeam_setShip (*list, i++, MELEE_SPATHI);
list->ShipList[i++] = MELEE_SPATHI; MeleeTeam_setShip (*list, i++, MELEE_ILWRATH);
list->ShipList[i++] = MELEE_ILWRATH; MeleeTeam_setShip (*list, i++, MELEE_VUX);
list->ShipList[i++] = MELEE_VUX;
list++; list++;
} }
{ {
/* "Behemoth Zenith" */ /* "Behemoth Zenith" */
FleetShipIndex i = 0; FleetShipIndex i = 0;
utf8StringCopy (list->TeamName, sizeof (list->TeamName), MeleeTeam_setName (*list, GAME_STRING (MELEE_STRING_BASE + 7));
GAME_STRING (MELEE_STRING_BASE + 7)); MeleeTeam_setShip (*list, i++, MELEE_CHENJESU);
list->ShipList[i++] = MELEE_CHENJESU; MeleeTeam_setShip (*list, i++, MELEE_CHENJESU);
list->ShipList[i++] = MELEE_CHENJESU; MeleeTeam_setShip (*list, i++, MELEE_CHMMR);
list->ShipList[i++] = MELEE_CHMMR; MeleeTeam_setShip (*list, i++, MELEE_CHMMR);
list->ShipList[i++] = MELEE_CHMMR; MeleeTeam_setShip (*list, i++, MELEE_KOHR_AH);
list->ShipList[i++] = MELEE_KOHR_AH; MeleeTeam_setShip (*list, i++, MELEE_KOHR_AH);
list->ShipList[i++] = MELEE_KOHR_AH; MeleeTeam_setShip (*list, i++, MELEE_URQUAN);
list->ShipList[i++] = MELEE_URQUAN; MeleeTeam_setShip (*list, i++, MELEE_URQUAN);
list->ShipList[i++] = MELEE_URQUAN; MeleeTeam_setShip (*list, i++, MELEE_UTWIG);
list->ShipList[i++] = MELEE_UTWIG; MeleeTeam_setShip (*list, i++, MELEE_UTWIG);
list->ShipList[i++] = MELEE_UTWIG;
list++; list++;
} }
{ {
/* "The Peeled Eyes" */ /* "The Peeled Eyes" */
FleetShipIndex i = 0; FleetShipIndex i = 0;
utf8StringCopy (list->TeamName, sizeof (list->TeamName), MeleeTeam_setName (*list, GAME_STRING (MELEE_STRING_BASE + 8));
GAME_STRING (MELEE_STRING_BASE + 8)); MeleeTeam_setShip (*list, i++, MELEE_URQUAN);
list->ShipList[i++] = MELEE_URQUAN; MeleeTeam_setShip (*list, i++, MELEE_CHENJESU);
list->ShipList[i++] = MELEE_CHENJESU; MeleeTeam_setShip (*list, i++, MELEE_MYCON);
list->ShipList[i++] = MELEE_MYCON; MeleeTeam_setShip (*list, i++, MELEE_SYREEN);
list->ShipList[i++] = MELEE_SYREEN; MeleeTeam_setShip (*list, i++, MELEE_ZOQFOTPIK);
list->ShipList[i++] = MELEE_ZOQFOTPIK; MeleeTeam_setShip (*list, i++, MELEE_SHOFIXTI);
list->ShipList[i++] = MELEE_SHOFIXTI; MeleeTeam_setShip (*list, i++, MELEE_EARTHLING);
list->ShipList[i++] = MELEE_EARTHLING; MeleeTeam_setShip (*list, i++, MELEE_KOHR_AH);
list->ShipList[i++] = MELEE_KOHR_AH; MeleeTeam_setShip (*list, i++, MELEE_MELNORME);
list->ShipList[i++] = MELEE_MELNORME; MeleeTeam_setShip (*list, i++, MELEE_DRUUGE);
list->ShipList[i++] = MELEE_DRUUGE; MeleeTeam_setShip (*list, i++, MELEE_PKUNK);
list->ShipList[i++] = MELEE_PKUNK; MeleeTeam_setShip (*list, i++, MELEE_ORZ);
list->ShipList[i++] = MELEE_ORZ;
list++; list++;
} }
{ {
FleetShipIndex i = 0; FleetShipIndex i = 0;
utf8StringCopy (list->TeamName, sizeof (list->TeamName), MeleeTeam_setName (*list, "Ford's Fighters");
"Ford's Fighters"); MeleeTeam_setShip (*list, i++, MELEE_CHMMR);
list->ShipList[i++] = MELEE_CHMMR; MeleeTeam_setShip (*list, i++, MELEE_ZOQFOTPIK);
list->ShipList[i++] = MELEE_ZOQFOTPIK; MeleeTeam_setShip (*list, i++, MELEE_MELNORME);
list->ShipList[i++] = MELEE_MELNORME; MeleeTeam_setShip (*list, i++, MELEE_SUPOX);
list->ShipList[i++] = MELEE_SUPOX; MeleeTeam_setShip (*list, i++, MELEE_UTWIG);
list->ShipList[i++] = MELEE_UTWIG; MeleeTeam_setShip (*list, i++, MELEE_UMGAH);
list->ShipList[i++] = MELEE_UMGAH;
list++; list++;
} }
{ {
FleetShipIndex i = 0; FleetShipIndex i = 0;
utf8StringCopy (list->TeamName, sizeof (list->TeamName), MeleeTeam_setName (*list, "Leyland's Lashers");
"Leyland's Lashers"); MeleeTeam_setShip (*list, i++, MELEE_ANDROSYNTH);
list->ShipList[i++] = MELEE_ANDROSYNTH; MeleeTeam_setShip (*list, i++, MELEE_EARTHLING);
list->ShipList[i++] = MELEE_EARTHLING; MeleeTeam_setShip (*list, i++, MELEE_MYCON);
list->ShipList[i++] = MELEE_MYCON; MeleeTeam_setShip (*list, i++, MELEE_ORZ);
list->ShipList[i++] = MELEE_ORZ; MeleeTeam_setShip (*list, i++, MELEE_URQUAN);
list->ShipList[i++] = MELEE_URQUAN;
list++; list++;
} }
{ {
FleetShipIndex i = 0; FleetShipIndex i = 0;
utf8StringCopy (list->TeamName, sizeof (list->TeamName), MeleeTeam_setName (*list, "The Gregorizers 200");
"The Gregorizers 200"); MeleeTeam_setShip (*list, i++, MELEE_ANDROSYNTH);
list->ShipList[i++] = MELEE_ANDROSYNTH; MeleeTeam_setShip (*list, i++, MELEE_CHMMR);
list->ShipList[i++] = MELEE_CHMMR; MeleeTeam_setShip (*list, i++, MELEE_DRUUGE);
list->ShipList[i++] = MELEE_DRUUGE; MeleeTeam_setShip (*list, i++, MELEE_MELNORME);
list->ShipList[i++] = MELEE_MELNORME; MeleeTeam_setShip (*list, i++, MELEE_EARTHLING);
list->ShipList[i++] = MELEE_EARTHLING; MeleeTeam_setShip (*list, i++, MELEE_KOHR_AH);
list->ShipList[i++] = MELEE_KOHR_AH; MeleeTeam_setShip (*list, i++, MELEE_SUPOX);
list->ShipList[i++] = MELEE_SUPOX; MeleeTeam_setShip (*list, i++, MELEE_ORZ);
list->ShipList[i++] = MELEE_ORZ; MeleeTeam_setShip (*list, i++, MELEE_PKUNK);
list->ShipList[i++] = MELEE_PKUNK; MeleeTeam_setShip (*list, i++, MELEE_SPATHI);
list->ShipList[i++] = MELEE_SPATHI;
list++; list++;
} }
{ {
FleetShipIndex i = 0; FleetShipIndex i = 0;
utf8StringCopy (list->TeamName, sizeof (list->TeamName), MeleeTeam_setName (*list, "300 point Armada!");
"300 point Armada!"); MeleeTeam_setShip (*list, i++, MELEE_ANDROSYNTH);
list->ShipList[i++] = MELEE_ANDROSYNTH; MeleeTeam_setShip (*list, i++, MELEE_CHMMR);
list->ShipList[i++] = MELEE_CHMMR; MeleeTeam_setShip (*list, i++, MELEE_CHENJESU);
list->ShipList[i++] = MELEE_CHENJESU; MeleeTeam_setShip (*list, i++, MELEE_DRUUGE);
list->ShipList[i++] = MELEE_DRUUGE; MeleeTeam_setShip (*list, i++, MELEE_EARTHLING);
list->ShipList[i++] = MELEE_EARTHLING; MeleeTeam_setShip (*list, i++, MELEE_KOHR_AH);
list->ShipList[i++] = MELEE_KOHR_AH; MeleeTeam_setShip (*list, i++, MELEE_MELNORME);
list->ShipList[i++] = MELEE_MELNORME; MeleeTeam_setShip (*list, i++, MELEE_MYCON);
list->ShipList[i++] = MELEE_MYCON; MeleeTeam_setShip (*list, i++, MELEE_ORZ);
list->ShipList[i++] = MELEE_ORZ; MeleeTeam_setShip (*list, i++, MELEE_PKUNK);
list->ShipList[i++] = MELEE_PKUNK; MeleeTeam_setShip (*list, i++, MELEE_SPATHI);
list->ShipList[i++] = MELEE_SPATHI; MeleeTeam_setShip (*list, i++, MELEE_SUPOX);
list->ShipList[i++] = MELEE_SUPOX; MeleeTeam_setShip (*list, i++, MELEE_URQUAN);
list->ShipList[i++] = MELEE_URQUAN; MeleeTeam_setShip (*list, i++, MELEE_YEHAT);
list->ShipList[i++] = MELEE_YEHAT;
list++; list++;
} }
{ {
FleetShipIndex i = 0; FleetShipIndex i = 0;
utf8StringCopy (list->TeamName, sizeof (list->TeamName), MeleeTeam_setName (*list, "Little Dudes with Attitudes");
"Little Dudes with Attitudes"); MeleeTeam_setShip (*list, i++, MELEE_UMGAH);
list->ShipList[i++] = MELEE_UMGAH; MeleeTeam_setShip (*list, i++, MELEE_THRADDASH);
list->ShipList[i++] = MELEE_THRADDASH; MeleeTeam_setShip (*list, i++, MELEE_SHOFIXTI);
list->ShipList[i++] = MELEE_SHOFIXTI; MeleeTeam_setShip (*list, i++, MELEE_EARTHLING);
list->ShipList[i++] = MELEE_EARTHLING; MeleeTeam_setShip (*list, i++, MELEE_VUX);
list->ShipList[i++] = MELEE_VUX; MeleeTeam_setShip (*list, i++, MELEE_ZOQFOTPIK);
list->ShipList[i++] = MELEE_ZOQFOTPIK;
list++; list++;
} }
{ {
FleetShipIndex i = 0; FleetShipIndex i = 0;
utf8StringCopy (list->TeamName, sizeof (list->TeamName), MeleeTeam_setName (*list, "New Alliance Ships");
"New Alliance Ships"); MeleeTeam_setShip (*list, i++, MELEE_ARILOU);
list->ShipList[i++] = MELEE_ARILOU; MeleeTeam_setShip (*list, i++, MELEE_CHMMR);
list->ShipList[i++] = MELEE_CHMMR; MeleeTeam_setShip (*list, i++, MELEE_EARTHLING);
list->ShipList[i++] = MELEE_EARTHLING; MeleeTeam_setShip (*list, i++, MELEE_ORZ);
list->ShipList[i++] = MELEE_ORZ; MeleeTeam_setShip (*list, i++, MELEE_PKUNK);
list->ShipList[i++] = MELEE_PKUNK; MeleeTeam_setShip (*list, i++, MELEE_SHOFIXTI);
list->ShipList[i++] = MELEE_SHOFIXTI; MeleeTeam_setShip (*list, i++, MELEE_SUPOX);
list->ShipList[i++] = MELEE_SUPOX; MeleeTeam_setShip (*list, i++, MELEE_SYREEN);
list->ShipList[i++] = MELEE_SYREEN; MeleeTeam_setShip (*list, i++, MELEE_UTWIG);
list->ShipList[i++] = MELEE_UTWIG; MeleeTeam_setShip (*list, i++, MELEE_ZOQFOTPIK);
list->ShipList[i++] = MELEE_ZOQFOTPIK; MeleeTeam_setShip (*list, i++, MELEE_YEHAT);
list->ShipList[i++] = MELEE_YEHAT; MeleeTeam_setShip (*list, i++, MELEE_DRUUGE);
list->ShipList[i++] = MELEE_DRUUGE; MeleeTeam_setShip (*list, i++, MELEE_THRADDASH);
list->ShipList[i++] = MELEE_THRADDASH; MeleeTeam_setShip (*list, i++, MELEE_SPATHI);
list->ShipList[i++] = MELEE_SPATHI;
list++; list++;
} }
{ {
FleetShipIndex i = 0; FleetShipIndex i = 0;
utf8StringCopy (list->TeamName, sizeof (list->TeamName), MeleeTeam_setName (*list, "Old Alliance Ships");
"Old Alliance Ships"); MeleeTeam_setShip (*list, i++, MELEE_ARILOU);
list->ShipList[i++] = MELEE_ARILOU; MeleeTeam_setShip (*list, i++, MELEE_CHENJESU);
list->ShipList[i++] = MELEE_CHENJESU; MeleeTeam_setShip (*list, i++, MELEE_EARTHLING);
list->ShipList[i++] = MELEE_EARTHLING; MeleeTeam_setShip (*list, i++, MELEE_MMRNMHRM);
list->ShipList[i++] = MELEE_MMRNMHRM; MeleeTeam_setShip (*list, i++, MELEE_SHOFIXTI);
list->ShipList[i++] = MELEE_SHOFIXTI; MeleeTeam_setShip (*list, i++, MELEE_SYREEN);
list->ShipList[i++] = MELEE_SYREEN; MeleeTeam_setShip (*list, i++, MELEE_YEHAT);
list->ShipList[i++] = MELEE_YEHAT;
list++; list++;
} }
{ {
FleetShipIndex i = 0; FleetShipIndex i = 0;
utf8StringCopy (list->TeamName, sizeof (list->TeamName), MeleeTeam_setName (*list, "Old Hierarchy Ships");
"Old Hierarchy Ships"); MeleeTeam_setShip (*list, i++, MELEE_ANDROSYNTH);
list->ShipList[i++] = MELEE_ANDROSYNTH; MeleeTeam_setShip (*list, i++, MELEE_ILWRATH);
list->ShipList[i++] = MELEE_ILWRATH; MeleeTeam_setShip (*list, i++, MELEE_MYCON);
list->ShipList[i++] = MELEE_MYCON; MeleeTeam_setShip (*list, i++, MELEE_SPATHI);
list->ShipList[i++] = MELEE_SPATHI; MeleeTeam_setShip (*list, i++, MELEE_UMGAH);
list->ShipList[i++] = MELEE_UMGAH; MeleeTeam_setShip (*list, i++, MELEE_URQUAN);
list->ShipList[i++] = MELEE_URQUAN; MeleeTeam_setShip (*list, i++, MELEE_VUX);
list->ShipList[i++] = MELEE_VUX;
list++; list++;
} }
{ {
FleetShipIndex i = 0; FleetShipIndex i = 0;
utf8StringCopy (list->TeamName, sizeof (list->TeamName), MeleeTeam_setName (*list, "Star Control 1");
"Star Control 1"); MeleeTeam_setShip (*list, i++, MELEE_ANDROSYNTH);
list->ShipList[i++] = MELEE_ANDROSYNTH; MeleeTeam_setShip (*list, i++, MELEE_ARILOU);
list->ShipList[i++] = MELEE_ARILOU; MeleeTeam_setShip (*list, i++, MELEE_CHENJESU);
list->ShipList[i++] = MELEE_CHENJESU; MeleeTeam_setShip (*list, i++, MELEE_EARTHLING);
list->ShipList[i++] = MELEE_EARTHLING; MeleeTeam_setShip (*list, i++, MELEE_ILWRATH);
list->ShipList[i++] = MELEE_ILWRATH; MeleeTeam_setShip (*list, i++, MELEE_MMRNMHRM);
list->ShipList[i++] = MELEE_MMRNMHRM; MeleeTeam_setShip (*list, i++, MELEE_MYCON);
list->ShipList[i++] = MELEE_MYCON; MeleeTeam_setShip (*list, i++, MELEE_SHOFIXTI);
list->ShipList[i++] = MELEE_SHOFIXTI; MeleeTeam_setShip (*list, i++, MELEE_SPATHI);
list->ShipList[i++] = MELEE_SPATHI; MeleeTeam_setShip (*list, i++, MELEE_SYREEN);
list->ShipList[i++] = MELEE_SYREEN; MeleeTeam_setShip (*list, i++, MELEE_UMGAH);
list->ShipList[i++] = MELEE_UMGAH; MeleeTeam_setShip (*list, i++, MELEE_URQUAN);
list->ShipList[i++] = MELEE_URQUAN; MeleeTeam_setShip (*list, i++, MELEE_VUX);
list->ShipList[i++] = MELEE_VUX; MeleeTeam_setShip (*list, i++, MELEE_YEHAT);
list->ShipList[i++] = MELEE_YEHAT;
list++; list++;
} }
{ {
FleetShipIndex i = 0; FleetShipIndex i = 0;
utf8StringCopy (list->TeamName, sizeof (list->TeamName), MeleeTeam_setName (*list, "Star Control 2");
"Star Control 2"); MeleeTeam_setShip (*list, i++, MELEE_CHMMR);
list->ShipList[i++] = MELEE_CHMMR; MeleeTeam_setShip (*list, i++, MELEE_DRUUGE);
list->ShipList[i++] = MELEE_DRUUGE; MeleeTeam_setShip (*list, i++, MELEE_KOHR_AH);
list->ShipList[i++] = MELEE_KOHR_AH; MeleeTeam_setShip (*list, i++, MELEE_MELNORME);
list->ShipList[i++] = MELEE_MELNORME; MeleeTeam_setShip (*list, i++, MELEE_ORZ);
list->ShipList[i++] = MELEE_ORZ; MeleeTeam_setShip (*list, i++, MELEE_PKUNK);
list->ShipList[i++] = MELEE_PKUNK; MeleeTeam_setShip (*list, i++, MELEE_SLYLANDRO);
list->ShipList[i++] = MELEE_SLYLANDRO; MeleeTeam_setShip (*list, i++, MELEE_SUPOX);
list->ShipList[i++] = MELEE_SUPOX; MeleeTeam_setShip (*list, i++, MELEE_THRADDASH);
list->ShipList[i++] = MELEE_THRADDASH; MeleeTeam_setShip (*list, i++, MELEE_UTWIG);
list->ShipList[i++] = MELEE_UTWIG; MeleeTeam_setShip (*list, i++, MELEE_ZOQFOTPIK);
list->ShipList[i++] = MELEE_ZOQFOTPIK; MeleeTeam_setShip (*list, i++, MELEE_ZOQFOTPIK);
list->ShipList[i++] = MELEE_ZOQFOTPIK; MeleeTeam_setShip (*list, i++, MELEE_ZOQFOTPIK);
list->ShipList[i++] = MELEE_ZOQFOTPIK; MeleeTeam_setShip (*list, i++, MELEE_ZOQFOTPIK);
list->ShipList[i++] = MELEE_ZOQFOTPIK;
list++; list++;
} }
@@ -844,21 +785,47 @@ InitPreBuilt (MELEE_STATE *pMS)
} }
static void static void
UninitPreBuilt (MELEE_STATE *pMS) { UninitPreBuilt (MELEE_STATE *pMS)
{
size_t fleetI;
for (fleetI = 0; fleetI < pMS->load.preBuiltCount; fleetI++)
MeleeTeam_delete (pMS->load.preBuiltList[fleetI]);
HFree (pMS->load.preBuiltList); HFree (pMS->load.preBuiltList);
pMS->load.preBuiltCount = 0; pMS->load.preBuiltCount = 0;
} }
static void
InitLoadView (MELEE_STATE *pMS)
{
size_t viewI;
MeleeTeam **view = pMS->load.view;
for (viewI = 0; viewI < LOAD_TEAM_VIEW_SIZE; viewI++)
view[viewI] = MeleeTeam_new ();
}
static void
UninitLoadView (MELEE_STATE *pMS)
{
size_t viewI;
MeleeTeam **view = pMS->load.view;
for (viewI = 0; viewI < LOAD_TEAM_VIEW_SIZE; viewI++)
MeleeTeam_delete(view[viewI]);
}
void void
InitMeleeLoadState (MELEE_STATE *pMS) InitMeleeLoadState (MELEE_STATE *pMS)
{ {
pMS->load.entryIndices = NULL; pMS->load.entryIndices = NULL;
InitPreBuilt (pMS); InitPreBuilt (pMS);
InitLoadView (pMS);
} }
void void
UninitMeleeLoadState (MELEE_STATE *pMS) UninitMeleeLoadState (MELEE_STATE *pMS)
{ {
UninitLoadView (pMS);
UninitPreBuilt (pMS); UninitPreBuilt (pMS);
if (pMS->load.entryIndices != NULL) if (pMS->load.entryIndices != NULL)
HFree (pMS->load.entryIndices); HFree (pMS->load.entryIndices);
+5 -4
View File
@@ -24,17 +24,18 @@
struct melee_load_state; struct melee_load_state;
#include "melee.h" #include "melee.h"
#include "meleesetup.h"
struct melee_load_state struct melee_load_state
{ {
TEAM_IMAGE *preBuiltList; MeleeTeam **preBuiltList;
COUNT preBuiltCount; COUNT preBuiltCount;
DIRENTRY dirEntries; DIRENTRY dirEntries;
COUNT *entryIndices; COUNT *entryIndices;
COUNT numIndices; COUNT numIndices;
TEAM_IMAGE view[LOAD_TEAM_VIEW_SIZE]; MeleeTeam *view[LOAD_TEAM_VIEW_SIZE];
COUNT top; COUNT top;
// Index of the first entry for the view. // Index of the first entry for the view.
COUNT bot; COUNT bot;
@@ -51,8 +52,8 @@ void UninitMeleeLoadState (MELEE_STATE *pMS);
BOOLEAN DoLoadTeam (MELEE_STATE *pMS); BOOLEAN DoLoadTeam (MELEE_STATE *pMS);
BOOLEAN DoSaveTeam (MELEE_STATE *pMS); BOOLEAN DoSaveTeam (MELEE_STATE *pMS);
bool ReadTeamImage (TEAM_IMAGE *pTI, uio_Stream *load_fp); bool ReadTeamImage (MeleeTeam *pTI, uio_Stream *load_fp);
int WriteTeamImage (TEAM_IMAGE *pTI, uio_Stream *save_fp); int WriteTeamImage (const MeleeTeam *pTI, uio_Stream *save_fp);
void LoadTeamList (MELEE_STATE *pMS); void LoadTeamList (MELEE_STATE *pMS);
#endif /* _LOADMELE_H */ #endif /* _LOADMELE_H */
File diff suppressed because it is too large Load Diff
+36 -58
View File
@@ -30,39 +30,6 @@
typedef struct melee_state MELEE_STATE; typedef struct melee_state MELEE_STATE;
enum
{
MELEE_ANDROSYNTH,
MELEE_ARILOU,
MELEE_CHENJESU,
MELEE_CHMMR,
MELEE_DRUUGE,
MELEE_EARTHLING,
MELEE_ILWRATH,
MELEE_KOHR_AH,
MELEE_MELNORME,
MELEE_MMRNMHRM,
MELEE_MYCON,
MELEE_ORZ,
MELEE_PKUNK,
MELEE_SHOFIXTI,
MELEE_SLYLANDRO,
MELEE_SPATHI,
MELEE_SUPOX,
MELEE_SYREEN,
MELEE_THRADDASH,
MELEE_UMGAH,
MELEE_URQUAN,
MELEE_UTWIG,
MELEE_VUX,
MELEE_YEHAT,
MELEE_ZOQFOTPIK,
NUM_MELEE_SHIPS,
MELEE_NONE = (BYTE) ~0
};
#define NUM_MELEE_ROWS 2 #define NUM_MELEE_ROWS 2
#define NUM_MELEE_COLUMNS 7 #define NUM_MELEE_COLUMNS 7
//#define NUM_MELEE_COLUMNS 6 //#define NUM_MELEE_COLUMNS 6
@@ -82,23 +49,10 @@ extern FRAME PickMeleeFrame;
#define NUM_PICK_ROWS 5 #define NUM_PICK_ROWS 5
typedef BYTE MELEE_OPTIONS; typedef BYTE MELEE_OPTIONS;
typedef COUNT FleetShipIndex;
typedef struct
{
BYTE ShipList[MELEE_FLEET_SIZE];
UNICODE TeamName[MAX_TEAM_CHARS + 1 + 24];
/* The +1 is for the terminating \0; the +24 is in case some
* default name in starcon.txt is unknowingly mangled. */
} TEAM_IMAGE;
#include "loadmele.h" #include "loadmele.h"
#include "meleesetup.h"
struct melee_side_state #include "meleeship.h"
{
TEAM_IMAGE TeamImage;
COUNT star_bucks;
};
struct melee_state struct melee_state
{ {
@@ -106,10 +60,24 @@ struct melee_state
BOOLEAN Initialized; BOOLEAN Initialized;
MELEE_OPTIONS MeleeOption; MELEE_OPTIONS MeleeOption;
COUNT side, row, col; COUNT side;
struct melee_side_state SideState[NUM_SIDES]; COUNT row;
COUNT col;
MeleeSetup *meleeSetup;
struct melee_load_state load; struct melee_load_state load;
MeleeShip currentShip;
// The ship currently displayed. Not really needed.
// Also the current ship position when selecting a ship.
COUNT CurIndex; COUNT CurIndex;
#define MELEE_STATE_INDEX_DONE ((COUNT) -1)
// Current position in the team string when editing it.
// Set to MELEE_STATE_INDEX_DONE when done.
BOOLEAN buildPickConfirmed;
// Used by DoPickShip () to communicate to the calling
// function BuildPickShip() whether a ship has been selected
// to add to the fleet, or whether the operation has been
// cancelled. If a ship was selected, it is set in
// currentShip.
RandomContext *randomContext; RandomContext *randomContext;
/* RNG state for all local random decisions, i.e. those /* RNG state for all local random decisions, i.e. those
* decisions that are not shared among network parties. */ * decisions that are not shared among network parties. */
@@ -123,17 +91,14 @@ extern void Melee (void);
// Some prototypes for use by loadmele.c: // Some prototypes for use by loadmele.c:
BOOLEAN DoMelee (MELEE_STATE *pMS); BOOLEAN DoMelee (MELEE_STATE *pMS);
void DrawMeleeIcon (COUNT which_icon); void DrawMeleeIcon (COUNT which_icon);
COUNT GetTeamValue (TEAM_IMAGE *pTI); void GetShipBox (RECT *pRect, COUNT side, COUNT row, COUNT col);
void RepairMeleeFrame (RECT *pRect); void RepairMeleeFrame (const RECT *pRect);
void DrawMeleeShipStrings (MELEE_STATE *pMS, MeleeShip NewStarShip);
extern FRAME MeleeFrame; extern FRAME MeleeFrame;
void Melee_flashSelection (MELEE_STATE *pMS);
void teamStringChanged (MELEE_STATE *pMS, int player); COUNT GetShipValue (MeleeShip StarShip);
void entireFleetChanged (MELEE_STATE *pMS, int player);
void fleetShipChanged (MELEE_STATE *pMS, int player, size_t index);
void updateTeamName (MELEE_STATE *pMS, COUNT side, const char *name,
size_t len);
bool updateFleetShip (MELEE_STATE *pMS, COUNT side, COUNT index, BYTE ship);
void updateRandomSeed (MELEE_STATE *pMS, COUNT side, DWORD seed); void updateRandomSeed (MELEE_STATE *pMS, COUNT side, DWORD seed);
void confirmationCancelled(MELEE_STATE *pMS, COUNT side); void confirmationCancelled(MELEE_STATE *pMS, COUNT side);
void connectedFeedback (NetConnection *conn); void connectedFeedback (NetConnection *conn);
@@ -143,5 +108,18 @@ void resetFeedback (NetConnection *conn, NetplayResetReason reason,
void errorFeedback (NetConnection *conn); void errorFeedback (NetConnection *conn);
void closeFeedback (NetConnection *conn); void closeFeedback (NetConnection *conn);
bool Melee_Change_ship (MELEE_STATE *pMS, COUNT side, FleetShipIndex index,
MeleeShip ship);
bool Melee_Change_teamName (MELEE_STATE *pMS, COUNT side, const char *name);
bool Melee_Change_fleet (MELEE_STATE *pMS, size_t teamNr,
const MeleeShip *fleet);
bool Melee_Change_team (MELEE_STATE *pMS, size_t teamNr,
const MeleeTeam *team);
void Melee_RemoteChange_ship (MELEE_STATE *pMS, NetConnection *conn,
COUNT side, FleetShipIndex index, MeleeShip ship);
void Melee_RemoteChange_teamName (MELEE_STATE *pMS, NetConnection *conn,
COUNT side, const char *name);
#endif /* _MELEE_H */ #endif /* _MELEE_H */
+325
View File
@@ -0,0 +1,325 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#define MELEESETUP_INTERNAL
#include "port.h"
#include "meleesetup.h"
#include "../master.h"
#include "libs/log.h"
///////////////////////////////////////////////////////////////////////////
// Temporary
const size_t MeleeTeam_size = sizeof (MeleeTeam);
void
MeleeTeam_init (MeleeTeam *team)
{
FleetShipIndex slotI;
for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++)
team->ships[slotI] = MELEE_NONE;
}
void
MeleeTeam_uninit (MeleeTeam *team)
{
(void) team;
}
MeleeTeam *
MeleeTeam_new (void)
{
MeleeTeam *result = HMalloc (sizeof (MeleeTeam));
MeleeTeam_init (result);
return result;
}
void
MeleeTeam_delete (MeleeTeam *team)
{
MeleeTeam_uninit (team);
HFree (team);
}
int
MeleeTeam_serialize (const MeleeTeam *team, uio_Stream *stream)
{
FleetShipIndex slotI;
for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++) {
if (uio_putc ((int) team->ships[slotI], stream) == EOF)
return -1;
}
if (uio_fwrite ((char *) team->name, sizeof team->name, 1, stream) != 1)
return -1;
return 0;
}
int
MeleeTeam_deserialize (MeleeTeam *team, uio_Stream *stream)
{
FleetShipIndex slotI;
// Sanity check on the ships.
for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++)
{
int ship = uio_getc (stream);
if (ship == EOF)
goto err;
team->ships[slotI] = (MeleeShip) ship;
if (team->ships[slotI] == MELEE_NONE)
continue;
if (team->ships[slotI] >= NUM_MELEE_SHIPS)
{
log_add (log_Warning, "Invalid ship type in loaded team (index "
"%d, ship type is %d, max valid is %d).",
slotI, team->ships[slotI], NUM_MELEE_SHIPS - 1);
team->ships[slotI] = MELEE_NONE;
}
}
if (uio_fread (team->name, sizeof team->name, 1, stream) != 1)
goto err;
team->name[MAX_TEAM_CHARS] = '\0';
return 0;
err:
MeleeTeam_delete(team);
return -1;
}
// XXX: move this to elsewhere?
COUNT
MeleeTeam_getValue (const MeleeTeam *team)
{
COUNT total = 0;
FleetShipIndex slotI;
for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++)
{
MeleeShip ship = team->ships[slotI];
COUNT shipValue = GetShipValue (ship);
if (shipValue == (COUNT)~0)
{
// Invalid ship.
continue;
}
total += shipValue;
}
return total;
}
MeleeShip
MeleeTeam_getShip (const MeleeTeam *team, FleetShipIndex slotNr)
{
return team->ships[slotNr];
}
void
MeleeTeam_setShip (MeleeTeam *team, FleetShipIndex slotNr, MeleeShip ship)
{
team->ships[slotNr] = ship;
}
const MeleeShip *
MeleeTeam_getFleet (const MeleeTeam *team)
{
return team->ships;
}
const char *
MeleeTeam_getTeamName (const MeleeTeam *team)
{
return team->name;
}
// Returns true iff the state has actually changed.
void
MeleeTeam_setName (MeleeTeam *team, const UNICODE *name)
{
strncpy (team->name, name, sizeof team->name - 1);
team->name[sizeof team->name - 1] = '\0';
}
void
MeleeTeam_copy (MeleeTeam *copy, const MeleeTeam *original)
{
*copy = *original;
}
///////////////////////////////////////////////////////////////////////////
MeleeSetup *
MeleeSetup_new (void)
{
size_t teamI;
MeleeSetup *result = HMalloc (sizeof (MeleeSetup));
if (result == NULL)
return NULL;
for (teamI = 0; teamI < NUM_SIDES; teamI++)
{
MeleeTeam_init (&result->teams[teamI]);
result->fleetValue[teamI] = 0;
#ifdef NETPLAY
MeleeTeam_init (&result->confirmedTeams[teamI]);
#endif /* NETPLAY */
}
return result;
}
void
MeleeSetup_delete (MeleeSetup *setup)
{
HFree (setup);
}
// Returns true iff the state has actually changed.
bool
MeleeSetup_setShip (MeleeSetup *setup, size_t teamNr, FleetShipIndex slotNr,
MeleeShip ship)
{
MeleeTeam *team = &setup->teams[teamNr];
MeleeShip oldShip = MeleeTeam_getShip (team, slotNr);
if (ship == oldShip)
return false;
if (oldShip != MELEE_NONE)
setup->fleetValue[teamNr] -= GetShipCostFromIndex (oldShip);
MeleeTeam_setShip (team, slotNr, ship);
if (ship != MELEE_NONE)
setup->fleetValue[teamNr] += GetShipCostFromIndex (ship);
return true;
}
MeleeShip
MeleeSetup_getShip (const MeleeSetup *setup, size_t teamNr,
FleetShipIndex slotNr)
{
return MeleeTeam_getShip (&setup->teams[teamNr], slotNr);
}
const MeleeShip *
MeleeSetup_getFleet (const MeleeSetup *setup, size_t teamNr)
{
return MeleeTeam_getFleet (&setup->teams[teamNr]);
}
// Returns true iff the state has actually changed.
bool
MeleeSetup_setTeamName (MeleeSetup *setup, size_t teamNr,
const UNICODE *name)
{
MeleeTeam *team = &setup->teams[teamNr];
const UNICODE *oldName = MeleeTeam_getTeamName (team);
if (strcmp (oldName, name) == 0)
return false;
MeleeTeam_setName (team, name);
return true;
}
const char *
MeleeSetup_getTeamName (const MeleeSetup *setup, size_t teamNr)
{
return MeleeTeam_getTeamName (&setup->teams[teamNr]);
}
COUNT
MeleeSetup_getFleetValue (const MeleeSetup *setup, size_t teamNr)
{
return setup->fleetValue[teamNr];
}
int
MeleeSetup_deserializeTeam (MeleeSetup *setup, size_t teamNr,
uio_Stream *stream)
{
MeleeTeam *team = &setup->teams[teamNr];
return MeleeTeam_deserialize (team, stream);
}
int
MeleeSetup_serializeTeam (const MeleeSetup *setup, size_t teamNr,
uio_Stream *stream)
{
const MeleeTeam *team = &setup->teams[teamNr];
return MeleeTeam_serialize (team, stream);
}
#ifdef NETPLAY
MeleeShip
MeleeSetup_getConfirmedShip (const MeleeSetup *setup, size_t teamNr,
FleetShipIndex slotNr)
{
return MeleeTeam_getShip (&setup->confirmedTeams[teamNr], slotNr);
}
const char *
MeleeSetup_getConfirmedTeamName (const MeleeSetup *setup, size_t teamNr)
{
return MeleeTeam_getTeamName (&setup->confirmedTeams[teamNr]);
}
// Returns true iff the state has actually changed.
bool
MeleeSetup_setConfirmedShip (MeleeSetup *setup, size_t teamNr,
FleetShipIndex slotNr, MeleeShip ship)
{
MeleeTeam *team = &setup->confirmedTeams[teamNr];
MeleeShip oldShip = MeleeTeam_getShip (team, slotNr);
if (ship == oldShip)
return false;
MeleeTeam_setShip (team, slotNr, ship);
return true;
}
// Returns true iff the state has actually changed.
bool
MeleeSetup_setConfirmedTeamName (MeleeSetup *setup, size_t teamNr,
const UNICODE *name)
{
MeleeTeam *team = &setup->confirmedTeams[teamNr];
const UNICODE *oldName = MeleeTeam_getTeamName (team);
if (strcmp (oldName, name) == 0)
return false;
MeleeTeam_setName (team, name);
return true;
}
#endif /* NETPLAY */
///////////////////////////////////////////////////////////////////////////
+144
View File
@@ -0,0 +1,144 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef MELEESETUP_H
#define MELEESETUP_H
typedef struct MeleeTeam MeleeTeam;
typedef struct MeleeSetup MeleeSetup;
#ifdef MELEESETUP_INTERNAL
# define MELEETEAM_INTERNAL
#endif /* MELEESETUP_INTERNAL */
#include "libs/compiler.h"
typedef COUNT FleetShipIndex;
#include "libs/uio.h"
#include "melee.h"
#include "meleeship.h"
#ifdef MELEETEAM_INTERNAL
struct MeleeTeam
{
MeleeShip ships[MELEE_FLEET_SIZE];
UNICODE name[MAX_TEAM_CHARS + 1 + 24];
/* The +1 is for the terminating \0; the +24 is in case some
* default name in starcon.txt is unknowingly mangled. */
};
#endif /* MELEETEAM_INTERNAL */
#ifdef MELEESETUP_INTERNAL
// When Netplay is enabled, we keep two copies of the teams: the team as we
// consider it to be locally, and last confirmed team.
// There are no separate change and confirmation messages; a confirmation
// message is a message reporting a change to the value which was specified
// by the remote side.
// When a local change is made, the current team is updated, and a message
// is sent to the other side.
// When we receive a message of a remote update:
// - if the current value is the same as the received value, we change
// the confirmed value to the current/received value
// - if the current value is different from the received value, and
// the current value is the same as the confirmed value, we change both
// the current value and the confirmed value to the received value,
// and sent a message to the remote side of our modification.
// - if the current value is different from the received value, and
// the current value is not the same as the confirmed value, our
// action depends on who "owns" the value:
// - if the change is to the remote fleet, we change the current and
// confirmed value to the received value, and send a message to the
// remote side of our modification (as above)
// - if the change is to the local fleet, we take no action.
// (In this situation, a local change has been made, and a message of
// this has already been sent to the other side, and a confirmation
// from the other side will arrive eventually.)
// XXX: put this in docs/netplay/protocols.
// XXX: this not only works for teams, but also for other properties.
struct MeleeSetup
{
MeleeTeam teams[NUM_SIDES];
COUNT fleetValue[NUM_SIDES];
#ifdef NETPLAY
MeleeTeam confirmedTeams[NUM_SIDES];
// The least team which both sides agreed upon.
// XXX: this may actually be deallocated when the battle starts.
#endif
};
#endif /* MELEESETUP_INTERNAL */
extern const size_t MeleeTeam_size;
void MeleeTeam_init (MeleeTeam *team);
void MeleeTeam_uninit (MeleeTeam *team);
MeleeTeam *MeleeTeam_new (void);
void MeleeTeam_delete (MeleeTeam *team);
int MeleeTeam_serialize (const MeleeTeam *team, uio_Stream *stream);
int MeleeTeam_deserialize (MeleeTeam *team, uio_Stream *stream);
COUNT MeleeTeam_getValue (const MeleeTeam *team);
MeleeShip MeleeTeam_getShip (const MeleeTeam *team, FleetShipIndex slotNr);
void MeleeTeam_setShip (MeleeTeam *team, FleetShipIndex slotNr,
MeleeShip ship);
const MeleeShip *MeleeTeam_getFleet (const MeleeTeam *team);
const char *MeleeTeam_getTeamName (const MeleeTeam *team);
void MeleeTeam_setName (MeleeTeam *team, const UNICODE *name);
void MeleeTeam_copy (MeleeTeam *copy, const MeleeTeam *original);
#ifdef NETPLAY
MeleeShip MeleeSetup_getConfirmedShip (const MeleeSetup *setup, size_t teamNr,
FleetShipIndex slotNr);
const char *MeleeSetup_getConfirmedTeamName (const MeleeSetup *setup,
size_t teamNr);
bool MeleeSetup_setConfirmedShip (MeleeSetup *setup, size_t teamNr,
FleetShipIndex slotNr, MeleeShip ship);
bool MeleeSetup_setConfirmedTeamName (MeleeSetup *setup, size_t teamNr,
const UNICODE *name);
#endif /* NETPLAY */
MeleeSetup *MeleeSetup_new (void);
void MeleeSetup_delete (MeleeSetup *setup);
bool MeleeSetup_setShip (MeleeSetup *setup, size_t teamNr,
FleetShipIndex slotNr, MeleeShip ship);
MeleeShip MeleeSetup_getShip (const MeleeSetup *setup, size_t teamNr,
FleetShipIndex slotNr);
bool MeleeSetup_setFleet (MeleeSetup *setup, size_t teamNr,
const MeleeShip *fleet);
const MeleeShip *MeleeSetup_getFleet (const MeleeSetup *setup, size_t teamNr);
bool MeleeSetup_setTeamName (MeleeSetup *setup, size_t teamNr,
const UNICODE *name);
const char *MeleeSetup_getTeamName (const MeleeSetup *setup,
size_t teamNr);
COUNT MeleeSetup_getFleetValue (const MeleeSetup *setup, size_t teamNr);
int MeleeSetup_deserializeTeam (MeleeSetup *setup, size_t teamNr,
uio_Stream *stream);
int MeleeSetup_serializeTeam (const MeleeSetup *setup, size_t teamNr,
uio_Stream *stream);
void MeleeState_setShip (MELEE_STATE *pMS, size_t teamNr,
FleetShipIndex slotNr, MeleeShip ship);
void MeleeState_setFleet (MELEE_STATE *pMS, size_t teamNr,
const MeleeShip *fleet);
void MeleeState_setTeamName (MELEE_STATE *pMS, size_t teamNr,
const UNICODE *name);
void MeleeState_setTeam (MELEE_STATE *pMS, size_t teamNr,
const MeleeTeam *team);
#endif /* MELEESETUP_H */
+44
View File
@@ -0,0 +1,44 @@
#ifndef MELEESHIP_H
#define MELEESHIP_H
#include <stdbool.h>
typedef enum MeleeShip {
MELEE_ANDROSYNTH,
MELEE_ARILOU,
MELEE_CHENJESU,
MELEE_CHMMR,
MELEE_DRUUGE,
MELEE_EARTHLING,
MELEE_ILWRATH,
MELEE_KOHR_AH,
MELEE_MELNORME,
MELEE_MMRNMHRM,
MELEE_MYCON,
MELEE_ORZ,
MELEE_PKUNK,
MELEE_SHOFIXTI,
MELEE_SLYLANDRO,
MELEE_SPATHI,
MELEE_SUPOX,
MELEE_SYREEN,
MELEE_THRADDASH,
MELEE_UMGAH,
MELEE_URQUAN,
MELEE_UTWIG,
MELEE_VUX,
MELEE_YEHAT,
MELEE_ZOQFOTPIK,
MELEE_NONE = (BYTE) ~0
} MeleeShip;
#define NUM_MELEE_SHIPS (MELEE_ZOQFOTPIK + 1)
static inline bool
MeleeShip_valid (MeleeShip ship)
{
return (ship < NUM_MELEE_SHIPS) || (ship == MELEE_NONE);
}
#endif /* MELEESHIP_H */
+208 -17
View File
@@ -20,10 +20,14 @@
#include "pickmele.h" #include "pickmele.h"
#include "../battlecontrols.h" #include "../battlecontrols.h"
#include "../battle.h"
#include "../build.h"
#include "../controls.h" #include "../controls.h"
#include "../flash.h" #include "../flash.h"
#include "../igfxres.h"
#include "../intel.h" #include "../intel.h"
#include "../battle.h" #include "../master.h"
#include "../nameref.h"
#include "melee.h" #include "melee.h"
#ifdef NETPLAY #ifdef NETPLAY
# include "../netplay/netmelee.h" # include "../netplay/netmelee.h"
@@ -37,15 +41,49 @@
#include "libs/mathlib.h" #include "libs/mathlib.h"
#define NUM_MELEE_COLS_ORIG NUM_MELEE_COLUMNS #define NUM_PICKMELEE_ROWS 2
#define NUM_PICKMELEE_COLUMNS 7
#define PICK_X_OFFS 57 #define PICK_X_OFFS 57
#define PICK_Y_OFFS 24 #define PICK_Y_OFFS 24
#define PICK_SIDE_OFFS 100 #define PICK_SIDE_OFFS 100
#define NAME_AREA_HEIGHT 7
#define MELEE_WIDTH 149
#define MELEE_HEIGHT (48 + NAME_AREA_HEIGHT)
#define PICKSHIP_TEAM_NAME_TEXT_COLOR \
BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)
#define PICKSHIP_TEAM_START_VALUE_COLOR \
BUILD_COLOR (MAKE_RGB15 (0x04, 0x05, 0x1F), 0x4B)
#ifdef NETPLAY #ifdef NETPLAY
static void reportShipSelected (GETMELEE_STATE *gms, COUNT index); static void reportShipSelected (GETMELEE_STATE *gms, COUNT index);
#endif #endif
FRAME PickMeleeFrame;
static FleetShipIndex
PickMelee_GetShipIndex (BYTE row, BYTE col)
{
return row * NUM_PICKMELEE_COLUMNS + col;
}
static BYTE
PickMelee_GetShipRow (FleetShipIndex index)
{
return index / NUM_PICKMELEE_COLUMNS;
}
static BYTE
PickMelee_GetShipColumn (int index)
{
return index % NUM_PICKMELEE_COLUMNS;
}
// Returns the <index>th ship in the queue, or 0 if it is not available. // Returns the <index>th ship in the queue, or 0 if it is not available.
static HSTARSHIP static HSTARSHIP
MeleeShipByQueueIndex (const QUEUE *queue, COUNT index) MeleeShipByQueueIndex (const QUEUE *queue, COUNT index)
@@ -161,13 +199,13 @@ SelectShip_processInput (GETMELEE_STATE *gms, COUNT playerI,
{ {
if (inputState & BATTLE_WEAPON) if (inputState & BATTLE_WEAPON)
{ {
if (gms->player[playerI].col == NUM_MELEE_COLS_ORIG && if (gms->player[playerI].col == NUM_PICKMELEE_COLUMNS &&
gms->player[playerI].row == 0) gms->player[playerI].row == 0)
{ {
// Random ship // Random ship
(void) setShipSelected (gms, playerI, (COUNT) ~0, TRUE); (void) setShipSelected (gms, playerI, (COUNT) ~0, TRUE);
} }
else if (gms->player[playerI].col == NUM_MELEE_COLS_ORIG && else if (gms->player[playerI].col == NUM_PICKMELEE_COLUMNS &&
gms->player[playerI].row == 1) gms->player[playerI].row == 1)
{ {
// Selected exit // Selected exit
@@ -177,10 +215,9 @@ SelectShip_processInput (GETMELEE_STATE *gms, COUNT playerI,
else else
{ {
// Selection is on a ship slot. // Selection is on a ship slot.
COUNT shipI = COUNT slotNr = PickMelee_GetShipIndex (gms->player[playerI].row,
(gms->player[playerI].row * NUM_MELEE_COLS_ORIG) gms->player[playerI].col);
+ gms->player[playerI].col; (void) setShipSelected (gms, playerI, slotNr, TRUE);
(void) setShipSelected (gms, playerI, shipI, TRUE);
// If the choice is not valid, setShipSelected() // If the choice is not valid, setShipSelected()
// will not set .done. // will not set .done.
} }
@@ -195,21 +232,21 @@ SelectShip_processInput (GETMELEE_STATE *gms, COUNT playerI,
if (inputState & BATTLE_LEFT) if (inputState & BATTLE_LEFT)
{ {
if (new_col-- == 0) if (new_col-- == 0)
new_col = NUM_MELEE_COLS_ORIG; new_col = NUM_PICKMELEE_COLUMNS;
} }
else if (inputState & BATTLE_RIGHT) else if (inputState & BATTLE_RIGHT)
{ {
if (new_col++ == NUM_MELEE_COLS_ORIG) if (new_col++ == NUM_PICKMELEE_COLUMNS)
new_col = 0; new_col = 0;
} }
if (inputState & BATTLE_THRUST) if (inputState & BATTLE_THRUST)
{ {
if (new_row-- == 0) if (new_row-- == 0)
new_row = NUM_MELEE_ROWS - 1; new_row = NUM_PICKMELEE_ROWS - 1;
} }
else if (inputState & BATTLE_DOWN) else if (inputState & BATTLE_DOWN)
{ {
if (++new_row == NUM_MELEE_ROWS) if (++new_row == NUM_PICKMELEE_ROWS)
new_row = 0; new_row = 0;
} }
@@ -384,17 +421,19 @@ GetRaceQueueValue (const QUEUE *queue) {
// 'shipI' is the index in the ship list. // 'shipI' is the index in the ship list.
// Pre: caller holds the graphics lock. // Pre: caller holds the graphics lock.
static void static void
CrossOutShip (FRAME frame, COUNT shipI) CrossOutShip (FRAME frame, COUNT shipNr)
{ {
CONTEXT OldContext; CONTEXT OldContext;
STAMP s; STAMP s;
BYTE row = PickMelee_GetShipRow (shipNr);
BYTE col = PickMelee_GetShipColumn (shipNr);
OldContext = SetContext (OffScreenContext); OldContext = SetContext (OffScreenContext);
SetContextFGFrame (frame); SetContextFGFrame (frame);
s.origin.x = 3 + ((ICON_WIDTH + 2) * (shipI % NUM_MELEE_COLS_ORIG)); s.origin.x = 3 + ((ICON_WIDTH + 2) * col);
s.origin.y = 9 + ((ICON_HEIGHT + 2) * (shipI / NUM_MELEE_COLS_ORIG)); s.origin.y = 9 + ((ICON_HEIGHT + 2) * row);
s.frame = SetAbsFrameIndex (StatusFrame, 3); s.frame = SetAbsFrameIndex (StatusFrame, 3);
// Cross for through the ship image. // Cross for through the ship image.
DrawStamp (&s); DrawStamp (&s);
@@ -442,6 +481,158 @@ UpdatePickMeleeFleetValue (FRAME frame, COUNT which_player)
SetContext (OldContext); SetContext (OldContext);
} }
// Create a frame for each player to display their current fleet in,
// to be used when selecting the next ship to fight with.
void
BuildPickMeleeFrame (void)
{
STAMP s;
CONTEXT OldContext = SetContext (OffScreenContext);
if (PickMeleeFrame)
DestroyDrawable (ReleaseDrawable (PickMeleeFrame));
PickMeleeFrame = CaptureDrawable (CreateDrawable (
WANT_PIXMAP, MELEE_WIDTH, MELEE_HEIGHT, 2));
s.origin.x = 0;
s.origin.y = 0;
s.frame = CaptureDrawable (LoadGraphic (MELEE_PICK_MASK_PMAP_ANIM));
SetContextFGFrame (PickMeleeFrame);
DrawStamp (&s);
s.frame = IncFrameIndex (s.frame);
SetContextFGFrame (IncFrameIndex (PickMeleeFrame));
DrawStamp (&s);
DestroyDrawable (ReleaseDrawable (s.frame));
SetContext (OldContext);
}
// Put the ship icons in the PickMeleeFrame, and create a queue
// for each player.
// XXX TODO: split off creating the queue into a separate function.
void
FillPickMeleeFrame (MeleeSetup *setup)
{
COUNT sideI;
CONTEXT OldContext;
OldContext = SetContext (OffScreenContext);
for (sideI = 0; sideI < NUM_SIDES; ++sideI)
{
COUNT side;
RECT r;
TEXT t;
STAMP s;
UNICODE buf[30];
FleetShipIndex index;
side = !sideI;
s.frame = SetAbsFrameIndex (PickMeleeFrame, side);
SetContextFGFrame (s.frame);
GetFrameRect (s.frame, &r);
t.baseline.x = r.extent.width >> 1;
t.baseline.y = r.extent.height - NAME_AREA_HEIGHT + 4;
r.corner.x += 2;
r.corner.y += 2;
r.extent.width -= (2 * 2) + (ICON_WIDTH + 2) + 1;
r.extent.height -= (2 * 2) + NAME_AREA_HEIGHT;
SetContextForeGroundColor (PICK_BG_COLOR);
DrawFilledRectangle (&r);
r.corner.x += 2;
r.extent.width += (ICON_WIDTH + 2) - (2 * 2);
r.corner.y += r.extent.height;
r.extent.height = NAME_AREA_HEIGHT;
DrawFilledRectangle (&r);
// Team name at the bottom of the frame:
t.align = ALIGN_CENTER;
t.pStr = MeleeSetup_getTeamName (setup, sideI);
t.CharCount = (COUNT) ~0;
SetContextFont (TinyFont);
SetContextForeGroundColor (PICKSHIP_TEAM_NAME_TEXT_COLOR);
font_DrawText (&t);
// Total team value of the starting team:
sprintf (buf, "%u", MeleeSetup_getFleetValue (setup, sideI));
t.baseline.x = 4;
t.baseline.y = 7;
t.align = ALIGN_LEFT;
t.pStr = buf;
t.CharCount = (COUNT)~0;
SetContextForeGroundColor (PICKSHIP_TEAM_START_VALUE_COLOR);
font_DrawText (&t);
assert (CountLinks (&race_q[side]) == 0);
for (index = 0; index < MELEE_FLEET_SIZE; index++)
{
MeleeShip StarShip;
StarShip = MeleeSetup_getShip (setup, sideI, index);
if (StarShip == MELEE_NONE)
continue;
{
BYTE row, col;
BYTE ship_cost;
HMASTERSHIP hMasterShip;
HSTARSHIP hBuiltShip;
MASTER_SHIP_INFO *MasterPtr;
STARSHIP *BuiltShipPtr;
BYTE captains_name_index;
hMasterShip = GetStarShipFromIndex (&master_q, StarShip);
MasterPtr = LockMasterShip (&master_q, hMasterShip);
captains_name_index = NameCaptain (&race_q[side],
MasterPtr->SpeciesID);
hBuiltShip = Build (&race_q[side], MasterPtr->SpeciesID);
// Draw the icon.
row = PickMelee_GetShipRow (index);
col = PickMelee_GetShipColumn (index);
s.origin.x = 4 + ((ICON_WIDTH + 2) * col);
s.origin.y = 10 + ((ICON_HEIGHT + 2) * row);
s.frame = MasterPtr->ShipInfo.icons;
DrawStamp (&s);
ship_cost = MasterPtr->ShipInfo.ship_cost;
UnlockMasterShip (&master_q, hMasterShip);
BuiltShipPtr = LockStarShip (&race_q[side], hBuiltShip);
BuiltShipPtr->index = index;
BuiltShipPtr->ship_cost = ship_cost;
BuiltShipPtr->playerNr = side;
BuiltShipPtr->captains_name_index = captains_name_index;
// The next ones are not used in Melee
BuiltShipPtr->crew_level = 0;
BuiltShipPtr->max_crew = 0;
BuiltShipPtr->race_strings = 0;
BuiltShipPtr->icons = 0;
BuiltShipPtr->RaceDescPtr = 0;
UnlockStarShip (&race_q[side], hBuiltShip);
}
}
}
SetContext (OldContext);
}
void
DestroyPickMeleeFrame (void)
{
DestroyDrawable (ReleaseDrawable (PickMeleeFrame));
PickMeleeFrame = 0;
}
// Pre: caller holds the graphics lock. // Pre: caller holds the graphics lock.
static void static void
DrawPickMeleeFrame (COUNT which_player) DrawPickMeleeFrame (COUNT which_player)
@@ -574,7 +765,7 @@ GetMeleeStarShips (COUNT playerMask, HSTARSHIP *ships)
gmstate.player[playerI].timeIn = now; gmstate.player[playerI].timeIn = now;
gmstate.player[playerI].row = 0; gmstate.player[playerI].row = 0;
gmstate.player[playerI].col = NUM_MELEE_COLS_ORIG; gmstate.player[playerI].col = NUM_PICKMELEE_COLUMNS;
#ifdef NETPLAY #ifdef NETPLAY
gmstate.player[playerI].remoteSelected = FALSE; gmstate.player[playerI].remoteSelected = FALSE;
#endif #endif
@@ -764,7 +955,7 @@ reportShipSelected (GETMELEE_STATE *gms, COUNT index)
if (!NetConnection_isConnected (conn)) if (!NetConnection_isConnected (conn))
continue; continue;
Netplay_selectShip (conn, index); Netplay_Notify_shipSelected (conn, index);
} }
(void) gms; (void) gms;
} }
+4
View File
@@ -21,9 +21,13 @@ typedef struct getmelee_struct GETMELEE_STATE;
#include "../races.h" #include "../races.h"
#include "../battlecontrols.h" #include "../battlecontrols.h"
#include "meleesetup.h"
#include "libs/compiler.h" #include "libs/compiler.h"
BOOLEAN MeleeShipDeath (STARSHIP *ship, COUNT which_player); BOOLEAN MeleeShipDeath (STARSHIP *ship, COUNT which_player);
void BuildPickMeleeFrame (void);
void DestroyPickMeleeFrame (void);
void FillPickMeleeFrame (MeleeSetup *setup);
void MeleeGameOver (void); void MeleeGameOver (void);
BOOLEAN GetInitialMeleeStarShips (HSTARSHIP *result); BOOLEAN GetInitialMeleeStarShips (HSTARSHIP *result);
BOOLEAN GetNextMeleeStarShip (COUNT which_player, HSTARSHIP *result); BOOLEAN GetNextMeleeStarShip (COUNT which_player, HSTARSHIP *result);
+1 -1
View File
@@ -90,7 +90,7 @@ readyToEndCallback (NetConnection *conn, void *arg)
NetConnection_setState (conn, NetState_endingBattle); NetConnection_setState (conn, NetState_endingBattle);
if (battleFrameCount + 1 > battleStateData->endFrameCount) if (battleFrameCount + 1 > battleStateData->endFrameCount)
battleStateData->endFrameCount = battleFrameCount + 1; battleStateData->endFrameCount = battleFrameCount + 1;
Netplay_sendFrameCount (conn, battleFrameCount + 1); Netplay_Notify_frameCount (conn, battleFrameCount + 1);
// The +1 is to ensure that after the remote side receives the // The +1 is to ensure that after the remote side receives the
// frame count it will still receive one more frame data packet, // frame count it will still receive one more frame data packet,
// so it will know in advance when the last frame data packet // so it will know in advance when the last frame data packet