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
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;
}
BOOL sendDroidEmbark(const DROID* psDroid)
// broadcast droid & transporter loading information
BOOL sendDroidEmbark(const DROID* psDroid,const DROID* psTransporter )
{
if (!bMultiPlayer)
return true;
@ -228,51 +228,78 @@ BOOL sendDroidEmbark(const DROID* psDroid)
NETbeginEncode(NET_DROIDEMBARK, NET_ALL_PLAYERS);
{
uint8_t player = psDroid->player;
uint32_t droid = psDroid->id;
uint32_t droidID = psDroid->id;
uint32_t transporterID = psTransporter->id;
NETuint8_t(&player);
NETuint32_t(&droid);
NETuint32_t(&droidID);
NETuint32_t(&transporterID);
}
return NETend();
}
// receive droid & transporter loading information
BOOL recvDroidEmbark()
{
DROID* psDroid;
DROID *psDroid;
DROID *psTransporterDroid;
BOOL bDroidRemoved;
NETbeginDecode(NET_DROIDEMBARK);
{
uint8_t player;
uint32_t droid;
uint32_t droidID;
uint32_t transporterID;
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();
// Possible it already died? (sync error?)
debug(LOG_WARNING,"player's %d droid %d wasn't found?",player,droidID);
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();
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;
}
BOOL sendDroidDisEmbark(const DROID* psDroid)
// sending information that droid is being unloaded from a transporter
BOOL sendDroidDisEmbark(const DROID* psDroid, const DROID* psTransporter)
{
if (!bMultiPlayer)
return true;
@ -280,64 +307,87 @@ BOOL sendDroidDisEmbark(const DROID* psDroid)
NETbeginEncode(NET_DROIDDISEMBARK, NET_ALL_PLAYERS);
{
uint8_t player = psDroid->player;
uint32_t droid = psDroid->id;
uint32_t droidID = psDroid->id;
uint32_t transporterID = psTransporter->id;
Vector3uw pos = psDroid->pos;
NETuint8_t(&player);
NETuint32_t(&droid);
NETuint32_t(&droidID);
NETuint32_t(&transporterID);
NETVector3uw(&pos);
}
return NETend();
}
// getting informaton about droid is being unloaded from a transporter
BOOL recvDroidDisEmbark()
{
DROID* psDroid;
DROID *psFoundDroid = NULL, *psTransporterDroid = NULL;
DROID *psCheckDroid = NULL;
NETbeginDecode(NET_DROIDDISEMBARK);
{
uint8_t player;
uint32_t droid;
uint32_t droidID;
uint32_t transporterID;
Vector3uw pos;
NETuint8_t(&player);
NETuint32_t(&droid);
NETuint32_t(&droidID);
NETuint32_t(&transporterID);
NETVector3uw(&pos);
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;
}
if (psDroid == NULL)
{
return true;
}
// remove it from the transporter
grpLeave(psFoundDroid->psGroup, psFoundDroid);
// and add it back to the bloody droid list
addDroid(psFoundDroid, apsDroidLists);
// Add it back into the world at the x/y
psDroid->pos = pos;
}
psFoundDroid->pos = pos;
if (!droidOnMap(psDroid))
{
debug(LOG_ERROR, "recvDroidDisEmbark: droid not disembarked on map");
return false;
}
if (!droidOnMap(psFoundDroid))
{
debug(LOG_ERROR,"droid %d disembarked was NOT on map?",psFoundDroid->id);
return false;
}
updateDroidOrientation(psDroid);
// Initialise the movement data
initDroidMovement(psDroid);
// Reset droid orders
orderDroid(psDroid, DORDER_STOP);
gridAddObject((BASE_OBJECT *)psDroid);
psDroid->cluster = 0;
addDroid(psDroid, apsDroidLists);
updateDroidOrientation(psFoundDroid);
// Initialise the movement data
initDroidMovement(psFoundDroid);
// must add it to the grid for targeting to work
gridAddObject((BASE_OBJECT *)psFoundDroid);
} // NetBeginDecode
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 sendDroidSecondaryAll(const DROID* psDroid);
extern BOOL sendDroidEmbark (const DROID* psDroid);
extern BOOL sendDroidDisEmbark (const DROID* psDroid);
extern BOOL sendDroidEmbark (const DROID* psDroid, const DROID* psTransporter);
extern BOOL sendDroidDisEmbark (const DROID* psDroid, const DROID* psTransporter);
extern BOOL sendHappyVtol (const DROID* psDroid);
// Startup. mulitopt
@ -191,7 +191,7 @@ extern BOOL addTemplate (UDWORD player,DROID_TEMPLATE *psNew);
extern BOOL sendCheck (void); //send/recv check info
extern BOOL sendScoreCheck (void); //score check only(frontend)
extern BOOL sendPing (void); // allow game to request pings.
extern BOOL ForceDroidSync( DROID* droidToSend ); // force a sync on a droid to happen
// multijoin
extern void modifyResources (POWER_GEN_FUNCTION* psFunction);

