Cyborg transports now can load/unload correctly.

git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@5838 4a71c877-e1ca-e34f-864e-861f7616d084
master
Buginator 2008-08-18 03:28:03 +00:00
parent d3881835d0
commit 807549b8e2
6 changed files with 231 additions and 134 deletions

View File

@ -2184,7 +2184,10 @@ void unloadTransporter(DROID *psTransporter, UDWORD x, UDWORD y, BOOL goingHome)
// Inform all other players // Inform all other players
if (bMultiPlayer) if (bMultiPlayer)
{ {
sendDroidDisEmbark(psDroid); // This isn't used for cyber transports, only 'normal' one, but that isn't used in MP games AFAIK?
// which is why I don't know why this is here. Maybe for mod support?
debug(LOG_ERROR,"If you see this, then notify dev team. Code: 0xDEADF00D");
sendDroidDisEmbark(psDroid,psTransporter);
} }
} }

View File

@ -219,8 +219,8 @@ BOOL recvDroidSecondaryAll()
return true; return true;
} }
// broadcast droid & transporter loading information
BOOL sendDroidEmbark(const DROID* psDroid) BOOL sendDroidEmbark(const DROID* psDroid,const DROID* psTransporter )
{ {
if (!bMultiPlayer) if (!bMultiPlayer)
return true; return true;
@ -228,51 +228,78 @@ BOOL sendDroidEmbark(const DROID* psDroid)
NETbeginEncode(NET_DROIDEMBARK, NET_ALL_PLAYERS); NETbeginEncode(NET_DROIDEMBARK, NET_ALL_PLAYERS);
{ {
uint8_t player = psDroid->player; uint8_t player = psDroid->player;
uint32_t droid = psDroid->id; uint32_t droidID = psDroid->id;
uint32_t transporterID = psTransporter->id;
NETuint8_t(&player); NETuint8_t(&player);
NETuint32_t(&droid); NETuint32_t(&droidID);
NETuint32_t(&transporterID);
} }
return NETend(); return NETend();
} }
// receive droid & transporter loading information
BOOL recvDroidEmbark() BOOL recvDroidEmbark()
{ {
DROID* psDroid; DROID *psDroid;
DROID *psTransporterDroid;
BOOL bDroidRemoved;
NETbeginDecode(NET_DROIDEMBARK); NETbeginDecode(NET_DROIDEMBARK);
{ {
uint8_t player; uint8_t player;
uint32_t droid; uint32_t droidID;
uint32_t transporterID;
NETuint8_t(&player); NETuint8_t(&player);
NETuint32_t(&droid); NETuint32_t(&droidID);
NETuint32_t(&transporterID);
if (!IdToDroid(droid, player, &psDroid)) // we have to find the droid on our (local) list first.
if (!IdToDroid(droidID, player, &psDroid))
{ {
NETend(); NETend();
// Possible it already died? (sync error?)
debug(LOG_WARNING,"player's %d droid %d wasn't found?",player,droidID);
return false; return false;
} }
if (!IdToDroid(transporterID, player, &psTransporterDroid))
{
NETend();
// Possible it already died? (sync error?)
debug(LOG_WARNING,"player's %d transport droid %d wasn't found?",player,transporterID);
return false;
}
if (psDroid == NULL)
{
// how can this happen?
return true;
}
// Take it out of the world without destroying it (just removes it from the droid list)
bDroidRemoved = droidRemove(psDroid, apsDroidLists);
// Init the order for when disembark
psDroid->order = DORDER_NONE;
setDroidTarget(psDroid, NULL);
psDroid->psTarStats = NULL;
if (bDroidRemoved)
{
// and now we need to add it to their transporter group!
grpJoin(psTransporterDroid->psGroup, psDroid);
}
else
{
// possible sync error?
debug(LOG_WARNING,"Eh? Where did unit %d go? Couldn't load droid onto transporter.",droidID);
}
} }
NETend(); NETend();
if (psDroid == NULL)
{
return true;
}
// Take it out of the world without destroying it
droidRemove(psDroid, apsDroidLists);
// Init the order for when disembark
psDroid->order = DORDER_NONE;
setDroidTarget(psDroid, NULL);
psDroid->psTarStats = NULL;
return true; return true;
} }
// sending information that droid is being unloaded from a transporter
BOOL sendDroidDisEmbark(const DROID* psDroid) BOOL sendDroidDisEmbark(const DROID* psDroid, const DROID* psTransporter)
{ {
if (!bMultiPlayer) if (!bMultiPlayer)
return true; return true;
@ -280,64 +307,87 @@ BOOL sendDroidDisEmbark(const DROID* psDroid)
NETbeginEncode(NET_DROIDDISEMBARK, NET_ALL_PLAYERS); NETbeginEncode(NET_DROIDDISEMBARK, NET_ALL_PLAYERS);
{ {
uint8_t player = psDroid->player; uint8_t player = psDroid->player;
uint32_t droid = psDroid->id; uint32_t droidID = psDroid->id;
uint32_t transporterID = psTransporter->id;
Vector3uw pos = psDroid->pos; Vector3uw pos = psDroid->pos;
NETuint8_t(&player); NETuint8_t(&player);
NETuint32_t(&droid); NETuint32_t(&droidID);
NETuint32_t(&transporterID);
NETVector3uw(&pos); NETVector3uw(&pos);
} }
return NETend(); return NETend();
} }
// getting informaton about droid is being unloaded from a transporter
BOOL recvDroidDisEmbark() BOOL recvDroidDisEmbark()
{ {
DROID* psDroid; DROID *psFoundDroid = NULL, *psTransporterDroid = NULL;
DROID *psCheckDroid = NULL;
NETbeginDecode(NET_DROIDDISEMBARK); NETbeginDecode(NET_DROIDDISEMBARK);
{ {
uint8_t player; uint8_t player;
uint32_t droid; uint32_t droidID;
uint32_t transporterID;
Vector3uw pos; Vector3uw pos;
NETuint8_t(&player); NETuint8_t(&player);
NETuint32_t(&droid); NETuint32_t(&droidID);
NETuint32_t(&transporterID);
NETVector3uw(&pos); NETVector3uw(&pos);
NETend(); NETend();
if (!IdToDroid(droid, player, &psDroid)) // find the transporter first
if (!IdToDroid(transporterID, player, &psTransporterDroid))
{ {
// Possible it already died? (sync error?)
debug(LOG_WARNING,"player's %d transport droid %d wasn't found?",player,transporterID);
return false;
}
// we need to find the droid *in* the transporter
psCheckDroid = psTransporterDroid ->psGroup->psList;
while (psCheckDroid)
{
// is this the one we want?
if( psCheckDroid->id == droidID)
{
psFoundDroid = psCheckDroid;
break;
}
// not found, so check next one in *group*
psCheckDroid = psCheckDroid->psGrpNext;
}
// don't continue if we couldn't find it.
if (!psFoundDroid)
{
// I don't think this could ever be possible...but
debug(LOG_ERROR,"Couldn't find droid %d to disembark from player %d's transporter?",droidID,player);
return false; return false;
} }
if (psDroid == NULL) // remove it from the transporter
{ grpLeave(psFoundDroid->psGroup, psFoundDroid);
return true;
} // and add it back to the bloody droid list
addDroid(psFoundDroid, apsDroidLists);
// Add it back into the world at the x/y // Add it back into the world at the x/y
psDroid->pos = pos; psFoundDroid->pos = pos;
}
if (!droidOnMap(psDroid)) if (!droidOnMap(psFoundDroid))
{ {
debug(LOG_ERROR, "recvDroidDisEmbark: droid not disembarked on map"); debug(LOG_ERROR,"droid %d disembarked was NOT on map?",psFoundDroid->id);
return false; return false;
} }
updateDroidOrientation(psDroid); updateDroidOrientation(psFoundDroid);
// Initialise the movement data
initDroidMovement(psDroid);
// Reset droid orders
orderDroid(psDroid, DORDER_STOP);
gridAddObject((BASE_OBJECT *)psDroid);
psDroid->cluster = 0;
addDroid(psDroid, apsDroidLists);
// Initialise the movement data
initDroidMovement(psFoundDroid);
// must add it to the grid for targeting to work
gridAddObject((BASE_OBJECT *)psFoundDroid);
} // NetBeginDecode
return true; return true;
} }

View File

@ -169,8 +169,8 @@ extern BOOL SendGroupOrderGroup(const DROID_GROUP* psGroup, DROID_ORDER order, u
extern BOOL sendDroidSecondary (const DROID* psDroid, SECONDARY_ORDER sec, SECONDARY_STATE state); extern BOOL sendDroidSecondary (const DROID* psDroid, SECONDARY_ORDER sec, SECONDARY_STATE state);
extern BOOL sendDroidSecondaryAll(const DROID* psDroid); extern BOOL sendDroidSecondaryAll(const DROID* psDroid);
extern BOOL sendDroidEmbark (const DROID* psDroid); extern BOOL sendDroidEmbark (const DROID* psDroid, const DROID* psTransporter);
extern BOOL sendDroidDisEmbark (const DROID* psDroid); extern BOOL sendDroidDisEmbark (const DROID* psDroid, const DROID* psTransporter);
extern BOOL sendHappyVtol (const DROID* psDroid); extern BOOL sendHappyVtol (const DROID* psDroid);
// Startup. mulitopt // Startup. mulitopt
@ -191,7 +191,7 @@ extern BOOL addTemplate (UDWORD player,DROID_TEMPLATE *psNew);
extern BOOL sendCheck (void); //send/recv check info extern BOOL sendCheck (void); //send/recv check info
extern BOOL sendScoreCheck (void); //score check only(frontend) extern BOOL sendScoreCheck (void); //score check only(frontend)
extern BOOL sendPing (void); // allow game to request pings. extern BOOL sendPing (void); // allow game to request pings.
extern BOOL ForceDroidSync( DROID* droidToSend ); // force a sync on a droid to happen
// multijoin // multijoin
extern void modifyResources (POWER_GEN_FUNCTION* psFunction); extern void modifyResources (POWER_GEN_FUNCTION* psFunction);

View File

@ -205,7 +205,20 @@ static DROID* pickADroid(void)
return pD; return pD;
} }
// ///////////////////////////////////////////////////////////////////////////
// force a droid sync
// We need to update the droid in question ASAP, to prevent 'lost' droids until
// the next 'real' update is done.
BOOL ForceDroidSync( DROID* droidToSend )
{
uint8_t count = 1; // *always* one
if(!droidToSend) return false;
debug(LOG_SYNC,"Force sync of droid %d from player %d",droidToSend->id,droidToSend->player);
NETbeginEncode(NET_CHECK_DROID, NET_ALL_PLAYERS);
NETuint8_t(&count);
packageCheck(droidToSend);
return NETend();
}
// /////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////
// send a droid info packet. // send a droid info packet.
static BOOL sendDroidCheck(void) static BOOL sendDroidCheck(void)