View File

@ -205,7 +205,20 @@ static DROID* pickADroid(void)
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.
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 (!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
orderDroid(psDroid, DORDER_STOP);
setDroidTarget(psDroid, NULL);
psDroid->psTarStats = NULL;
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)

View File

@ -1376,71 +1376,82 @@ void transporterRemoveDroid(UDWORD id)
}
if (psDroid)
{
/*if we're offWorld we can't pick a tile without swapping the map
pointers - can't be bothered so just do this...*/
if (onMission)
{
psDroid->pos.x = INVALID_XY;
psDroid->pos.y = INVALID_XY;
}
else
{
if (bMultiPlayer)
{
//set the units next to the transporter's current location
droidX = map_coord(psCurrTransporter->pos.x);
droidY = map_coord(psCurrTransporter->pos.y);
}
else
{
//pick a tile because save games won't remember where the droid was when it was loaded
droidX = map_coord(getLandingX(0));
droidY = map_coord(getLandingY(0));
}
if (!pickATileGen(&droidX, &droidY,LOOK_FOR_EMPTY_TILE,zonedPAT))
{
ASSERT( false, "transporterRemoveUnit: Unable to find a valid location" );
}
psDroid->pos.x = (UWORD)world_coord(droidX);
psDroid->pos.y = (UWORD)world_coord(droidY);
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;
}
/*if we're offWorld we can't pick a tile without swapping the map
pointers - can't be bothered so just do this...*/
if (onMission)
{
psDroid->pos.x = INVALID_XY;
psDroid->pos.y = INVALID_XY;
}
else
{
if (bMultiPlayer)
{
//set the units next to the transporter's current location
droidX = map_coord(psCurrTransporter->pos.x);
droidY = map_coord(psCurrTransporter->pos.y);
}
else
{
//pick a tile because save games won't remember where the droid was when it was loaded
droidX = map_coord(getLandingX(0));
droidY = map_coord(getLandingY(0));
}
if (!pickATileGen(&droidX, &droidY,LOOK_FOR_EMPTY_TILE,zonedPAT))
{
ASSERT( false, "transporterRemoveUnit: Unable to find a valid location" );
}
psDroid->pos.x = (UWORD)world_coord(droidX);
psDroid->pos.y = (UWORD)world_coord(droidY);
psDroid->pos.z = map_Height(psDroid->pos.x, psDroid->pos.y);
grpLeave(psDroid->psGroup, psDroid);
}
// remove it from the transporter group
grpLeave(psDroid->psGroup, psDroid);
//add it back into apsDroidLists
if (onMission)
{
//addDroid(psDroid, mission.apsBuiltDroids);
addDroid(psDroid, mission.apsDroidLists);
}
else
{
addDroid(psDroid, apsDroidLists);
}
//add it back into apsDroidLists
if (onMission)
{
//addDroid(psDroid, mission.apsBuiltDroids);
addDroid(psDroid, mission.apsDroidLists);
}
else
{
// 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 (grpCreate(&psGroup))
{
grpJoin(psGroup, psDroid);
}
}
psDroid->selected = true;
if (calcRemainingCapacity(psCurrTransporter))
{
//make sure the button isn't flashing
stopMissionButtonFlash(IDTRANS_LAUNCH);
}
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*/
@ -1474,8 +1485,16 @@ void intTransporterAddDroid(UDWORD id)
/*Adds a droid to the transporter, removing it from the world */
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 */
if (!checkTransporterSpace(psTransporter, psDroidToAdd))
{
@ -1483,24 +1502,31 @@ void transporterAddDroid(DROID *psTransporter, DROID *psDroidToAdd)
}
if (onMission)
{
// removing from droid mission list
bDroidRemoved = droidRemove(psDroidToAdd, mission.apsDroidLists);
}
else
{
// removing from droid list
bDroidRemoved = droidRemove(psDroidToAdd, apsDroidLists);
//inform all other players
if (bMultiPlayer)
{
sendDroidEmbark(psDroidToAdd);
}
}
if (bDroidRemoved)
{
grpJoin(psTransporter->psGroup, psDroidToAdd);
}
//this is called by droidRemove
if (bDroidRemoved)
{
// adding to transporter unit's group list
grpJoin(psTransporter->psGroup, psDroidToAdd);
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();
}