View File

@ -794,12 +794,17 @@ void orderUpdateDroid(DROID *psDroid)
// if in multiPlayer, only want to process if this player's droid // if in multiPlayer, only want to process if this player's droid
if (!bMultiPlayer || psDroid->player == selectedPlayer) if (!bMultiPlayer || psDroid->player == selectedPlayer)
{ {
transporterAddDroid((DROID *)psDroid->psTarget, psDroid); // save the target of current droid (the transporter)
DROID * transporter = (DROID *)psDroid->psTarget;
// order the droid to stop so moveUpdateDroid does not process this unit // order the droid to stop so moveUpdateDroid does not process this unit
orderDroid(psDroid, DORDER_STOP); orderDroid(psDroid, DORDER_STOP);
setDroidTarget(psDroid, NULL); setDroidTarget(psDroid, NULL);
psDroid->psTarStats = NULL; psDroid->psTarStats = NULL;
secondarySetState(psDroid, DSO_RETURN_TO_LOC, DSS_NONE); secondarySetState(psDroid, DSO_RETURN_TO_LOC, DSS_NONE);
// process orders *before* adding unit to transporter
// since we remove it from the list!
transporterAddDroid(transporter, psDroid);
} }
} }
else if (psDroid->action == DACTION_NONE) else if (psDroid->action == DACTION_NONE)

View File

@ -1376,71 +1376,82 @@ void transporterRemoveDroid(UDWORD id)
} }
if (psDroid) if (psDroid)
{ {
/*if we're offWorld we can't pick a tile without swapping the map /*if we're offWorld we can't pick a tile without swapping the map
pointers - can't be bothered so just do this...*/ pointers - can't be bothered so just do this...*/
if (onMission) if (onMission)
{ {
psDroid->pos.x = INVALID_XY; psDroid->pos.x = INVALID_XY;
psDroid->pos.y = INVALID_XY; psDroid->pos.y = INVALID_XY;
} }
else else
{ {
if (bMultiPlayer) if (bMultiPlayer)
{ {
//set the units next to the transporter's current location //set the units next to the transporter's current location
droidX = map_coord(psCurrTransporter->pos.x); droidX = map_coord(psCurrTransporter->pos.x);
droidY = map_coord(psCurrTransporter->pos.y); droidY = map_coord(psCurrTransporter->pos.y);
} }
else else
{ {
//pick a tile because save games won't remember where the droid was when it was loaded //pick a tile because save games won't remember where the droid was when it was loaded
droidX = map_coord(getLandingX(0)); droidX = map_coord(getLandingX(0));
droidY = map_coord(getLandingY(0)); droidY = map_coord(getLandingY(0));
} }
if (!pickATileGen(&droidX, &droidY,LOOK_FOR_EMPTY_TILE,zonedPAT)) if (!pickATileGen(&droidX, &droidY,LOOK_FOR_EMPTY_TILE,zonedPAT))
{ {
ASSERT( false, "transporterRemoveUnit: Unable to find a valid location" ); ASSERT( false, "transporterRemoveUnit: Unable to find a valid location" );
} }
psDroid->pos.x = (UWORD)world_coord(droidX); psDroid->pos.x = (UWORD)world_coord(droidX);
psDroid->pos.y = (UWORD)world_coord(droidY); psDroid->pos.y = (UWORD)world_coord(droidY);
psDroid->pos.z = map_Height(psDroid->pos.x, psDroid->pos.y); psDroid->pos.z = map_Height(psDroid->pos.x, psDroid->pos.y);
updateDroidOrientation(psDroid);
//initialise the movement data
initDroidMovement(psDroid);
//reset droid orders
orderDroid(psDroid, DORDER_STOP);
gridAddObject((BASE_OBJECT *)psDroid);
psDroid->cluster = 0;
}
grpLeave(psDroid->psGroup, psDroid); }
// remove it from the transporter group
grpLeave(psDroid->psGroup, psDroid);
//add it back into apsDroidLists //add it back into apsDroidLists
if (onMission) if (onMission)
{ {
//addDroid(psDroid, mission.apsBuiltDroids); //addDroid(psDroid, mission.apsBuiltDroids);
addDroid(psDroid, mission.apsDroidLists); addDroid(psDroid, mission.apsDroidLists);
} }
else else
{ {
addDroid(psDroid, apsDroidLists); // add the droid back onto the droid list
} addDroid(psDroid, apsDroidLists);
//inform all other players about that
if (bMultiPlayer)
{
sendDroidDisEmbark(psDroid,psCurrTransporter);
}
}
// We can update the orders now, since everyone has been
// notified of the droid exiting the transporter
updateDroidOrientation(psDroid);
//initialise the movement data
initDroidMovement(psDroid);
//reset droid orders
orderDroid(psDroid, DORDER_STOP);
gridAddObject((BASE_OBJECT *)psDroid);
psDroid->cluster = 0;
// check if it is a commander
if (psDroid->droidType == DROID_COMMAND)
{
if (grpCreate(&psGroup))
{
grpJoin(psGroup, psDroid);
}
}
psDroid->selected = true;
if (psDroid->droidType == DROID_COMMAND) if (calcRemainingCapacity(psCurrTransporter))
{ {
if (grpCreate(&psGroup)) //make sure the button isn't flashing
{ stopMissionButtonFlash(IDTRANS_LAUNCH);
grpJoin(psGroup, psDroid); }
}
}
psDroid->selected = true;
if (calcRemainingCapacity(psCurrTransporter))
{
//make sure the button isn't flashing
stopMissionButtonFlash(IDTRANS_LAUNCH);
}
} }
// we want to sync with all clients *now*.
ForceDroidSync(psDroid);
} }
/*adds a droid to the current transporter via the interface*/ /*adds a droid to the current transporter via the interface*/
@ -1474,8 +1485,16 @@ void intTransporterAddDroid(UDWORD id)
/*Adds a droid to the transporter, removing it from the world */ /*Adds a droid to the transporter, removing it from the world */
void transporterAddDroid(DROID *psTransporter, DROID *psDroidToAdd) void transporterAddDroid(DROID *psTransporter, DROID *psDroidToAdd)
{ {
BOOL bDroidRemoved; BOOL bDroidRemoved;
ASSERT( psTransporter != NULL, "Was passed a NULL transporter" );
ASSERT( psDroidToAdd != NULL, "Was passed a NULL droid, can't add to transporter" );
if (!psTransporter || !psDroidToAdd)
{
debug(LOG_ERROR,"We can't add the unit to the transporter!");
return;
}
/* check for space */ /* check for space */
if (!checkTransporterSpace(psTransporter, psDroidToAdd)) if (!checkTransporterSpace(psTransporter, psDroidToAdd))
{ {
@ -1483,24 +1502,31 @@ void transporterAddDroid(DROID *psTransporter, DROID *psDroidToAdd)
} }
if (onMission) if (onMission)
{ {
// removing from droid mission list
bDroidRemoved = droidRemove(psDroidToAdd, mission.apsDroidLists); bDroidRemoved = droidRemove(psDroidToAdd, mission.apsDroidLists);
} }
else else
{ {
// removing from droid list
bDroidRemoved = droidRemove(psDroidToAdd, apsDroidLists); bDroidRemoved = droidRemove(psDroidToAdd, apsDroidLists);
//inform all other players
if (bMultiPlayer)
{
sendDroidEmbark(psDroidToAdd);
}
} }
if (bDroidRemoved) if (bDroidRemoved)
{ {
grpJoin(psTransporter->psGroup, psDroidToAdd); // adding to transporter unit's group list
} grpJoin(psTransporter->psGroup, psDroidToAdd);
//this is called by droidRemove
if (bMultiPlayer)
{
//inform all other players to update their local lists
sendDroidEmbark(psDroidToAdd,psTransporter);
}
}
else
{
debug(LOG_ERROR,"droid %d not found, so nothing added to transporter!",psDroidToAdd->id);
}
//this is called by droidRemove
//intRefreshScreen(); //intRefreshScreen();
} }